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