stream pushing ok without access permission of /dev/video0
[rtmpclient.git] / app / src / main / jni / libuvc / src / diag.c
1 /*********************************************************************
2  *********************************************************************/
3 /*********************************************************************
4  * changed to using LogCat than stderr when compiling for Android
5  * Copyright (C) 2014 saki@serenegiant All rights reserved.
6  *********************************************************************/
7 /*********************************************************************
8  * Software License Agreement (BSD License)
9  *
10  *  Copyright (C) 2010-2012 Ken Tossell
11  *  All rights reserved.
12  *
13  *  Redistribution and use in source and binary forms, with or without
14  *  modification, are permitted provided that the following conditions
15  *  are met:
16  *
17  *   * Redistributions of source code must retain the above copyright
18  *     notice, this list of conditions and the following disclaimer.
19  *   * Redistributions in binary form must reproduce the above
20  *     copyright notice, this list of conditions and the following
21  *     disclaimer in the documentation and/or other materials provided
22  *     with the distribution.
23  *   * Neither the name of the author nor other contributors may be
24  *     used to endorse or promote products derived from this software
25  *     without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  *  POSSIBILITY OF SUCH DAMAGE.
39  *********************************************************************/
40 /**
41  * @defgroup diag Diagnostics
42  * @brief Interpretation of devices, error codes and negotiated stream parameters
43  */
44
45 #include "libuvc/libuvc.h"
46 #include "libuvc/libuvc_internal.h"
47
48 /** @internal */
49 typedef struct _uvc_error_msg {
50         uvc_error_t err;
51         const char *msg;
52 } _uvc_error_msg_t;
53
54 static const _uvc_error_msg_t uvc_error_msgs[] = {
55         { UVC_SUCCESS, "Success" },
56         { UVC_ERROR_IO, "I/O error" },
57         { UVC_ERROR_INVALID_PARAM, "Invalid parameter" },
58         { UVC_ERROR_ACCESS, "Access denied" },
59         { UVC_ERROR_NO_DEVICE, "No such device" },
60         { UVC_ERROR_NOT_FOUND,  "Not found" },
61         { UVC_ERROR_BUSY, "Busy" },
62         { UVC_ERROR_TIMEOUT, "Timeout" },
63         { UVC_ERROR_OVERFLOW, "Overflow" },
64         { UVC_ERROR_PIPE, "Pipe" },
65         { UVC_ERROR_INTERRUPTED, "Interrupted" },
66         { UVC_ERROR_NO_MEM, "Out of memory" },
67         { UVC_ERROR_NOT_SUPPORTED, "Not supported" },
68         { UVC_ERROR_INVALID_DEVICE, "Invalid device" },
69         { UVC_ERROR_INVALID_MODE, "Invalid mode" },
70         { UVC_ERROR_CALLBACK_EXISTS, "Callback exists" }
71 };
72
73 #ifdef __ANDROID__
74 #define FPRINTF(stream, ...) MARK(__VA_ARGS__); usleep(1000);
75 #define FPRINTF_ERR(stream, ...) LOGW(__VA_ARGS__)
76 #else
77 #define FPRINTF(stream, ...) fprintf(stream, __VA_ARGS__)
78 #define FPRINTF_ERR(stream, ...) fprintf(stream, __VA_ARGS__)
79 #endif
80 /** @brief Print a message explaining an error in the UVC driver
81  * @ingroup diag
82  *
83  * @param err UVC error code
84  * @param msg Optional custom message, prepended to output
85  */
86 void uvc_perror(uvc_error_t err, const char *msg) {
87         if (msg && *msg) {
88                 FPRINTF_ERR(stderr, "%s:%s (%d)\n", msg, uvc_strerror(err), err);
89         } else {
90                 FPRINTF_ERR(stderr, "%s (%d)\n", uvc_strerror(err), err);
91         }
92 /*
93          if (msg && *msg) {
94                  fputs(msg, stderr);
95                  fputs(": ", stderr);
96          }
97
98          FPRINTF(stderr, "%s (%d)\n", uvc_strerror(err), err);
99 */
100 }
101
102 /** @brief Return a string explaining an error in the UVC driver
103  * @ingroup diag
104  *
105  * @param err UVC error code
106  * @return error message
107  */
108 const char* uvc_strerror(uvc_error_t err) {
109         size_t idx;
110
111         for (idx = 0; idx < sizeof(uvc_error_msgs) / sizeof(*uvc_error_msgs);
112                         ++idx) {
113                 if (uvc_error_msgs[idx].err == err) {
114                         return uvc_error_msgs[idx].msg;
115                 }
116         }
117
118         return "Unknown error";
119 }
120
121 /** @brief Print the values in a stream control block
122  * @ingroup diag
123  *
124  * @param devh UVC device
125  * @param stream Output stream (stderr if NULL)
126  */
127 void uvc_print_stream_ctrl(uvc_stream_ctrl_t *ctrl, FILE *stream) {
128         if (stream == NULL)
129                 stream = stderr;
130
131         FPRINTF(stream, "bmHint: %04x\n", ctrl->bmHint);
132         FPRINTF(stream, "bFormatIndex: %d\n", ctrl->bFormatIndex);
133         FPRINTF(stream, "bFrameIndex: %d\n", ctrl->bFrameIndex);
134         FPRINTF(stream, "dwFrameInterval: %u\n", ctrl->dwFrameInterval);
135         FPRINTF(stream, "wKeyFrameRate: %d\n", ctrl->wKeyFrameRate);
136         FPRINTF(stream, "wPFrameRate: %d\n", ctrl->wPFrameRate);
137         FPRINTF(stream, "wCompQuality: %d\n", ctrl->wCompQuality);
138         FPRINTF(stream, "wCompWindowSize: %d\n", ctrl->wCompWindowSize);
139         FPRINTF(stream, "wDelay: %d\n", ctrl->wDelay);
140         FPRINTF(stream, "dwMaxVideoFrameSize: %u\n", ctrl->dwMaxVideoFrameSize);
141         FPRINTF(stream, "dwMaxPayloadTransferSize: %u\n", ctrl->dwMaxPayloadTransferSize);
142         FPRINTF(stream, "bInterfaceNumber: %d\n", ctrl->bInterfaceNumber);
143 //
144         /** add UVC 1.1 parameters */
145         FPRINTF(stream, "dwClockFrequency: %d\n", ctrl->dwClockFrequency);
146         FPRINTF(stream, "bmFramingInfo: %d\n", ctrl->bmFramingInfo);
147         FPRINTF(stream, "bPreferedVersion: %d\n", ctrl->bPreferedVersion);
148         FPRINTF(stream, "bMinVersion: %d\n", ctrl->bMinVersion);
149         FPRINTF(stream, "bMaxVersion: %d\n", ctrl->bMaxVersion);
150         /** add UVC 1.5 parameters */
151         FPRINTF(stream, "bUsage: %d\n", ctrl->bUsage);
152         FPRINTF(stream, "bBitDepthLuma: %d\n", ctrl->bBitDepthLuma);
153         FPRINTF(stream, "bmSettings: %d\n", ctrl->bmSettings);
154         FPRINTF(stream, "bMaxNumberOfRefFramesPlus1: %d\n", ctrl->bMaxNumberOfRefFramesPlus1);
155         FPRINTF(stream, "bmRateControlModes: %d\n", ctrl->bmRateControlModes);
156 #if !defined(__LP64__)
157         FPRINTF(stream, "bmLayoutPerStream: %llx\n", ctrl->bmLayoutPerStream);
158 #else
159         FPRINTF(stream, "bmLayoutPerStream: %lx\n", ctrl->bmLayoutPerStream);
160 #endif
161 }
162
163 static const char *_uvc_name_for_desc_type(const uint8_t type) {
164         switch (type) {
165         case LIBUSB_DT_DEVICE:                                          // 0x01,
166                 return "Device Descriptor(0x01)";
167         case LIBUSB_DT_CONFIG:                                          // 0x02,
168                 return "Config Descriptor(0x02)";
169         case LIBUSB_DT_STRING:                                          // 0x03,
170                 return "String Descriptor(0x03)";
171         case LIBUSB_DT_INTERFACE:                                       // 0x04,
172                 return "Interface Descriptor(0x04)";
173         case LIBUSB_DT_ENDPOINT:                                        // 0x05,
174                 return "Endpoint Descriptor(0x05)";
175         case LIBUSB_DT_DEVICE_QUALIFIER:                        // 0x06,        // deprecated on USB3.0
176                 return "Qualifier Descriptor(0x06)";
177         case LIBUSB_DT_OTHER_SPEED_CONFIGURATION:       // 0x07,        // deprecated on USB3.0
178                 return "Other speed Config Descriptor(0x07)";
179         case LIBUSB_DT_INTERFACE_POWER:                         // 0x08,
180                 return "Power interface Descriptor(0x08)";
181         case LIBUSB_DT_OTG:                                                     // 0x09,
182                 return "OTG Interface Descriptor(0x09)";
183         case LIBUSB_DT_DEBUG:                                           // 0x0a,
184                 return "Debug Descriptor(0x0a)";
185         case LIBUSB_DT_ASSOCIATION:                                     // 0x0b,
186                 return "Association Descriptor(0x0b)";
187         case LIBUSB_DT_BOS:                                                     // 0x0f,
188                 return "BOS Descriptor(0x0f)";
189         case LIBUSB_DT_DEVICE_CAPABILITY:                       // 0x10,
190                 return "Device capability Descriptor(0x10)";
191 // Class specified descriptors
192         case LIBUSB_DT_HID:                                                     // 0x21,
193                 return "CS:HID Descriptor(0x21)";
194         case LIBUSB_DT_HID_REPORT:                                      // 0x22,
195                 return "CS:HID Report Descriptor(0x22)";
196         case LIBUSB_DT_HID_PHYSICAL:                            // 0x23,
197                 return "CS:HID Pysical Descriptor(0x23)";
198         case LIBUSB_DT_CS_INTERFACE:                            // 0x24,
199                 return "CS:Interface Descriptor(0x24)";
200         case LIBUSB_DT_CS_ENDPOINT:                                     // 0x25,
201                 return "CS:Endpoint Descriptor(0x25)";
202         case LIBUSB_DT_HUB:                                             // 0x29,
203                 return "CS:Hub Descriptor(0x29)";
204         case LIBUSB_DT_SUPERSPEED_HUB:                          // 0x2a,
205                 return "CS:Superspeed Hub Descriptor(0x2a)";
206         case LIBUSB_DT_SS_ENDPOINT_COMPANION:           // 0x30         // defined on USB 3.0
207                 return "CS:Superspeed Endpoint Companion Descriptor(0x30)";
208         default:
209                 return "Unknown descriptor";
210         }
211 }
212
213 static const char *_uvc_name_for_class(const uint8_t clazz) {
214         switch (clazz) {
215         case LIBUSB_CLASS_AUDIO:                                // 1,           /** Audio class */
216                 return "Audio";
217         case LIBUSB_CLASS_COMM:                                 // 2,           /** Communications class */
218                 return "Comm";
219         case LIBUSB_CLASS_HID:                                  // 3,           /** Human Interface Device class */
220                 return "HID";
221         case LIBUSB_CLASS_PHYSICAL:                             // 5,           /** Physical */
222                 return "Physical";
223         case LIBUSB_CLASS_IMAGE:                                // 6,           /** Image class */
224                 return "Image";
225         case LIBUSB_CLASS_PRINTER:                              // 7,           /** Printer class */
226                 return "Printer";
227         case LIBUSB_CLASS_MASS_STORAGE:                 // 8,           /** Mass storage class */
228                 return "Mass storage";
229         case LIBUSB_CLASS_HUB:                                  // 9,           /** Hub class */
230                 return "Hub";
231         case LIBUSB_CLASS_DATA:                                 // 0x0a,        /** Data class */
232                 return "Data";
233         case LIBUSB_CLASS_SMART_CARD:                   // 0x0b,        /** Smart Card */
234                 return "Smart card";
235         case LIBUSB_CLASS_CONTENT_SECURITY:             // 0x0d,        /** Content Security */
236                 return "Security";
237         case LIBUSB_CLASS_VIDEO:                                // 0x0e,        /** Video */
238                 return "Video";
239         case LIBUSB_CLASS_PERSONAL_HEALTHCARE:  // 0x0f,        /** Personal Healthcare */
240                 return "Helthcare";
241         case LIBUSB_CLASS_DIAGNOSTIC_DEVICE:    // 0xdc,        /** Diagnostic Device */
242                 return "Diag";
243         case LIBUSB_CLASS_WIRELESS:                             // 0xe0,        /** Wireless class */
244                 return "Wireless";
245         case LIBUSB_CLASS_APPLICATION:                  // 0xfe,        /** Application class */
246                 return "App";
247         case LIBUSB_CLASS_VENDOR_SPEC:                  // 0xff         /** Class is vendor-specific */
248                 return "Vender specific";
249         default:
250                 return "Unknown";
251         }
252 }
253
254 static const char *_uvc_name_for_subtype(const uint8_t subtype) {
255         switch (subtype) {
256         case UVC_VS_UNDEFINED:                          // 0x00,
257                 return "Undefined(0x00)";
258         case UVC_VS_INPUT_HEADER:                       // 0x01,
259                 return "Header(Input,0x01)";
260         case UVC_VS_OUTPUT_HEADER:                      // 0x02,
261                 return "Header(Output,0x02)";
262         case UVC_VS_STILL_IMAGE_FRAME:          // 0x03,
263                 return "Frame(StillImage,0x03)";
264         case UVC_VS_FORMAT_UNCOMPRESSED:        // 0x04,
265                 return "Format(Uncompressed,0x04)";
266         case UVC_VS_FRAME_UNCOMPRESSED:         // 0x05,
267                 return "Frame(Uncompressed,0x05)";
268         case UVC_VS_FORMAT_MJPEG:                       // 0x06,
269                 return "Format(MJPEG,0x06)";
270         case UVC_VS_FRAME_MJPEG:                        // 0x07,
271                 return "Frame(MJPEG,0x07)";
272         case UVC_VS_FORMAT_MPEG2TS:                     // 0x0a,
273                 return "Format(MPEG2TS,0x0a)";
274         case UVC_VS_FORMAT_DV:                          // 0x0c,
275                 return "Format(DV,0x0c)";
276         case UVC_VS_COLORFORMAT:                        // 0x0d,
277                 return "ColorFormat(0x0d)";
278         case UVC_VS_FORMAT_FRAME_BASED:         // 0x10,
279                 return "Format(FRAME_BASED,0x10)";
280         case UVC_VS_FRAME_FRAME_BASED:          // 0x11,
281                 return "Frame(FRAME_BASED,0x10)";
282         case UVC_VS_FORMAT_STREAM_BASED:        // 0x12
283                 return "Format(STREAM_BASED,0x10)";
284         default:
285                 return "Unknown";
286         }
287 }
288
289 /** @brief Print camera capabilities and configuration.
290  * @ingroup diag
291  *
292  * @param devh UVC device
293  * @param stream Output stream (stderr if NULL)
294  */
295 void uvc_print_diag(uvc_device_handle_t *devh, FILE *stream) {
296         UVC_ENTER();
297
298         if (stream == NULL)
299                 stream = stderr;
300
301         if (devh->info->ctrl_if.bcdUVC) {
302                 uvc_streaming_interface_t *stream_if;
303                 int stream_idx = 0;
304
305                 uvc_device_descriptor_t *desc;
306                 uvc_get_device_descriptor(devh->dev, &desc);
307
308                 FPRINTF(stream, "DEVICE CONFIGURATION (%04x:%04x/%s) ---\n",
309                                 desc->idVendor, desc->idProduct,
310                                 desc->serialNumber ? desc->serialNumber : "[none]");
311
312                 uvc_free_device_descriptor(desc);
313
314                 FPRINTF(stream, "Status: %s\n", devh->streams ? "streaming" : "idle");
315
316                 FPRINTF(stream, "VideoControl:\n"
317                                 "\tbcdUVC: 0x%04x\n", devh->info->ctrl_if.bcdUVC);
318
319                 DL_FOREACH(devh->info->stream_ifs, stream_if)
320                 {
321                         uvc_format_desc_t *fmt_desc;
322
323                         ++stream_idx;
324
325                         FPRINTF(stream,
326                                 "VideoStreaming(%d):\n"
327                                 "\tbEndpointAddress: %d\n\tFormats:\n",
328                                 stream_idx, stream_if->bEndpointAddress);
329                         uvc_print_format_desc(stream_if->format_descs, stream);
330                 }
331
332                 FPRINTF(stream, "END DEVICE CONFIGURATION\n");
333         } else {
334                 FPRINTF(stream, "uvc_print_diag: Device not configured!\n");
335         }
336         UVC_EXIT_VOID();
337 }
338
339 void uvc_print_format_desc_one(uvc_format_desc_t *format_desc, FILE *stream) {
340
341         uvc_frame_desc_t *frame_desc;
342         int i;
343
344         switch (format_desc->bDescriptorSubtype) {
345         case UVC_VS_FORMAT_UNCOMPRESSED:
346         case UVC_VS_FORMAT_MJPEG:
347                 FPRINTF(stream, "\t\tFormatDescriptor(bFormatIndex=%d)", format_desc->bFormatIndex);
348                 FPRINTF(stream, "\t\t  bDescriptorSubtype: %s",
349                         _uvc_name_for_subtype(format_desc->bDescriptorSubtype));
350                 FPRINTF(stream, "\t\t  bits per pixel: %d", format_desc->bBitsPerPixel);
351                 FPRINTF(stream,
352                                 "\t\t  GUID:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
353                                 format_desc->guidFormat[0], format_desc->guidFormat[1],
354                                 format_desc->guidFormat[2], format_desc->guidFormat[3],
355                                 format_desc->guidFormat[4], format_desc->guidFormat[5],
356                                 format_desc->guidFormat[6], format_desc->guidFormat[7],
357                                 format_desc->guidFormat[8], format_desc->guidFormat[9],
358                                 format_desc->guidFormat[10], format_desc->guidFormat[11],
359                                 format_desc->guidFormat[12], format_desc->guidFormat[13],
360                                 format_desc->guidFormat[14], format_desc->guidFormat[15]);
361
362                 FPRINTF(stream, "\t\t  bDefaultFrameIndex: %d", format_desc->bDefaultFrameIndex);
363                 FPRINTF(stream, "\t\t  bAspectRatio(x,y): %dx%d", format_desc->bAspectRatioX, format_desc->bAspectRatioY);
364                 FPRINTF(stream, "\t\t  bmInterlaceFlags: 0x%02x", format_desc->bmInterlaceFlags);
365                 FPRINTF(stream, "\t\t  bCopyProtect: 0x%02x", format_desc->bCopyProtect);
366
367                 DL_FOREACH(format_desc->frame_descs, frame_desc)
368                 {
369                         uint32_t *interval_ptr;
370
371                         FPRINTF(stream, "\t\t\tFrameDescriptor(bFrameIndex=%d)", frame_desc->bFrameIndex);
372                         FPRINTF(stream, "\t\t\t  bDescriptorSubtype: %s", _uvc_name_for_subtype(frame_desc->bDescriptorSubtype));
373                         FPRINTF(stream, "\t\t\t  bmCapabilities: 0x%02x", frame_desc->bmCapabilities);
374                         FPRINTF(stream, "\t\t\t  size(w,h):(%d,%d)", frame_desc->wWidth, frame_desc->wHeight);
375                         FPRINTF(stream, "\t\t\t  bit rate(min,max): (%d,%d)", frame_desc->dwMinBitRate, frame_desc->dwMaxBitRate);
376                         FPRINTF(stream, "\t\t\t  dwMaxVideoFrameBufferSize: %d", frame_desc->dwMaxVideoFrameBufferSize);
377                         FPRINTF(stream, "\t\t\t  dwDefaultFrameInterval: 1/%d", 10000000 / frame_desc->dwDefaultFrameInterval);
378                         if (frame_desc->intervals) {
379                                 for (interval_ptr = frame_desc->intervals;
380                                                 *interval_ptr; ++interval_ptr) {
381                                         FPRINTF(stream, "\t\t\t  interval[%d]: 1/%d",
382                                                         (int ) (interval_ptr - frame_desc->intervals),
383                                                         10000000 / *interval_ptr);
384                                 }
385                         } else {
386                                 FPRINTF(stream, "\t\t\t  min interval[%d] = 1/%d",
387                                         frame_desc->dwMinFrameInterval,
388                                         10000000 / frame_desc->dwMinFrameInterval);
389                                 FPRINTF(stream, "\t\t\t  max interval[%d] = 1/%d",
390                                         frame_desc->dwMaxFrameInterval,
391                                         10000000 / frame_desc->dwMaxFrameInterval);
392                                 if (frame_desc->dwFrameIntervalStep)
393                                         FPRINTF(stream, "\t\t\t  interval step[%d] = 1/%d",
394                                                 frame_desc->dwFrameIntervalStep,
395                                                 10000000 / frame_desc->dwFrameIntervalStep);
396                         }
397                 }
398                 break;
399         default:
400                 FPRINTF(stream, "\t-UnknownFormat:0x%2d", format_desc->bDescriptorSubtype);
401         }
402 }
403
404 void uvc_print_format_desc(uvc_format_desc_t *format_descriptors, FILE *stream) {
405         ENTER();
406
407         if (stream == NULL)
408                 stream = stderr;
409
410         uvc_format_desc_t *fmt_desc;
411         MARK("FORMAT DESCRIPTOR");
412         DL_FOREACH(format_descriptors, fmt_desc)
413         {
414                 uvc_print_format_desc_one(fmt_desc, stream);
415         }
416         MARK("END FORMAT DESCRIPTOR");
417
418         EXIT();
419 }
420
421 void uvc_print_device_desc(uvc_device_handle_t *devh, FILE *stream) {
422         ENTER();
423
424         if (stream == NULL)
425                 stream = stderr;
426
427         struct libusb_device_descriptor usb_desc;
428         uvc_error_t ret;
429
430         ret = libusb_get_device_descriptor(devh->dev->usb_dev, &usb_desc);
431
432         if (UNLIKELY(ret != UVC_SUCCESS)) {
433                 LOGE("failed libusb_get_device_descriptor");
434                 EXIT();
435         }
436
437         FPRINTF(stream, "DEVICE DESCRIPTOR (%04x:%04x)", usb_desc.idVendor, usb_desc.idProduct);
438         FPRINTF(stream, "\t bLength:%d", usb_desc.bLength);
439         FPRINTF(stream, "\t bDescriptorType: %s", _uvc_name_for_desc_type(usb_desc.bDescriptorType));
440         FPRINTF(stream, "\t bcdUSB:0x%04x", usb_desc.bcdUSB);
441         FPRINTF(stream, "\t bDeviceClass: %s(0x%02x)", _uvc_name_for_class(usb_desc.bDeviceClass), usb_desc.bDeviceClass);
442         FPRINTF(stream, "\t bDeviceSubClass:0x%02x", usb_desc.bDeviceSubClass);
443         FPRINTF(stream, "\t bDeviceProtocol:0x%02x", usb_desc.bDeviceProtocol);
444         FPRINTF(stream, "\t bMaxPacketSize0:%d", usb_desc.bMaxPacketSize0);
445         FPRINTF(stream, "\t idVendor:0x%04x", usb_desc.idVendor);
446         FPRINTF(stream, "\t idProduct:0x%04x", usb_desc.idProduct);
447         FPRINTF(stream, "\t bcdDevice:0x%04x", usb_desc.bcdDevice);
448         FPRINTF(stream, "\t iManufacturer:%d", usb_desc.iManufacturer);
449         FPRINTF(stream, "\t iProduct:%d", usb_desc.iProduct);
450         FPRINTF(stream, "\t iSerialNumber:%d", usb_desc.iSerialNumber);
451         FPRINTF(stream, "\t bNumConfigurations:%d", usb_desc.bNumConfigurations);
452
453         EXIT();
454 }
455
456 void uvc_print_endpoint_desc(
457         const struct libusb_endpoint_descriptor *endpoint, const int num_endpoint,
458         const char *prefix, FILE *stream) {
459
460 //      ENTER();
461
462         if (stream == NULL)
463                 stream = stderr;
464
465         int ep_ix;
466         const struct libusb_endpoint_descriptor *ep;
467
468         for (ep_ix = 0; ep_ix < num_endpoint; ep_ix++) {
469                 ep = endpoint + ep_ix;
470                 FPRINTF(stream, "%s endpoint(%d)", prefix, ep_ix);
471                 if LIKELY(ep) {
472                         FPRINTF(stream, "%s\t bLength:%d", prefix, ep->bLength);
473                         FPRINTF(stream, "%s\t bDescriptorType: %s", prefix, _uvc_name_for_desc_type(ep->bDescriptorType));
474                         FPRINTF(stream, "%s\t bEndpointAddress:0x%02x", prefix, ep->bEndpointAddress);
475                         FPRINTF(stream, "%s\t bmAttributes:0x%02x", prefix, ep->bmAttributes);
476                         FPRINTF(stream, "%s\t wMaxPacketSize:%d", prefix, ep->wMaxPacketSize);
477                         FPRINTF(stream, "%s\t bInterval:%d", prefix, ep->bInterval);
478                         FPRINTF(stream, "%s\t bRefresh(audio):%d", prefix, ep->bRefresh);
479                         FPRINTF(stream, "%s\t bSynchAddress(audio):%d", prefix, ep->bSynchAddress);
480                         FPRINTF(stream, "%s\t extra_length:%d", prefix, ep->extra_length);
481                 }
482         }
483 //      EXIT();
484 }
485
486 void uvc_print_interface_desc(
487         const struct libusb_interface *interface, const int num_interface,
488         const char *prefix, FILE *stream) {
489
490 //      ENTER();
491
492         if (stream == NULL)
493                 stream = stderr;
494
495         const struct libusb_interface *usb_if;
496         const struct libusb_interface_descriptor *altsetting;
497         int if_ix, alt_ix;
498         char pre[64];
499         sprintf(pre, "%s\t\t", prefix);
500         for (if_ix = 0; if_ix < num_interface; if_ix++) {
501                 usb_if = interface + if_ix;
502                 if LIKELY(usb_if) {
503                         FPRINTF(stream, "%s interface(%d)", prefix, if_ix);
504                         for (alt_ix = 0; alt_ix < usb_if->num_altsetting; alt_ix++) {
505                                 altsetting = usb_if->altsetting + alt_ix;
506                                 if LIKELY(altsetting) {
507                                         FPRINTF(stream, "%s\t altsetting:%d", prefix, alt_ix);
508                                         FPRINTF(stream, "%s\t\t bLength:%d", prefix, altsetting->bLength);
509                                         FPRINTF(stream, "%s\t\t bDescriptorType: %s", prefix, _uvc_name_for_desc_type(altsetting->bDescriptorType));
510                                         FPRINTF(stream, "%s\t\t bInterfaceNumber:%d", prefix, altsetting->bInterfaceNumber);
511                                         FPRINTF(stream, "%s\t\t bAlternateSetting:%d", prefix, altsetting->bAlternateSetting);
512                                         FPRINTF(stream, "%s\t\t bNumEndpoints:%d", prefix, altsetting->bNumEndpoints);
513                                         FPRINTF(stream, "%s\t\t bInterfaceClass: %s(0x%02x)", prefix, _uvc_name_for_class(altsetting->bInterfaceClass), altsetting->bInterfaceClass);
514                                         FPRINTF(stream, "%s\t\t bInterfaceSubClass:0x%02x", prefix, altsetting->bInterfaceSubClass);
515                                         FPRINTF(stream, "%s\t\t bInterfaceProtocol:0x%02x", prefix, altsetting->bInterfaceProtocol);
516                                         FPRINTF(stream, "%s\t\t iInterface:%d", prefix, altsetting->iInterface);
517                                         FPRINTF(stream, "%s\t\t extra_length:%d", prefix, altsetting->extra_length);
518                                         if (altsetting->bNumEndpoints)
519                                                 uvc_print_endpoint_desc(altsetting->endpoint, altsetting->bNumEndpoints, pre, stream);
520                                 }
521                         }
522                 }
523         }
524
525 //      EXIT();
526 }
527
528 void uvc_print_configuration_desc(uvc_device_handle_t *devh, FILE *stream) {
529         ENTER();
530
531         if (stream == NULL)
532                 stream = stderr;
533
534         int ret;
535         libusb_device_handle *usb_devh = uvc_get_libusb_handle(devh);
536         libusb_device *usb_dev = devh->dev->usb_dev;
537         struct libusb_config_descriptor *config_desc;
538         int config;
539
540         FPRINTF(stream, "CONFIGURATION DESCRIPTOR");
541         ret = libusb_get_configuration(usb_devh, &config);
542         if (!ret) {
543                 FPRINTF(stream, "\t current=%d", config);
544                 if LIKELY(config >= 0) {
545                         ret = libusb_get_active_config_descriptor(usb_dev, &config_desc);
546                         if LIKELY(!ret) {
547                                 FPRINTF(stream, "\t\t bLength:%d", config_desc->bLength);
548                                 FPRINTF(stream, "\t\t bDescriptorType: %s", _uvc_name_for_desc_type(config_desc->bDescriptorType));
549                                 FPRINTF(stream, "\t\t wTotalLength:%d", config_desc->wTotalLength);
550                                 FPRINTF(stream, "\t\t bNumInterfaces:%d", config_desc->bNumInterfaces);
551                                 FPRINTF(stream, "\t\t bConfigurationValue:%d", config_desc->bConfigurationValue);
552                                 FPRINTF(stream, "\t\t iConfiguration:%d", config_desc->iConfiguration);
553                                 FPRINTF(stream, "\t\t bmAttributes:0x%02x", config_desc->bmAttributes);
554                                 FPRINTF(stream, "\t\t MaxPower:%d x2[mA]", config_desc->MaxPower);
555                                 FPRINTF(stream, "\t\t extra_length:%d", config_desc->extra_length);
556                                 if (config_desc->wTotalLength && config_desc->bNumInterfaces)
557                                         uvc_print_interface_desc(config_desc->interface, config_desc->bNumInterfaces, "\t\t", stream);
558                                 libusb_free_config_descriptor(config_desc);
559                         }
560                 }
561         }
562
563         EXIT();
564 }