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:
@@ -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 {
|
||||||
|
|||||||
@@ -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 */
|
||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user