dev.c
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (C) 2010-2012 Ken Tossell
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the author nor other contributors may be
00018 *     used to endorse or promote products derived from this software
00019 *     without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00039 #include "libuvc.h"
00040 #include "libuvc_internal.h"
00041 
00042 int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev);
00043 void uvc_free_devh(uvc_device_handle_t *devh);
00044 
00045 uvc_error_t uvc_get_device_info(uvc_device_t *dev, uvc_device_info_t **info);
00046 uvc_error_t uvc_get_device_info2(uvc_device_t *dev, uvc_device_info_t **info, int camera_number);
00047 void uvc_free_device_info(uvc_device_info_t *info);
00048 
00049 uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info);
00050 uvc_error_t uvc_parse_vc(uvc_device_t *dev,
00051              uvc_device_info_t *info,
00052              const unsigned char *block, size_t block_size);
00053 uvc_error_t uvc_parse_vc_extension_unit(uvc_device_t *dev,
00054                     uvc_device_info_t *info,
00055                     const unsigned char *block,
00056                     size_t block_size);
00057 uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
00058                 uvc_device_info_t *info,
00059                 const unsigned char *block, size_t block_size);
00060 uvc_error_t uvc_parse_vc_input_terminal(uvc_device_t *dev,
00061                     uvc_device_info_t *info,
00062                     const unsigned char *block,
00063                     size_t block_size);
00064 uvc_error_t uvc_parse_vc_processing_unit(uvc_device_t *dev,
00065                      uvc_device_info_t *info,
00066                      const unsigned char *block,
00067                      size_t block_size);
00068 
00069 uvc_error_t uvc_scan_streaming(uvc_device_t *dev,
00070                    uvc_device_info_t *info,
00071                    int interface_idx);
00072 uvc_error_t uvc_parse_vs(uvc_device_t *dev,
00073              uvc_device_info_t *info,
00074              uvc_streaming_interface_t *stream_if,
00075              const unsigned char *block, size_t block_size);
00076 uvc_error_t uvc_parse_vs_format_uncompressed(uvc_streaming_interface_t *stream_if,
00077                          const unsigned char *block,
00078                          size_t block_size);
00079 uvc_error_t uvc_parse_vs_format_mjpeg(uvc_streaming_interface_t *stream_if,
00080                          const unsigned char *block,
00081                          size_t block_size);
00082 uvc_error_t uvc_parse_vs_frame_uncompressed(uvc_streaming_interface_t *stream_if,
00083                         const unsigned char *block,
00084                         size_t block_size);
00085 uvc_error_t uvc_parse_vs_frame_format(uvc_streaming_interface_t *stream_if,
00086                         const unsigned char *block,
00087                         size_t block_size);
00088 uvc_error_t uvc_parse_vs_frame_frame(uvc_streaming_interface_t *stream_if,
00089                         const unsigned char *block,
00090                         size_t block_size);
00091 uvc_error_t uvc_parse_vs_input_header(uvc_streaming_interface_t *stream_if,
00092                       const unsigned char *block,
00093                       size_t block_size);
00094 
00095 void LIBUSB_CALL _uvc_status_callback(struct libusb_transfer *transfer);
00096 
00105 int uvc_already_open(uvc_context_t *ctx, struct libusb_device *usb_dev) {
00106   uvc_device_handle_t *devh;
00107 
00108   DL_FOREACH(ctx->open_devices, devh) {
00109     if (usb_dev == devh->dev->usb_dev)
00110       return 1;
00111   }
00112 
00113   return 0;
00114 }
00115 
00126 uvc_error_t uvc_find_device(
00127     uvc_context_t *ctx, uvc_device_t **dev,
00128     int vid, int pid, const char *sn) {
00129   uvc_error_t ret = UVC_SUCCESS;
00130 
00131   uvc_device_t **list;
00132   uvc_device_t *test_dev;
00133   int dev_idx;
00134   int found_dev;
00135 
00136   UVC_ENTER();
00137 
00138   ret = uvc_get_device_list(ctx, &list);
00139 
00140   if (ret != UVC_SUCCESS) {
00141     UVC_EXIT(ret);
00142     return ret;
00143   }
00144 
00145   dev_idx = 0;
00146   found_dev = 0;
00147 
00148   while (!found_dev && (test_dev = list[dev_idx++]) != NULL) {
00149     uvc_device_descriptor_t *desc;
00150 
00151     if (uvc_get_device_descriptor(test_dev, &desc) != UVC_SUCCESS)
00152       continue;
00153 
00154     if ((!vid || desc->idVendor == vid)
00155         && (!pid || desc->idProduct == pid)
00156         && (!sn || (desc->serialNumber && !strcmp(desc->serialNumber, sn))))
00157       found_dev = 1;
00158 
00159     uvc_free_device_descriptor(desc);
00160   }
00161 
00162   if (found_dev)
00163     uvc_ref_device(test_dev);
00164 
00165   uvc_free_device_list(list, 1);
00166 
00167   if (found_dev) {
00168     *dev = test_dev;
00169     UVC_EXIT(UVC_SUCCESS);
00170     return UVC_SUCCESS;
00171   } else {
00172     UVC_EXIT(UVC_ERROR_NO_DEVICE);
00173     return UVC_ERROR_NO_DEVICE;
00174   }
00175 }
00176 
00180 uint8_t uvc_get_bus_number(uvc_device_t *dev) {
00181   return libusb_get_bus_number(dev->usb_dev);
00182 }
00183 
00187 uint8_t uvc_get_device_address(uvc_device_t *dev) {
00188   return libusb_get_device_address(dev->usb_dev);
00189 }
00190 
00191 
00200 uvc_error_t uvc_open(
00201     uvc_device_t *dev,
00202     uvc_device_handle_t **devh) {
00203   return uvc_open2(dev, devh, 0);
00204 }
00205 
00215 uvc_error_t uvc_open2(
00216     uvc_device_t *dev,
00217     uvc_device_handle_t **devh,
00218     int camera_number) {
00219   uvc_error_t ret;
00220   struct libusb_device_handle *usb_devh;
00221   uvc_device_handle_t *internal_devh;
00222   struct libusb_device_descriptor desc;
00223 
00224   UVC_ENTER();
00225 
00226   ret = libusb_open(dev->usb_dev, &usb_devh);
00227   UVC_DEBUG("libusb_open() = %d", ret);
00228 
00229   if (ret != UVC_SUCCESS) {
00230     UVC_EXIT(ret);
00231     return ret;
00232   }
00233 
00234   uvc_ref_device(dev);
00235 
00236   internal_devh = calloc(1, sizeof(*internal_devh));
00237   internal_devh->dev = dev;
00238   internal_devh->usb_devh = usb_devh;
00239 
00240   ret = uvc_get_device_info2(dev, &(internal_devh->info), camera_number);
00241 
00242   if (ret != UVC_SUCCESS)
00243     goto fail;
00244 
00245   UVC_DEBUG("claiming control interface %d", internal_devh->info->ctrl_if.bInterfaceNumber);
00246   ret = uvc_claim_if(internal_devh, internal_devh->info->ctrl_if.bInterfaceNumber);
00247   if (ret != UVC_SUCCESS)
00248     goto fail;
00249 
00250   libusb_get_device_descriptor(dev->usb_dev, &desc);
00251   internal_devh->is_isight = (desc.idVendor == 0x05ac && desc.idProduct == 0x8501);
00252 
00253   if (internal_devh->info->ctrl_if.bEndpointAddress) {
00254     internal_devh->status_xfer = libusb_alloc_transfer(0);
00255     if (!internal_devh->status_xfer) {
00256       ret = UVC_ERROR_NO_MEM;
00257       goto fail;
00258     }
00259 
00260     libusb_fill_interrupt_transfer(internal_devh->status_xfer,
00261                                    usb_devh,
00262                                    internal_devh->info->ctrl_if.bEndpointAddress,
00263                                    internal_devh->status_buf,
00264                                    sizeof(internal_devh->status_buf),
00265                                    _uvc_status_callback,
00266                                    internal_devh,
00267                                    0);
00268     ret = libusb_submit_transfer(internal_devh->status_xfer);
00269     UVC_DEBUG("libusb_submit_transfer() = %d", ret);
00270 
00271     if (ret) {
00272       UVC_DEBUG("device has a status interrupt endpoint, but unable to read from it",);
00273       goto fail;
00274     }
00275   }
00276 
00277   if (dev->ctx->own_usb_ctx && dev->ctx->open_devices == NULL) {
00278     /* Since this is our first device, we need to spawn the event handler thread */
00279     uvc_start_handler_thread(dev->ctx);
00280   }
00281 
00282   DL_APPEND(dev->ctx->open_devices, internal_devh);
00283   *devh = internal_devh;
00284 
00285   UVC_EXIT(ret);
00286 
00287   return ret;
00288 
00289  fail:
00290   if ( internal_devh->info ) {
00291     uvc_release_if(internal_devh, internal_devh->info->ctrl_if.bInterfaceNumber);
00292   }
00293   libusb_close(usb_devh);
00294   uvc_unref_device(dev);
00295   uvc_free_devh(internal_devh);
00296 
00297   UVC_EXIT(ret);
00298 
00299   return ret;
00300 }
00301 
00312 uvc_error_t uvc_get_device_info(uvc_device_t *dev,
00313                 uvc_device_info_t **info) {
00314   return uvc_get_device_info2(dev, info, 0);
00315 }
00316 
00328 uvc_error_t uvc_get_device_info2(uvc_device_t *dev,
00329                 uvc_device_info_t **info,
00330                 int camera_number) {
00331   uvc_error_t ret;
00332   uvc_device_info_t *internal_info;
00333 
00334   UVC_ENTER();
00335 
00336   internal_info = calloc(1, sizeof(*internal_info));
00337   if (!internal_info) {
00338     UVC_EXIT(UVC_ERROR_NO_MEM);
00339     return UVC_ERROR_NO_MEM;
00340   }
00341 
00342   if (libusb_get_config_descriptor(dev->usb_dev,
00343                    0,
00344                    &(internal_info->config)) != 0) {
00345     free(internal_info);
00346     UVC_EXIT(UVC_ERROR_IO);
00347     return UVC_ERROR_IO;
00348   }
00349 
00350   if (camera_number*2 > internal_info->config->bNumInterfaces)
00351     {
00352       free(internal_info);
00353       UVC_EXIT(UVC_ERROR_NO_DEVICE);
00354       return UVC_ERROR_NO_DEVICE;
00355     }
00356 
00357   //Which camera interface to pick up
00358   internal_info->camera_number = camera_number;
00359 
00360 
00361   ret = uvc_scan_control(dev, internal_info);
00362   if (ret != UVC_SUCCESS) {
00363     uvc_free_device_info(internal_info);
00364     UVC_EXIT(ret);
00365     return ret;
00366   }
00367 
00368   *info = internal_info;
00369 
00370   UVC_EXIT(ret);
00371   return ret;
00372 }
00373 
00381 void uvc_free_device_info(uvc_device_info_t *info) {
00382   uvc_input_terminal_t *input_term, *input_term_tmp;
00383   uvc_processing_unit_t *proc_unit, *proc_unit_tmp;
00384   uvc_extension_unit_t *ext_unit, *ext_unit_tmp;
00385 
00386   uvc_streaming_interface_t *stream_if, *stream_if_tmp;
00387   uvc_format_desc_t *format, *format_tmp;
00388   uvc_frame_desc_t *frame, *frame_tmp;
00389 
00390   UVC_ENTER();
00391 
00392   DL_FOREACH_SAFE(info->ctrl_if.input_term_descs, input_term, input_term_tmp) {
00393     DL_DELETE(info->ctrl_if.input_term_descs, input_term);
00394     free(input_term);
00395   }
00396 
00397   DL_FOREACH_SAFE(info->ctrl_if.processing_unit_descs, proc_unit, proc_unit_tmp) {
00398     DL_DELETE(info->ctrl_if.processing_unit_descs, proc_unit);
00399     free(proc_unit);
00400   }
00401 
00402   DL_FOREACH_SAFE(info->ctrl_if.extension_unit_descs, ext_unit, ext_unit_tmp) {
00403     DL_DELETE(info->ctrl_if.extension_unit_descs, ext_unit);
00404     free(ext_unit);
00405   }
00406 
00407   DL_FOREACH_SAFE(info->stream_ifs, stream_if, stream_if_tmp) {
00408     DL_FOREACH_SAFE(stream_if->format_descs, format, format_tmp) {
00409       DL_FOREACH_SAFE(format->frame_descs, frame, frame_tmp) {
00410         if (frame->intervals)
00411           free(frame->intervals);
00412 
00413         DL_DELETE(format->frame_descs, frame);
00414         free(frame);
00415       }
00416 
00417       DL_DELETE(stream_if->format_descs, format);
00418       free(format);
00419     }
00420 
00421     DL_DELETE(info->stream_ifs, stream_if);
00422     free(stream_if);
00423   }
00424 
00425   if (info->config)
00426     libusb_free_config_descriptor(info->config);
00427 
00428   free(info);
00429 
00430   UVC_EXIT_VOID();
00431 }
00432 
00444 uvc_error_t uvc_get_device_descriptor(
00445     uvc_device_t *dev,
00446     uvc_device_descriptor_t **desc) {
00447   uvc_device_descriptor_t *desc_internal;
00448   struct libusb_device_descriptor usb_desc;
00449   struct libusb_device_handle *usb_devh;
00450   uvc_error_t ret;
00451 
00452   UVC_ENTER();
00453 
00454   ret = libusb_get_device_descriptor(dev->usb_dev, &usb_desc);
00455 
00456   if (ret != UVC_SUCCESS) {
00457     UVC_EXIT(ret);
00458     return ret;
00459   }
00460 
00461   desc_internal = calloc(1, sizeof(*desc_internal));
00462   desc_internal->idVendor = usb_desc.idVendor;
00463   desc_internal->idProduct = usb_desc.idProduct;
00464 
00465   if (libusb_open(dev->usb_dev, &usb_devh) == 0) {
00466     unsigned char buf[64];
00467 
00468     int bytes = libusb_get_string_descriptor_ascii(
00469         usb_devh, usb_desc.iSerialNumber, buf, sizeof(buf));
00470 
00471     if (bytes > 0)
00472       desc_internal->serialNumber = strdup((const char*) buf);
00473 
00474     bytes = libusb_get_string_descriptor_ascii(
00475         usb_devh, usb_desc.iManufacturer, buf, sizeof(buf));
00476 
00477     if (bytes > 0)
00478       desc_internal->manufacturer = strdup((const char*) buf);
00479 
00480     bytes = libusb_get_string_descriptor_ascii(
00481         usb_devh, usb_desc.iProduct, buf, sizeof(buf));
00482 
00483     if (bytes > 0)
00484       desc_internal->product = strdup((const char*) buf);
00485 
00486     libusb_close(usb_devh);
00487   } else {
00488     UVC_DEBUG("can't open device %04x:%04x, not fetching serial etc.",
00489           usb_desc.idVendor, usb_desc.idProduct);
00490   }
00491 
00492   *desc = desc_internal;
00493 
00494   UVC_EXIT(ret);
00495   return ret;
00496 }
00497 
00504 void uvc_free_device_descriptor(
00505     uvc_device_descriptor_t *desc) {
00506   UVC_ENTER();
00507 
00508   if (desc->serialNumber)
00509     free((void*) desc->serialNumber);
00510 
00511   if (desc->manufacturer)
00512     free((void*) desc->manufacturer);
00513 
00514   if (desc->product)
00515     free((void*) desc->product);
00516 
00517   free(desc);
00518 
00519   UVC_EXIT_VOID();
00520 }
00521 
00532 uvc_error_t uvc_get_device_list(
00533     uvc_context_t *ctx,
00534     uvc_device_t ***list) {
00535   uvc_error_t ret;
00536   struct libusb_device **usb_dev_list;
00537   struct libusb_device *usb_dev;
00538   int num_usb_devices;
00539 
00540   uvc_device_t **list_internal;
00541   int num_uvc_devices;
00542 
00543   /* per device */
00544   int dev_idx;
00545   struct libusb_device_handle *usb_devh;
00546   struct libusb_config_descriptor *config;
00547   struct libusb_device_descriptor desc;
00548   uint8_t got_interface;
00549 
00550   /* per interface */
00551   int interface_idx;
00552   const struct libusb_interface *interface;
00553 
00554   /* per altsetting */
00555   int altsetting_idx;
00556   const struct libusb_interface_descriptor *if_desc;
00557 
00558   UVC_ENTER();
00559 
00560   num_usb_devices = libusb_get_device_list(ctx->usb_ctx, &usb_dev_list);
00561 
00562   if (num_usb_devices < 0) {
00563     UVC_EXIT(UVC_ERROR_IO);
00564     return UVC_ERROR_IO;
00565   }
00566 
00567   list_internal = malloc(sizeof(*list_internal));
00568   *list_internal = NULL;
00569 
00570   num_uvc_devices = 0;
00571   dev_idx = -1;
00572 
00573   while ((usb_dev = usb_dev_list[++dev_idx]) != NULL) {
00574     usb_devh = NULL;
00575     got_interface = 0;
00576 
00577     if (libusb_get_config_descriptor(usb_dev, 0, &config) != 0)
00578       continue;
00579 
00580     if ( libusb_get_device_descriptor ( usb_dev, &desc ) != LIBUSB_SUCCESS )
00581       continue;
00582 
00583     // Special case for Imaging Source cameras
00584     if ( 0x199e == desc.idVendor && 0x8101 == desc.idProduct ) {
00585       got_interface = 1;
00586     } else {
00587 
00588       for (interface_idx = 0;
00589        !got_interface && interface_idx < config->bNumInterfaces;
00590        ++interface_idx) {
00591         interface = &config->interface[interface_idx];
00592 
00593         for (altsetting_idx = 0;
00594          !got_interface && altsetting_idx < interface->num_altsetting;
00595          ++altsetting_idx) {
00596       if_desc = &interface->altsetting[altsetting_idx];
00597 
00598       /* Video, Streaming */
00599       if (if_desc->bInterfaceClass == 14 && if_desc->bInterfaceSubClass == 2) {
00600         got_interface = 1;
00601       }
00602         }
00603       }
00604     }
00605 
00606     libusb_free_config_descriptor(config);
00607 
00608     if (got_interface) {
00609       uvc_device_t *uvc_dev = malloc(sizeof(*uvc_dev));
00610       uvc_dev->ctx = ctx;
00611       uvc_dev->ref = 0;
00612       uvc_dev->usb_dev = usb_dev;
00613       uvc_ref_device(uvc_dev);
00614 
00615       num_uvc_devices++;
00616       list_internal = realloc(list_internal, (num_uvc_devices + 1) * sizeof(*list_internal));
00617 
00618       list_internal[num_uvc_devices - 1] = uvc_dev;
00619       list_internal[num_uvc_devices] = NULL;
00620 
00621       UVC_DEBUG("    UVC: %d", dev_idx);
00622     } else {
00623       UVC_DEBUG("non-UVC: %d", dev_idx);
00624     }
00625   }
00626 
00627   libusb_free_device_list(usb_dev_list, 1);
00628 
00629   *list = list_internal;
00630 
00631   UVC_EXIT(UVC_SUCCESS);
00632   return UVC_SUCCESS;
00633 }
00634 
00643 void uvc_free_device_list(uvc_device_t **list, uint8_t unref_devices) {
00644   uvc_device_t *dev;
00645   int dev_idx = 0;
00646 
00647   UVC_ENTER();
00648 
00649   if (unref_devices) {
00650     while ((dev = list[dev_idx++]) != NULL) {
00651       uvc_unref_device(dev);
00652     }
00653   }
00654 
00655   free(list);
00656 
00657   UVC_EXIT_VOID();
00658 }
00659 
00668 uvc_device_t *uvc_get_device(uvc_device_handle_t *devh) {
00669   uvc_ref_device(devh->dev);
00670   return devh->dev;
00671 }
00672 
00685 libusb_device_handle *uvc_get_libusb_handle(uvc_device_handle_t *devh) {
00686   return devh->usb_devh;
00687 }
00688 
00698 const uvc_input_terminal_t *uvc_get_input_terminals(uvc_device_handle_t *devh) {
00699   return devh->info->ctrl_if.input_term_descs;
00700 }
00701 
00711 const uvc_output_terminal_t *uvc_get_output_terminals(uvc_device_handle_t *devh) {
00712   return NULL; /* @todo */
00713 }
00714 
00724 const uvc_processing_unit_t *uvc_get_processing_units(uvc_device_handle_t *devh) {
00725   return devh->info->ctrl_if.processing_unit_descs;
00726 }
00727 
00737 const uvc_extension_unit_t *uvc_get_extension_units(uvc_device_handle_t *devh) {
00738   return devh->info->ctrl_if.extension_unit_descs;
00739 }
00740 
00747 void uvc_ref_device(uvc_device_t *dev) {
00748   UVC_ENTER();
00749 
00750   dev->ref++;
00751   libusb_ref_device(dev->usb_dev);
00752 
00753   UVC_EXIT_VOID();
00754 }
00755 
00763 void uvc_unref_device(uvc_device_t *dev) {
00764   UVC_ENTER();
00765 
00766   libusb_unref_device(dev->usb_dev);
00767   dev->ref--;
00768 
00769   if (dev->ref == 0)
00770     free(dev);
00771 
00772   UVC_EXIT_VOID();
00773 }
00774 
00782 uvc_error_t uvc_claim_if(uvc_device_handle_t *devh, int idx) {
00783   int ret;
00784 
00785   UVC_ENTER();
00786 
00787   /* Tell libusb to detach any active kernel drivers. libusb will keep track of whether
00788    * it found a kernel driver for this interface. */
00789   ret = libusb_detach_kernel_driver(devh->usb_devh, idx);
00790 
00791   if (ret == UVC_SUCCESS || ret == LIBUSB_ERROR_NOT_FOUND || ret == LIBUSB_ERROR_NOT_SUPPORTED) {
00792     UVC_DEBUG("claiming interface %d", idx);
00793     ret = libusb_claim_interface(devh->usb_devh, idx);
00794   } else {
00795     UVC_DEBUG("not claiming interface %d: unable to detach kernel driver (%s)",
00796               idx, uvc_strerror(ret));
00797   }
00798 
00799   UVC_EXIT(ret);
00800   return ret;
00801 }
00802 
00810 uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx) {
00811   int ret;
00812 
00813   UVC_ENTER();
00814   UVC_DEBUG("releasing interface %d", idx);
00815   /* libusb_release_interface *should* reset the alternate setting to the first available,
00816      but sometimes (e.g. on Darwin) it doesn't. Thus, we do it explicitly here.
00817      This is needed to de-initialize certain cameras. */
00818   libusb_set_interface_alt_setting(devh->usb_devh, idx, 0);
00819   ret = libusb_release_interface(devh->usb_devh, idx);
00820 
00821   if (UVC_SUCCESS == ret) {
00822     /* Reattach any kernel drivers that were disabled when we claimed this interface */
00823     ret = libusb_attach_kernel_driver(devh->usb_devh, idx);
00824 
00825     if (ret == UVC_SUCCESS) {
00826       UVC_DEBUG("reattached kernel driver to interface %d", idx);
00827     } else if (ret == LIBUSB_ERROR_NOT_FOUND || ret == LIBUSB_ERROR_NOT_SUPPORTED) {
00828       ret = UVC_SUCCESS;  /* NOT_FOUND and NOT_SUPPORTED are OK: nothing to do */
00829     } else {
00830       UVC_DEBUG("error reattaching kernel driver to interface %d: %s",
00831                 idx, uvc_strerror(ret));
00832     }
00833   }
00834 
00835   UVC_EXIT(ret);
00836   return ret;
00837 }
00838 
00843 uvc_error_t uvc_scan_control(uvc_device_t *dev, uvc_device_info_t *info) {
00844   const struct libusb_interface_descriptor *if_desc;
00845   uvc_error_t parse_ret, ret;
00846   int interface_idx;
00847   const unsigned char *buffer;
00848   size_t buffer_left, block_size;
00849 
00850   UVC_ENTER();
00851 
00852   ret = UVC_SUCCESS;
00853   if_desc = NULL;
00854 
00855   //Start looking for the control interface at the given camera number
00856 
00857   for (interface_idx = info->camera_number*2; interface_idx < info->config->bNumInterfaces; ++interface_idx) {
00858     if_desc = &info->config->interface[interface_idx].altsetting[0];
00859 
00860     if (if_desc->bInterfaceClass == 14 && if_desc->bInterfaceSubClass == 1) // Video, Control
00861       break;
00862 
00863     // Another TIS camera hack.
00864     if ( if_desc->bInterfaceClass == 255 && if_desc->bInterfaceSubClass == 1 ) {
00865       uvc_device_descriptor_t* dev_desc;
00866       int haveTISCamera = 0;
00867       uvc_get_device_descriptor ( dev, &dev_desc );
00868       if ( dev_desc->idVendor == 0x199e && dev_desc->idProduct == 0x8101 ) {
00869         haveTISCamera = 1;
00870       }
00871       uvc_free_device_descriptor ( dev_desc );
00872       if ( haveTISCamera ) {
00873         break;
00874       }
00875     }
00876 
00877     if_desc = NULL;
00878   }
00879 
00880   if (if_desc == NULL) {
00881     UVC_EXIT(UVC_ERROR_INVALID_DEVICE);
00882     return UVC_ERROR_INVALID_DEVICE;
00883   }
00884 
00885   info->ctrl_if.bInterfaceNumber = interface_idx;
00886   if (if_desc->bNumEndpoints != 0) {
00887     info->ctrl_if.bEndpointAddress = if_desc->endpoint[0].bEndpointAddress;
00888   }
00889 
00890   buffer = if_desc->extra;
00891   buffer_left = if_desc->extra_length;
00892 
00893   while (buffer_left >= 3) { // parseX needs to see buf[0,2] = length,type
00894     block_size = buffer[0];
00895     parse_ret = uvc_parse_vc(dev, info, buffer, block_size);
00896 
00897     if (parse_ret != UVC_SUCCESS) {
00898       ret = parse_ret;
00899       break;
00900     }
00901 
00902     buffer_left -= block_size;
00903     buffer += block_size;
00904   }
00905 
00906   UVC_EXIT(ret);
00907   return ret;
00908 }
00909 
00914 uvc_error_t uvc_parse_vc_header(uvc_device_t *dev,
00915                 uvc_device_info_t *info,
00916                 const unsigned char *block, size_t block_size) {
00917   size_t i;
00918   uvc_error_t scan_ret, ret = UVC_SUCCESS;
00919 
00920   UVC_ENTER();
00921 
00922   /*
00923   int uvc_version;
00924   uvc_version = (block[4] >> 4) * 1000 + (block[4] & 0x0f) * 100
00925     + (block[3] >> 4) * 10 + (block[3] & 0x0f);
00926   */
00927 
00928   info->ctrl_if.bcdUVC = SW_TO_SHORT(&block[3]);
00929 
00930   switch (info->ctrl_if.bcdUVC) {
00931   case 0x0100:
00932   case 0x010a:
00933   case 0x0110:
00934     break;
00935   default:
00936     UVC_EXIT(UVC_ERROR_NOT_SUPPORTED);
00937     return UVC_ERROR_NOT_SUPPORTED;
00938   }
00939 
00940   for (i = 12; i < block_size; ++i) {
00941     scan_ret = uvc_scan_streaming(dev, info, block[i]);
00942     if (scan_ret != UVC_SUCCESS) {
00943       ret = scan_ret;
00944       break;
00945     }
00946   }
00947 
00948   UVC_EXIT(ret);
00949   return ret;
00950 }
00951 
00956 uvc_error_t uvc_parse_vc_input_terminal(uvc_device_t *dev,
00957                     uvc_device_info_t *info,
00958                     const unsigned char *block, size_t block_size) {
00959   uvc_input_terminal_t *term;
00960   size_t i;
00961 
00962   UVC_ENTER();
00963 
00964   /* only supporting camera-type input terminals */
00965   if (SW_TO_SHORT(&block[4]) != UVC_ITT_CAMERA) {
00966     UVC_EXIT(UVC_SUCCESS);
00967     return UVC_SUCCESS;
00968   }
00969 
00970   term = calloc(1, sizeof(*term));
00971 
00972   term->bTerminalID = block[3];
00973   term->wTerminalType = SW_TO_SHORT(&block[4]);
00974   term->wObjectiveFocalLengthMin = SW_TO_SHORT(&block[8]);
00975   term->wObjectiveFocalLengthMax = SW_TO_SHORT(&block[10]);
00976   term->wOcularFocalLength = SW_TO_SHORT(&block[12]);
00977 
00978   for (i = 14 + block[14]; i >= 15; --i)
00979     term->bmControls = block[i] + (term->bmControls << 8);
00980 
00981   DL_APPEND(info->ctrl_if.input_term_descs, term);
00982 
00983   UVC_EXIT(UVC_SUCCESS);
00984   return UVC_SUCCESS;
00985 }
00986 
00991 uvc_error_t uvc_parse_vc_processing_unit(uvc_device_t *dev,
00992                      uvc_device_info_t *info,
00993                      const unsigned char *block, size_t block_size) {
00994   uvc_processing_unit_t *unit;
00995   size_t i;
00996 
00997   UVC_ENTER();
00998 
00999   unit = calloc(1, sizeof(*unit));
01000   unit->bUnitID = block[3];
01001   unit->bSourceID = block[4];
01002   
01003   for (i = 7 + block[7]; i >= 8; --i)
01004     unit->bmControls = block[i] + (unit->bmControls << 8);
01005   
01006   DL_APPEND(info->ctrl_if.processing_unit_descs, unit);
01007 
01008   UVC_EXIT(UVC_SUCCESS);
01009   return UVC_SUCCESS;
01010 }
01011 
01016 uvc_error_t uvc_parse_vc_extension_unit(uvc_device_t *dev,
01017                     uvc_device_info_t *info,
01018                     const unsigned char *block, size_t block_size) {
01019   uvc_extension_unit_t *unit = calloc(1, sizeof(*unit));
01020   const uint8_t *start_of_controls;
01021   int size_of_controls, num_in_pins;
01022   int i;
01023 
01024   UVC_ENTER();
01025 
01026   unit->bUnitID = block[3];
01027   memcpy(unit->guidExtensionCode, &block[4], 16);
01028   
01029   num_in_pins = block[21];
01030   size_of_controls = block[22 + num_in_pins];
01031   start_of_controls = &block[23 + num_in_pins];
01032   
01033   for (i = size_of_controls - 1; i >= 0; --i)
01034     unit->bmControls = start_of_controls[i] + (unit->bmControls << 8);
01035   
01036   DL_APPEND(info->ctrl_if.extension_unit_descs, unit);
01037 
01038   UVC_EXIT(UVC_SUCCESS);
01039   return UVC_SUCCESS;
01040 }
01041 
01046 uvc_error_t uvc_parse_vc(
01047     uvc_device_t *dev,
01048     uvc_device_info_t *info,
01049     const unsigned char *block, size_t block_size) {
01050   int descriptor_subtype;
01051   uvc_error_t ret = UVC_SUCCESS;
01052 
01053   UVC_ENTER();
01054 
01055   if (block[1] != 36) { // not a CS_INTERFACE descriptor??
01056     UVC_EXIT(UVC_SUCCESS);
01057     return UVC_SUCCESS; // UVC_ERROR_INVALID_DEVICE;
01058   }
01059 
01060   descriptor_subtype = block[2];
01061 
01062   switch (descriptor_subtype) {
01063   case UVC_VC_HEADER:
01064     ret = uvc_parse_vc_header(dev, info, block, block_size);
01065     break;
01066   case UVC_VC_INPUT_TERMINAL:
01067     ret = uvc_parse_vc_input_terminal(dev, info, block, block_size);
01068     break;
01069   case UVC_VC_OUTPUT_TERMINAL:
01070     break;
01071   case UVC_VC_SELECTOR_UNIT:
01072     break;
01073   case UVC_VC_PROCESSING_UNIT:
01074     ret = uvc_parse_vc_processing_unit(dev, info, block, block_size);
01075     break;
01076   case UVC_VC_EXTENSION_UNIT:
01077     ret = uvc_parse_vc_extension_unit(dev, info, block, block_size);
01078     break;
01079   default:
01080     ret = UVC_ERROR_INVALID_DEVICE;
01081   }
01082 
01083   UVC_EXIT(ret);
01084   return ret;
01085 }
01086 
01091 uvc_error_t uvc_scan_streaming(uvc_device_t *dev,
01092                    uvc_device_info_t *info,
01093                    int interface_idx) {
01094   const struct libusb_interface_descriptor *if_desc;
01095   const unsigned char *buffer;
01096   size_t buffer_left, block_size;
01097   uvc_error_t ret, parse_ret;
01098   uvc_streaming_interface_t *stream_if;
01099 
01100   UVC_ENTER();
01101 
01102   ret = UVC_SUCCESS;
01103 
01104   if_desc = &(info->config->interface[interface_idx].altsetting[0]);
01105   buffer = if_desc->extra;
01106   buffer_left = if_desc->extra_length;
01107 
01108   stream_if = calloc(1, sizeof(*stream_if));
01109   stream_if->parent = info;
01110   stream_if->bInterfaceNumber = if_desc->bInterfaceNumber;
01111   DL_APPEND(info->stream_ifs, stream_if);
01112 
01113   while (buffer_left >= 3) {
01114     block_size = buffer[0];
01115     parse_ret = uvc_parse_vs(dev, info, stream_if, buffer, block_size);
01116 
01117     if (parse_ret != UVC_SUCCESS) {
01118       ret = parse_ret;
01119       break;
01120     }
01121 
01122     buffer_left -= block_size;
01123     buffer += block_size;
01124   }
01125 
01126   UVC_EXIT(ret);
01127   return ret;
01128 }
01129 
01134 uvc_error_t uvc_parse_vs_input_header(uvc_streaming_interface_t *stream_if,
01135                       const unsigned char *block,
01136                       size_t block_size) {
01137   UVC_ENTER();
01138 
01139   stream_if->bEndpointAddress = block[6] & 0x8f;
01140   stream_if->bTerminalLink = block[8];
01141 
01142   UVC_EXIT(UVC_SUCCESS);
01143   return UVC_SUCCESS;
01144 }
01145 
01150 uvc_error_t uvc_parse_vs_format_uncompressed(uvc_streaming_interface_t *stream_if,
01151                          const unsigned char *block,
01152                          size_t block_size) {
01153   UVC_ENTER();
01154 
01155   uvc_format_desc_t *format = calloc(1, sizeof(*format));
01156 
01157   format->parent = stream_if;
01158   format->bDescriptorSubtype = block[2];
01159   format->bFormatIndex = block[3];
01160   //format->bmCapabilities = block[4];
01161   //format->bmFlags = block[5];
01162   memcpy(format->guidFormat, &block[5], 16);
01163   format->bBitsPerPixel = block[21];
01164   format->bDefaultFrameIndex = block[22];
01165   format->bAspectRatioX = block[23];
01166   format->bAspectRatioY = block[24];
01167   format->bmInterlaceFlags = block[25];
01168   format->bCopyProtect = block[26];
01169 
01170   DL_APPEND(stream_if->format_descs, format);
01171 
01172   UVC_EXIT(UVC_SUCCESS);
01173   return UVC_SUCCESS;
01174 }
01175 
01180 uvc_error_t uvc_parse_vs_frame_format(uvc_streaming_interface_t *stream_if,
01181                          const unsigned char *block,
01182                          size_t block_size) {
01183   UVC_ENTER();
01184 
01185   uvc_format_desc_t *format = calloc(1, sizeof(*format));
01186 
01187   format->parent = stream_if;
01188   format->bDescriptorSubtype = block[2];
01189   format->bFormatIndex = block[3];
01190   format->bNumFrameDescriptors = block[4];
01191   memcpy(format->guidFormat, &block[5], 16);
01192   format->bBitsPerPixel = block[21];
01193   format->bDefaultFrameIndex = block[22];
01194   format->bAspectRatioX = block[23];
01195   format->bAspectRatioY = block[24];
01196   format->bmInterlaceFlags = block[25];
01197   format->bCopyProtect = block[26];
01198   format->bVariableSize = block[27];
01199 
01200   DL_APPEND(stream_if->format_descs, format);
01201 
01202   UVC_EXIT(UVC_SUCCESS);
01203   return UVC_SUCCESS;
01204 }
01205 
01210 uvc_error_t uvc_parse_vs_format_mjpeg(uvc_streaming_interface_t *stream_if,
01211                          const unsigned char *block,
01212                          size_t block_size) {
01213   UVC_ENTER();
01214 
01215   uvc_format_desc_t *format = calloc(1, sizeof(*format));
01216 
01217   format->parent = stream_if;
01218   format->bDescriptorSubtype = block[2];
01219   format->bFormatIndex = block[3];
01220   memcpy(format->fourccFormat, "MJPG", 4);
01221   format->bmFlags = block[5];
01222   format->bBitsPerPixel = 0;
01223   format->bDefaultFrameIndex = block[6];
01224   format->bAspectRatioX = block[7];
01225   format->bAspectRatioY = block[8];
01226   format->bmInterlaceFlags = block[9];
01227   format->bCopyProtect = block[10];
01228 
01229   DL_APPEND(stream_if->format_descs, format);
01230 
01231   UVC_EXIT(UVC_SUCCESS);
01232   return UVC_SUCCESS;
01233 }
01234 
01239 uvc_error_t uvc_parse_vs_frame_frame(uvc_streaming_interface_t *stream_if,
01240                         const unsigned char *block,
01241                         size_t block_size) {
01242   uvc_format_desc_t *format;
01243   uvc_frame_desc_t *frame;
01244 
01245   const unsigned char *p;
01246   int i;
01247 
01248   UVC_ENTER();
01249 
01250   format = stream_if->format_descs->prev;
01251   frame = calloc(1, sizeof(*frame));
01252 
01253   frame->parent = format;
01254 
01255   frame->bDescriptorSubtype = block[2];
01256   frame->bFrameIndex = block[3];
01257   frame->bmCapabilities = block[4];
01258   frame->wWidth = block[5] + (block[6] << 8);
01259   frame->wHeight = block[7] + (block[8] << 8);
01260   frame->dwMinBitRate = DW_TO_INT(&block[9]);
01261   frame->dwMaxBitRate = DW_TO_INT(&block[13]);
01262   frame->dwDefaultFrameInterval = DW_TO_INT(&block[17]);
01263   frame->bFrameIntervalType = block[21];
01264   frame->dwBytesPerLine = DW_TO_INT(&block[22]);
01265 
01266   if (block[21] == 0) {
01267     frame->dwMinFrameInterval = DW_TO_INT(&block[26]);
01268     frame->dwMaxFrameInterval = DW_TO_INT(&block[30]);
01269     frame->dwFrameIntervalStep = DW_TO_INT(&block[34]);
01270   } else {
01271     frame->intervals = calloc(block[21] + 1, sizeof(frame->intervals[0]));
01272     p = &block[26];
01273 
01274     for (i = 0; i < block[21]; ++i) {
01275       frame->intervals[i] = DW_TO_INT(p);
01276       p += 4;
01277     }
01278     frame->intervals[block[21]] = 0;
01279   }
01280 
01281   DL_APPEND(format->frame_descs, frame);
01282 
01283   UVC_EXIT(UVC_SUCCESS);
01284   return UVC_SUCCESS;
01285 }
01286 
01291 uvc_error_t uvc_parse_vs_frame_uncompressed(uvc_streaming_interface_t *stream_if,
01292                         const unsigned char *block,
01293                         size_t block_size) {
01294   uvc_format_desc_t *format;
01295   uvc_frame_desc_t *frame;
01296 
01297   const unsigned char *p;
01298   int i;
01299 
01300   UVC_ENTER();
01301 
01302   format = stream_if->format_descs->prev;
01303   frame = calloc(1, sizeof(*frame));
01304 
01305   frame->parent = format;
01306 
01307   frame->bDescriptorSubtype = block[2];
01308   frame->bFrameIndex = block[3];
01309   frame->bmCapabilities = block[4];
01310   frame->wWidth = block[5] + (block[6] << 8);
01311   frame->wHeight = block[7] + (block[8] << 8);
01312   frame->dwMinBitRate = DW_TO_INT(&block[9]);
01313   frame->dwMaxBitRate = DW_TO_INT(&block[13]);
01314   frame->dwMaxVideoFrameBufferSize = DW_TO_INT(&block[17]);
01315   frame->dwDefaultFrameInterval = DW_TO_INT(&block[21]);
01316   frame->bFrameIntervalType = block[25];
01317 
01318   if (block[25] == 0) {
01319     frame->dwMinFrameInterval = DW_TO_INT(&block[26]);
01320     frame->dwMaxFrameInterval = DW_TO_INT(&block[30]);
01321     frame->dwFrameIntervalStep = DW_TO_INT(&block[34]);
01322   } else {
01323     frame->intervals = calloc(block[25] + 1, sizeof(frame->intervals[0]));
01324     p = &block[26];
01325 
01326     for (i = 0; i < block[25]; ++i) {
01327       frame->intervals[i] = DW_TO_INT(p);
01328       p += 4;
01329     }
01330     frame->intervals[block[25]] = 0;
01331   }
01332 
01333   DL_APPEND(format->frame_descs, frame);
01334 
01335   UVC_EXIT(UVC_SUCCESS);
01336   return UVC_SUCCESS;
01337 }
01338 
01343 uvc_error_t uvc_parse_vs(
01344     uvc_device_t *dev,
01345     uvc_device_info_t *info,
01346     uvc_streaming_interface_t *stream_if,
01347     const unsigned char *block, size_t block_size) {
01348   uvc_error_t ret;
01349   int descriptor_subtype;
01350 
01351   UVC_ENTER();
01352 
01353   ret = UVC_SUCCESS;
01354   descriptor_subtype = block[2];
01355 
01356   switch (descriptor_subtype) {
01357   case UVC_VS_INPUT_HEADER:
01358     ret = uvc_parse_vs_input_header(stream_if, block, block_size);
01359     break;
01360   case UVC_VS_FORMAT_UNCOMPRESSED:
01361     ret = uvc_parse_vs_format_uncompressed(stream_if, block, block_size);
01362     break;
01363   case UVC_VS_FORMAT_MJPEG:
01364     ret = uvc_parse_vs_format_mjpeg(stream_if, block, block_size);
01365     break;
01366   case UVC_VS_FRAME_UNCOMPRESSED:
01367   case UVC_VS_FRAME_MJPEG:
01368     ret = uvc_parse_vs_frame_uncompressed(stream_if, block, block_size);
01369     break;
01370   case UVC_VS_FORMAT_FRAME_BASED:
01371     ret = uvc_parse_vs_frame_format ( stream_if, block, block_size );
01372     break;
01373   case UVC_VS_FRAME_FRAME_BASED:
01374     ret = uvc_parse_vs_frame_frame ( stream_if, block, block_size );
01375     break;
01376   default:
01378     UVC_DEBUG ("unsupported descriptor subtype: %d\n", descriptor_subtype);
01379     break;
01380   }
01381 
01382   UVC_EXIT(ret);
01383   return ret;
01384 }
01385 
01390 void uvc_free_devh(uvc_device_handle_t *devh) {
01391   UVC_ENTER();
01392 
01393   if (devh->info)
01394     uvc_free_device_info(devh->info);
01395 
01396   if (devh->status_xfer)
01397     libusb_free_transfer(devh->status_xfer);
01398 
01399   free(devh);
01400 
01401   UVC_EXIT_VOID();
01402 }
01403 
01412 void uvc_close(uvc_device_handle_t *devh) {
01413   UVC_ENTER();
01414   uvc_context_t *ctx = devh->dev->ctx;
01415 
01416   if (devh->streams)
01417     uvc_stop_streaming(devh);
01418 
01419   uvc_release_if(devh, devh->info->ctrl_if.bInterfaceNumber);
01420 
01421   /* If we are managing the libusb context and this is the last open device,
01422    * then we need to cancel the handler thread. When we call libusb_close,
01423    * it'll cause a return from the thread's libusb_handle_events call, after
01424    * which the handler thread will check the flag we set and then exit. */
01425   if (ctx->own_usb_ctx && ctx->open_devices == devh && devh->next == NULL) {
01426     ctx->kill_handler_thread = 1;
01427     libusb_close(devh->usb_devh);
01428     pthread_join(ctx->handler_thread, NULL);
01429   } else {
01430     libusb_close(devh->usb_devh);
01431   }
01432 
01433   DL_DELETE(ctx->open_devices, devh);
01434 
01435   uvc_unref_device(devh->dev);
01436 
01437   uvc_free_devh(devh);
01438 
01439   UVC_EXIT_VOID();
01440 }
01441 
01445 size_t uvc_num_devices(uvc_context_t *ctx) {
01446   size_t count = 0;
01447 
01448   uvc_device_handle_t *devh;
01449 
01450   UVC_ENTER();
01451 
01452   DL_FOREACH(ctx->open_devices, devh) {
01453     count++;
01454   }
01455 
01456   UVC_EXIT((int) count);
01457   return count;
01458 }
01459 
01460 void uvc_process_status_xfer(uvc_device_handle_t *devh, struct libusb_transfer *transfer) {
01461   enum uvc_status_class status_class;
01462   uint8_t originator = 0, selector = 0, event = 0;
01463   enum uvc_status_attribute attribute = UVC_STATUS_ATTRIBUTE_UNKNOWN;
01464   void *data = NULL;
01465   size_t data_len = 0;
01466 
01467   UVC_ENTER();
01468 
01469   /* printf("Got transfer of aLen = %d\n", transfer->actual_length); */
01470 
01471   if (transfer->actual_length < 4) {
01472     UVC_DEBUG("Short read of status update (%d bytes)", transfer->actual_length);
01473     UVC_EXIT_VOID();
01474     return;
01475   }
01476 
01477   originator = transfer->buffer[1];
01478 
01479   switch (transfer->buffer[0] & 0x0f) {
01480   case 1: {  /* VideoControl interface */
01481     int found_entity = 0;
01482     struct uvc_input_terminal *input_terminal;
01483     struct uvc_processing_unit *processing_unit;
01484 
01485     if (transfer->actual_length < 5) {
01486       UVC_DEBUG("Short read of VideoControl status update (%d bytes)",
01487         transfer->actual_length);
01488       UVC_EXIT_VOID();
01489       return;
01490     }
01491 
01492     event = transfer->buffer[2];
01493     selector = transfer->buffer[3];
01494 
01495     if (originator == 0) {
01496       UVC_DEBUG("Unhandled update from VC interface", );
01497       UVC_EXIT_VOID();
01498       return;  /* @todo VideoControl virtual entity interface updates */
01499     }
01500 
01501     if (event != 0) {
01502       UVC_DEBUG("Unhandled VC event %d", (int) event);
01503       UVC_EXIT_VOID();
01504       return;
01505     }
01506 
01507     /* printf("bSelector: %d\n", selector); */
01508 
01509     DL_FOREACH(devh->info->ctrl_if.input_term_descs, input_terminal) {
01510       if (input_terminal->bTerminalID == originator) {
01511         status_class = UVC_STATUS_CLASS_CONTROL_CAMERA;
01512         found_entity = 1;
01513         break;
01514       }
01515     }
01516 
01517     if (!found_entity) {
01518       DL_FOREACH(devh->info->ctrl_if.processing_unit_descs, processing_unit) {
01519         if (processing_unit->bUnitID == originator) {
01520           status_class = UVC_STATUS_CLASS_CONTROL_PROCESSING;
01521           found_entity = 1;
01522           break;
01523         }
01524       }
01525     }
01526 
01527     if (!found_entity) {
01528       UVC_DEBUG("Got status update for unknown VideoControl entity %d",
01529         (int) originator);
01530       UVC_EXIT_VOID();
01531       return;
01532     }
01533 
01534     attribute = transfer->buffer[4];
01535     data = transfer->buffer + 5;
01536     data_len = transfer->actual_length - 5;
01537     break;
01538   }
01539   case 2:  /* VideoStreaming interface */
01540     UVC_DEBUG("Unhandled update from VideoStreaming interface",);
01541     UVC_EXIT_VOID();
01542     return;  /* @todo VideoStreaming updates */
01543   }
01544 
01545   UVC_DEBUG("Event: class=%d, event=%d, selector=%d, attribute=%d, data_len=%zd",
01546     status_class, event, selector, attribute, data_len);
01547 
01548   if(devh->status_cb) {
01549     UVC_DEBUG("Running user-supplied status callback",);
01550     devh->status_cb(status_class,
01551                     event,
01552                     selector,
01553                     attribute,
01554                     data, data_len,
01555                     devh->status_user_ptr);
01556   }
01557 
01558   UVC_EXIT_VOID();
01559 }
01560 
01564 void LIBUSB_CALL _uvc_status_callback(struct libusb_transfer *transfer) {
01565   UVC_ENTER();
01566 
01567   uvc_device_handle_t *devh = (uvc_device_handle_t *) transfer->user_data;
01568 
01569   switch (transfer->status) {
01570   case LIBUSB_TRANSFER_ERROR:
01571   case LIBUSB_TRANSFER_CANCELLED:
01572   case LIBUSB_TRANSFER_NO_DEVICE:
01573     UVC_DEBUG("retrying transfer, status = %s", libusb_error_name(transfer->status));
01574     break;
01575   case LIBUSB_TRANSFER_COMPLETED:
01576     uvc_process_status_xfer(devh, transfer);
01577     break;
01578   case LIBUSB_TRANSFER_TIMED_OUT:
01579   case LIBUSB_TRANSFER_STALL:
01580   case LIBUSB_TRANSFER_OVERFLOW:
01581     UVC_DEBUG("retrying transfer, status = %s", libusb_error_name(transfer->status));
01582     break;
01583   }
01584 
01585   uvc_error_t ret = libusb_submit_transfer(transfer);
01586   UVC_DEBUG("libusb_submit_transfer() = %d", ret);
01587 
01588   UVC_EXIT_VOID();
01589 }
01590 
01595 void uvc_set_status_callback(uvc_device_handle_t *devh,
01596                              uvc_status_callback_t cb,
01597                              void *user_ptr) {
01598   UVC_ENTER();
01599 
01600   devh->status_cb = cb;
01601   devh->status_user_ptr = user_ptr;
01602 
01603   UVC_EXIT_VOID();
01604 }
01605 
01606 
01614 const uvc_format_desc_t *uvc_get_format_descs(uvc_device_handle_t *devh) {
01615   return devh->info->stream_ifs->format_descs;
01616 }
01617 


librealsense
Author(s): Sergey Dorodnicov , Mark Horn , Reagan Lopez
autogenerated on Tue Jun 25 2019 19:54:38