xref: /haiku/src/add-ons/media/media-add-ons/finepix_webcam/FinePixUSBKit/FinePix.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
1 #include <stdio.h>
2 #include "FinePix.h"
3 
4 /* Describes the hardware. */
5 struct camera_hw {
6 	unsigned long /*__u16*/ vendor;
7 	unsigned long /*__u16*/ product;
8 	/* Offical name of the camera. */
9 	char name[32];
10 };
11 
12 static struct camera_hw cam_supp[23] = {
13 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_4800_PID, "Fujifilm FinePix 4800"},
14 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A202_PID, "Fujifilm FinePix A202"},
15 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A203_PID, "Fujifilm FinePix A203"},
16 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A204_PID, "Fujifilm FinePix A204"},
17 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A205_PID, "Fujifilm FinePix A205"},
18 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A210_PID, "Fujifilm FinePix A210"},
19 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A303_PID, "Fujifilm FinePix A303"},
20 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_A310_PID, "Fujifilm FinePix A310"},
21 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_F401_PID, "Fujifilm FinePix F401"},
22 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_F402_PID, "Fujifilm FinePix F402"},
23 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_F410_PID, "Fujifilm FinePix F410"},
24 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_F601_PID, "Fujifilm FinePix F601"},
25 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_F700_PID, "Fujifilm FinePix F700"},
26 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_M603_PID, "Fujifilm FinePix M603"},
27 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_S3000_PID,
28 	 "Fujifilm FinePix S3000"},
29 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_S304_PID, "Fujifilm FinePix S304"},
30 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_S5000_PID,
31 	 "Fujifilm FinePix S5000"},
32 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_S602_PID, "Fujifilm FinePix S602"},
33 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_S7000_PID,
34 	 "Fujifilm FinePix S7000"},
35 
36 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_X1_PID,
37 	 "Fujifilm FinePix unknown model"},
38 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_X2_PID,
39 	 "Fujifilm FinePix unknown model"},
40 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_X3_PID,
41 	 "Fujifilm FinePix unknown model"},
42 	{USB_FUJIFILM_VENDOR_ID, USB_FINEPIX_X4_PID,
43 	 "Fujifilm FinePix unknown model"},
44 };
45 
46 FinePix::FinePix()
47 {
48 	fprintf(stderr, "FinePix::FinePix()\n");
49 
50 	// Initially we don't have a camera device opened.
51 	camera = NULL;
52 
53 	// Start the roster that will wait for FinePix USB devices.
54 	BUSBRoster::Start();
55 }
56 
57 FinePix::~FinePix()
58 {
59 	fprintf(stderr, "FinePix: ~FinePix()\n");
60 
61 	BUSBRoster::Stop();
62 }
63 
64 status_t FinePix::InitCheck()
65 {
66 	fprintf(stderr, "FinePix: InitCheck()\n");
67 
68 	if (camera != NULL)
69 		return B_NO_ERROR;
70 	else
71 		return B_ERROR;
72 }
73 
74 int FinePix::SetupCam()
75 {
76 	int ret; // Return value
77 
78 	fprintf(stderr, "FinePix: SetupCam()\n");
79 
80 	/* Reset bulk in endpoint */
81 	camera->ControlTransfer (USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_IN,
82 						 USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, 0, NULL);
83 
84 	/* Reset the camera *//* Init the device */
85 
86 		unsigned char data[] = { 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 };
87 
88 		ret = camera->ControlTransfer(USB_REQTYPE_INTERFACE_OUT |USB_REQTYPE_CLASS ,
89 										 USB_REQUEST_GET_STATUS, 0x00, 0x00, 12, data);
90 
91 		fprintf(stderr,"data: %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x\n",
92 					data[0], data[1],data[2], data[3],data[4], data[5],
93 					data[6], data[7],data[8], data[9],data[10], data[11]);
94 
95 		if (ret != 12) {
96 			fprintf(stderr,"usb_control_msg failed (%d)\n", ret);
97 			return 1;
98 		}
99 
100 		unsigned char data3[MAX_BUFFER_SIZE];
101 		ret = bulk_in->BulkTransfer(data3, MAX_BUFFER_SIZE);
102 			fprintf(stderr,"BulkIn: %x, %x, %x, %x, %x, %x\n",
103 					data3[0],data3[1],data3[2],data3[3],data3[4],data3[5]);
104 
105 		if (ret < 0) {
106 			fprintf(stderr,"failed to read the result (%d)\n", ret);
107 			//return 1;
108 		}
109 
110 	/* Again, reset bulk in endpoints */
111 	camera->ControlTransfer (USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_IN,
112 						 USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, 0, NULL);
113 
114 	return 0;
115 }
116 
117 int FinePix::GetPic(uint8 *frame, int &total_size)
118 {
119 	fprintf(stderr, "FinePix: GetPic()\n");
120 	int ret; // Return value
121 
122 	/* Request a frame */
123 	fprintf(stderr,"request a frame\n");
124 
125 	unsigned char data2[] = { 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 };
126 
127 	ret = camera->ControlTransfer(USB_REQTYPE_INTERFACE_OUT |USB_REQTYPE_CLASS ,
128 									 USB_REQUEST_GET_STATUS, 0x00, 0x00, 12, data2);
129 
130 	fprintf(stderr,"data: %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x\n",
131 				data2[0], data2[1],data2[2], data2[3],data2[4], data2[5],
132 				data2[6], data2[7],data2[8], data2[9],data2[10], data2[11]);
133 
134 	if (ret != 12)
135 	{
136 		fprintf(stderr,"usb_control_msg failed (%d)\n", ret);
137 		return 1;
138 	}
139 
140 	/* Read the frame */
141 	int offset = 0;
142 	total_size = 0;
143 
144 	do
145 	{
146 		fprintf(stderr,"reading part of the frame\n");
147 
148 		ret = bulk_in->BulkTransfer(&frame[offset], MAX_BUFFER_SIZE);
149 
150 		fprintf(stderr,"frame: %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x\n",
151 			frame[offset+0], frame[offset+1],frame[offset+2], frame[offset+3],
152 			frame[offset+4], frame[offset+5],frame[offset+6], frame[offset+7],
153 			frame[offset+8], frame[offset+9],frame[offset+10], frame[offset+11]);
154 
155 		if (ret < 0) { //this doesn't help, if we have an error we hang at the transfer
156 			fprintf(stderr,"failed to read (%d)\n", ret);
157 
158 			return 1;
159 		}
160 
161 		offset += ret;
162 		total_size += ret;
163 
164 		if (ret != MAX_BUFFER_SIZE) // not a full buffer, must be end of frame
165 			break;
166 	} while(1);
167 
168 	fprintf(stderr,"this frame was %d bytes\n", total_size);
169 
170 	return 0;
171 }
172 
173 status_t FinePix::DeviceAdded(BUSBDevice *dev)
174 {
175 	fprintf(stderr, "FinePix: DeviceAdded()\n");
176 
177 	// Waits for FinePix devices.  When one is attached, configure it,
178 	// so that we are ready to use it.
179 
180 	if (camera != NULL)
181 		return B_ERROR;
182 
183 	int myCam = -1;
184 	// Find the device in our hardware list
185 	if (dev->VendorID() == USB_FUJIFILM_VENDOR_ID)
186 	{
187 		for (int j = 0; j < 23; j++) //TODO use a cleaner way to check j < cam_supp.count
188 		{
189 			if (cam_supp[j].product == dev->ProductID())
190 			{
191 				myCam = j;
192 				break;
193 			}
194 		}
195 	}
196 
197 	if (myCam >= 0)
198 	{
199 		fprintf(stderr, "Found cam: ");
200 		fprintf(stderr, cam_supp[myCam].name);
201 		fprintf(stderr, "\n");
202 
203 		if (dev->SetConfiguration(dev->ConfigurationAt(0)) == 0)
204 		{
205 			camera = dev;
206 
207 			//set endpoint
208 			bulk_in = 0;
209 
210 			int num_epoints = camera->ActiveConfiguration()->InterfaceAt(0)->CountEndpoints();
211 
212 			fprintf(stderr, "CountEndpoints: %d\n", num_epoints);
213 
214 			for (int i = 0; i < num_epoints; i++)
215 			{
216 				if (camera->ActiveConfiguration()->InterfaceAt(0)->EndpointAt(i)->IsBulk())
217 					if (camera->ActiveConfiguration()->InterfaceAt(0)->EndpointAt(i)->IsInput())
218 						bulk_in = camera->ActiveConfiguration()->InterfaceAt(0)->EndpointAt(i);
219 			}
220 
221 			if (bulk_in == 0)
222 			{
223 				fprintf(stderr, "bad endpoint");
224 				return B_ERROR;
225 			}
226 
227 			fprintf(stderr, "Successfully set configuration!\n");
228 
229 			return B_OK;
230 		}
231 		else
232 			return B_ERROR;
233 	}
234 	else
235 		return B_ERROR;
236 }
237 
238 void FinePix::DeviceRemoved(BUSBDevice *dev)
239 {
240 	fprintf(stderr, "FinePix: DeviceRemoved()\n");
241 
242 	// If they remove our device, then we can't use it anymore.
243 	if (dev == camera)
244 		camera = NULL;
245 }
246