listusb: parse UVC devices

- Various cleanups to the USB-audio side, which is similar
- Add in the UVC (USB Video) specific info with parsing of some of the
  descriptors (most of the "control" part).
This commit is contained in:
Adrien Destugues
2016-11-02 15:26:04 +01:00
parent 56f749a63f
commit e64640878a
7 changed files with 565 additions and 21 deletions
+7 -7
View File
@@ -14,18 +14,18 @@ enum {
USB_AUDIO_INTERFACE_AUDIO_CLASS = 0x01 USB_AUDIO_INTERFACE_AUDIO_CLASS = 0x01
}; };
enum { // Audio Interface Subclasses enum { // Audio Interface Subclasses
USB_AUDIO_INTERFACE_UNDEFINED_SUBCLASS = 0x00, USB_AUDIO_INTERFACE_UNDEFINED_SUBCLASS = 0x00,
USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS = 0x01, USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS = 0x01,
USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS, // USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS,
USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS // USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS
}; };
enum { // Audio Interface Protocol Codes enum { // Audio Interface Protocol Codes
USB_AUDIO_PROTOCOL_UNDEFINED = 0x00 USB_AUDIO_PROTOCOL_UNDEFINED = 0x00
}; };
enum { // Audio Interface Protocol Codes enum { // Audio Interface Class-Specific Descriptor Types
USB_AUDIO_CS_UNDEFINED = 0x20, USB_AUDIO_CS_UNDEFINED = 0x20,
USB_AUDIO_CS_DEVICE = 0x21, USB_AUDIO_CS_DEVICE = 0x21,
USB_AUDIO_CS_CONFIGURATION = 0x22, USB_AUDIO_CS_CONFIGURATION = 0x22,
@@ -66,7 +66,7 @@ typedef struct {
struct { struct {
uint16 total_length; uint16 total_length;
uint8 in_collection; uint8 in_collection;
uint8 interface_numbers[1]; uint8 interface_numbers[0];
} _PACKED r1; } _PACKED r1;
struct { struct {
+142
View File
@@ -0,0 +1,142 @@
/*
* Copyright 2016, Adrien Destugues, [email protected]
* Distributed under terms of the MIT license.
*/
#ifndef USB_VIDEO_H
#define USB_VIDEO_H
// Based on specification for UVC version 1.5.
#include <SupportDefs.h>
#define USB_VIDEO_DEVICE_CLASS 0x0E
enum { // Video Interface Subclasses
USB_VIDEO_INTERFACE_UNDEFINED_SUBCLASS = 0x00,
USB_VIDEO_INTERFACE_VIDEOCONTROL_SUBCLASS = 0x01,
USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS,
USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS,
};
enum { // Video Interface Protocol Codes
USB_VIDEO_PROTOCOL_UNDEFINED = 0x00,
USB_VIDEO_PROTOCOL_15 = 0x01,
};
enum { // Video Interface Class-Specific Descriptor Types
USB_VIDEO_CS_UNDEFINED = 0x20,
USB_VIDEO_CS_DEVICE = 0x21,
USB_VIDEO_CS_CONFIGURATION = 0x22,
USB_VIDEO_CS_STRING = 0x23,
USB_VIDEO_CS_INTERFACE = 0x24,
USB_VIDEO_CS_ENDPOINT = 0x25,
};
enum { // Video Class-Specific VideoControl Interface descriptor subtypes
USB_VIDEO_VC_DESCRIPTOR_UNDEFINED = 0x00,
USB_VIDEO_VC_HEADER = 0x01,
USB_VIDEO_VC_INPUT_TERMINAL = 0x02,
USB_VIDEO_VC_OUTPUT_TERMINAL = 0x03,
USB_VIDEO_VC_SELECTOR_UNIT = 0x04,
USB_VIDEO_VC_PROCESSING_UNIT = 0x05,
USB_VIDEO_VC_EXTENSION_UNIT = 0x06,
USB_VIDEO_VC_ENCODING_UNIT = 0x07,
};
enum {
// USB Terminal Types
USB_VIDEO_VENDOR_USB_IO = 0x100,
USB_VIDEO_STREAMING_USB_IO = 0x101,
// Input terminal types
USB_VIDEO_VENDOR_IN = 0x200,
USB_VIDEO_CAMERA_IN = 0x201,
USB_VIDEO_MEDIA_TRANSPORT_IN = 0x202,
// Output terminal types
USB_VIDEO_VENDOR_OUT = 0x300,
USB_VIDEO_DISPLAY_OUT = 0x301,
USB_VIDEO_MEDIA_TRANSPORT_OUT = 0x302,
// External terminal types
USB_VIDEO_VENDOR_EXT = 0x400,
USB_VIDEO_COMPOSITE_EXT = 0x401,
USB_VIDEO_SVIDEO_EXT = 0x402,
USB_VIDEO_COMPONENT_EXT = 0x403,
};
// Class Specific Video Control Interface Header
// 1.5: Table 3-3 p.48
typedef struct {
uint8 length;
uint8 descriptor_type; // USB_AUDIO_CS_INTERFACE
uint8 descriptor_subtype; // USB_AUDIO_AC_HEADER
uint16 bcd_release_no;
uint16 total_length;
uint32 clock_frequency;
uint8 in_collection;
uint8 interface_numbers[0];
} _PACKED usb_videocontrol_header_descriptor;
// Input Terminal Descriptor
// 1.5: Table 3-4, page 50
typedef struct {
uint8 length;
uint8 descriptor_type; // USB_VIDEO_CS_INTERFACE
uint8 descriptor_subtype; // USB_VIDEO_VC_INPUT_TERMINAL
uint8 terminal_id;
uint16 terminal_type;
uint8 assoc_terminal;
uint8 terminal;
union {
struct {
uint16 focal_length_min;
uint16 focal_length_max;
uint16 focal_length;
uint8 control_size;
uint8 controls[3];
} _PACKED camera;
};
} _PACKED usb_video_input_terminal_descriptor;
// Output terminal descriptor
// 1.5: Table 3-5, page 51
typedef struct {
uint8 length;
uint8 descriptor_type; // USB_VIDEO_CS_INTERFACE
uint8 descriptor_subtype; // USB_VIDEO_VC_OUTPUT_TERMINAL
uint8 terminal_id;
uint16 terminal_type;
uint8 assoc_terminal;
uint8 source_id;
uint8 terminal;
} _PACKED usb_video_output_terminal_descriptor;
// Processing unit descriptor
// 1.5: Table 3-8, page 54
typedef struct {
uint8 length;
uint8 descriptor_type;
uint8 descriptor_subtype;
uint8 unit_id;
uint8 source_id;
uint16 max_multiplier;
uint8 control_size;
uint8 controls[3];
uint8 processing;
uint8 video_standards;
} _PACKED usb_video_processing_unit_descriptor;
#endif /* !USB_VIDEO_H */
+1
View File
@@ -6,6 +6,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel bus_managers usb ] ;
BinCommand listusb : BinCommand listusb :
listusb.cpp listusb.cpp
usb_audio.cpp usb_audio.cpp
usb_video.cpp
: be libdevice.so ; : be libdevice.so ;
# Manually reference generated headers # Manually reference generated headers
+72 -11
View File
@@ -10,20 +10,22 @@
#include <Entry.h> #include <Entry.h>
#include <Path.h> #include <Path.h>
#include <String.h> #include <String.h>
#include <USBKit.h>
#include <stdio.h> #include <stdio.h>
#include <usb/USB_audio.h> #include <usb/USB_audio.h>
#include <usb/USB_video.h>
#include "usbspec_private.h" #include "usbspec_private.h"
#include "usb-utils.h" #include "usb-utils.h"
#include "listusb.h"
const char* const char*
ClassName(int classNumber) { ClassName(int classNumber) {
switch (classNumber) { switch (classNumber) {
case 0: case 0:
return "Per-interface classes"; return "Per-interface classes";
case 1: case USB_AUDIO_DEVICE_CLASS:
return "Audio"; return "Audio";
case 2: case 2:
return "Communication"; return "Communication";
@@ -45,7 +47,7 @@ ClassName(int classNumber) {
return "Smart card"; return "Smart card";
case 13: case 13:
return "Content security"; return "Content security";
case 14: case USB_VIDEO_DEVICE_CLASS:
return "Video"; return "Video";
case 15: case 15:
return "Personal Healthcare"; return "Personal Healthcare";
@@ -65,7 +67,58 @@ ClassName(int classNumber) {
} }
void DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass); const char*
SubclassName(int classNumber, int subclass)
{
if (classNumber == 0xEF) {
if (subclass == 0x02)
return " (Common)";
}
if (classNumber == USB_VIDEO_DEVICE_CLASS) {
switch (subclass) {
case USB_VIDEO_INTERFACE_UNDEFINED_SUBCLASS:
return " (Undefined)";
case USB_VIDEO_INTERFACE_VIDEOCONTROL_SUBCLASS:
return " (Control)";
case USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS:
return " (Streaming)";
case USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS:
return " (Collection)";
}
}
return "";
}
const char*
ProtocolName(int classNumber, int subclass, int protocol)
{
switch (classNumber) {
case 0x09:
if (subclass == 0x00)
{
switch (protocol) {
case 0x00:
return " (Full speed)";
case 0x01:
return " (Hi-speed, single TT)";
case 0x02:
return " (Hi-speed, multiple TT)";
case 0x03:
return " (Super speed)";
}
}
case 0xE0:
if (subclass == 0x01 && protocol == 0x01)
return " (Bluetooth)";
case 0xEF:
if (subclass == 0x02 && protocol == 0x01)
return " (Interface Association)";
break;
}
return "";
}
void void
@@ -90,6 +143,9 @@ DumpDescriptor(const usb_generic_descriptor* descriptor,
case USB_AUDIO_DEVICE_CLASS: case USB_AUDIO_DEVICE_CLASS:
DumpAudioDescriptor(descriptor, subclass); DumpAudioDescriptor(descriptor, subclass);
break; break;
case USB_VIDEO_DEVICE_CLASS:
DumpVideoDescriptor(descriptor, subclass);
break;
default: default:
DumpDescriptorData(descriptor); DumpDescriptorData(descriptor);
break; break;
@@ -105,10 +161,12 @@ DumpInterface(const BUSBInterface* interface)
printf(" Class .............. 0x%02x (%s)\n", printf(" Class .............. 0x%02x (%s)\n",
interface->Class(), ClassName(interface->Class())); interface->Class(), ClassName(interface->Class()));
printf(" Subclass ........... 0x%02x\n", printf(" Subclass ........... 0x%02x%s\n",
interface->Subclass()); interface->Subclass(),
printf(" Protocol ........... 0x%02x\n", SubclassName(interface->Class(), interface->Subclass()));
interface->Protocol()); printf(" Protocol ........... 0x%02x%s\n",
interface->Protocol(), ProtocolName(interface->Class(),
interface->Subclass(), interface->Protocol()));
printf(" Interface String ... \"%s\"\n", printf(" Interface String ... \"%s\"\n",
interface->InterfaceString()); interface->InterfaceString());
@@ -190,10 +248,13 @@ DumpInfo(BUSBDevice& device, bool verbose)
printf("[Device /dev/bus/usb%s]\n", device.Location()); printf("[Device /dev/bus/usb%s]\n", device.Location());
printf(" Class .................. 0x%02x (%s)\n", device.Class(), printf(" Class .................. 0x%02x (%s)\n", device.Class(),
ClassName(device.Class())); ClassName(device.Class()));
printf(" Subclass ............... 0x%02x\n", device.Subclass()); printf(" Subclass ............... 0x%02x%s\n", device.Subclass(),
printf(" Protocol ............... 0x%02x\n", device.Protocol()); SubclassName(device.Class(), device.Subclass()));
printf(" Protocol ............... 0x%02x%s\n", device.Protocol(),
ProtocolName(device.Class(), device.Subclass(), device.Protocol()));
printf(" Max Endpoint 0 Packet .. %d\n", device.MaxEndpoint0PacketSize()); printf(" Max Endpoint 0 Packet .. %d\n", device.MaxEndpoint0PacketSize());
printf(" USB Version ............ 0x%04x\n", device.USBVersion()); uint32_t version = device.USBVersion();
printf(" USB Version ............ %d.%d\n", version >> 8, version & 0xFF);
printf(" Vendor ID .............. 0x%04x", device.VendorID()); printf(" Vendor ID .............. 0x%04x", device.VendorID());
if (vendorName != NULL) if (vendorName != NULL)
printf(" (%s)", vendorName); printf(" (%s)", vendorName);
+5
View File
@@ -11,8 +11,13 @@
#define LISTUSB_H #define LISTUSB_H
#include <USBKit.h>
void DumpDescriptorData(const usb_generic_descriptor* descriptor); void DumpDescriptorData(const usb_generic_descriptor* descriptor);
void DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass); void DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass);
void DumpVideoDescriptor(const usb_generic_descriptor* descriptor, int subclass);
#endif /* !LISTUSB_H */ #endif /* !LISTUSB_H */
+18 -3
View File
@@ -19,10 +19,12 @@ void
DumpAudioCSInterfaceDescriptorHeader( DumpAudioCSInterfaceDescriptorHeader(
const usb_audiocontrol_header_descriptor* descriptor) const usb_audiocontrol_header_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Header)\n", printf(" Subtype ........... 0x%02x (Header)\n",
descriptor->descriptor_subtype); descriptor->descriptor_subtype);
printf(" bcdADC Release date 0x%04x\n", printf(" ADC Release ....... %d.%d\n",
descriptor->bcd_release_no); descriptor->bcd_release_no >> 8, descriptor->bcd_release_no & 0xFF);
printf(" Total Length ...... %u\n", printf(" Total Length ...... %u\n",
descriptor->r1.total_length); descriptor->r1.total_length);
printf(" Interfaces ........ "); printf(" Interfaces ........ ");
@@ -81,7 +83,7 @@ DumpChannelConfig(uint32 wChannelConfig)
} }
const char* static const char*
TerminalTypeName(uint16 terminalType) TerminalTypeName(uint16 terminalType)
{ {
switch (terminalType) { switch (terminalType) {
@@ -138,6 +140,8 @@ void
DumpAudioCSInterfaceDescriptorInputTerminal( DumpAudioCSInterfaceDescriptorInputTerminal(
const usb_audio_input_terminal_descriptor* descriptor) const usb_audio_input_terminal_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Input Terminal)\n", printf(" Subtype ........... 0x%02x (Input Terminal)\n",
descriptor->descriptor_subtype); descriptor->descriptor_subtype);
printf(" Terminal ID ....... %u\n", printf(" Terminal ID ....... %u\n",
@@ -164,6 +168,8 @@ void
DumpAudioCSInterfaceDescriptorOutputTerminal( DumpAudioCSInterfaceDescriptorOutputTerminal(
const usb_audio_output_terminal_descriptor* descriptor) const usb_audio_output_terminal_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Output Terminal)\n", printf(" Subtype ........... 0x%02x (Output Terminal)\n",
descriptor->descriptor_subtype); descriptor->descriptor_subtype);
printf(" Terminal ID ....... %u\n", printf(" Terminal ID ....... %u\n",
@@ -184,6 +190,8 @@ void
DumpAudioCSInterfaceDescriptorMixerUnit( DumpAudioCSInterfaceDescriptorMixerUnit(
const usb_audio_mixer_unit_descriptor* descriptor) const usb_audio_mixer_unit_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Mixer Unit)\n", printf(" Subtype ........... 0x%02x (Mixer Unit)\n",
descriptor->descriptor_subtype); descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n", printf(" Unit ID ........... %u\n",
@@ -222,6 +230,8 @@ void
DumpAudioCSInterfaceDescriptorSelectorUnit( DumpAudioCSInterfaceDescriptorSelectorUnit(
const usb_audio_selector_unit_descriptor* descriptor) const usb_audio_selector_unit_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Selector Unit)\n", printf(" Subtype ........... 0x%02x (Selector Unit)\n",
descriptor->descriptor_subtype); descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n", printf(" Unit ID ........... %u\n",
@@ -275,6 +285,8 @@ void
DumpAudioCSInterfaceDescriptorFeatureUnit( DumpAudioCSInterfaceDescriptorFeatureUnit(
const usb_audio_feature_unit_descriptor* descriptor) const usb_audio_feature_unit_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Feature Unit)\n", printf(" Subtype ........... 0x%02x (Feature Unit)\n",
descriptor->descriptor_subtype); descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n", printf(" Unit ID ........... %u\n",
@@ -316,6 +328,8 @@ void
DumpAudioCSInterfaceDescriptorAssociated( DumpAudioCSInterfaceDescriptorAssociated(
const usb_generic_descriptor* descriptor) const usb_generic_descriptor* descriptor)
{ {
printf(" Type .............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (Associate Interface)\n", printf(" Subtype ........... 0x%02x (Associate Interface)\n",
(uint8)descriptor->data[0]); (uint8)descriptor->data[0]);
printf(" Interface ......... %u\n", printf(" Interface ......... %u\n",
@@ -324,6 +338,7 @@ DumpAudioCSInterfaceDescriptorAssociated(
printf(" Data .............. "); printf(" Data .............. ");
for (uint8 i = 0; i < descriptor->length - 2; i++) for (uint8 i = 0; i < descriptor->length - 2; i++)
printf("%02x ", descriptor->data[i]); printf("%02x ", descriptor->data[i]);
printf("\n");
} }
+320
View File
@@ -0,0 +1,320 @@
/*
* Copyright 2016, Adrien Destugues, [email protected]
* 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->assoc_terminal);
printf(" Source ID ......... %u\n",
descriptor->source_id);
printf(" Terminal .......... %u\n",
descriptor->terminal);
}
void
DumpVideoCSInterfaceDescriptorInputTerminal(
const usb_video_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.focal_length_min);
printf(" Max. Focal length . %u\n",
descriptor->camera.focal_length_min);
printf(" Focal length ...... %u\n",
descriptor->camera.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))) {
printf(ProcessingControlString(i));
}
}
printf("\n");
printf(" Processing ........ %u\n",
descriptor->processing);
printf(" Video Standards ... 0x%02x\n",
descriptor->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; // Skip the input pin count
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_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
DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor);
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;
default:
DumpDescriptorData(descriptor);
break;
}
break;
case USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_VIDEO_CS_INTERFACE:
DumpAudioStreamCSInterfaceDescriptor(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
case USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_VIDEO_CS_INTERFACE:
// TODO
DumpDescriptorData(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
default:
DumpDescriptorData(descriptor);
break;
}
}