1 /*********************************************************************
2 * Software License Agreement (BSD License)
4 * Copyright (C) 2010-2012 Ken Tossell
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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 *********************************************************************/
35 * @defgroup device Device handling and enumeration
36 * @brief Support for finding, inspecting and opening UVC devices
39 #include "libuvc/libuvc.h"
40 #include "libuvc/libuvc_internal.h"
42 int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev);
43 void uvc_free_devh(uvc_device_handle_t *devh);
45 uvc_error_t uvc_get_device_info(uvc_device_t *dev, uvc_device_info_t **info);
46 void uvc_free_device_info(uvc_device_info_t *info);
48 uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info);
49 uvc_error_t uvc_parse_vc(uvc_device_t *dev,
50 uvc_device_info_t *info,
51 const unsigned char *block, size_t block_size);
52 uvc_error_t uvc_parse_vc_selector_unit(uvc_device_t *dev,
53 uvc_device_info_t *info,
54 const unsigned char *block, size_t block_size);
55 uvc_error_t uvc_parse_vc_extension_unit(uvc_device_t *dev,
56 uvc_device_info_t *info,
57 const unsigned char *block,
59 uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
60 uvc_device_info_t *info,
61 const unsigned char *block, size_t block_size);
62 uvc_error_t uvc_parse_vc_input_terminal(uvc_device_t *dev,
63 uvc_device_info_t *info,
64 const unsigned char *block,
66 uvc_error_t uvc_parse_vc_processing_unit(uvc_device_t *dev,
67 uvc_device_info_t *info,
68 const unsigned char *block,
71 uvc_error_t uvc_scan_streaming(uvc_device_t *dev,
72 uvc_device_info_t *info,
74 uvc_error_t uvc_parse_vs(uvc_device_t *dev,
75 uvc_device_info_t *info,
76 uvc_streaming_interface_t *stream_if,
77 const unsigned char *block, size_t block_size);
78 uvc_error_t uvc_parse_vs_format_uncompressed(uvc_streaming_interface_t *stream_if,
79 const unsigned char *block,
81 uvc_error_t uvc_parse_vs_format_mjpeg(uvc_streaming_interface_t *stream_if,
82 const unsigned char *block,
84 uvc_error_t uvc_parse_vs_frame_uncompressed(uvc_streaming_interface_t *stream_if,
85 const unsigned char *block,
87 uvc_error_t uvc_parse_vs_frame_format(uvc_streaming_interface_t *stream_if,
88 const unsigned char *block,
90 uvc_error_t uvc_parse_vs_frame_frame(uvc_streaming_interface_t *stream_if,
91 const unsigned char *block,
93 uvc_error_t uvc_parse_vs_input_header(uvc_streaming_interface_t *stream_if,
94 const unsigned char *block,
97 void LIBUSB_CALL _uvc_status_callback(struct libusb_transfer *transfer);
100 * @brief Test whether the specified USB device has been opened as a UVC device
103 * @param ctx Context in which to search for the UVC device
104 * @param usb_dev USB device to find
105 * @return true if the device is open in this context
107 int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev) {
108 uvc_device_handle_t *devh;
110 DL_FOREACH(ctx->open_devices, devh) {
111 if (usb_dev == devh->dev->usb_dev)
118 /** @brief Finds a camera identified by vendor, product and/or serial number
121 * @param[in] ctx UVC context in which to search for the camera
122 * @param[out] dev Reference to the camera, or NULL if not found
123 * @param[in] vid Vendor ID number, optional
124 * @param[in] pid Product ID number, optional
125 * @param[in] sn Serial number or NULL
126 * @return Error finding device or UVC_SUCCESS
128 uvc_error_t uvc_find_device(
129 uvc_context_t *ctx, uvc_device_t **dev,
130 int vid, int pid, const char *sn) {
131 uvc_error_t ret = UVC_SUCCESS;
134 uvc_device_t *test_dev;
140 ret = uvc_get_device_list(ctx, &list);
142 if (ret != UVC_SUCCESS) {
150 while (!found_dev && (test_dev = list[dev_idx++]) != NULL) {
151 uvc_device_descriptor_t *desc;
153 if (uvc_get_device_descriptor(test_dev, &desc) != UVC_SUCCESS)
156 if ((!vid || desc->idVendor == vid)
157 && (!pid || desc->idProduct == pid)
158 && (!sn || (desc->serialNumber && !strcmp(desc->serialNumber, sn))))
161 uvc_free_device_descriptor(desc);
165 uvc_ref_device(test_dev);
167 uvc_free_device_list(list, 1);
171 UVC_EXIT(UVC_SUCCESS);
174 UVC_EXIT(UVC_ERROR_NO_DEVICE);
175 return UVC_ERROR_NO_DEVICE;
179 /** @brief Finds all cameras identified by vendor, product and/or serial number
182 * @param[in] ctx UVC context in which to search for the camera
183 * @param[out] devs List of matching cameras
184 * @param[in] vid Vendor ID number, optional
185 * @param[in] pid Product ID number, optional
186 * @param[in] sn Serial number or NULL
187 * @return Error finding device or UVC_SUCCESS
189 uvc_error_t uvc_find_devices(
190 uvc_context_t *ctx, uvc_device_t ***devs,
191 int vid, int pid, const char *sn) {
192 uvc_error_t ret = UVC_SUCCESS;
195 uvc_device_t *test_dev;
199 uvc_device_t **list_internal;
204 ret = uvc_get_device_list(ctx, &list);
206 if (ret != UVC_SUCCESS) {
215 list_internal = malloc(sizeof(*list_internal));
216 *list_internal = NULL;
218 while ((test_dev = list[dev_idx++]) != NULL) {
219 uvc_device_descriptor_t *desc;
221 if (uvc_get_device_descriptor(test_dev, &desc) != UVC_SUCCESS)
224 if ((!vid || desc->idVendor == vid)
225 && (!pid || desc->idProduct == pid)
226 && (!sn || (desc->serialNumber && !strcmp(desc->serialNumber, sn)))) {
228 uvc_ref_device(test_dev);
231 list_internal = realloc(list_internal, (num_uvc_devices + 1) * sizeof(*list_internal));
233 list_internal[num_uvc_devices - 1] = test_dev;
234 list_internal[num_uvc_devices] = NULL;
237 uvc_free_device_descriptor(desc);
240 uvc_free_device_list(list, 1);
243 *devs = list_internal;
244 UVC_EXIT(UVC_SUCCESS);
247 UVC_EXIT(UVC_ERROR_NO_DEVICE);
248 return UVC_ERROR_NO_DEVICE;
252 /** @brief Get the number of the bus to which the device is attached
255 uint8_t uvc_get_bus_number(uvc_device_t *dev) {
256 return libusb_get_bus_number(dev->usb_dev);
259 /** @brief Get the number assigned to the device within its bus
262 uint8_t uvc_get_device_address(uvc_device_t *dev) {
263 return libusb_get_device_address(dev->usb_dev);
267 * XXX add for non-rooted Android device, >= Android7
268 * generate fake libusb_device according to specific params
269 * and set it to uvc_device_t to access UVC device on Android7 or later
271 uvc_error_t uvc_get_device_with_fd(uvc_context_t *ctx, uvc_device_t **device,
272 int vid, int pid, const char *serial, int fd, int busnum, int devaddr) {
275 //LOGD("call libusb_get_device_with_fd");
276 UVC_DEBUG("call uvc_get_device_with_fd");
277 struct libusb_device *usb_dev = libusb_get_device_with_fd(ctx->usb_ctx, vid, pid, serial, fd, busnum, devaddr);
279 if (usb_dev != NULL) {
280 *device = malloc(sizeof(uvc_device_t/* *device */));
281 (*device)->ctx = ctx;
283 (*device)->usb_dev = usb_dev;
284 // libusb_set_device_fd(usb_dev, fd); // assign fd to libusb_device for non-rooted Android devices
285 uvc_ref_device(*device);
286 UVC_EXIT(UVC_SUCCESS);
287 //RETURN(UVC_SUCCESS, int);
289 UVC_DEBUG("could not find specific device");
291 UVC_EXIT(UVC_ERROR_NO_DEVICE);
292 //RETURN(UVC_ERROR_NO_DEVICE, int);
297 /** @brief Open a UVC device
300 * @param dev Device to open
301 * @param[out] devh Handle on opened device
302 * @return Error opening device or SUCCESS
304 uvc_error_t uvc_open(
306 uvc_device_handle_t **devh) {
308 struct libusb_device_handle *usb_devh;
309 uvc_device_handle_t *internal_devh;
310 struct libusb_device_descriptor desc;
314 ret = libusb_open(dev->usb_dev, &usb_devh);
315 UVC_DEBUG("libusb_open() = %d", ret);
317 if (ret != UVC_SUCCESS) {
324 internal_devh = calloc(1, sizeof(*internal_devh));
325 internal_devh->dev = dev;
326 internal_devh->usb_devh = usb_devh;
328 ret = uvc_get_device_info(dev, &(internal_devh->info));
330 if (ret != UVC_SUCCESS)
333 UVC_DEBUG("claiming control interface %d", internal_devh->info->ctrl_if.bInterfaceNumber);
334 ret = uvc_claim_if(internal_devh, internal_devh->info->ctrl_if.bInterfaceNumber);
335 if (ret != UVC_SUCCESS)
338 libusb_get_device_descriptor(dev->usb_dev, &desc);
339 internal_devh->is_isight = (desc.idVendor == 0x05ac && desc.idProduct == 0x8501);
341 if (internal_devh->info->ctrl_if.bEndpointAddress) {
342 internal_devh->status_xfer = libusb_alloc_transfer(0);
343 if (!internal_devh->status_xfer) {
344 ret = UVC_ERROR_NO_MEM;
348 libusb_fill_interrupt_transfer(internal_devh->status_xfer,
350 internal_devh->info->ctrl_if.bEndpointAddress,
351 internal_devh->status_buf,
352 sizeof(internal_devh->status_buf),
353 _uvc_status_callback,
356 ret = libusb_submit_transfer(internal_devh->status_xfer);
357 UVC_DEBUG("libusb_submit_transfer() = %d", ret);
361 "uvc: device has a status interrupt endpoint, but unable to read from it\n");
366 if (dev->ctx->own_usb_ctx && dev->ctx->open_devices == NULL) {
367 /* Since this is our first device, we need to spawn the event handler thread */
368 uvc_start_handler_thread(dev->ctx);
371 DL_APPEND(dev->ctx->open_devices, internal_devh);
372 *devh = internal_devh;
379 if ( internal_devh->info ) {
380 uvc_release_if(internal_devh, internal_devh->info->ctrl_if.bInterfaceNumber);
382 libusb_close(usb_devh);
383 uvc_unref_device(dev);
384 uvc_free_devh(internal_devh);
393 * @brief Parses the complete device descriptor for a device
395 * @note Free *info with uvc_free_device_info when you're done
397 * @param dev Device to parse descriptor for
398 * @param info Where to store a pointer to the new info struct
400 uvc_error_t uvc_get_device_info(uvc_device_t *dev,
401 uvc_device_info_t **info) {
403 uvc_device_info_t *internal_info;
407 internal_info = calloc(1, sizeof(*internal_info));
408 if (!internal_info) {
409 UVC_EXIT(UVC_ERROR_NO_MEM);
410 return UVC_ERROR_NO_MEM;
413 if (libusb_get_config_descriptor(dev->usb_dev,
415 &(internal_info->config)) != 0) {
417 UVC_EXIT(UVC_ERROR_IO);
421 ret = uvc_scan_control(dev, internal_info);
422 if (ret != UVC_SUCCESS) {
423 uvc_free_device_info(internal_info);
428 *info = internal_info;
436 * @brief Frees the device descriptor for a device
439 * @param info Which device info block to free
441 void uvc_free_device_info(uvc_device_info_t *info) {
442 uvc_input_terminal_t *input_term, *input_term_tmp;
443 uvc_processing_unit_t *proc_unit, *proc_unit_tmp;
444 uvc_extension_unit_t *ext_unit, *ext_unit_tmp;
446 uvc_streaming_interface_t *stream_if, *stream_if_tmp;
447 uvc_format_desc_t *format, *format_tmp;
448 uvc_frame_desc_t *frame, *frame_tmp;
452 DL_FOREACH_SAFE(info->ctrl_if.input_term_descs, input_term, input_term_tmp) {
453 DL_DELETE(info->ctrl_if.input_term_descs, input_term);
457 DL_FOREACH_SAFE(info->ctrl_if.processing_unit_descs, proc_unit, proc_unit_tmp) {
458 DL_DELETE(info->ctrl_if.processing_unit_descs, proc_unit);
462 DL_FOREACH_SAFE(info->ctrl_if.extension_unit_descs, ext_unit, ext_unit_tmp) {
463 DL_DELETE(info->ctrl_if.extension_unit_descs, ext_unit);
467 DL_FOREACH_SAFE(info->stream_ifs, stream_if, stream_if_tmp) {
468 DL_FOREACH_SAFE(stream_if->format_descs, format, format_tmp) {
469 DL_FOREACH_SAFE(format->frame_descs, frame, frame_tmp) {
470 if (frame->intervals)
471 free(frame->intervals);
473 DL_DELETE(format->frame_descs, frame);
477 DL_DELETE(stream_if->format_descs, format);
481 DL_DELETE(info->stream_ifs, stream_if);
486 libusb_free_config_descriptor(info->config);
494 * @brief Get a descriptor that contains the general information about
498 * Free *desc with uvc_free_device_descriptor when you're done.
500 * @param dev Device to fetch information about
501 * @param[out] desc Descriptor structure
502 * @return Error if unable to fetch information, else SUCCESS
504 uvc_error_t uvc_get_device_descriptor(
506 uvc_device_descriptor_t **desc) {
507 uvc_device_descriptor_t *desc_internal;
508 struct libusb_device_descriptor usb_desc;
509 struct libusb_device_handle *usb_devh;
514 ret = libusb_get_device_descriptor(dev->usb_dev, &usb_desc);
516 if (ret != UVC_SUCCESS) {
521 desc_internal = calloc(1, sizeof(*desc_internal));
522 desc_internal->idVendor = usb_desc.idVendor;
523 desc_internal->idProduct = usb_desc.idProduct;
525 if (libusb_open(dev->usb_dev, &usb_devh) == 0) {
526 unsigned char buf[64];
528 int bytes = libusb_get_string_descriptor_ascii(
529 usb_devh, usb_desc.iSerialNumber, buf, sizeof(buf));
532 desc_internal->serialNumber = strdup((const char*) buf);
534 bytes = libusb_get_string_descriptor_ascii(
535 usb_devh, usb_desc.iManufacturer, buf, sizeof(buf));
538 desc_internal->manufacturer = strdup((const char*) buf);
540 bytes = libusb_get_string_descriptor_ascii(
541 usb_devh, usb_desc.iProduct, buf, sizeof(buf));
544 desc_internal->product = strdup((const char*) buf);
546 libusb_close(usb_devh);
548 UVC_DEBUG("can't open device %04x:%04x, not fetching serial etc.",
549 usb_desc.idVendor, usb_desc.idProduct);
552 *desc = desc_internal;
559 * @brief Frees a device descriptor created with uvc_get_device_descriptor
562 * @param desc Descriptor to free
564 void uvc_free_device_descriptor(
565 uvc_device_descriptor_t *desc) {
568 if (desc->serialNumber)
569 free((void*) desc->serialNumber);
571 if (desc->manufacturer)
572 free((void*) desc->manufacturer);
575 free((void*) desc->product);
583 * @brief Get a list of the UVC devices attached to the system
586 * @note Free the list with uvc_free_device_list when you're done.
588 * @param ctx UVC context in which to list devices
589 * @param list List of uvc_device structures
590 * @return Error if unable to list devices, else SUCCESS
592 uvc_error_t uvc_get_device_list(
594 uvc_device_t ***list) {
595 struct libusb_device **usb_dev_list;
596 struct libusb_device *usb_dev;
599 uvc_device_t **list_internal;
604 struct libusb_config_descriptor *config;
605 struct libusb_device_descriptor desc;
606 uint8_t got_interface;
610 const struct libusb_interface *interface;
614 const struct libusb_interface_descriptor *if_desc;
618 num_usb_devices = libusb_get_device_list(ctx->usb_ctx, &usb_dev_list);
620 if (num_usb_devices < 0) {
621 UVC_EXIT(UVC_ERROR_IO);
625 list_internal = malloc(sizeof(*list_internal));
626 *list_internal = NULL;
631 while ((usb_dev = usb_dev_list[++dev_idx]) != NULL) {
634 if (libusb_get_config_descriptor(usb_dev, 0, &config) != 0)
637 if ( libusb_get_device_descriptor ( usb_dev, &desc ) != LIBUSB_SUCCESS )
640 for (interface_idx = 0;
641 !got_interface && interface_idx < config->bNumInterfaces;
643 interface = &config->interface[interface_idx];
645 for (altsetting_idx = 0;
646 !got_interface && altsetting_idx < interface->num_altsetting;
648 if_desc = &interface->altsetting[altsetting_idx];
650 // Skip TIS cameras that definitely aren't UVC even though they might
653 if ( 0x199e == desc.idVendor && desc.idProduct >= 0x8201 &&
654 desc.idProduct <= 0x8208 ) {
658 // Special case for Imaging Source cameras
659 /* Video, Streaming */
660 if ( 0x199e == desc.idVendor && ( 0x8101 == desc.idProduct ||
661 0x8102 == desc.idProduct ) &&
662 if_desc->bInterfaceClass == 255 &&
663 if_desc->bInterfaceSubClass == 2 ) {
667 /* Video, Streaming */
668 if (if_desc->bInterfaceClass == 14 && if_desc->bInterfaceSubClass == 2) {
674 libusb_free_config_descriptor(config);
677 uvc_device_t *uvc_dev = malloc(sizeof(*uvc_dev));
680 uvc_dev->usb_dev = usb_dev;
681 uvc_ref_device(uvc_dev);
684 list_internal = realloc(list_internal, (num_uvc_devices + 1) * sizeof(*list_internal));
686 list_internal[num_uvc_devices - 1] = uvc_dev;
687 list_internal[num_uvc_devices] = NULL;
689 UVC_DEBUG(" UVC: %d", dev_idx);
691 UVC_DEBUG("non-UVC: %d", dev_idx);
695 libusb_free_device_list(usb_dev_list, 1);
697 *list = list_internal;
699 UVC_EXIT(UVC_SUCCESS);
704 * @brief Frees a list of device structures created with uvc_get_device_list.
707 * @param list Device list to free
708 * @param unref_devices Decrement the reference counter for each device
709 * in the list, and destroy any entries that end up with zero references
711 void uvc_free_device_list(uvc_device_t **list, uint8_t unref_devices) {
718 while ((dev = list[dev_idx++]) != NULL) {
719 uvc_unref_device(dev);
729 * @brief Get the uvc_device_t corresponding to an open device
732 * @note Unref the uvc_device_t when you're done with it
734 * @param devh Device handle to an open UVC device
736 uvc_device_t *uvc_get_device(uvc_device_handle_t *devh) {
737 uvc_ref_device(devh->dev);
742 * @brief Get the underlying libusb device handle for an open device
745 * This can be used to access other interfaces on the same device, e.g.
746 * a webcam microphone.
748 * @note The libusb device handle is only valid while the UVC device is open;
749 * it will be invalidated upon calling uvc_close.
751 * @param devh UVC device handle to an open device
753 libusb_device_handle *uvc_get_libusb_handle(uvc_device_handle_t *devh) {
754 return devh->usb_devh;
758 * @brief Get camera terminal descriptor for the open device.
760 * @note Do not modify the returned structure.
761 * @note The returned structure is part of a linked list, but iterating through
762 * it will make it no longer the camera terminal
764 * @param devh Device handle to an open UVC device
766 const uvc_input_terminal_t *uvc_get_camera_terminal(uvc_device_handle_t *devh) {
767 const uvc_input_terminal_t *term = uvc_get_input_terminals(devh);
768 while(term != NULL) {
769 if (term->wTerminalType == UVC_ITT_CAMERA) {
781 * @brief Get input terminal descriptors for the open device.
783 * @note Do not modify the returned structure.
784 * @note The returned structure is part of a linked list. Iterate through
785 * it by using the 'next' pointers.
787 * @param devh Device handle to an open UVC device
789 const uvc_input_terminal_t *uvc_get_input_terminals(uvc_device_handle_t *devh) {
790 return devh->info->ctrl_if.input_term_descs;
794 * @brief Get output terminal descriptors for the open device.
796 * @note Do not modify the returned structure.
797 * @note The returned structure is part of a linked list. Iterate through
798 * it by using the 'next' pointers.
800 * @param devh Device handle to an open UVC device
802 const uvc_output_terminal_t *uvc_get_output_terminals(uvc_device_handle_t *devh) {
803 return NULL; /* @todo */
807 * @brief Get selector unit descriptors for the open device.
809 * @note Do not modify the returned structure.
810 * @note The returned structure is part of a linked list. Iterate through
811 * it by using the 'next' pointers.
813 * @param devh Device handle to an open UVC device
815 const uvc_selector_unit_t *uvc_get_selector_units(uvc_device_handle_t *devh) {
816 return devh->info->ctrl_if.selector_unit_descs;
820 * @brief Get processing unit descriptors for the open device.
822 * @note Do not modify the returned structure.
823 * @note The returned structure is part of a linked list. Iterate through
824 * it by using the 'next' pointers.
826 * @param devh Device handle to an open UVC device
828 const uvc_processing_unit_t *uvc_get_processing_units(uvc_device_handle_t *devh) {
829 return devh->info->ctrl_if.processing_unit_descs;
833 * @brief Get extension unit descriptors for the open device.
835 * @note Do not modify the returned structure.
836 * @note The returned structure is part of a linked list. Iterate through
837 * it by using the 'next' pointers.
839 * @param devh Device handle to an open UVC device
841 const uvc_extension_unit_t *uvc_get_extension_units(uvc_device_handle_t *devh) {
842 return devh->info->ctrl_if.extension_unit_descs;
846 * @brief Increment the reference count for a device
849 * @param dev Device to reference
851 void uvc_ref_device(uvc_device_t *dev) {
855 libusb_ref_device(dev->usb_dev);
861 * @brief Decrement the reference count for a device
863 * @note If the count reaches zero, the device will be discarded
865 * @param dev Device to unreference
867 void uvc_unref_device(uvc_device_t *dev) {
870 libusb_unref_device(dev->usb_dev);
880 * Claim a UVC interface, detaching the kernel driver if necessary.
883 * @param devh UVC device handle
884 * @param idx UVC interface index
886 uvc_error_t uvc_claim_if(uvc_device_handle_t *devh, int idx) {
887 int ret = UVC_SUCCESS;
891 if ( devh->claimed & ( 1 << idx )) {
892 fprintf ( stderr, "attempt to claim already-claimed interface %d\n", idx );
897 /* Tell libusb to detach any active kernel drivers. libusb will keep track of whether
898 * it found a kernel driver for this interface. */
899 ret = libusb_detach_kernel_driver(devh->usb_devh, idx);
901 if (ret == UVC_SUCCESS || ret == LIBUSB_ERROR_NOT_FOUND || ret == LIBUSB_ERROR_NOT_SUPPORTED) {
902 UVC_DEBUG("claiming interface %d", idx);
903 if (!( ret = libusb_claim_interface(devh->usb_devh, idx))) {
904 devh->claimed |= ( 1 << idx );
907 UVC_DEBUG("not claiming interface %d: unable to detach kernel driver (%s)",
908 idx, uvc_strerror(ret));
916 * Release a UVC interface.
919 * @param devh UVC device handle
920 * @param idx UVC interface index
922 uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx) {
923 int ret = UVC_SUCCESS;
926 UVC_DEBUG("releasing interface %d", idx);
927 if (!( devh->claimed & ( 1 << idx ))) {
928 fprintf ( stderr, "attempt to release unclaimed interface %d\n", idx );
933 /* libusb_release_interface *should* reset the alternate setting to the first available,
934 but sometimes (e.g. on Darwin) it doesn't. Thus, we do it explicitly here.
935 This is needed to de-initialize certain cameras. */
936 libusb_set_interface_alt_setting(devh->usb_devh, idx, 0);
937 ret = libusb_release_interface(devh->usb_devh, idx);
939 if (UVC_SUCCESS == ret) {
940 devh->claimed &= ~( 1 << idx );
941 /* Reattach any kernel drivers that were disabled when we claimed this interface */
942 ret = libusb_attach_kernel_driver(devh->usb_devh, idx);
944 if (ret == UVC_SUCCESS) {
945 UVC_DEBUG("reattached kernel driver to interface %d", idx);
946 } else if (ret == LIBUSB_ERROR_NOT_FOUND || ret == LIBUSB_ERROR_NOT_SUPPORTED) {
947 ret = UVC_SUCCESS; /* NOT_FOUND and NOT_SUPPORTED are OK: nothing to do */
949 UVC_DEBUG("error reattaching kernel driver to interface %d: %s",
950 idx, uvc_strerror(ret));
959 * Find a device's VideoControl interface and process its descriptor
962 uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {
963 const struct libusb_interface_descriptor *if_desc;
964 uvc_error_t parse_ret, ret;
966 const unsigned char *buffer;
967 size_t buffer_left, block_size;
974 uvc_device_descriptor_t* dev_desc;
975 int haveTISCamera = 0;
976 uvc_get_device_descriptor ( dev, &dev_desc );
977 if ( 0x199e == dev_desc->idVendor && ( 0x8101 == dev_desc->idProduct ||
978 0x8102 == dev_desc->idProduct )) {
981 uvc_free_device_descriptor ( dev_desc );
983 for (interface_idx = 0; interface_idx < info->config->bNumInterfaces; ++interface_idx) {
984 if_desc = &info->config->interface[interface_idx].altsetting[0];
986 if ( haveTISCamera && if_desc->bInterfaceClass == 255 && if_desc->bInterfaceSubClass == 1) // Video, Control
989 if (if_desc->bInterfaceClass == 14 && if_desc->bInterfaceSubClass == 1) // Video, Control
995 if (if_desc == NULL) {
996 UVC_EXIT(UVC_ERROR_INVALID_DEVICE);
997 return UVC_ERROR_INVALID_DEVICE;
1000 info->ctrl_if.bInterfaceNumber = interface_idx;
1001 if (if_desc->bNumEndpoints != 0) {
1002 info->ctrl_if.bEndpointAddress = if_desc->endpoint[0].bEndpointAddress;
1005 buffer = if_desc->extra;
1006 buffer_left = if_desc->extra_length;
1008 while (buffer_left >= 3) { // parseX needs to see buf[0,2] = length,type
1009 block_size = buffer[0];
1010 parse_ret = uvc_parse_vc(dev, info, buffer, block_size);
1012 if (parse_ret != UVC_SUCCESS) {
1017 buffer_left -= block_size;
1018 buffer += block_size;
1026 * @brief Parse a VideoControl header.
1029 uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
1030 uvc_device_info_t *info,
1031 const unsigned char *block, size_t block_size) {
1033 uvc_error_t scan_ret, ret = UVC_SUCCESS;
1039 uvc_version = (block[4] >> 4) * 1000 + (block[4] & 0x0f) * 100
1040 + (block[3] >> 4) * 10 + (block[3] & 0x0f);
1043 info->ctrl_if.bcdUVC = SW_TO_SHORT(&block[3]);
1045 switch (info->ctrl_if.bcdUVC) {
1047 info->ctrl_if.dwClockFrequency = DW_TO_INT(block + 7);
1049 info->ctrl_if.dwClockFrequency = DW_TO_INT(block + 7);
1053 UVC_EXIT(UVC_ERROR_NOT_SUPPORTED);
1054 return UVC_ERROR_NOT_SUPPORTED;
1057 for (i = 12; i < block_size; ++i) {
1058 scan_ret = uvc_scan_streaming(dev, info, block[i]);
1059 if (scan_ret != UVC_SUCCESS) {
1070 * @brief Parse a VideoControl input terminal.
1073 uvc_error_t uvc_parse_vc_input_terminal(uvc_device_t *dev,
1074 uvc_device_info_t *info,
1075 const unsigned char *block, size_t block_size) {
1076 uvc_input_terminal_t *term;
1081 /* only supporting camera-type input terminals */
1082 if (SW_TO_SHORT(&block[4]) != UVC_ITT_CAMERA) {
1083 UVC_EXIT(UVC_SUCCESS);
1087 term = calloc(1, sizeof(*term));
1089 term->bTerminalID = block[3];
1090 term->wTerminalType = SW_TO_SHORT(&block[4]);
1091 term->wObjectiveFocalLengthMin = SW_TO_SHORT(&block[8]);
1092 term->wObjectiveFocalLengthMax = SW_TO_SHORT(&block[10]);
1093 term->wOcularFocalLength = SW_TO_SHORT(&block[12]);
1095 for (i = 14 + block[14]; i >= 15; --i)
1096 term->bmControls = block[i] + (term->bmControls << 8);
1098 DL_APPEND(info->ctrl_if.input_term_descs, term);
1100 UVC_EXIT(UVC_SUCCESS);
1105 * @brief Parse a VideoControl processing unit.
1108 uvc_error_t uvc_parse_vc_processing_unit(uvc_device_t *dev,
1109 uvc_device_info_t *info,
1110 const unsigned char *block, size_t block_size) {
1111 uvc_processing_unit_t *unit;
1116 unit = calloc(1, sizeof(*unit));
1117 unit->bUnitID = block[3];
1118 unit->bSourceID = block[4];
1120 for (i = 7 + block[7]; i >= 8; --i)
1121 unit->bmControls = block[i] + (unit->bmControls << 8);
1123 DL_APPEND(info->ctrl_if.processing_unit_descs, unit);
1125 UVC_EXIT(UVC_SUCCESS);
1130 * @brief Parse a VideoControl selector unit.
1133 uvc_error_t uvc_parse_vc_selector_unit(uvc_device_t *dev,
1134 uvc_device_info_t *info,
1135 const unsigned char *block, size_t block_size) {
1136 uvc_selector_unit_t *unit;
1140 unit = calloc(1, sizeof(*unit));
1141 unit->bUnitID = block[3];
1143 DL_APPEND(info->ctrl_if.selector_unit_descs, unit);
1145 UVC_EXIT(UVC_SUCCESS);
1150 * @brief Parse a VideoControl extension unit.
1153 uvc_error_t uvc_parse_vc_extension_unit(uvc_device_t *dev,
1154 uvc_device_info_t *info,
1155 const unsigned char *block, size_t block_size) {
1156 uvc_extension_unit_t *unit = calloc(1, sizeof(*unit));
1157 const uint8_t *start_of_controls;
1158 int size_of_controls, num_in_pins;
1163 unit->bUnitID = block[3];
1164 memcpy(unit->guidExtensionCode, &block[4], 16);
1166 num_in_pins = block[21];
1167 size_of_controls = block[22 + num_in_pins];
1168 start_of_controls = &block[23 + num_in_pins];
1170 for (i = size_of_controls - 1; i >= 0; --i)
1171 unit->bmControls = start_of_controls[i] + (unit->bmControls << 8);
1173 DL_APPEND(info->ctrl_if.extension_unit_descs, unit);
1175 UVC_EXIT(UVC_SUCCESS);
1180 * Process a single VideoControl descriptor block
1183 uvc_error_t uvc_parse_vc(
1185 uvc_device_info_t *info,
1186 const unsigned char *block, size_t block_size) {
1187 int descriptor_subtype;
1188 uvc_error_t ret = UVC_SUCCESS;
1192 if (block[1] != 36) { // not a CS_INTERFACE descriptor??
1193 UVC_EXIT(UVC_SUCCESS);
1194 return UVC_SUCCESS; // UVC_ERROR_INVALID_DEVICE;
1197 descriptor_subtype = block[2];
1199 switch (descriptor_subtype) {
1201 ret = uvc_parse_vc_header(dev, info, block, block_size);
1203 case UVC_VC_INPUT_TERMINAL:
1204 ret = uvc_parse_vc_input_terminal(dev, info, block, block_size);
1206 case UVC_VC_OUTPUT_TERMINAL:
1208 case UVC_VC_SELECTOR_UNIT:
1209 ret = uvc_parse_vc_selector_unit(dev, info, block, block_size);
1211 case UVC_VC_PROCESSING_UNIT:
1212 ret = uvc_parse_vc_processing_unit(dev, info, block, block_size);
1214 case UVC_VC_EXTENSION_UNIT:
1215 ret = uvc_parse_vc_extension_unit(dev, info, block, block_size);
1218 ret = UVC_ERROR_INVALID_DEVICE;
1226 * Process a VideoStreaming interface
1229 uvc_error_t uvc_scan_streaming(uvc_device_t *dev,
1230 uvc_device_info_t *info,
1231 int interface_idx) {
1232 const struct libusb_interface_descriptor *if_desc;
1233 const unsigned char *buffer;
1234 size_t buffer_left, block_size;
1235 uvc_error_t ret, parse_ret;
1236 uvc_streaming_interface_t *stream_if;
1242 if_desc = &(info->config->interface[interface_idx].altsetting[0]);
1243 buffer = if_desc->extra;
1244 buffer_left = if_desc->extra_length;
1246 stream_if = calloc(1, sizeof(*stream_if));
1247 stream_if->parent = info;
1248 stream_if->bInterfaceNumber = if_desc->bInterfaceNumber;
1249 DL_APPEND(info->stream_ifs, stream_if);
1251 while (buffer_left >= 3) {
1252 block_size = buffer[0];
1253 parse_ret = uvc_parse_vs(dev, info, stream_if, buffer, block_size);
1255 if (parse_ret != UVC_SUCCESS) {
1260 buffer_left -= block_size;
1261 buffer += block_size;
1269 * @brief Parse a VideoStreaming header block.
1272 uvc_error_t uvc_parse_vs_input_header(uvc_streaming_interface_t *stream_if,
1273 const unsigned char *block,
1274 size_t block_size) {
1277 stream_if->bEndpointAddress = block[6] & 0x8f;
1278 stream_if->bTerminalLink = block[8];
1280 UVC_EXIT(UVC_SUCCESS);
1285 * @brief Parse a VideoStreaming uncompressed format block.
1288 uvc_error_t uvc_parse_vs_format_uncompressed(uvc_streaming_interface_t *stream_if,
1289 const unsigned char *block,
1290 size_t block_size) {
1293 uvc_format_desc_t *format = calloc(1, sizeof(*format));
1295 format->parent = stream_if;
1296 format->bDescriptorSubtype = block[2];
1297 format->bFormatIndex = block[3];
1298 //format->bmCapabilities = block[4];
1299 //format->bmFlags = block[5];
1300 memcpy(format->guidFormat, &block[5], 16);
1301 format->bBitsPerPixel = block[21];
1302 format->bDefaultFrameIndex = block[22];
1303 format->bAspectRatioX = block[23];
1304 format->bAspectRatioY = block[24];
1305 format->bmInterlaceFlags = block[25];
1306 format->bCopyProtect = block[26];
1308 DL_APPEND(stream_if->format_descs, format);
1310 UVC_EXIT(UVC_SUCCESS);
1315 * @brief Parse a VideoStreaming frame format block.
1318 uvc_error_t uvc_parse_vs_frame_format(uvc_streaming_interface_t *stream_if,
1319 const unsigned char *block,
1320 size_t block_size) {
1323 uvc_format_desc_t *format = calloc(1, sizeof(*format));
1325 format->parent = stream_if;
1326 format->bDescriptorSubtype = block[2];
1327 format->bFormatIndex = block[3];
1328 format->bNumFrameDescriptors = block[4];
1329 memcpy(format->guidFormat, &block[5], 16);
1330 format->bBitsPerPixel = block[21];
1331 format->bDefaultFrameIndex = block[22];
1332 format->bAspectRatioX = block[23];
1333 format->bAspectRatioY = block[24];
1334 format->bmInterlaceFlags = block[25];
1335 format->bCopyProtect = block[26];
1336 format->bVariableSize = block[27];
1338 DL_APPEND(stream_if->format_descs, format);
1340 UVC_EXIT(UVC_SUCCESS);
1345 * @brief Parse a VideoStreaming MJPEG format block.
1348 uvc_error_t uvc_parse_vs_format_mjpeg(uvc_streaming_interface_t *stream_if,
1349 const unsigned char *block,
1350 size_t block_size) {
1353 uvc_format_desc_t *format = calloc(1, sizeof(*format));
1355 format->parent = stream_if;
1356 format->bDescriptorSubtype = block[2];
1357 format->bFormatIndex = block[3];
1358 memcpy(format->fourccFormat, "MJPG", 4);
1359 format->bmFlags = block[5];
1360 format->bBitsPerPixel = 0;
1361 format->bDefaultFrameIndex = block[6];
1362 format->bAspectRatioX = block[7];
1363 format->bAspectRatioY = block[8];
1364 format->bmInterlaceFlags = block[9];
1365 format->bCopyProtect = block[10];
1367 DL_APPEND(stream_if->format_descs, format);
1369 UVC_EXIT(UVC_SUCCESS);
1374 * @brief Parse a VideoStreaming uncompressed frame block.
1377 uvc_error_t uvc_parse_vs_frame_frame(uvc_streaming_interface_t *stream_if,
1378 const unsigned char *block,
1379 size_t block_size) {
1380 uvc_format_desc_t *format;
1381 uvc_frame_desc_t *frame;
1383 const unsigned char *p;
1388 format = stream_if->format_descs->prev;
1389 frame = calloc(1, sizeof(*frame));
1391 frame->parent = format;
1393 frame->bDescriptorSubtype = block[2];
1394 frame->bFrameIndex = block[3];
1395 frame->bmCapabilities = block[4];
1396 frame->wWidth = block[5] + (block[6] << 8);
1397 frame->wHeight = block[7] + (block[8] << 8);
1398 frame->dwMinBitRate = DW_TO_INT(&block[9]);
1399 frame->dwMaxBitRate = DW_TO_INT(&block[13]);
1400 frame->dwDefaultFrameInterval = DW_TO_INT(&block[17]);
1401 frame->bFrameIntervalType = block[21];
1402 frame->dwBytesPerLine = DW_TO_INT(&block[22]);
1404 if (block[21] == 0) {
1405 frame->dwMinFrameInterval = DW_TO_INT(&block[26]);
1406 frame->dwMaxFrameInterval = DW_TO_INT(&block[30]);
1407 frame->dwFrameIntervalStep = DW_TO_INT(&block[34]);
1409 frame->intervals = calloc(block[21] + 1, sizeof(frame->intervals[0]));
1412 for (i = 0; i < block[21]; ++i) {
1413 frame->intervals[i] = DW_TO_INT(p);
1416 frame->intervals[block[21]] = 0;
1419 DL_APPEND(format->frame_descs, frame);
1421 UVC_EXIT(UVC_SUCCESS);
1426 * @brief Parse a VideoStreaming uncompressed frame block.
1429 uvc_error_t uvc_parse_vs_frame_uncompressed(uvc_streaming_interface_t *stream_if,
1430 const unsigned char *block,
1431 size_t block_size) {
1432 uvc_format_desc_t *format;
1433 uvc_frame_desc_t *frame;
1435 const unsigned char *p;
1440 format = stream_if->format_descs->prev;
1441 frame = calloc(1, sizeof(*frame));
1443 frame->parent = format;
1445 frame->bDescriptorSubtype = block[2];
1446 frame->bFrameIndex = block[3];
1447 frame->bmCapabilities = block[4];
1448 frame->wWidth = block[5] + (block[6] << 8);
1449 frame->wHeight = block[7] + (block[8] << 8);
1450 frame->dwMinBitRate = DW_TO_INT(&block[9]);
1451 frame->dwMaxBitRate = DW_TO_INT(&block[13]);
1452 frame->dwMaxVideoFrameBufferSize = DW_TO_INT(&block[17]);
1453 frame->dwDefaultFrameInterval = DW_TO_INT(&block[21]);
1454 frame->bFrameIntervalType = block[25];
1456 if (block[25] == 0) {
1457 frame->dwMinFrameInterval = DW_TO_INT(&block[26]);
1458 frame->dwMaxFrameInterval = DW_TO_INT(&block[30]);
1459 frame->dwFrameIntervalStep = DW_TO_INT(&block[34]);
1461 frame->intervals = calloc(block[25] + 1, sizeof(frame->intervals[0]));
1464 for (i = 0; i < block[25]; ++i) {
1465 frame->intervals[i] = DW_TO_INT(p);
1468 frame->intervals[block[25]] = 0;
1471 DL_APPEND(format->frame_descs, frame);
1473 UVC_EXIT(UVC_SUCCESS);
1478 * Process a single VideoStreaming descriptor block
1481 uvc_error_t uvc_parse_vs(
1483 uvc_device_info_t *info,
1484 uvc_streaming_interface_t *stream_if,
1485 const unsigned char *block, size_t block_size) {
1487 int descriptor_subtype;
1492 descriptor_subtype = block[2];
1494 switch (descriptor_subtype) {
1495 case UVC_VS_INPUT_HEADER:
1496 ret = uvc_parse_vs_input_header(stream_if, block, block_size);
1498 case UVC_VS_OUTPUT_HEADER:
1499 fprintf ( stderr, "unsupported descriptor subtype VS_OUTPUT_HEADER\n" );
1501 case UVC_VS_STILL_IMAGE_FRAME:
1502 fprintf ( stderr, "unsupported descriptor subtype VS_STILL_IMAGE_FRAME\n" );
1504 case UVC_VS_FORMAT_UNCOMPRESSED:
1505 ret = uvc_parse_vs_format_uncompressed(stream_if, block, block_size);
1507 case UVC_VS_FORMAT_MJPEG:
1508 ret = uvc_parse_vs_format_mjpeg(stream_if, block, block_size);
1510 case UVC_VS_FRAME_UNCOMPRESSED:
1511 case UVC_VS_FRAME_MJPEG:
1512 ret = uvc_parse_vs_frame_uncompressed(stream_if, block, block_size);
1514 case UVC_VS_FORMAT_MPEG2TS:
1515 fprintf ( stderr, "unsupported descriptor subtype VS_FORMAT_MPEG2TS\n" );
1517 case UVC_VS_FORMAT_DV:
1518 fprintf ( stderr, "unsupported descriptor subtype VS_FORMAT_DV\n" );
1520 case UVC_VS_COLORFORMAT:
1521 fprintf ( stderr, "unsupported descriptor subtype VS_COLORFORMAT\n" );
1523 case UVC_VS_FORMAT_FRAME_BASED:
1524 ret = uvc_parse_vs_frame_format ( stream_if, block, block_size );
1526 case UVC_VS_FRAME_FRAME_BASED:
1527 ret = uvc_parse_vs_frame_frame ( stream_if, block, block_size );
1529 case UVC_VS_FORMAT_STREAM_BASED:
1530 fprintf ( stderr, "unsupported descriptor subtype VS_FORMAT_STREAM_BASED\n" );
1533 /** @todo handle JPEG and maybe still frames or even DV... */
1534 //fprintf ( stderr, "unsupported descriptor subtype: %d\n",descriptor_subtype );
1543 * @brief Free memory associated with a UVC device
1544 * @pre Streaming must be stopped, and threads must have died
1546 void uvc_free_devh(uvc_device_handle_t *devh) {
1550 uvc_free_device_info(devh->info);
1552 if (devh->status_xfer)
1553 libusb_free_transfer(devh->status_xfer);
1560 /** @brief Close a device
1564 * Ends any stream that's in progress.
1566 * The device handle and frame structures will be invalidated.
1568 void uvc_close(uvc_device_handle_t *devh) {
1570 uvc_context_t *ctx = devh->dev->ctx;
1573 uvc_stop_streaming(devh);
1575 uvc_release_if(devh, devh->info->ctrl_if.bInterfaceNumber);
1577 /* If we are managing the libusb context and this is the last open device,
1578 * then we need to cancel the handler thread. When we call libusb_close,
1579 * it'll cause a return from the thread's libusb_handle_events call, after
1580 * which the handler thread will check the flag we set and then exit. */
1581 if (ctx->own_usb_ctx && ctx->open_devices == devh && devh->next == NULL) {
1582 ctx->kill_handler_thread = 1;
1583 libusb_close(devh->usb_devh);
1584 pthread_join(ctx->handler_thread, NULL);
1586 libusb_close(devh->usb_devh);
1589 DL_DELETE(ctx->open_devices, devh);
1591 uvc_unref_device(devh->dev);
1593 uvc_free_devh(devh);
1599 * @brief Get number of open devices
1601 size_t uvc_num_devices(uvc_context_t *ctx) {
1604 uvc_device_handle_t *devh;
1608 DL_FOREACH(ctx->open_devices, devh) {
1612 UVC_EXIT((int) count);
1616 void uvc_process_control_status(uvc_device_handle_t *devh, unsigned char *data, int len) {
1617 enum uvc_status_class status_class;
1618 uint8_t originator = 0, selector = 0, event = 0;
1619 enum uvc_status_attribute attribute = UVC_STATUS_ATTRIBUTE_UNKNOWN;
1620 void *content = NULL;
1621 size_t content_len = 0;
1622 int found_entity = 0;
1623 struct uvc_input_terminal *input_terminal;
1624 struct uvc_processing_unit *processing_unit;
1629 UVC_DEBUG("Short read of VideoControl status update (%d bytes)", len);
1634 originator = data[1];
1638 if (originator == 0) {
1639 UVC_DEBUG("Unhandled update from VC interface");
1641 return; /* @todo VideoControl virtual entity interface updates */
1645 UVC_DEBUG("Unhandled VC event %d", (int) event);
1650 /* printf("bSelector: %d\n", selector); */
1652 DL_FOREACH(devh->info->ctrl_if.input_term_descs, input_terminal) {
1653 if (input_terminal->bTerminalID == originator) {
1654 status_class = UVC_STATUS_CLASS_CONTROL_CAMERA;
1660 if (!found_entity) {
1661 DL_FOREACH(devh->info->ctrl_if.processing_unit_descs, processing_unit) {
1662 if (processing_unit->bUnitID == originator) {
1663 status_class = UVC_STATUS_CLASS_CONTROL_PROCESSING;
1670 if (!found_entity) {
1671 UVC_DEBUG("Got status update for unknown VideoControl entity %d",
1677 attribute = data[4];
1679 content_len = len - 5;
1681 UVC_DEBUG("Event: class=%d, event=%d, selector=%d, attribute=%d, content_len=%zd",
1682 status_class, event, selector, attribute, content_len);
1684 if(devh->status_cb) {
1685 UVC_DEBUG("Running user-supplied status callback");
1686 devh->status_cb(status_class,
1690 content, content_len,
1691 devh->status_user_ptr);
1697 void uvc_process_streaming_status(uvc_device_handle_t *devh, unsigned char *data, int len) {
1702 UVC_DEBUG("Invalid streaming status event received.\n");
1709 UVC_DEBUG("Short read of status update (%d bytes)", len);
1713 UVC_DEBUG("Button (intf %u) %s len %d\n", data[1], data[3] ? "pressed" : "released", len);
1715 if(devh->button_cb) {
1716 UVC_DEBUG("Running user-supplied button callback");
1717 devh->button_cb(data[1],
1719 devh->button_user_ptr);
1722 UVC_DEBUG("Stream %u error event %02x %02x len %d.\n", data[1], data[2], data[3], len);
1728 void uvc_process_status_xfer(uvc_device_handle_t *devh, struct libusb_transfer *transfer) {
1732 /* printf("Got transfer of aLen = %d\n", transfer->actual_length); */
1734 if (transfer->actual_length > 0) {
1735 switch (transfer->buffer[0] & 0x0f) {
1736 case 1: /* VideoControl interface */
1737 uvc_process_control_status(devh, transfer->buffer, transfer->actual_length);
1739 case 2: /* VideoStreaming interface */
1740 uvc_process_streaming_status(devh, transfer->buffer, transfer->actual_length);
1749 * @brief Process asynchronous status updates from the device.
1751 void LIBUSB_CALL _uvc_status_callback(struct libusb_transfer *transfer) {
1754 uvc_device_handle_t *devh = (uvc_device_handle_t *) transfer->user_data;
1756 switch (transfer->status) {
1757 case LIBUSB_TRANSFER_ERROR:
1758 case LIBUSB_TRANSFER_CANCELLED:
1759 case LIBUSB_TRANSFER_NO_DEVICE:
1760 UVC_DEBUG("not processing/resubmitting, status = %d", transfer->status);
1763 case LIBUSB_TRANSFER_COMPLETED:
1764 uvc_process_status_xfer(devh, transfer);
1766 case LIBUSB_TRANSFER_TIMED_OUT:
1767 case LIBUSB_TRANSFER_STALL:
1768 case LIBUSB_TRANSFER_OVERFLOW:
1769 UVC_DEBUG("retrying transfer, status = %d", transfer->status);
1773 #ifdef UVC_DEBUGGING
1776 libusb_submit_transfer(transfer);
1777 UVC_DEBUG("libusb_submit_transfer() = %d", ret);
1782 /** @brief Set a callback function to receive status updates
1786 void uvc_set_status_callback(uvc_device_handle_t *devh,
1787 uvc_status_callback_t cb,
1791 devh->status_cb = cb;
1792 devh->status_user_ptr = user_ptr;
1797 /** @brief Set a callback function to receive button events
1801 void uvc_set_button_callback(uvc_device_handle_t *devh,
1802 uvc_button_callback_t cb,
1806 devh->button_cb = cb;
1807 devh->button_user_ptr = user_ptr;
1813 * @brief Get format descriptions for the open device.
1815 * @note Do not modify the returned structure.
1817 * @param devh Device handle to an open UVC device
1819 const uvc_format_desc_t *uvc_get_format_descs(uvc_device_handle_t *devh) {
1820 return devh->info->stream_ifs->format_descs;