* Copyright 2016, Adrien Destugues, pulkomandy@pulkomandy.tk
* Distributed under terms of the MIT license.
*/
#include <stdio.h>
#include <usb/USB_video.h>
#include "listusb.h"
void
DumpVideoCSInterfaceDescriptorHeader(
const usb_videocontrol_header_descriptor* descriptor)
{
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Header)\n",
descriptor->descriptor_subtype);
printf(" UVC Release ....... %d.%d\n",
descriptor->bcd_release_no >> 8, descriptor->bcd_release_no & 0xFF);
printf(" Total Length ...... %u\n",
descriptor->total_length);
printf(" Clock Frequency ... %" B_PRIu32 "\n",
descriptor->clock_frequency);
printf(" Interfaces ........ ");
for (uint8 i = 0; i < descriptor->in_collection; i++)
printf("%u, ", descriptor->interface_numbers[i]);
printf("\n");
}
static const char*
TerminalTypeName(uint16 terminalType)
{
switch (terminalType) {
case USB_VIDEO_VENDOR_USB_IO:
return "Vendor specific";
case USB_VIDEO_STREAMING_USB_IO:
return "Streaming";
case USB_VIDEO_VENDOR_IN:
return "Vendor specific input";
case USB_VIDEO_CAMERA_IN:
return "Camera";
case USB_VIDEO_MEDIA_TRANSPORT_IN:
return "Media transport input";
case USB_VIDEO_VENDOR_OUT:
return "Vendor specific output";
case USB_VIDEO_DISPLAY_OUT:
return "Display";
case USB_VIDEO_MEDIA_TRANSPORT_OUT:
return "Media transport output";
case USB_VIDEO_VENDOR_EXT:
return "Vendor specific format";
case USB_VIDEO_COMPOSITE_EXT:
return "Composite";
case USB_VIDEO_SVIDEO_EXT:
return "S-Video";
case USB_VIDEO_COMPONENT_EXT:
return "Component";
default:
return "Unknown";
}
}
void
DumpVideoCSInterfaceDescriptorOutputTerminal(
const usb_video_output_terminal_descriptor* descriptor)
{
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Output Terminal)\n",
descriptor->descriptor_subtype);
printf(" Terminal ID ....... %u\n",
descriptor->terminal_id);
printf(" Terminal Type ..... 0x%04x (%s)\n",
descriptor->terminal_type,
TerminalTypeName(descriptor->terminal_type));
printf(" Associated Terminal %u\n",
descriptor->associated_terminal);
printf(" Source ID ......... %u\n",
descriptor->source_id);
printf(" Terminal .......... %u\n",
descriptor->terminal);
}
void
DumpVideoCSInterfaceDescriptorInputTerminal(
const usb_video_camera_input_terminal_descriptor* descriptor)
{
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Input Terminal)\n",
descriptor->descriptor_subtype);
printf(" Terminal ID ....... %u\n",
descriptor->terminal_id);
printf(" Terminal Type ..... 0x%04x (%s)\n",
descriptor->terminal_type,
TerminalTypeName(descriptor->terminal_type));
printf(" Terminal .......... %u\n",
descriptor->terminal);
if (descriptor->terminal_type == USB_VIDEO_CAMERA_IN)
{
printf(" Min. Focal length . %u\n",
descriptor->camera.objective_focal_length_min);
printf(" Max. Focal length . %u\n",
descriptor->camera.objective_focal_length_min);
printf(" Focal length ...... %u\n",
descriptor->camera.ocular_focal_length);
printf(" Controls .......... %02x%02x%02x\n",
descriptor->camera.controls[0],
descriptor->camera.controls[1],
descriptor->camera.controls[2]);
}
}
static const char*
ProcessingControlString(int index)
{
switch(index)
{
case 0:
return "Brightness, ";
case 1:
return "Contrast, ";
case 2:
return "Hue, ";
case 3:
return "Saturation, ";
case 4:
return "Sharpness, ";
case 5:
return "Gamma, ";
case 6:
return "White balance temp., ";
case 7:
return "White balance component, ";
case 8:
return "Backlight compensation, ";
case 9:
return "Gain, ";
case 10:
return "Power line frequency, ";
case 11:
return "Automatic hue, ";
case 12:
return "Automatic white balance temp., ";
case 13:
return "Automatic white balance component, ";
case 14:
return "Digital multiplier, ";
case 15:
return "Digital multiplier limit, ";
case 16:
return "Analog video standard, ";
case 17:
return "Analog video lock status, ";
case 18:
return "Automatic contrast, ";
default:
return "Unknown, ";
}
}
void
DumpVideoCSInterfaceDescriptorProcessingUnit(
const usb_video_processing_unit_descriptor* descriptor)
{
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Processing unit)\n",
descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n",
descriptor->unit_id);
printf(" Source ID ......... %u\n",
descriptor->source_id);
printf(" Max Multiplier .... %f\n",
descriptor->max_multiplier / 100.f);
printf(" Controls .......... ");
uint32_t controls = (descriptor->controls[0] << 16)
| (descriptor->controls[1] << 8)
| descriptor->controls[2];
for (int i = 0; i < 19; i++)
{
if (controls & (1 << (23 - i))) {
fputs(ProcessingControlString(i), stdout);
}
}
printf("\n");
printf(" Processing ........ %u\n",
descriptor->Processing());
printf(" Video Standards ... 0x%02x\n",
descriptor->VideoStandards().video_standards);
}
void
DumpVideoCSInterfaceDescriptorExtensionUnit(
const usb_generic_descriptor* descriptor)
{
uint8 i = 0;
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Extension unit)\n",
(uint8)descriptor->data[i++]);
printf(" Unit ID ........... %u\n",
(uint8)descriptor->data[i++]);
printf(" GUID .............. ");
for (i = 2; i < 16 + 2; i++)
printf("%02x ", descriptor->data[i]);
printf("\n");
printf(" Control count ..... %u\n",
(uint8)descriptor->data[i++]);
printf(" Input pins ........ ");
i = 20;
for (; i - 20 < descriptor->data[19]; i++)
printf("%u, ", descriptor->data[i]);
printf("\n");
printf(" Controls .......... ");
uint8_t end = descriptor->data[i++];
uint8_t start = i;
for (; i - start < end; i++)
printf("%02x", (uint8)descriptor->data[i]);
printf("\n");
printf(" Extension ......... %u\n",
(uint8)descriptor->data[i++]);
}
void
DumpVideoControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
{
uint8 descriptorSubtype = descriptor->data[0];
switch (descriptorSubtype) {
case USB_VIDEO_VC_HEADER:
DumpVideoCSInterfaceDescriptorHeader(
(usb_videocontrol_header_descriptor*)descriptor);
break;
case USB_VIDEO_VC_INPUT_TERMINAL:
DumpVideoCSInterfaceDescriptorInputTerminal(
(usb_video_camera_input_terminal_descriptor*)descriptor);
break;
case USB_VIDEO_VC_OUTPUT_TERMINAL:
DumpVideoCSInterfaceDescriptorOutputTerminal(
(usb_video_output_terminal_descriptor*)descriptor);
break;
case USB_VIDEO_VC_PROCESSING_UNIT:
DumpVideoCSInterfaceDescriptorProcessingUnit(
(usb_video_processing_unit_descriptor*)descriptor);
break;
case USB_VIDEO_VC_EXTENSION_UNIT:
DumpVideoCSInterfaceDescriptorExtensionUnit(descriptor);
break;
default:
DumpDescriptorData(descriptor);
}
}
void
DumpVideoControlCSInterruptEndpointDescriptor(const usb_generic_descriptor* descriptor)
{
printf(" Type .............. 0x%02x (Endpoint)\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Interrupt)\n",
(uint8)descriptor->data[0]);
printf(" Max Transfer Size . %u\n",
(uint16)((descriptor->data[1] << 8) | descriptor->data[2]));
}
void
DumpVideoControlCSEndpointDescriptor(const usb_generic_descriptor* descriptor)
{
uint8 descriptorSubtype = descriptor->data[0];
switch (descriptorSubtype) {
case EP_SUBTYPE_INTERRUPT:
DumpVideoControlCSInterruptEndpointDescriptor(descriptor);
break;
default:
DumpDescriptorData(descriptor);
}
}
void
DumpVideoStreamInputHeaderDescriptor(const usb_generic_descriptor* descriptor)
{
printf(" Type .............. 0x%02x (VideoStream Interface)\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Input header)\n",
(uint8)descriptor->data[0]);
printf(" Format count ...... %u\n",
(uint8)descriptor->data[1]);
printf(" Total length ...... %u\n",
(uint16)((descriptor->data[2] << 8) | descriptor->data[3]));
printf(" Endpoint .......... 0x%02x\n",
(uint8)descriptor->data[4]);
printf(" Info .............. 0x%02x\n",
(uint8)descriptor->data[5]);
printf(" Terminal Link ..... 0x%02x\n",
(uint8)descriptor->data[6]);
printf(" Still capture ..... 0x%02x\n",
(uint8)descriptor->data[7]);
printf(" Trigger support ... %u\n",
(uint8)descriptor->data[8]);
printf(" Trigger usage ..... %u\n",
(uint8)descriptor->data[9]);
uint8 nformat = descriptor->data[1];
uint8 formatsize = descriptor->data[10];
uint8 i, j;
for (i = 0; i < nformat; i++)
{
printf(" Format %2d ......... 0x", i);
for (j = 0; j < formatsize; j++)
printf("%02x", (uint8)descriptor->data[11 + i * formatsize + j]);
printf("\n");
}
}
void
DumpVideoStillImageDescriptor(const usb_generic_descriptor* descriptor)
{
printf(" Type .............. 0x%02x (VideoStream Interface)\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Still Image)\n",
(uint8)descriptor->data[0]);
printf(" Endpoint .......... %u\n",
(uint8)descriptor->data[1]);
uint8 npatterns = descriptor->data[2];
uint8 i;
printf(" Resolutions ....... ");
for (i = 0; i < npatterns; i++)
{
printf("%ux%u, ",
(uint16)((descriptor->data[i * 4 + 4] << 8) | (descriptor->data[i * 4 + 3])),
(uint16)((descriptor->data[i * 4 + 6] << 8) | (descriptor->data[i * 4 + 5])));
}
printf("\n");
i = i * 4 + 3;
npatterns = descriptor->data[i];
while (npatterns > 0)
{
printf(" Compression ....... %u\n",
(uint8)descriptor->data[i]);
npatterns--;
}
}
static const char*
VSInterfaceString(int subtype)
{
switch(subtype) {
case USB_VIDEO_VS_UNDEFINED:
return "Undefined";
case USB_VIDEO_VS_INPUT_HEADER:
return "Input header";
case USB_VIDEO_VS_OUTPUT_HEADER:
return "Output header";
case USB_VIDEO_VS_STILL_IMAGE_FRAME:
return "Still image";
case USB_VIDEO_VS_FORMAT_UNCOMPRESSED:
return "Uncompressed format";
case USB_VIDEO_VS_FRAME_UNCOMPRESSED:
return "Uncompressed frame";
case USB_VIDEO_VS_FORMAT_MJPEG:
return "MJPEG format";
case USB_VIDEO_VS_FRAME_MJPEG:
return "MJPEG frame";
case USB_VIDEO_VS_FORMAT_MPEG2TS:
return "MPEG2TS format";
case USB_VIDEO_VS_FORMAT_DV:
return "DV format";
case USB_VIDEO_VS_COLORFORMAT:
return "Color format";
case USB_VIDEO_VS_FORMAT_FRAME_BASED:
return "Frame based format";
case USB_VIDEO_VS_FRAME_FRAME_BASED:
return "Frame based frame";
case USB_VIDEO_VS_FORMAT_STREAM_BASED:
return "Stream based format";
case USB_VIDEO_VS_FORMAT_H264:
return "H264 format";
case USB_VIDEO_VS_FRAME_H264:
return "H264 frame";
case USB_VIDEO_VS_FORMAT_H264_SIMULCAST:
return "H264 simulcast";
case USB_VIDEO_VS_FORMAT_VP8:
return "VP8 format";
case USB_VIDEO_VS_FRAME_VP8:
return "VP8 frame";
case USB_VIDEO_VS_FORMAT_VP8_SIMULCAST:
return "VP8 simulcast";
default:
return "Unknown";
};
}
void
DumpVideoFormatDescriptor(const usb_generic_descriptor* descriptor)
{
printf(" Type .............. 0x%02x (VideoStream Interface)\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (%s)\n",
(uint8)descriptor->data[0], VSInterfaceString(descriptor->data[0]));
printf(" Index ............. 0x%02x\n",
(uint8)descriptor->data[1]);
printf(" Frame number ...... 0x%02x\n",
(uint8)descriptor->data[2]);
printf(" GUID .............. ");
for (uint8 i = 3; i < 16 + 3; i++)
printf("%02x ", descriptor->data[i]);
printf("\n");
printf(" Bits per pixel .... %u\n",
(uint8)descriptor->data[19]);
printf(" Default frame idx . 0x%02x\n",
(uint8)descriptor->data[20]);
printf(" Aspect ratio ...... %u:%u\n",
(uint8)descriptor->data[21], (uint8)descriptor->data[22]);
printf(" Interlace flags ... 0x%02x\n",
(uint8)descriptor->data[23]);
printf(" Copy protect ...... %u\n",
(uint8)descriptor->data[24]);
}
void
DumpVideoFrameDescriptor(const usb_video_frame_descriptor* descriptor)
{
printf(" Type .............. 0x%02x (VideoStream Interface)\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (%s)\n",
descriptor->descriptor_subtype,
VSInterfaceString(descriptor->descriptor_subtype));
printf(" Index ............. 0x%02x\n",
descriptor->frame_index);
printf(" Capabilities ...... 0x%02x\n",
descriptor->capabilities);
printf(" Resolution ........ %u x %u\n",
descriptor->width, descriptor->height);
printf(" Bit rates ......... %" B_PRIu32 " - %" B_PRIu32 "\n",
descriptor->min_bit_rate, descriptor->max_bit_rate);
printf(" Frame buffer size . %" B_PRIu32 "\n",
descriptor->max_video_frame_buffer_size);
printf(" Frame interval .... %.4fms\n",
descriptor->default_frame_interval / 10000.f);
for (uint8 i = 0; i < descriptor->frame_interval_type; i++)
{
printf(" Frame interval %2d . %.4fms\n",
i, descriptor->discrete_frame_intervals[i] / 10000.f);
}
}
static const char*
ColorPrimariesString(uint8_t value)
{
switch (value) {
case 0:
return "Unspecified";
case 1:
return "BT.709, sRGB";
case 2:
return "BT.470-2 (M)";
case 3:
return "BT.470-2 (B, G)";
case 4:
return "SMPTE 170M";
case 5:
return "SMPTE 240M";
default:
return "??";
}
}
static const char*
TransferCharacteristicsString(uint8_t value)
{
switch (value) {
case 0:
return "Unspecified";
case 1:
return "BT.709";
case 2:
return "BT.470-2 (M)";
case 3:
return "BT.470-2 (B, G)";
case 4:
return "SMPTE 170M";
case 5:
return "SMPTE 240M";
case 6:
return "Linear (V = Lc)";
case 7:
return "sRGB";
default:
return "??";
}
}
static const char*
MatrixCoefficientsString(uint8_t value)
{
switch (value) {
case 0:
return "Unspecified";
case 1:
return "BT.709";
case 2:
return "FCC";
case 3:
return "BT.470-2 (B, G)";
case 4:
return "SMPTE 170M (BT.601)";
case 5:
return "SMPTE 240M";
default:
return "??";
}
}
static void
DumpVideoStreamColorFormatDescriptor(const usb_video_color_matching_descriptor* descriptor)
{
printf(" Type ..................... 0x%02x (VideoStream Interface)\n",
descriptor->descriptor_type);
printf(" Subtype .................. 0x%02x (%s)\n",
descriptor->descriptor_sub_type,
VSInterfaceString(descriptor->descriptor_sub_type));
printf(" Color Primaries .......... 0x%02x (%s)\n",
descriptor->color_primaries,
ColorPrimariesString(descriptor->color_primaries));
printf(" Transfer characteristics . 0x%02x (%s)\n",
descriptor->transfer_characteristics,
TransferCharacteristicsString(descriptor->transfer_characteristics));
printf(" Matrix coefficients ...... 0x%02x (%s)\n",
descriptor->matrix_coefficients,
MatrixCoefficientsString(descriptor->matrix_coefficients));
}
void
DumpVideoStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
{
uint8 subtype = descriptor->data[0];
switch (subtype) {
case USB_VIDEO_VS_INPUT_HEADER:
DumpVideoStreamInputHeaderDescriptor(descriptor);
break;
case USB_VIDEO_VS_STILL_IMAGE_FRAME:
DumpVideoStillImageDescriptor(descriptor);
break;
case USB_VIDEO_VS_FORMAT_UNCOMPRESSED:
case USB_VIDEO_VS_FORMAT_MJPEG:
DumpVideoFormatDescriptor(descriptor);
break;
case USB_VIDEO_VS_FRAME_UNCOMPRESSED:
case USB_VIDEO_VS_FRAME_MJPEG:
DumpVideoFrameDescriptor((usb_video_frame_descriptor*)descriptor);
break;
case USB_VIDEO_VS_COLORFORMAT:
DumpVideoStreamColorFormatDescriptor((usb_video_color_matching_descriptor*)descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
}
void
DumpVideoDescriptor(const usb_generic_descriptor* descriptor, int subclass)
{
switch (subclass) {
case USB_VIDEO_INTERFACE_VIDEOCONTROL_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_VIDEO_CS_INTERFACE:
DumpVideoControlCSInterfaceDescriptor(descriptor);
break;
case USB_VIDEO_CS_ENDPOINT:
DumpVideoControlCSEndpointDescriptor(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
case USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_VIDEO_CS_INTERFACE:
DumpVideoStreamCSInterfaceDescriptor(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
case USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_VIDEO_CS_INTERFACE:
DumpDescriptorData(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
default:
DumpDescriptorData(descriptor);
break;
}
}