stream pushing ok without access permission of /dev/video0
[rtmpclient.git] / app / src / main / jni / libuvc / src / device_original.c
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 *  Copyright (C) 2010-2012 Ken Tossell
5 *  All rights reserved.
6 *
7 *  Redistribution and use in source and binary forms, with or without
8 *  modification, are permitted provided that the following conditions
9 *  are met:
10 *
11 *   * Redistributions of source code must retain the above copyright
12 *     notice, this list of conditions and the following disclaimer.
13 *   * Redistributions in binary form must reproduce the above
14 *     copyright notice, this list of conditions and the following
15 *     disclaimer in the documentation and/or other materials provided
16 *     with the distribution.
17 *   * Neither the name of the author nor other contributors may be
18 *     used to endorse or promote products derived from this software
19 *     without specific prior written permission.
20 *
21 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 *  POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 /**
35  * @defgroup device Device handling and enumeration
36  */
37
38 #include "libuvc/libuvc.h"
39 #include "libuvc/libuvc_internal.h"
40
41 int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev);
42 void uvc_free_devh(uvc_device_handle_t *devh);
43
44 uvc_error_t uvc_get_device_info(uvc_device_t *dev, uvc_device_info_t **info);
45 void uvc_free_device_info(uvc_device_info_t *info);
46
47 uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info);
48 uvc_error_t uvc_parse_vc(uvc_device_t *dev,
49                          uvc_device_info_t *info,
50                          const unsigned char *block, size_t block_size);
51 uvc_error_t uvc_parse_vc_extension_unit(uvc_device_t *dev,
52                                         uvc_device_info_t *info,
53                                         const unsigned char *block,
54                                         size_t block_size);
55 uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
56                                 uvc_device_info_t *info,
57                                 const unsigned char *block, size_t block_size);
58 uvc_error_t uvc_parse_vc_input_terminal(uvc_device_t *dev,
59                                         uvc_device_info_t *info,
60                                         const unsigned char *block,
61                                         size_t block_size);
62 uvc_error_t uvc_parse_vc_processing_unit(uvc_device_t *dev,
63                                          uvc_device_info_t *info,
64                                          const unsigned char *block,
65                                          size_t block_size);
66
67 uvc_error_t uvc_scan_streaming(uvc_device_t *dev,
68                                uvc_device_info_t *info,
69                                int interface_idx);
70 uvc_error_t uvc_parse_vs(uvc_device_t *dev,
71                          uvc_device_info_t *info,
72                          uvc_streaming_interface_t *stream_if,
73                          const unsigned char *block, size_t block_size);
74 uvc_error_t uvc_parse_vs_format_uncompressed(uvc_streaming_interface_t *stream_if,
75                                              const unsigned char *block,
76                                              size_t block_size);
77 uvc_error_t uvc_parse_vs_format_mjpeg(uvc_streaming_interface_t *stream_if,
78                                              const unsigned char *block,
79                                              size_t block_size);
80 uvc_error_t uvc_parse_vs_frame_uncompressed(uvc_streaming_interface_t *stream_if,
81                                             const unsigned char *block,
82                                             size_t block_size);
83 uvc_error_t uvc_parse_vs_input_header(uvc_streaming_interface_t *stream_if,
84                                       const unsigned char *block,
85                                       size_t block_size);
86
87 void _uvc_status_callback(struct libusb_transfer *transfer);
88
89 /** @internal
90  * @brief Test whether the specified USB device has been opened as a UVC device
91  * @ingroup device
92  *
93  * @param ctx Context in which to search for the UVC device
94  * @param usb_dev USB device to find
95  * @return true if the device is open in this context
96  */
97 int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev) {
98   uvc_device_handle_t *devh;
99
100   DL_FOREACH(ctx->open_devices, devh) {
101     if (usb_dev == devh->dev->usb_dev)
102       return 1;
103   }
104
105   return 0;
106 }
107
108 /** @brief Finds a camera identified by vendor, product and/or serial number
109  * @ingroup device
110  *
111  * @param[in] ctx UVC context in which to search for the camera
112  * @param[out] dev Reference to the camera, or NULL if not found
113  * @param[in] vid Vendor ID number, optional
114  * @param[in] pid Product ID number, optional
115  * @param[in] sn Serial number or NULL
116  * @return Error finding device or UVC_SUCCESS
117  */
118 uvc_error_t uvc_find_device(
119     uvc_context_t *ctx, uvc_device_t **dev,
120     int vid, int pid, const char *sn) {
121   uvc_error_t ret = UVC_SUCCESS;
122
123   uvc_device_t **list;
124   uvc_device_t *test_dev;
125   int dev_idx;
126   int found_dev;
127
128   UVC_ENTER();
129
130   ret = uvc_get_device_list(ctx, &list);
131
132   if (ret != UVC_SUCCESS) {
133     UVC_EXIT(ret);
134     return ret;
135   }
136
137   dev_idx = 0;
138   found_dev = 0;
139
140   while (!found_dev && (test_dev = list[dev_idx++]) != NULL) {
141     uvc_device_descriptor_t *desc;
142
143     if (uvc_get_device_descriptor(test_dev, &desc) != UVC_SUCCESS)
144       continue;
145
146     if ((!vid || desc->idVendor == vid)
147         && (!pid || desc->idProduct == pid)
148         && (!sn || (desc->serialNumber && !strcmp(desc->serialNumber, sn))))
149       found_dev = 1;
150
151     uvc_free_device_descriptor(desc);
152   }
153
154   if (found_dev)
155     uvc_ref_device(test_dev);
156
157   uvc_free_device_list(list, 1);
158
159   if (found_dev) {
160     *dev = test_dev;
161     UVC_EXIT(UVC_SUCCESS);
162     return UVC_SUCCESS;
163   } else {
164     UVC_EXIT(UVC_ERROR_NO_DEVICE);
165     return UVC_ERROR_NO_DEVICE;
166   }
167 }
168
169 /** @brief Get the number of the bus to which the device is attached
170  * @ingroup device
171  */
172 uint8_t uvc_get_bus_number(uvc_device_t *dev) {
173   return libusb_get_bus_number(dev->usb_dev);
174 }
175
176 /** @brief Get the number assigned to the device within its bus
177  * @ingroup device
178  */
179 uint8_t uvc_get_device_address(uvc_device_t *dev) {
180   return libusb_get_device_address(dev->usb_dev);
181 }
182
183 /** @brief Open a UVC device
184  * @ingroup device
185  *
186  * @param dev Device to open
187  * @param[out] devh Handle on opened device
188  * @return Error opening device or SUCCESS
189  */
190 uvc_error_t uvc_open(
191     uvc_device_t *dev,
192     uvc_device_handle_t **devh) {
193   uvc_error_t ret;
194   struct libusb_device_handle *usb_devh;
195   uvc_device_handle_t *internal_devh;
196   struct libusb_device_descriptor desc;
197
198   UVC_ENTER();
199
200   ret = libusb_open(dev->usb_dev, &usb_devh);
201   UVC_DEBUG("libusb_open() = %d", ret);
202
203   if (ret != UVC_SUCCESS) {
204     UVC_EXIT(ret);
205     return ret;
206   }
207
208   uvc_ref_device(dev);
209
210   internal_devh = calloc(1, sizeof(*internal_devh));
211   internal_devh->dev = dev;
212   internal_devh->usb_devh = usb_devh;
213
214   ret = uvc_get_device_info(dev, &(internal_devh->info));
215
216   if (ret != UVC_SUCCESS)
217     goto fail;
218
219   /* Automatically attach/detach kernel driver on supported platforms */
220   libusb_set_auto_detach_kernel_driver(usb_devh, 1);
221
222   UVC_DEBUG("claiming control interface %d", internal_devh->info->ctrl_if.bInterfaceNumber);
223   ret = uvc_claim_if(internal_devh, internal_devh->info->ctrl_if.bInterfaceNumber);
224   if (ret != UVC_SUCCESS)
225     goto fail;
226
227   libusb_get_device_descriptor(dev->usb_dev, &desc);
228   internal_devh->is_isight = (desc.idVendor == 0x05ac && desc.idProduct == 0x8501);
229
230   if (internal_devh->info->ctrl_if.bEndpointAddress) {
231     internal_devh->status_xfer = libusb_alloc_transfer(0);
232     if (!internal_devh->status_xfer) {
233       ret = UVC_ERROR_NO_MEM;
234       goto fail;
235     }
236
237     libusb_fill_interrupt_transfer(internal_devh->status_xfer,
238                                    usb_devh,
239                                    internal_devh->info->ctrl_if.bEndpointAddress,
240                                    internal_devh->status_buf,
241                                    sizeof(internal_devh->status_buf),
242                                    _uvc_status_callback,
243                                    internal_devh,
244                                    0);
245     ret = libusb_submit_transfer(internal_devh->status_xfer);
246     UVC_DEBUG("libusb_submit_transfer() = %d", ret);
247
248     if (ret) {
249       fprintf(stderr,
250               "uvc: device has a status interrupt endpoint, but unable to read from it\n");
251       goto fail;
252     }
253   }
254
255   if (dev->ctx->own_usb_ctx && dev->ctx->open_devices == NULL) {
256     /* Since this is our first device, we need to spawn the event handler thread */
257     uvc_start_handler_thread(dev->ctx);
258   }
259
260   DL_APPEND(dev->ctx->open_devices, internal_devh);
261   *devh = internal_devh;
262
263   UVC_EXIT(ret);
264
265   return ret;
266
267  fail:
268   uvc_release_if(internal_devh, internal_devh->info->ctrl_if.bInterfaceNumber);
269   libusb_close(usb_devh);
270   uvc_unref_device(dev);
271   uvc_free_devh(internal_devh);
272
273   UVC_EXIT(ret);
274
275   return ret;
276 }
277
278 /**
279  * @internal
280  * @brief Parses the complete device descriptor for a device
281  * @ingroup device
282  * @note Free *info with uvc_free_device_info when you're done
283  *
284  * @param dev Device to parse descriptor for
285  * @param info Where to store a pointer to the new info struct
286  */
287 uvc_error_t uvc_get_device_info(uvc_device_t *dev,
288                                 uvc_device_info_t **info) {
289   uvc_error_t ret;
290   uvc_device_info_t *internal_info;
291
292   UVC_ENTER();
293
294   internal_info = calloc(1, sizeof(*internal_info));
295   if (!internal_info) {
296     UVC_EXIT(UVC_ERROR_NO_MEM);
297     return UVC_ERROR_NO_MEM;
298   }
299
300   if (libusb_get_config_descriptor(dev->usb_dev,
301                                    0,
302                                    &(internal_info->config)) != 0) {
303     free(internal_info);
304     UVC_EXIT(UVC_ERROR_IO);
305     return UVC_ERROR_IO;
306   }
307
308   ret = uvc_scan_control(dev, internal_info);
309   if (ret != UVC_SUCCESS) {
310     uvc_free_device_info(internal_info);
311     UVC_EXIT(ret);
312     return ret;
313   }
314
315   *info = internal_info;
316
317   UVC_EXIT(ret);
318   return ret;
319 }
320
321 /**
322  * @internal
323  * @brief Frees the device descriptor for a device
324  * @ingroup device
325  *
326  * @param info Which device info block to free
327  */
328 void uvc_free_device_info(uvc_device_info_t *info) {
329   uvc_input_terminal_t *input_term, *input_term_tmp;
330   uvc_processing_unit_t *proc_unit, *proc_unit_tmp;
331   uvc_extension_unit_t *ext_unit, *ext_unit_tmp;
332
333   uvc_streaming_interface_t *stream_if, *stream_if_tmp;
334   uvc_format_desc_t *format, *format_tmp;
335   uvc_frame_desc_t *frame, *frame_tmp;
336
337   UVC_ENTER();
338
339   DL_FOREACH_SAFE(info->ctrl_if.input_term_descs, input_term, input_term_tmp) {
340     DL_DELETE(info->ctrl_if.input_term_descs, input_term);
341     free(input_term);
342   }
343
344   DL_FOREACH_SAFE(info->ctrl_if.processing_unit_descs, proc_unit, proc_unit_tmp) {
345     DL_DELETE(info->ctrl_if.processing_unit_descs, proc_unit);
346     free(proc_unit);
347   }
348
349   DL_FOREACH_SAFE(info->ctrl_if.extension_unit_descs, ext_unit, ext_unit_tmp) {
350     DL_DELETE(info->ctrl_if.extension_unit_descs, ext_unit);
351     free(ext_unit);
352   }
353
354   DL_FOREACH_SAFE(info->stream_ifs, stream_if, stream_if_tmp) {
355     DL_FOREACH_SAFE(stream_if->format_descs, format, format_tmp) {
356       DL_FOREACH_SAFE(format->frame_descs, frame, frame_tmp) {
357         if (frame->intervals)
358           free(frame->intervals);
359
360         DL_DELETE(format->frame_descs, frame);
361         free(frame);
362       }
363
364       DL_DELETE(stream_if->format_descs, format);
365       free(format);
366     }
367
368     DL_DELETE(info->stream_ifs, stream_if);
369     free(stream_if);
370   }
371
372   if (info->config)
373     libusb_free_config_descriptor(info->config);
374
375   free(info);
376
377   UVC_EXIT_VOID();
378 }
379
380 /**
381  * @brief Get a descriptor that contains the general information about
382  * a device
383  * @ingroup device
384  *
385  * Free *desc with uvc_free_device_descriptor when you're done.
386  *
387  * @param dev Device to fetch information about
388  * @param[out] desc Descriptor structure
389  * @return Error if unable to fetch information, else SUCCESS
390  */
391 uvc_error_t uvc_get_device_descriptor(
392     uvc_device_t *dev,
393     uvc_device_descriptor_t **desc) {
394   uvc_device_descriptor_t *desc_internal;
395   struct libusb_device_descriptor usb_desc;
396   struct libusb_device_handle *usb_devh;
397   uvc_error_t ret;
398
399   UVC_ENTER();
400
401   ret = libusb_get_device_descriptor(dev->usb_dev, &usb_desc);
402
403   if (ret != UVC_SUCCESS) {
404     UVC_EXIT(ret);
405     return ret;
406   }
407
408   desc_internal = calloc(1, sizeof(*desc_internal));
409   desc_internal->idVendor = usb_desc.idVendor;
410   desc_internal->idProduct = usb_desc.idProduct;
411
412   if (libusb_open(dev->usb_dev, &usb_devh) == 0) {
413     unsigned char serial_buf[64];
414
415     int serial_bytes = libusb_get_string_descriptor_ascii(
416         usb_devh, usb_desc.iSerialNumber, serial_buf, sizeof(serial_buf));
417
418     if (serial_bytes > 0)
419       desc_internal->serialNumber = strdup((const char*) serial_buf);
420
421     /** @todo get manufacturer, product names */
422
423     libusb_close(usb_devh);
424   } else {
425     UVC_DEBUG("can't open device %04x:%04x, not fetching serial",
426               usb_desc.idVendor, usb_desc.idProduct);
427   }
428
429   *desc = desc_internal;
430
431   UVC_EXIT(ret);
432   return ret;
433 }
434
435 /**
436  * @brief Frees a device descriptor created with uvc_get_device_descriptor
437  * @ingroup device
438  *
439  * @param desc Descriptor to free
440  */
441 void uvc_free_device_descriptor(
442     uvc_device_descriptor_t *desc) {
443   UVC_ENTER();
444
445   if (desc->serialNumber)
446     free((void*) desc->serialNumber);
447
448   if (desc->manufacturer)
449     free((void*) desc->manufacturer);
450
451   if (desc->product)
452     free((void*) desc->product);
453
454   free(desc);
455
456   UVC_EXIT_VOID();
457 }
458
459 /**
460  * @brief Get a list of the UVC devices attached to the system
461  * @ingroup device
462  *
463  * @note Free the list with uvc_free_device_list when you're done.
464  *
465  * @param ctx UVC context in which to list devices
466  * @param list List of uvc_device structures
467  * @return Error if unable to list devices, else SUCCESS
468  */
469 uvc_error_t uvc_get_device_list(
470     uvc_context_t *ctx,
471     uvc_device_t ***list) {
472   uvc_error_t ret;
473   struct libusb_device **usb_dev_list;
474   struct libusb_device *usb_dev;
475   int num_usb_devices;
476
477   uvc_device_t **list_internal;
478   int num_uvc_devices;
479
480   /* per device */
481   int dev_idx;
482   struct libusb_device_handle *usb_devh;
483   struct libusb_config_descriptor *config;
484   uint8_t got_interface;
485
486   /* per interface */
487   int interface_idx;
488   const struct libusb_interface *interface;
489
490   /* per altsetting */
491   int altsetting_idx;
492   const struct libusb_interface_descriptor *if_desc;
493
494   UVC_ENTER();
495
496   num_usb_devices = libusb_get_device_list(ctx->usb_ctx, &usb_dev_list);
497
498   if (num_usb_devices < 0) {
499     UVC_EXIT(UVC_ERROR_IO);
500     return UVC_ERROR_IO;
501   }
502
503   list_internal = malloc(sizeof(*list_internal));
504   *list_internal = NULL;
505
506   num_uvc_devices = 0;
507   dev_idx = -1;
508
509   while ((usb_dev = usb_dev_list[++dev_idx]) != NULL) {
510     usb_devh = NULL;
511     got_interface = 0;
512
513     if (libusb_get_config_descriptor(usb_dev, 0, &config) != 0)
514       continue;
515
516     for (interface_idx = 0;
517          !got_interface && interface_idx < config->bNumInterfaces;
518          ++interface_idx) {
519       interface = &config->interface[interface_idx];
520
521       for (altsetting_idx = 0;
522            !got_interface && altsetting_idx < interface->num_altsetting;
523            ++altsetting_idx) {
524         if_desc = &interface->altsetting[altsetting_idx];
525
526         /* Video, Streaming */
527         if (if_desc->bInterfaceClass == 14 && if_desc->bInterfaceSubClass == 2) {
528           got_interface = 1;
529         }
530       }
531     }
532
533     libusb_free_config_descriptor(config);
534
535     if (got_interface) {
536       uvc_device_t *uvc_dev = malloc(sizeof(*uvc_dev));
537       uvc_dev->ctx = ctx;
538       uvc_dev->ref = 0;
539       uvc_dev->usb_dev = usb_dev;
540       uvc_ref_device(uvc_dev);
541
542       num_uvc_devices++;
543       list_internal = realloc(list_internal, (num_uvc_devices + 1) * sizeof(*list_internal));
544
545       list_internal[num_uvc_devices - 1] = uvc_dev;
546       list_internal[num_uvc_devices] = NULL;
547
548       UVC_DEBUG("    UVC: %d", dev_idx);
549     } else {
550       UVC_DEBUG("non-UVC: %d", dev_idx);
551     }
552   }
553
554   libusb_free_device_list(usb_dev_list, 1);
555
556   *list = list_internal;
557
558   UVC_EXIT(UVC_SUCCESS);
559   return UVC_SUCCESS;
560 }
561
562 /**
563  * @brief Frees a list of device structures created with uvc_get_device_list.
564  * @ingroup device
565  *
566  * @param list Device list to free
567  * @param unref_devices Decrement the reference counter for each device
568  * in the list, and destroy any entries that end up with zero references
569  */
570 void uvc_free_device_list(uvc_device_t **list, uint8_t unref_devices) {
571   uvc_device_t *dev;
572   int dev_idx = 0;
573
574   UVC_ENTER();
575
576   if (unref_devices) {
577     while ((dev = list[dev_idx++]) != NULL) {
578       uvc_unref_device(dev);
579     }
580   }
581
582   free(list);
583
584   UVC_EXIT_VOID();
585 }
586
587 /**
588  * @brief Get the uvc_device_t corresponding to an open device
589  * @ingroup device
590  *
591  * @note Unref the uvc_device_t when you're done with it
592  *
593  * @param devh Device handle to an open UVC device
594  */
595 uvc_device_t *uvc_get_device(uvc_device_handle_t *devh) {
596   uvc_ref_device(devh->dev);
597   return devh->dev;
598 }
599
600 /**
601  * @brief Get the underlying libusb device handle for an open device
602  * @ingroup device
603  *
604  * This can be used to access other interfaces on the same device, e.g.
605  * a webcam microphone.
606  *
607  * @note The libusb device handle is only valid while the UVC device is open;
608  * it will be invalidated upon calling uvc_close.
609  *
610  * @param devh UVC device handle to an open device
611  */
612 libusb_device_handle *uvc_get_libusb_handle(uvc_device_handle_t *devh) {
613   return devh->usb_devh;
614 }
615
616 /**
617  * @brief Get input terminal descriptors for the open device.
618  *
619  * @note Do not modify the returned structure.
620  * @note The returned structure is part of a linked list. Iterate through
621  *       it by using the 'next' pointers.
622  *
623  * @param devh Device handle to an open UVC device
624  */
625 const uvc_input_terminal_t *uvc_get_input_terminals(uvc_device_handle_t *devh) {
626   return devh->info->ctrl_if.input_term_descs;
627 }
628
629 /**
630  * @brief Get output terminal descriptors for the open device.
631  *
632  * @note Do not modify the returned structure.
633  * @note The returned structure is part of a linked list. Iterate through
634  *       it by using the 'next' pointers.
635  *
636  * @param devh Device handle to an open UVC device
637  */
638 const uvc_output_terminal_t *uvc_get_output_terminals(uvc_device_handle_t *devh) {
639   return NULL; /* @todo */
640 }
641
642 /**
643  * @brief Get processing unit descriptors for the open device.
644  *
645  * @note Do not modify the returned structure.
646  * @note The returned structure is part of a linked list. Iterate through
647  *       it by using the 'next' pointers.
648  *
649  * @param devh Device handle to an open UVC device
650  */
651 const uvc_processing_unit_t *uvc_get_processing_units(uvc_device_handle_t *devh) {
652   return devh->info->ctrl_if.processing_unit_descs;
653 }
654
655 /**
656  * @brief Get extension unit descriptors for the open device.
657  *
658  * @note Do not modify the returned structure.
659  * @note The returned structure is part of a linked list. Iterate through
660  *       it by using the 'next' pointers.
661  *
662  * @param devh Device handle to an open UVC device
663  */
664 const uvc_extension_unit_t *uvc_get_extension_units(uvc_device_handle_t *devh) {
665   return devh->info->ctrl_if.extension_unit_descs;
666 }
667
668 /**
669  * @brief Increment the reference count for a device
670  * @ingroup device
671  *
672  * @param dev Device to reference
673  */
674 void uvc_ref_device(uvc_device_t *dev) {
675   UVC_ENTER();
676
677   dev->ref++;
678   libusb_ref_device(dev->usb_dev);
679
680   UVC_EXIT_VOID();
681 }
682
683 /**
684  * @brief Decrement the reference count for a device
685  * @ingropu device
686  * @note If the count reaches zero, the device will be discarded
687  *
688  * @param dev Device to unreference
689  */
690 void uvc_unref_device(uvc_device_t *dev) {
691   UVC_ENTER();
692
693   libusb_unref_device(dev->usb_dev);
694   dev->ref--;
695
696   if (dev->ref == 0)
697     free(dev);
698
699   UVC_EXIT_VOID();
700 }
701
702 /** @internal
703  * Claim a UVC interface, detaching the kernel driver if necessary.
704  * @ingroup device
705  *
706  * @param devh UVC device handle
707  * @param idx UVC interface index
708  */
709 uvc_error_t uvc_claim_if(uvc_device_handle_t *devh, int idx) {
710   int ret;
711
712   UVC_ENTER();
713
714   UVC_DEBUG("claiming interface %d", idx);
715   ret = libusb_claim_interface(devh->usb_devh, idx);
716
717   UVC_EXIT(ret);
718   return ret;
719 }
720
721 /** @internal
722  * Release a UVC interface.
723  * @ingroup device
724  *
725  * @param devh UVC device handle
726  * @param idx UVC interface index
727  */
728 uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx) {
729   int ret;
730
731   UVC_ENTER();
732   UVC_DEBUG("releasing interface %d", idx);
733   /* libusb_release_interface *should* reset the alternate setting to the first available,
734      but sometimes (e.g. on Darwin) it doesn't. Thus, we do it explicitly here.
735      This is needed to de-initialize certain cameras. */
736   libusb_set_interface_alt_setting(devh->usb_devh, idx, 0);
737   ret = libusb_release_interface(devh->usb_devh, idx);
738
739   UVC_EXIT(ret);
740   return ret;
741 }
742
743 /** @internal
744  * Find a device's VideoControl interface and process its descriptor
745  * @ingroup device
746  */
747 uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {
748   const struct libusb_interface_descriptor *if_desc;
749   uvc_error_t parse_ret, ret;
750   int interface_idx;
751   const unsigned char *buffer;
752   size_t buffer_left, block_size;
753
754   UVC_ENTER();
755
756   ret = UVC_SUCCESS;
757   if_desc = NULL;
758
759   for (interface_idx = 0; interface_idx < info->config->bNumInterfaces; ++interface_idx) {
760     if_desc = &info->config->interface[interface_idx].altsetting[0];
761
762     if (if_desc->bInterfaceClass == 14 && if_desc->bInterfaceSubClass == 1) // Video, Control
763       break;
764
765     if_desc = NULL;
766   }
767
768   if (if_desc == NULL) {
769     UVC_EXIT(UVC_ERROR_INVALID_DEVICE);
770     return UVC_ERROR_INVALID_DEVICE;
771   }
772
773   info->ctrl_if.bInterfaceNumber = interface_idx;
774   if (if_desc->bNumEndpoints != 0) {
775     info->ctrl_if.bEndpointAddress = if_desc->endpoint[0].bEndpointAddress;
776   }
777
778   buffer = if_desc->extra;
779   buffer_left = if_desc->extra_length;
780
781   while (buffer_left >= 3) { // parseX needs to see buf[0,2] = length,type
782     block_size = buffer[0];
783     parse_ret = uvc_parse_vc(dev, info, buffer, block_size);
784
785     if (parse_ret != UVC_SUCCESS) {
786       ret = parse_ret;
787       break;
788     }
789
790     buffer_left -= block_size;
791     buffer += block_size;
792   }
793
794   UVC_EXIT(ret);
795   return ret;
796 }
797
798 /** @internal
799  * @brief Parse a VideoControl header.
800  * @ingroup device
801  */
802 uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
803                                 uvc_device_info_t *info,
804                                 const unsigned char *block, size_t block_size) {
805   size_t i;
806   uvc_error_t scan_ret, ret = UVC_SUCCESS;
807
808   UVC_ENTER();
809
810   /*
811   int uvc_version;
812   uvc_version = (block[4] >> 4) * 1000 + (block[4] & 0x0f) * 100
813     + (block[3] >> 4) * 10 + (block[3] & 0x0f);
814   */
815
816   info->ctrl_if.bcdUVC = SW_TO_SHORT(&block[3]);
817
818   switch (info->ctrl_if.bcdUVC) {
819   case 0x0100:
820   case 0x010a:
821   case 0x0110:
822     break;
823   default:
824     UVC_EXIT(UVC_ERROR_NOT_SUPPORTED);
825     return UVC_ERROR_NOT_SUPPORTED;
826   }
827
828   for (i = 12; i < block_size; ++i) {
829     scan_ret = uvc_scan_streaming(dev, info, block[i]);
830     if (scan_ret != UVC_SUCCESS) {
831       ret = scan_ret;
832       break;
833     }
834   }
835
836   UVC_EXIT(ret);
837   return ret;
838 }
839
840 /** @internal
841  * @brief Parse a VideoControl input terminal.
842  * @ingroup device
843  */
844 uvc_error_t uvc_parse_vc_input_terminal(uvc_device_t *dev,
845                                         uvc_device_info_t *info,
846                                         const unsigned char *block, size_t block_size) {
847   uvc_input_terminal_t *term;
848   size_t i;
849
850   UVC_ENTER();
851
852   /* only supporting camera-type input terminals */
853   if (SW_TO_SHORT(&block[4]) != UVC_ITT_CAMERA) {
854     UVC_EXIT(UVC_SUCCESS);
855     return UVC_SUCCESS;
856   }
857
858   term = calloc(1, sizeof(*term));
859
860   term->bTerminalID = block[3];
861   term->wTerminalType = SW_TO_SHORT(&block[4]);
862   term->wObjectiveFocalLengthMin = SW_TO_SHORT(&block[8]);
863   term->wObjectiveFocalLengthMax = SW_TO_SHORT(&block[10]);
864   term->wOcularFocalLength = SW_TO_SHORT(&block[12]);
865
866   for (i = 14 + block[14]; i >= 15; --i)
867     term->bmControls = block[i] + (term->bmControls << 8);
868
869   DL_APPEND(info->ctrl_if.input_term_descs, term);
870
871   UVC_EXIT(UVC_SUCCESS);
872   return UVC_SUCCESS;
873 }
874
875 /** @internal
876  * @brief Parse a VideoControl processing unit.
877  * @ingroup device
878  */
879 uvc_error_t uvc_parse_vc_processing_unit(uvc_device_t *dev,
880                                          uvc_device_info_t *info,
881                                          const unsigned char *block, size_t block_size) {
882   uvc_processing_unit_t *unit;
883   size_t i;
884
885   UVC_ENTER();
886
887   unit = calloc(1, sizeof(*unit));
888   unit->bUnitID = block[3];
889   unit->bSourceID = block[4];
890   
891   for (i = 7 + block[7]; i >= 8; --i)
892     unit->bmControls = block[i] + (unit->bmControls << 8);
893   
894   DL_APPEND(info->ctrl_if.processing_unit_descs, unit);
895
896   UVC_EXIT(UVC_SUCCESS);
897   return UVC_SUCCESS;
898 }
899
900 /** @internal
901  * @brief Parse a VideoControl extension unit.
902  * @ingroup device
903  */
904 uvc_error_t uvc_parse_vc_extension_unit(uvc_device_t *dev,
905                                         uvc_device_info_t *info,
906                                         const unsigned char *block, size_t block_size) {
907   uvc_extension_unit_t *unit = calloc(1, sizeof(*unit));
908   const uint8_t *start_of_controls;
909   int size_of_controls, num_in_pins;
910   int i;
911
912   UVC_ENTER();
913
914   unit->bUnitID = block[3];
915   memcpy(unit->guidExtensionCode, &block[4], 16);
916   
917   num_in_pins = block[21];
918   size_of_controls = block[22 + num_in_pins];
919   start_of_controls = &block[23 + num_in_pins];
920   
921   for (i = size_of_controls - 1; i >= 0; --i)
922     unit->bmControls = start_of_controls[i] + (unit->bmControls << 8);
923   
924   DL_APPEND(info->ctrl_if.extension_unit_descs, unit);
925
926   UVC_EXIT(UVC_SUCCESS);
927   return UVC_SUCCESS;
928 }
929
930 /** @internal
931  * Process a single VideoControl descriptor block
932  * @ingroup device
933  */
934 uvc_error_t uvc_parse_vc(
935     uvc_device_t *dev,
936     uvc_device_info_t *info,
937     const unsigned char *block, size_t block_size) {
938   int descriptor_subtype;
939   uvc_error_t ret = UVC_SUCCESS;
940
941   UVC_ENTER();
942
943   if (block[1] != 36) { // not a CS_INTERFACE descriptor??
944     UVC_EXIT(UVC_SUCCESS);
945     return UVC_SUCCESS; // UVC_ERROR_INVALID_DEVICE;
946   }
947
948   descriptor_subtype = block[2];
949
950   switch (descriptor_subtype) {
951   case UVC_VC_HEADER:
952     ret = uvc_parse_vc_header(dev, info, block, block_size);
953     break;
954   case UVC_VC_INPUT_TERMINAL:
955     ret = uvc_parse_vc_input_terminal(dev, info, block, block_size);
956     break;
957   case UVC_VC_OUTPUT_TERMINAL:
958     break;
959   case UVC_VC_SELECTOR_UNIT:
960     break;
961   case UVC_VC_PROCESSING_UNIT:
962     ret = uvc_parse_vc_processing_unit(dev, info, block, block_size);
963     break;
964   case UVC_VC_EXTENSION_UNIT:
965     ret = uvc_parse_vc_extension_unit(dev, info, block, block_size);
966     break;
967   default:
968     ret = UVC_ERROR_INVALID_DEVICE;
969   }
970
971   UVC_EXIT(ret);
972   return ret;
973 }
974
975 /** @internal
976  * Process a VideoStreaming interface
977  * @ingroup device
978  */
979 uvc_error_t uvc_scan_streaming(uvc_device_t *dev,
980                                uvc_device_info_t *info,
981                                int interface_idx) {
982   const struct libusb_interface_descriptor *if_desc;
983   const unsigned char *buffer;
984   size_t buffer_left, block_size;
985   uvc_error_t ret, parse_ret;
986   uvc_streaming_interface_t *stream_if;
987
988   UVC_ENTER();
989
990   ret = UVC_SUCCESS;
991
992   if_desc = &(info->config->interface[interface_idx].altsetting[0]);
993   buffer = if_desc->extra;
994   buffer_left = if_desc->extra_length;
995
996   stream_if = calloc(1, sizeof(*stream_if));
997   stream_if->parent = info;
998   stream_if->bInterfaceNumber = if_desc->bInterfaceNumber;
999   DL_APPEND(info->stream_ifs, stream_if);
1000
1001   while (buffer_left >= 3) {
1002     block_size = buffer[0];
1003     parse_ret = uvc_parse_vs(dev, info, stream_if, buffer, block_size);
1004
1005     if (parse_ret != UVC_SUCCESS) {
1006       ret = parse_ret;
1007       break;
1008     }
1009
1010     buffer_left -= block_size;
1011     buffer += block_size;
1012   }
1013
1014   UVC_EXIT(ret);
1015   return ret;
1016 }
1017
1018 /** @internal
1019  * @brief Parse a VideoStreaming header block.
1020  * @ingroup device
1021  */
1022 uvc_error_t uvc_parse_vs_input_header(uvc_streaming_interface_t *stream_if,
1023                                       const unsigned char *block,
1024                                       size_t block_size) {
1025   UVC_ENTER();
1026
1027   stream_if->bEndpointAddress = block[6] & 0x8f;
1028   stream_if->bTerminalLink = block[8];
1029
1030   UVC_EXIT(UVC_SUCCESS);
1031   return UVC_SUCCESS;
1032 }
1033
1034 /** @internal
1035  * @brief Parse a VideoStreaming uncompressed format block.
1036  * @ingroup device
1037  */
1038 uvc_error_t uvc_parse_vs_format_uncompressed(uvc_streaming_interface_t *stream_if,
1039                                              const unsigned char *block,
1040                                              size_t block_size) {
1041   UVC_ENTER();
1042
1043   uvc_format_desc_t *format = calloc(1, sizeof(*format));
1044
1045   format->parent = stream_if;
1046   format->bDescriptorSubtype = block[2];
1047   format->bFormatIndex = block[3];
1048   //format->bmCapabilities = block[4];
1049   //format->bmFlags = block[5];
1050   memcpy(format->guidFormat, &block[5], 16);
1051   format->bBitsPerPixel = block[21];
1052   format->bDefaultFrameIndex = block[22];
1053   format->bAspectRatioX = block[23];
1054   format->bAspectRatioY = block[24];
1055   format->bmInterlaceFlags = block[25];
1056   format->bCopyProtect = block[26];
1057
1058   DL_APPEND(stream_if->format_descs, format);
1059
1060   UVC_EXIT(UVC_SUCCESS);
1061   return UVC_SUCCESS;
1062 }
1063
1064 /** @internal
1065  * @brief Parse a VideoStreaming MJPEG format block.
1066  * @ingroup device
1067  */
1068 uvc_error_t uvc_parse_vs_format_mjpeg(uvc_streaming_interface_t *stream_if,
1069                                              const unsigned char *block,
1070                                              size_t block_size) {
1071   UVC_ENTER();
1072
1073   uvc_format_desc_t *format = calloc(1, sizeof(*format));
1074
1075   format->parent = stream_if;
1076   format->bDescriptorSubtype = block[2];
1077   format->bFormatIndex = block[3];
1078   memcpy(format->fourccFormat, "MJPG", 4);
1079   format->bmFlags = block[5];
1080   format->bBitsPerPixel = 0;
1081   format->bDefaultFrameIndex = block[6];
1082   format->bAspectRatioX = block[7];
1083   format->bAspectRatioY = block[8];
1084   format->bmInterlaceFlags = block[9];
1085   format->bCopyProtect = block[10];
1086
1087   DL_APPEND(stream_if->format_descs, format);
1088
1089   UVC_EXIT(UVC_SUCCESS);
1090   return UVC_SUCCESS;
1091 }
1092
1093 /** @internal
1094  * @brief Parse a VideoStreaming uncompressed frame block.
1095  * @ingroup device
1096  */
1097 uvc_error_t uvc_parse_vs_frame_uncompressed(uvc_streaming_interface_t *stream_if,
1098                                             const unsigned char *block,
1099                                             size_t block_size) {
1100   uvc_format_desc_t *format;
1101   uvc_frame_desc_t *frame;
1102
1103   const unsigned char *p;
1104   int i;
1105
1106   UVC_ENTER();
1107
1108   format = stream_if->format_descs->prev;
1109   frame = calloc(1, sizeof(*frame));
1110
1111   frame->parent = format;
1112
1113   frame->bDescriptorSubtype = block[2];
1114   frame->bFrameIndex = block[3];
1115   frame->bmCapabilities = block[4];
1116   frame->wWidth = block[5] + (block[6] << 8);
1117   frame->wHeight = block[7] + (block[8] << 8);
1118   frame->dwMinBitRate = DW_TO_INT(&block[9]);
1119   frame->dwMaxBitRate = DW_TO_INT(&block[13]);
1120   frame->dwMaxVideoFrameBufferSize = DW_TO_INT(&block[17]);
1121   frame->dwDefaultFrameInterval = DW_TO_INT(&block[21]);
1122   // frame->bFrameIntervalType = block[25];
1123
1124   if (block[25] == 0) {
1125     frame->dwMinFrameInterval = DW_TO_INT(&block[26]);
1126     frame->dwMaxFrameInterval = DW_TO_INT(&block[30]);
1127     frame->dwFrameIntervalStep = DW_TO_INT(&block[34]);
1128   } else {
1129     frame->intervals = calloc(block[25] + 1, sizeof(frame->intervals[0]));
1130     p = &block[26];
1131
1132     for (i = 0; i < block[25]; ++i) {
1133       frame->intervals[i] = DW_TO_INT(p);
1134       p += 4;
1135     }
1136     frame->intervals[block[25]] = 0;
1137   }
1138
1139   DL_APPEND(format->frame_descs, frame);
1140
1141   UVC_EXIT(UVC_SUCCESS);
1142   return UVC_SUCCESS;
1143 }
1144
1145 /** @internal
1146  * Process a single VideoStreaming descriptor block
1147  * @ingroup device
1148  */
1149 uvc_error_t uvc_parse_vs(
1150     uvc_device_t *dev,
1151     uvc_device_info_t *info,
1152     uvc_streaming_interface_t *stream_if,
1153     const unsigned char *block, size_t block_size) {
1154   uvc_error_t ret;
1155   int descriptor_subtype;
1156
1157   UVC_ENTER();
1158
1159   ret = UVC_SUCCESS;
1160   descriptor_subtype = block[2];
1161
1162   switch (descriptor_subtype) {
1163   case UVC_VS_INPUT_HEADER:
1164     ret = uvc_parse_vs_input_header(stream_if, block, block_size);
1165     break;
1166   case UVC_VS_FORMAT_UNCOMPRESSED:
1167     ret = uvc_parse_vs_format_uncompressed(stream_if, block, block_size);
1168     break;
1169   case UVC_VS_FORMAT_MJPEG:
1170     ret = uvc_parse_vs_format_mjpeg(stream_if, block, block_size);
1171     break;
1172   case UVC_VS_FRAME_UNCOMPRESSED:
1173   case UVC_VS_FRAME_MJPEG:
1174     ret = uvc_parse_vs_frame_uncompressed(stream_if, block, block_size);
1175     break;
1176   default:
1177     /** @todo handle JPEG and maybe still frames or even DV... */
1178     break;
1179   }
1180
1181   UVC_EXIT(ret);
1182   return ret;
1183 }
1184
1185 /** @internal
1186  * @brief Free memory associated with a UVC device
1187  * @pre Streaming must be stopped, and threads must have died
1188  */
1189 void uvc_free_devh(uvc_device_handle_t *devh) {
1190   UVC_ENTER();
1191
1192   if (devh->info)
1193     uvc_free_device_info(devh->info);
1194
1195   if (devh->status_xfer)
1196     libusb_free_transfer(devh->status_xfer);
1197
1198   free(devh);
1199
1200   UVC_EXIT_VOID();
1201 }
1202
1203 /** @brief Close a device
1204  *
1205  * @ingroup device
1206  *
1207  * Ends any stream that's in progress.
1208  *
1209  * The device handle and frame structures will be invalidated.
1210  */
1211 void uvc_close(uvc_device_handle_t *devh) {
1212   UVC_ENTER();
1213   uvc_context_t *ctx = devh->dev->ctx;
1214
1215   if (devh->streams)
1216     uvc_stop_streaming(devh);
1217
1218   uvc_release_if(devh, devh->info->ctrl_if.bInterfaceNumber);
1219
1220   /* If we are managing the libusb context and this is the last open device,
1221    * then we need to cancel the handler thread. When we call libusb_close,
1222    * it'll cause a return from the thread's libusb_handle_events call, after
1223    * which the handler thread will check the flag we set and then exit. */
1224   if (ctx->own_usb_ctx && ctx->open_devices == devh && devh->next == NULL) {
1225     ctx->kill_handler_thread = 1;
1226     libusb_close(devh->usb_devh);
1227     pthread_join(ctx->handler_thread, NULL);
1228   } else {
1229     libusb_close(devh->usb_devh);
1230   }
1231
1232   DL_DELETE(ctx->open_devices, devh);
1233
1234   uvc_unref_device(devh->dev);
1235
1236   uvc_free_devh(devh);
1237
1238   UVC_EXIT_VOID();
1239 }
1240
1241 /** @internal
1242  * @brief Get number of open devices
1243  */
1244 size_t uvc_num_devices(uvc_context_t *ctx) {
1245   size_t count = 0;
1246
1247   uvc_device_handle_t *devh;
1248
1249   UVC_ENTER();
1250
1251   DL_FOREACH(ctx->open_devices, devh) {
1252     count++;
1253   }
1254
1255   UVC_EXIT((int) count);
1256   return count;
1257 }
1258
1259 void uvc_process_status_xfer(uvc_device_handle_t *devh, struct libusb_transfer *transfer) {
1260   enum uvc_status_class status_class;
1261   uint8_t originator = 0, selector = 0, event = 0;
1262   enum uvc_status_attribute attribute = UVC_STATUS_ATTRIBUTE_UNKNOWN;
1263   void *data = NULL;
1264   size_t data_len = 0;
1265
1266   UVC_ENTER();
1267
1268   /* printf("Got transfer of aLen = %d\n", transfer->actual_length); */
1269
1270   if (transfer->actual_length < 4) {
1271     UVC_DEBUG("Short read of status update (%d bytes)", transfer->actual_length);
1272     UVC_EXIT_VOID();
1273     return;
1274   }
1275
1276   originator = transfer->buffer[1];
1277
1278   switch (transfer->buffer[0] & 0x0f) {
1279   case 1: {  /* VideoControl interface */
1280     int found_entity = 0;
1281     struct uvc_input_terminal *input_terminal;
1282     struct uvc_processing_unit *processing_unit;
1283
1284     if (transfer->actual_length < 5) {
1285       UVC_DEBUG("Short read of VideoControl status update (%d bytes)",
1286                 transfer->actual_length);
1287       UVC_EXIT_VOID();
1288       return;
1289     }
1290
1291     event = transfer->buffer[2];
1292     selector = transfer->buffer[3];
1293
1294     if (originator == 0) {
1295       UVC_DEBUG("Unhandled update from VC interface");
1296       UVC_EXIT_VOID();
1297       return;  /* @todo VideoControl virtual entity interface updates */
1298     }
1299
1300     if (event != 0) {
1301       UVC_DEBUG("Unhandled VC event %d", (int) event);
1302       UVC_EXIT_VOID();
1303       return;
1304     }
1305
1306     /* printf("bSelector: %d\n", selector); */
1307
1308     DL_FOREACH(devh->info->ctrl_if.input_term_descs, input_terminal) {
1309       if (input_terminal->bTerminalID == originator) {
1310         status_class = UVC_STATUS_CLASS_CONTROL_CAMERA;
1311         found_entity = 1;
1312         break;
1313       }
1314     }
1315
1316     if (!found_entity) {
1317       DL_FOREACH(devh->info->ctrl_if.processing_unit_descs, processing_unit) {
1318         if (processing_unit->bUnitID == originator) {
1319           status_class = UVC_STATUS_CLASS_CONTROL_PROCESSING;
1320           found_entity = 1;
1321           break;
1322         }
1323       }
1324     }
1325
1326     if (!found_entity) {
1327       UVC_DEBUG("Got status update for unknown VideoControl entity %d",
1328                 (int) originator);
1329       UVC_EXIT_VOID();
1330       return;
1331     }
1332
1333     attribute = transfer->buffer[4];
1334     data = transfer->buffer + 5;
1335     data_len = transfer->actual_length - 5;
1336     break;
1337   }
1338   case 2:  /* VideoStreaming interface */
1339     UVC_DEBUG("Unhandled update from VideoStreaming interface");
1340     UVC_EXIT_VOID();
1341     return;  /* @todo VideoStreaming updates */
1342   }
1343
1344   UVC_DEBUG("Event: class=%d, event=%d, selector=%d, attribute=%d, data_len=%zd",
1345     status_class, event, selector, attribute, data_len);
1346
1347   if(devh->status_cb) {
1348     UVC_DEBUG("Running user-supplied status callback");
1349     devh->status_cb(status_class,
1350                     event,
1351                     selector,
1352                     attribute,
1353                     data, data_len,
1354                     devh->status_user_ptr);
1355   }
1356
1357   UVC_EXIT_VOID();
1358 }
1359
1360 /** @internal
1361  * @brief Process asynchronous status updates from the device.
1362  */
1363 void _uvc_status_callback(struct libusb_transfer *transfer) {
1364   UVC_ENTER();
1365
1366   uvc_device_handle_t *devh = (uvc_device_handle_t *) transfer->user_data;
1367
1368   switch (transfer->status) {
1369   case LIBUSB_TRANSFER_ERROR:
1370   case LIBUSB_TRANSFER_CANCELLED:
1371   case LIBUSB_TRANSFER_NO_DEVICE:
1372     UVC_DEBUG("not processing/resubmitting, status = %d", transfer->status);
1373     UVC_EXIT_VOID();
1374     return;
1375   case LIBUSB_TRANSFER_COMPLETED:
1376     uvc_process_status_xfer(devh, transfer);
1377     break;
1378   case LIBUSB_TRANSFER_TIMED_OUT:
1379   case LIBUSB_TRANSFER_STALL:
1380   case LIBUSB_TRANSFER_OVERFLOW:
1381     UVC_DEBUG("retrying transfer, status = %d", transfer->status);
1382     break;
1383   }
1384
1385   uvc_error_t ret = libusb_submit_transfer(transfer);
1386   UVC_DEBUG("libusb_submit_transfer() = %d", ret);
1387
1388   UVC_EXIT_VOID();
1389 }
1390
1391 /** @brief Set a callback function to receive status updates
1392  *
1393  * @ingroup device
1394  */
1395 void uvc_set_status_callback(uvc_device_handle_t *devh,
1396                              uvc_status_callback_t cb,
1397                              void *user_ptr) {
1398   UVC_ENTER();
1399
1400   devh->status_cb = cb;
1401   devh->status_user_ptr = user_ptr;
1402
1403   UVC_EXIT_VOID();
1404 }