1 /*
2 * 1394-Based Digital Camera Control Library
3 *
4 * IIDC-over-USB using libusb backend for dc1394
5 *
6 * Written by David Moore <dcm@acm.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <inttypes.h>
27
28 #include "config.h"
29 #include "platform.h"
30 #include "internal.h"
31 #include "usb.h"
32
33
34 static platform_t *
dc1394_usb_new(void)35 dc1394_usb_new (void)
36 {
37 libusb_context *context;
38 if (libusb_init(&context) != 0)
39 return NULL;
40
41 platform_t * p = calloc (1, sizeof (platform_t));
42 p->context = context;
43 return p;
44 }
45 static void
dc1394_usb_free(platform_t * p)46 dc1394_usb_free (platform_t * p)
47 {
48 if (p->context)
49 libusb_exit(p->context);
50 p->context = NULL;
51 free (p);
52 }
53
54 struct _platform_device_t {
55 libusb_device * dev;
56 };
57
58 typedef struct _usb_device_list_t {
59 platform_device_list_t list;
60 libusb_device ** libusb_list;
61 } usb_device_list_t;
62
63 /* This is the list of USB vendor/products that we know support
64 * IIDC-over-USB. Currently, this is the only mechanism of detecting
65 * such cameras. */
66 static struct _vendor_product_t {
67 uint16_t vendor;
68 uint16_t product;
69 } usb_products[] = {
70 { 0x1e10, 0x2000 }, // Point Grey Firefly MV Color
71 { 0x1e10, 0x2001 }, // Point Grey Firefly MV Mono
72 { 0x1e10, 0x2002 }, // Point Grey High Res Firefly MV Color
73 { 0x1e10, 0x2003 }, // Point Grey High Res Firefly MV Mono
74 { 0x1e10, 0x2004 }, // Point Grey Chameleon Color
75 { 0x1e10, 0x2005 }, // Point Grey Chameleon Mono
76 { 0x1e10, 0x3000 }, // Point Grey Flea 3
77 { 0x1e10, 0x3005 }, // Point Grey Flea 3 (FL3-U3-13Y3M)
78 { 0x1e10, 0x3006 }, // Point Grey Flea 3 (FL3-U3-13S2C)
79 { 0x1e10, 0x3008 }, // Point Grey Flea 3 (FL3-U3-88S2C)
80 { 0x1e10, 0x300a }, // Point Grey Flea 3 (FL3-U3-13E4C)
81 { 0x1e10, 0x300b }, // Point Grey Flea 3 (FL3-U3-13E4M with 1.43.3.2 FW)
82 { 0x1e10, 0x3103 }, // Point Grey Grasshopper 3 (GS3-U3-23S6M)
83 { 0x1e10, 0x3300 }, // Point Grey Flea 3 (FL3-U3-13E4M with 2.7.3.0 FW)
84 { 0x1e10, 0x3800 }, // Point Grey Ladybug 5 (LD5-U3-51S5C-44)
85 { 0, 0 }
86 };
87
88 static int
is_device_iidc(uint16_t vendor,uint16_t product)89 is_device_iidc (uint16_t vendor, uint16_t product)
90 {
91 int j = 0;
92 while (usb_products[j].vendor != 0 && usb_products[j].product != 0) {
93 if (usb_products[j].vendor == vendor &&
94 usb_products[j].product == product)
95 return 1;
96 j++;
97 }
98 return 0;
99 }
100
101 static platform_device_list_t *
dc1394_usb_get_device_list(platform_t * p)102 dc1394_usb_get_device_list (platform_t * p)
103 {
104 usb_device_list_t * list;
105 libusb_device * dev;
106 int i;
107
108 list = calloc (1, sizeof (usb_device_list_t));
109 if (!list)
110 return NULL;
111
112 if (libusb_get_device_list (p->context, &list->libusb_list) < 0)
113 return NULL;
114
115 dev = list->libusb_list[0];
116 for (i=0, dev = list->libusb_list[0]; dev; dev = list->libusb_list[++i]) {
117 struct libusb_device_descriptor desc;
118 if (libusb_get_device_descriptor (dev, &desc) != 0) {
119 dc1394_log_warning ("usb: Failed to get descriptor for device %d",
120 i);
121 continue;
122 }
123
124 if (!is_device_iidc (desc.idVendor, desc.idProduct))
125 continue;
126
127 list->list.num_devices++;
128 list->list.devices = realloc (list->list.devices,
129 list->list.num_devices * sizeof (platform_device_t *));
130 platform_device_t * pdev = malloc(sizeof(platform_device_t));
131 pdev->dev = dev;
132 list->list.devices[list->list.num_devices-1] = pdev;
133
134 dc1394_log_debug ("usb: Found vendor:prod %x:%x at address %x:%x",
135 desc.idVendor, desc.idProduct,
136 libusb_get_bus_number (dev), libusb_get_device_address (dev));
137 }
138
139 return &list->list;
140 }
141
142 static void
dc1394_usb_free_device_list(platform_device_list_t * d)143 dc1394_usb_free_device_list (platform_device_list_t * d)
144 {
145 usb_device_list_t * list = (usb_device_list_t *) d;
146 int i;
147 for (i = 0; i < d->num_devices; i++)
148 free (d->devices[i]);
149 free (d->devices);
150 libusb_free_device_list (list->libusb_list, 1);
151 free (d);
152 }
153
154 /* The high 16 bits of the IEEE 1394 address space are mapped to the request
155 * byte of USB control transfers. Only a discrete set addresses are
156 * currently supported, as mapped by this function. */
157 static int
address_to_request(uint64_t address)158 address_to_request (uint64_t address)
159 {
160 switch (address >> 32) {
161 case 0xffff:
162 return 0x7f;
163 case 0xd000:
164 return 0x80;
165 case 0xd0001:
166 return 0x81;
167 }
168 dc1394_log_error("usb: Invalid high address %x for request",
169 address >> 32);
170 return -1;
171 }
172
173 #define REQUEST_TIMEOUT_MS 1000
174
175 static int
do_read(libusb_device_handle * handle,uint64_t address,uint32_t * quads,int num_quads)176 do_read (libusb_device_handle * handle, uint64_t address, uint32_t * quads,
177 int num_quads)
178 {
179 int request = address_to_request (address);
180 if (request < 0)
181 return -1;
182
183 unsigned char buf[num_quads*4];
184
185 /* IEEE 1394 address reads are mapped to USB control transfers as
186 * shown here. */
187 int ret = libusb_control_transfer (handle, 0xc0, request,
188 address & 0xffff, (address >> 16) & 0xffff,
189 buf, num_quads * 4, REQUEST_TIMEOUT_MS);
190 if (ret < 0)
191 return -1;
192 int i;
193 int ret_quads = (ret + 3) / 4;
194 /* Convert from little-endian to host-endian */
195 for (i = 0; i < ret_quads; i++) {
196 quads[i] = (buf[4*i+3] << 24) | (buf[4*i+2] << 16)
197 | (buf[4*i+1] << 8) | buf[4*i];
198 }
199 return ret_quads;
200 }
201
202 static int
do_write(libusb_device_handle * handle,uint64_t address,const uint32_t * quads,int num_quads)203 do_write (libusb_device_handle * handle, uint64_t address,
204 const uint32_t * quads, int num_quads)
205 {
206 int request = address_to_request (address);
207 if (request < 0)
208 return -1;
209
210 unsigned char buf[num_quads*4];
211 int i;
212 /* Convert from host-endian to little-endian */
213 for (i = 0; i < num_quads; i++) {
214 buf[4*i] = quads[i] & 0xff;
215 buf[4*i+1] = (quads[i] >> 8) & 0xff;
216 buf[4*i+2] = (quads[i] >> 16) & 0xff;
217 buf[4*i+3] = (quads[i] >> 24) & 0xff;
218 }
219 /* IEEE 1394 address writes are mapped to USB control transfers as
220 * shown here. */
221 int ret = libusb_control_transfer (handle, 0x40, request,
222 address & 0xffff, (address >> 16) & 0xffff,
223 buf, num_quads * 4, REQUEST_TIMEOUT_MS);
224 if (ret < 0)
225 return -1;
226 return ret / 4;
227 }
228
229 static int
dc1394_usb_device_get_config_rom(platform_device_t * device,uint32_t * quads,int * num_quads)230 dc1394_usb_device_get_config_rom (platform_device_t * device,
231 uint32_t * quads, int * num_quads)
232 {
233 libusb_device_handle * handle;
234 if (libusb_open (device->dev, &handle) < 0) {
235 dc1394_log_warning ("usb: Failed to open device for config ROM");
236 return DC1394_FAILURE;
237 }
238
239 if (*num_quads > 256)
240 *num_quads = 256;
241
242 /* Read the config ROM one quad at a time because a read longer than
243 * the length of the ROM will fail. */
244 int i;
245 for (i = 0; i < *num_quads; i++) {
246 int ret = do_read (handle, CONFIG_ROM_BASE + 0x400 + 4*i,
247 quads + i, 1);
248 if (ret < 1)
249 break;
250 }
251
252 if (i == 0) {
253 dc1394_log_error ("usb: Failed to read config ROM");
254 libusb_close (handle);
255 return -1;
256 }
257
258 *num_quads = i;
259 libusb_close (handle);
260 return 0;
261 }
262
263 static platform_camera_t *
dc1394_usb_camera_new(platform_t * p,platform_device_t * device,uint32_t unit_directory_offset)264 dc1394_usb_camera_new (platform_t * p, platform_device_t * device,
265 uint32_t unit_directory_offset)
266 {
267 libusb_device_handle * handle;
268 platform_camera_t * camera;
269
270 if (libusb_open (device->dev, &handle) < 0) {
271 dc1394_log_error ("usb: Failed to open device");
272 return NULL;
273 }
274
275 if (libusb_set_configuration (handle, 1) < 0) {
276 dc1394_log_error ("usb: Failed to set configuration 1 after open");
277 libusb_close (handle);
278 return NULL;
279 }
280
281 camera = calloc (1, sizeof (platform_camera_t));
282 camera->handle = handle;
283 return camera;
284 }
285
dc1394_usb_camera_free(platform_camera_t * cam)286 static void dc1394_usb_camera_free (platform_camera_t * cam)
287 {
288 libusb_close (cam->handle);
289 cam->handle = NULL;
290 free (cam);
291 }
292
293 static void
dc1394_usb_camera_set_parent(platform_camera_t * cam,dc1394camera_t * parent)294 dc1394_usb_camera_set_parent (platform_camera_t * cam, dc1394camera_t * parent)
295 {
296 cam->camera = parent;
297 }
298
299 static dc1394error_t
dc1394_usb_camera_print_info(platform_camera_t * camera,FILE * fd)300 dc1394_usb_camera_print_info (platform_camera_t * camera, FILE *fd)
301 {
302 libusb_device *dev = libusb_get_device (camera->handle);
303 struct libusb_device_descriptor desc;
304 libusb_get_device_descriptor (dev, &desc);
305 fprintf(fd,"------ Camera platform-specific information ------\n");
306 fprintf(fd,"USB Bus Number : %d\n",
307 libusb_get_bus_number (dev));
308 fprintf(fd,"USB Device Address : %d\n",
309 libusb_get_device_address (dev));
310 fprintf(fd,"Vendor ID : 0x%x\n",
311 desc.idVendor);
312 fprintf(fd,"Product ID : 0x%x\n",
313 desc.idProduct);
314 return DC1394_SUCCESS;
315 }
316
317 static dc1394error_t
dc1394_usb_camera_read(platform_camera_t * cam,uint64_t offset,uint32_t * quads,int num_quads)318 dc1394_usb_camera_read (platform_camera_t * cam, uint64_t offset,
319 uint32_t * quads, int num_quads)
320 {
321 if (do_read (cam->handle, CONFIG_ROM_BASE + offset, quads,
322 num_quads) != num_quads)
323 return DC1394_FAILURE;
324
325 return DC1394_SUCCESS;
326 }
327
328 static dc1394error_t
dc1394_usb_camera_write(platform_camera_t * cam,uint64_t offset,const uint32_t * quads,int num_quads)329 dc1394_usb_camera_write (platform_camera_t * cam, uint64_t offset,
330 const uint32_t * quads, int num_quads)
331 {
332 if (do_write (cam->handle, CONFIG_ROM_BASE + offset, quads,
333 num_quads) != num_quads)
334 return DC1394_FAILURE;
335
336 return DC1394_SUCCESS;
337 }
338
339 static dc1394error_t
dc1394_usb_camera_get_node(platform_camera_t * cam,uint32_t * node,uint32_t * generation)340 dc1394_usb_camera_get_node(platform_camera_t *cam, uint32_t *node,
341 uint32_t * generation)
342 {
343 /* Since node/generation doesn't really apply to USB, we instead
344 * put the device address in the "node" argument and "bus number"
345 * in the generation argument. */
346 if (node)
347 *node = libusb_get_device_address (libusb_get_device (cam->handle));
348 if (generation)
349 *generation = libusb_get_bus_number (libusb_get_device (cam->handle));
350 return DC1394_SUCCESS;
351 }
352
353 static dc1394error_t
dc1394_usb_reset_bus(platform_camera_t * cam)354 dc1394_usb_reset_bus (platform_camera_t * cam)
355 {
356 int ret = libusb_reset_device (cam->handle);
357 if (ret == 0 || ret == LIBUSB_ERROR_NOT_FOUND)
358 return DC1394_SUCCESS;
359
360 return DC1394_FAILURE;
361 }
362
363 static platform_dispatch_t
364 usb_dispatch = {
365 .platform_new = dc1394_usb_new,
366 .platform_free = dc1394_usb_free,
367
368 .get_device_list = dc1394_usb_get_device_list,
369 .free_device_list = dc1394_usb_free_device_list,
370 .device_get_config_rom = dc1394_usb_device_get_config_rom,
371
372 .camera_new = dc1394_usb_camera_new,
373 .camera_free = dc1394_usb_camera_free,
374 .camera_set_parent = dc1394_usb_camera_set_parent,
375
376 .camera_print_info = dc1394_usb_camera_print_info,
377 .camera_get_node = dc1394_usb_camera_get_node,
378 .reset_bus = dc1394_usb_reset_bus,
379
380 .camera_read = dc1394_usb_camera_read,
381 .camera_write = dc1394_usb_camera_write,
382
383 .capture_setup = dc1394_usb_capture_setup,
384 .capture_stop = dc1394_usb_capture_stop,
385 .capture_dequeue = dc1394_usb_capture_dequeue,
386 .capture_enqueue = dc1394_usb_capture_enqueue,
387 .capture_get_fileno = dc1394_usb_capture_get_fileno,
388 .capture_is_frame_corrupt = dc1394_usb_capture_is_frame_corrupt,
389
390 #ifdef HAVE_MACOSX
391 .capture_set_callback = dc1394_usb_capture_set_callback,
392 .capture_schedule_with_runloop = dc1394_usb_capture_schedule_with_runloop,
393 #else
394 .capture_set_callback = NULL,
395 .capture_schedule_with_runloop = NULL,
396 #endif
397 };
398
399 void
dc1394_usb_init(dc1394_t * d)400 dc1394_usb_init(dc1394_t * d)
401 {
402 register_platform (d, &usb_dispatch, "usb");
403 }
404