[haiku-commits] haiku: hrev50651 - src/bin/listusb src/bin headers/os/drivers/usb

  • From: pulkomandy@xxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 2 Nov 2016 15:26:34 +0100 (CET)

hrev50651 adds 3 changesets to branch 'master'
old head: 5abeb2b498599fc04956deea3dbd0a798cfe4b1f
new head: 12431ebff49970922ce0125bac58784467ecb39b
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=12431ebff499+%5E5abeb2b49859

----------------------------------------------------------------------------

56f749a63f63: listusb: split out USB audio dumping to own file.
  
  The code to dump audio descriptors is now twice as long as the other
  parts of the listusb code. Move it to its own file for clarity.

e64640878a71: 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).

12431ebff499: listusb: dump video streams from UVC devices.

                             [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

8 files changed, 1195 insertions(+), 315 deletions(-)
headers/os/drivers/usb/USB_audio.h             |  14 +-
headers/os/drivers/usb/USB_video.h             | 198 ++++++++
src/bin/Jamfile                                |   8 +-
src/bin/listusb/Jamfile                        |  18 +
src/bin/listusb/listusb.cpp                    | 372 ++++++++++++++
src/bin/listusb/listusb.h                      |  23 +
src/bin/{listusb.cpp => listusb/usb_audio.cpp} | 322 +-----------
src/bin/listusb/usb_video.cpp                  | 555 +++++++++++++++++++++

############################################################################

Commit:      56f749a63f63f30bdc3ee15c5ce07717be9da7cc
URL:         http://cgit.haiku-os.org/haiku/commit/?id=56f749a63f63
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Tue Nov  1 10:17:31 2016 UTC

listusb: split out USB audio dumping to own file.

The code to dump audio descriptors is now twice as long as the other
parts of the listusb code. Move it to its own file for clarity.

----------------------------------------------------------------------------

diff --git a/src/bin/Jamfile b/src/bin/Jamfile
index db293aa..18d4281 100644
--- a/src/bin/Jamfile
+++ b/src/bin/Jamfile
@@ -212,16 +212,9 @@ StdBinCommands
 
 # standard commands that need libbe.so, libdevice.so
 StdBinCommands
-       listusb.cpp
        setusbconfig.cpp
        : be libdevice.so : $(haiku-utils_rsrc) ;
 
-ObjectHdrs [ FGristFiles listusb$(SUFOBJ) ]
-       : [ FDirName $(SUBDIR) $(DOTDOT) add-ons kernel bus_managers usb ]
-               [ FDirName 
$(TARGET_COMMON_DEBUG_OBJECT_DIR_$(TARGET_PACKAGING_ARCH))
-                       apps devices ] ;
-Includes [ FGristFiles listusb.cpp ] : <src!apps!devices>usbhdr.h ;
-
 # standard commands that need libbluetooth.so, due the Bluetooth Kit
 StdBinCommands
        bt_dev_info.cpp
@@ -272,6 +265,7 @@ SubInclude HAIKU_TOP src bin ideinfo ;
 SubInclude HAIKU_TOP src bin keymap ;
 SubInclude HAIKU_TOP src bin keystore ;
 SubInclude HAIKU_TOP src bin listdev ;
+SubInclude HAIKU_TOP src bin listusb ;
 SubInclude HAIKU_TOP src bin locale ;
 SubInclude HAIKU_TOP src bin makebootable ;
 #SubInclude HAIKU_TOP src bin makeudfimage ;
diff --git a/src/bin/listusb/Jamfile b/src/bin/listusb/Jamfile
new file mode 100644
index 0000000..ed14442
--- /dev/null
+++ b/src/bin/listusb/Jamfile
@@ -0,0 +1,17 @@
+SubDir HAIKU_TOP src bin listusb ;
+
+UsePrivateHeaders shared usb ;
+UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel bus_managers usb ] ;
+
+BinCommand listusb :
+       listusb.cpp
+       usb_audio.cpp
+       : be libdevice.so ;
+
+# Manually reference generated headers
+ObjectHdrs [ FGristFiles listusb$(SUFOBJ) ]
+       :
+               [ FDirName 
$(TARGET_COMMON_DEBUG_OBJECT_DIR_$(TARGET_PACKAGING_ARCH))
+                       apps devices ] ;
+Includes [ FGristFiles listusb.cpp ] : <src!apps!devices>usbhdr.h ;
+
diff --git a/src/bin/listusb/listusb.cpp b/src/bin/listusb/listusb.cpp
new file mode 100644
index 0000000..107ca51
--- /dev/null
+++ b/src/bin/listusb/listusb.cpp
@@ -0,0 +1,311 @@
+/*
+ * Originally released under the Be Sample Code License.
+ * Copyright 2000, Be Incorporated. All rights reserved.
+ *
+ * Modified for Haiku by François Revol and Michael Lotz.
+ * Copyright 2007-2008, Haiku Inc. All rights reserved.
+ */
+
+#include <Directory.h>
+#include <Entry.h>
+#include <Path.h>
+#include <String.h>
+#include <USBKit.h>
+#include <stdio.h>
+#include <usb/USB_audio.h>
+
+#include "usbspec_private.h"
+#include "usb-utils.h"
+
+
+const char*
+ClassName(int classNumber) {
+       switch (classNumber) {
+               case 0:
+                       return "Per-interface classes";
+               case 1:
+                       return "Audio";
+               case 2:
+                       return "Communication";
+               case 3:
+                       return "HID";
+               case 5:
+                       return "Physical";
+               case 6:
+                       return "Image";
+               case 7:
+                       return "Printer";
+               case 8:
+                       return "Mass storage";
+               case 9:
+                       return "Hub";
+               case 10:
+                       return "CDC-Data";
+               case 11:
+                       return "Smart card";
+               case 13:
+                       return "Content security";
+               case 14:
+                       return "Video";
+               case 15:
+                       return "Personal Healthcare";
+               case 0xDC:
+                       return "Diagnostic device";
+               case 0xE0:
+                       return "Wireless controller";
+               case 0xEF:
+                       return "Miscellaneous";
+               case 0xFE:
+                       return "Application specific";
+               case 0xFF:
+                       return "Vendor specific";
+       }
+
+       return "Unknown";
+}
+
+
+void DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int 
subclass);
+
+
+void
+DumpDescriptorData(const usb_generic_descriptor* descriptor)
+{
+       printf("                    Type ............. 0x%02x\n",
+               descriptor->descriptor_type);
+
+       printf("                    Data ............. ");
+       // len includes len and descriptor_type field
+       for (int32 i = 0; i < descriptor->length - 2; i++)
+               printf("%02x ", descriptor->data[i]);
+       printf("\n");
+}
+
+
+void
+DumpDescriptor(const usb_generic_descriptor* descriptor,
+       int classNum, int subclass)
+{
+       switch (classNum) {
+               case USB_AUDIO_DEVICE_CLASS:
+                       DumpAudioDescriptor(descriptor, subclass);
+                       break;
+               default:
+                       DumpDescriptorData(descriptor);
+                       break;
+       }
+}
+
+
+static void
+DumpInterface(const BUSBInterface* interface)
+{
+       if (!interface)
+               return;
+
+       printf("                Class .............. 0x%02x (%s)\n",
+               interface->Class(), ClassName(interface->Class()));
+       printf("                Subclass ........... 0x%02x\n",
+               interface->Subclass());
+       printf("                Protocol ........... 0x%02x\n",
+               interface->Protocol());
+       printf("                Interface String ... \"%s\"\n",
+               interface->InterfaceString());
+
+       for (uint32 i = 0; i < interface->CountEndpoints(); i++) {
+               const BUSBEndpoint* endpoint = interface->EndpointAt(i);
+               if (!endpoint)
+                       continue;
+
+               printf("                [Endpoint %" B_PRIu32 "]\n", i);
+               printf("                    MaxPacketSize .... %d\n",
+                       endpoint->MaxPacketSize());
+               printf("                    Interval ......... %d\n",
+                       endpoint->Interval());
+
+               if (endpoint->IsControl())
+                       printf("                    Type ............. 
Control\n");
+               else if (endpoint->IsBulk())
+                       printf("                    Type ............. Bulk\n");
+               else if (endpoint->IsIsochronous())
+                       printf("                    Type ............. 
Isochronous\n");
+               else if (endpoint->IsInterrupt())
+                       printf("                    Type ............. 
Interrupt\n");
+
+               if (endpoint->IsInput())
+                       printf("                    Direction ........ 
Input\n");
+               else
+                       printf("                    Direction ........ 
Output\n");
+       }
+
+       char buffer[256];
+       usb_descriptor* generic = (usb_descriptor*)buffer;
+       for (uint32 i = 0;
+                       interface->OtherDescriptorAt(i, generic, 256) == B_OK; 
i++) {
+               printf("                [Descriptor %" B_PRIu32 "]\n", i);
+               DumpDescriptor(&generic->generic, interface->Class(), 
interface->Subclass());
+       }
+}
+
+
+static void
+DumpConfiguration(const BUSBConfiguration* configuration)
+{
+       if (!configuration)
+               return;
+
+       printf("        Configuration String . \"%s\"\n",
+               configuration->ConfigurationString());
+       for (uint32 i = 0; i < configuration->CountInterfaces(); i++) {
+               printf("        [Interface %" B_PRIu32 "]\n", i);
+               const BUSBInterface* interface = configuration->InterfaceAt(i);
+
+               for (uint32 j = 0; j < interface->CountAlternates(); j++) {
+                       const BUSBInterface* alternate = 
interface->AlternateAt(j);
+                       printf("            [Alternate %" B_PRIu32 "%s]\n", j,
+                               j == interface->AlternateIndex() ? " active" : 
"");
+                       DumpInterface(alternate);
+               }
+       }
+}
+
+
+static void
+DumpInfo(BUSBDevice& device, bool verbose)
+{
+       const char* vendorName = NULL;
+       const char* deviceName = NULL;
+       usb_get_vendor_info(device.VendorID(), &vendorName);
+       usb_get_device_info(device.VendorID(), device.ProductID(), &deviceName);
+
+       if (!verbose) {
+               printf("%04x:%04x /dev/bus/usb%s \"%s\" \"%s\" ver. %04x\n",
+                       device.VendorID(), device.ProductID(), 
device.Location(),
+                       vendorName ? vendorName : device.ManufacturerString(),
+                       deviceName ? deviceName : device.ProductString(),
+                       device.Version());
+               return;
+       }
+
+       printf("[Device /dev/bus/usb%s]\n", device.Location());
+       printf("    Class .................. 0x%02x (%s)\n", device.Class(),
+               ClassName(device.Class()));
+       printf("    Subclass ............... 0x%02x\n", device.Subclass());
+       printf("    Protocol ............... 0x%02x\n", device.Protocol());
+       printf("    Max Endpoint 0 Packet .. %d\n", 
device.MaxEndpoint0PacketSize());
+       printf("    USB Version ............ 0x%04x\n", device.USBVersion());
+       printf("    Vendor ID .............. 0x%04x", device.VendorID());
+       if (vendorName != NULL)
+               printf(" (%s)", vendorName);
+       printf("\n    Product ID ............. 0x%04x", device.ProductID());
+       if (deviceName != NULL)
+               printf(" (%s)", deviceName);
+       printf("\n    Product Version ........ 0x%04x\n", device.Version());
+       printf("    Manufacturer String .... \"%s\"\n", 
device.ManufacturerString());
+       printf("    Product String ......... \"%s\"\n", device.ProductString());
+       printf("    Serial Number .......... \"%s\"\n", 
device.SerialNumberString());
+
+       for (uint32 i = 0; i < device.CountConfigurations(); i++) {
+               printf("    [Configuration %" B_PRIu32 "]\n", i);
+               DumpConfiguration(device.ConfigurationAt(i));
+       }
+
+       if (device.Class() != 0x09)
+               return;
+
+       usb_hub_descriptor hubDescriptor;
+       size_t size = device.GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
+               (void*)&hubDescriptor, sizeof(usb_hub_descriptor));
+       if (size == sizeof(usb_hub_descriptor)) {
+               printf("    Hub ports count......... %d\n", 
hubDescriptor.num_ports);
+               printf("    Hub Controller Current.. %dmA\n", 
hubDescriptor.max_power);
+
+               for (int index = 1; index <= hubDescriptor.num_ports; index++) {
+                       usb_port_status portStatus;
+                       size_t actualLength = 
device.ControlTransfer(USB_REQTYPE_CLASS
+                               | USB_REQTYPE_OTHER_IN, USB_REQUEST_GET_STATUS, 
0,
+                               index, sizeof(portStatus), (void*)&portStatus);
+                       if (actualLength != sizeof(portStatus))
+                               continue;
+                       printf("      Port %d status....... 
%04x.%04x%s%s%s%s%s%s%s%s%s\n",
+                               index, portStatus.status, portStatus.change,
+                               portStatus.status & PORT_STATUS_CONNECTION ? " 
Connect": "",
+                               portStatus.status & PORT_STATUS_ENABLE ? " 
Enable": "",
+                               portStatus.status & PORT_STATUS_SUSPEND ? " 
Suspend": "",
+                               portStatus.status & PORT_STATUS_OVER_CURRENT ? 
" Overcurrent": "",
+                               portStatus.status & PORT_STATUS_RESET ? " 
Reset": "",
+                               portStatus.status & PORT_STATUS_POWER ? " 
Power": "",
+                               portStatus.status & PORT_STATUS_CONNECTION
+                                       ? (portStatus.status & 
PORT_STATUS_LOW_SPEED ? " Lowspeed"
+                                       : (portStatus.status & 
PORT_STATUS_HIGH_SPEED ? " Highspeed"
+                                               : " Fullspeed")) : "",
+                               portStatus.status & PORT_STATUS_TEST ? " Test": 
"",
+                               portStatus.status & PORT_STATUS_INDICATOR ? " 
Indicator": "");
+               }
+       }
+}
+
+
+class DumpRoster : public BUSBRoster {
+public:
+                                       DumpRoster(bool verbose)
+                                               :       fVerbose(verbose)
+                                       {
+                                       }
+
+
+virtual        status_t        DeviceAdded(BUSBDevice* device)
+                                       {
+                                               DumpInfo(*device, fVerbose);
+                                               return B_OK;
+                                       }
+
+
+virtual        void            DeviceRemoved(BUSBDevice* device)
+                                       {
+                                       }
+
+private:
+               bool            fVerbose;
+};
+
+
+
+int
+main(int argc, char* argv[])
+{
+       bool verbose = false;
+       BString devname = "";
+       for (int i = 1; i < argc; i++) {
+               if (argv[i][0] == '-') {
+                       if (argv[i][1] == 'v')
+                               verbose = true;
+                       else {
+                               printf("Usage: listusb [-v] [device]\n\n");
+                               printf("-v: Show more detailed information 
including "
+                                       "interfaces, configurations, etc.\n\n");
+                               printf("If a device is not specified, "
+                                       "all devices found on the bus will be 
listed\n");
+                               return 1;
+                       }
+               } else
+                       devname = argv[i];
+       }
+
+       if (devname.Length() > 0) {
+               BUSBDevice device(devname.String());
+               if (device.InitCheck() < B_OK) {
+                       printf("Cannot open USB device: %s\n", 
devname.String());
+                       return 1;
+               } else {
+                               DumpInfo(device, verbose);
+                               return 0;
+               }
+       } else {
+               DumpRoster roster(verbose);
+               roster.Start();
+               roster.Stop();
+       }
+
+       return 0;
+}
diff --git a/src/bin/listusb/listusb.h b/src/bin/listusb/listusb.h
new file mode 100644
index 0000000..27ae00a
--- /dev/null
+++ b/src/bin/listusb/listusb.h
@@ -0,0 +1,18 @@
+/*
+ * Originally released under the Be Sample Code License.
+ * Copyright 2000, Be Incorporated. All rights reserved.
+ *
+ * Modified for Haiku by François Revol and Michael Lotz.
+ * Copyright 2007-2016, Haiku Inc. All rights reserved.
+ */
+
+
+#ifndef LISTUSB_H
+#define LISTUSB_H
+
+
+void DumpDescriptorData(const usb_generic_descriptor* descriptor);
+void DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int 
subclass);
+
+
+#endif /* !LISTUSB_H */
diff --git a/src/bin/listusb.cpp b/src/bin/listusb/usb_audio.cpp
similarity index 75%
rename from src/bin/listusb.cpp
rename to src/bin/listusb/usb_audio.cpp
index bc1f29b..58c11eb 100644
--- a/src/bin/listusb.cpp
+++ b/src/bin/listusb/usb_audio.cpp
@@ -3,83 +3,17 @@
  * Copyright 2000, Be Incorporated. All rights reserved.
  *
  * Modified for Haiku by François Revol and Michael Lotz.
- * Copyright 2007-2008, Haiku Inc. All rights reserved.
+ * Copyright 2007-2016, Haiku Inc. All rights reserved.
  */
 
-#include <Directory.h>
-#include <Entry.h>
 #include <MediaDefs.h>
-#include <Path.h>
-#include <String.h>
 #include <USBKit.h>
 #include <stdio.h>
+
 #include <usb/USB_audio.h>
 #include <usb/USB_midi.h>
 
-#include "usbspec_private.h"
-#include "usb-utils.h"
-
-
-const char*
-ClassName(int classNumber) {
-       switch (classNumber) {
-               case 0:
-                       return "Per-interface classes";
-               case 1:
-                       return "Audio";
-               case 2:
-                       return "Communication";
-               case 3:
-                       return "HID";
-               case 5:
-                       return "Physical";
-               case 6:
-                       return "Image";
-               case 7:
-                       return "Printer";
-               case 8:
-                       return "Mass storage";
-               case 9:
-                       return "Hub";
-               case 10:
-                       return "CDC-Data";
-               case 11:
-                       return "Smart card";
-               case 13:
-                       return "Content security";
-               case 14:
-                       return "Video";
-               case 15:
-                       return "Personal Healthcare";
-               case 0xDC:
-                       return "Diagnostic device";
-               case 0xE0:
-                       return "Wireless controller";
-               case 0xEF:
-                       return "Miscellaneous";
-               case 0xFE:
-                       return "Application specific";
-               case 0xFF:
-                       return "Vendor specific";
-       }
-
-       return "Unknown";
-}
-
-
-void
-DumpDescriptorData(const usb_generic_descriptor* descriptor)
-{
-       printf("                    Type ............. 0x%02x\n",
-               descriptor->descriptor_type);
-
-       printf("                    Data ............. ");
-       // len includes len and descriptor_type field
-       for (int32 i = 0; i < descriptor->length - 2; i++)
-               printf("%02x ", descriptor->data[i]);
-       printf("\n");
-}
-
+#include "listusb.h"
 
 void
 DumpAudioCSInterfaceDescriptorHeader(
@@ -965,232 +899,3 @@ DumpAudioDescriptor(const usb_generic_descriptor* 
descriptor, int subclass)
                        break;
        }
 }
-
-
-void
-DumpDescriptor(const usb_generic_descriptor* descriptor,
-       int classNum, int subclass)
-{
-       switch (classNum) {
-               case USB_AUDIO_DEVICE_CLASS:
-                       DumpAudioDescriptor(descriptor, subclass);
-                       break;
-               default:
-                       DumpDescriptorData(descriptor);
-                       break;
-       }
-}
-
-
-static void
-DumpInterface(const BUSBInterface* interface)
-{
-       if (!interface)
-               return;
-
-       printf("                Class .............. 0x%02x (%s)\n",
-               interface->Class(), ClassName(interface->Class()));
-       printf("                Subclass ........... 0x%02x\n",
-               interface->Subclass());
-       printf("                Protocol ........... 0x%02x\n",
-               interface->Protocol());
-       printf("                Interface String ... \"%s\"\n",
-               interface->InterfaceString());
-
-       for (uint32 i = 0; i < interface->CountEndpoints(); i++) {
-               const BUSBEndpoint* endpoint = interface->EndpointAt(i);
-               if (!endpoint)
-                       continue;
-
-               printf("                [Endpoint %" B_PRIu32 "]\n", i);
-               printf("                    MaxPacketSize .... %d\n",
-                       endpoint->MaxPacketSize());
-               printf("                    Interval ......... %d\n",
-                       endpoint->Interval());
-
-               if (endpoint->IsControl())
-                       printf("                    Type ............. 
Control\n");
-               else if (endpoint->IsBulk())
-                       printf("                    Type ............. Bulk\n");
-               else if (endpoint->IsIsochronous())
-                       printf("                    Type ............. 
Isochronous\n");
-               else if (endpoint->IsInterrupt())
-                       printf("                    Type ............. 
Interrupt\n");
-
-               if (endpoint->IsInput())
-                       printf("                    Direction ........ 
Input\n");
-               else
-                       printf("                    Direction ........ 
Output\n");
-       }
-
-       char buffer[256];
-       usb_descriptor* generic = (usb_descriptor*)buffer;
-       for (uint32 i = 0;
-                       interface->OtherDescriptorAt(i, generic, 256) == B_OK; 
i++) {
-               printf("                [Descriptor %" B_PRIu32 "]\n", i);
-               DumpDescriptor(&generic->generic, interface->Class(), 
interface->Subclass());
-       }
-}
-
-
-static void
-DumpConfiguration(const BUSBConfiguration* configuration)
-{
-       if (!configuration)
-               return;
-
-       printf("        Configuration String . \"%s\"\n",
-               configuration->ConfigurationString());
-       for (uint32 i = 0; i < configuration->CountInterfaces(); i++) {
-               printf("        [Interface %" B_PRIu32 "]\n", i);
-               const BUSBInterface* interface = configuration->InterfaceAt(i);
-
-               for (uint32 j = 0; j < interface->CountAlternates(); j++) {
-                       const BUSBInterface* alternate = 
interface->AlternateAt(j);
-                       printf("            [Alternate %" B_PRIu32 "%s]\n", j,
-                               j == interface->AlternateIndex() ? " active" : 
"");
-                       DumpInterface(alternate);
-               }
-       }
-}
-
-
-static void
-DumpInfo(BUSBDevice& device, bool verbose)
-{
-       const char* vendorName = NULL;
-       const char* deviceName = NULL;
-       usb_get_vendor_info(device.VendorID(), &vendorName);
-       usb_get_device_info(device.VendorID(), device.ProductID(), &deviceName);
-
-       if (!verbose) {
-               printf("%04x:%04x /dev/bus/usb%s \"%s\" \"%s\" ver. %04x\n",
-                       device.VendorID(), device.ProductID(), 
device.Location(),
-                       vendorName ? vendorName : device.ManufacturerString(),
-                       deviceName ? deviceName : device.ProductString(),
-                       device.Version());
-               return;
-       }
-
-       printf("[Device /dev/bus/usb%s]\n", device.Location());
-       printf("    Class .................. 0x%02x (%s)\n", device.Class(),
-               ClassName(device.Class()));
-       printf("    Subclass ............... 0x%02x\n", device.Subclass());
-       printf("    Protocol ............... 0x%02x\n", device.Protocol());
-       printf("    Max Endpoint 0 Packet .. %d\n", 
device.MaxEndpoint0PacketSize());
-       printf("    USB Version ............ 0x%04x\n", device.USBVersion());
-       printf("    Vendor ID .............. 0x%04x", device.VendorID());
-       if (vendorName != NULL)
-               printf(" (%s)", vendorName);
-       printf("\n    Product ID ............. 0x%04x", device.ProductID());
-       if (deviceName != NULL)
-               printf(" (%s)", deviceName);
-       printf("\n    Product Version ........ 0x%04x\n", device.Version());
-       printf("    Manufacturer String .... \"%s\"\n", 
device.ManufacturerString());
-       printf("    Product String ......... \"%s\"\n", device.ProductString());
-       printf("    Serial Number .......... \"%s\"\n", 
device.SerialNumberString());
-
-       for (uint32 i = 0; i < device.CountConfigurations(); i++) {
-               printf("    [Configuration %" B_PRIu32 "]\n", i);
-               DumpConfiguration(device.ConfigurationAt(i));
-       }
-
-       if (device.Class() != 0x09)
-               return;
-
-       usb_hub_descriptor hubDescriptor;
-       size_t size = device.GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
-               (void*)&hubDescriptor, sizeof(usb_hub_descriptor));
-       if (size == sizeof(usb_hub_descriptor)) {
-               printf("    Hub ports count......... %d\n", 
hubDescriptor.num_ports);
-               printf("    Hub Controller Current.. %dmA\n", 
hubDescriptor.max_power);
-
-               for (int index = 1; index <= hubDescriptor.num_ports; index++) {
-                       usb_port_status portStatus;
-                       size_t actualLength = 
device.ControlTransfer(USB_REQTYPE_CLASS
-                               | USB_REQTYPE_OTHER_IN, USB_REQUEST_GET_STATUS, 
0,
-                               index, sizeof(portStatus), (void*)&portStatus);
-                       if (actualLength != sizeof(portStatus))
-                               continue;
-                       printf("      Port %d status....... 
%04x.%04x%s%s%s%s%s%s%s%s%s\n",
-                               index, portStatus.status, portStatus.change,
-                               portStatus.status & PORT_STATUS_CONNECTION ? " 
Connect": "",
-                               portStatus.status & PORT_STATUS_ENABLE ? " 
Enable": "",
-                               portStatus.status & PORT_STATUS_SUSPEND ? " 
Suspend": "",
-                               portStatus.status & PORT_STATUS_OVER_CURRENT ? 
" Overcurrent": "",
-                               portStatus.status & PORT_STATUS_RESET ? " 
Reset": "",
-                               portStatus.status & PORT_STATUS_POWER ? " 
Power": "",
-                               portStatus.status & PORT_STATUS_CONNECTION
-                                       ? (portStatus.status & 
PORT_STATUS_LOW_SPEED ? " Lowspeed"
-                                       : (portStatus.status & 
PORT_STATUS_HIGH_SPEED ? " Highspeed"
-                                               : " Fullspeed")) : "",
-                               portStatus.status & PORT_STATUS_TEST ? " Test": 
"",
-                               portStatus.status & PORT_STATUS_INDICATOR ? " 
Indicator": "");
-               }
-       }
-}
-
-
-class DumpRoster : public BUSBRoster {
-public:
-                                       DumpRoster(bool verbose)
-                                               :       fVerbose(verbose)
-                                       {
-                                       }
-
-
-virtual        status_t        DeviceAdded(BUSBDevice* device)
-                                       {
-                                               DumpInfo(*device, fVerbose);
-                                               return B_OK;
-                                       }
-
-
-virtual        void            DeviceRemoved(BUSBDevice* device)
-                                       {
-                                       }
-
-private:
-               bool            fVerbose;
-};
-
-
-
-int
-main(int argc, char* argv[])
-{
-       bool verbose = false;
-       BString devname = "";
-       for (int i = 1; i < argc; i++) {
-               if (argv[i][0] == '-') {
-                       if (argv[i][1] == 'v')
-                               verbose = true;
-                       else {
-                               printf("Usage: listusb [-v] [device]\n\n");
-                               printf("-v: Show more detailed information 
including "
-                                       "interfaces, configurations, etc.\n\n");
-                               printf("If a device is not specified, "
-                                       "all devices found on the bus will be 
listed\n");
-                               return 1;
-                       }
-               } else
-                       devname = argv[i];
-       }
-
-       if (devname.Length() > 0) {
-               BUSBDevice device(devname.String());
-               if (device.InitCheck() < B_OK) {
-                       printf("Cannot open USB device: %s\n", 
devname.String());
-                       return 1;
-               } else {
-                               DumpInfo(device, verbose);
-                               return 0;
-               }
-       } else {
-               DumpRoster roster(verbose);
-               roster.Start();
-               roster.Stop();
-       }
-
-       return 0;
-}

############################################################################

Commit:      e64640878a713d3923b423a341b09226235d1a85
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e64640878a71
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Wed Nov  2 11:28:02 2016 UTC

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).

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/usb/USB_audio.h 
b/headers/os/drivers/usb/USB_audio.h
index 77d5952..c02a767 100644
--- a/headers/os/drivers/usb/USB_audio.h
+++ b/headers/os/drivers/usb/USB_audio.h
@@ -14,18 +14,18 @@ enum {
        USB_AUDIO_INTERFACE_AUDIO_CLASS         = 0x01
 };
 
-enum { // Audio Interface Subclasses   
-       USB_AUDIO_INTERFACE_UNDEFINED_SUBCLASS =        0x00, 
+enum { // Audio Interface Subclasses
+       USB_AUDIO_INTERFACE_UNDEFINED_SUBCLASS =        0x00,
        USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS =     0x01,
-       USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS,            //
-       USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS                      // 
+       USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS,
+       USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS
 };
 
 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_DEVICE                                     = 0x21,
        USB_AUDIO_CS_CONFIGURATION                      = 0x22,
@@ -66,7 +66,7 @@ typedef struct {
                struct {
                        uint16  total_length;
                        uint8   in_collection;
-                       uint8   interface_numbers[1];
+                       uint8   interface_numbers[0];
                } _PACKED r1;
 
                struct {
diff --git a/headers/os/drivers/usb/USB_video.h 
b/headers/os/drivers/usb/USB_video.h
new file mode 100644
index 0000000..064e33a
--- /dev/null
+++ b/headers/os/drivers/usb/USB_video.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2016, Adrien Destugues, pulkomandy@xxxxxxxxxxxxx
+ * 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 */
diff --git a/src/bin/listusb/Jamfile b/src/bin/listusb/Jamfile
index ed14442..a759a0d 100644
--- a/src/bin/listusb/Jamfile
+++ b/src/bin/listusb/Jamfile
@@ -6,6 +6,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel 
bus_managers usb ] ;
 BinCommand listusb :
        listusb.cpp
        usb_audio.cpp
+       usb_video.cpp
        : be libdevice.so ;
 
 # Manually reference generated headers
diff --git a/src/bin/listusb/listusb.cpp b/src/bin/listusb/listusb.cpp
index 107ca51..2c21ef0 100644
--- a/src/bin/listusb/listusb.cpp
+++ b/src/bin/listusb/listusb.cpp
@@ -10,20 +10,22 @@
 #include <Entry.h>
 #include <Path.h>
 #include <String.h>
-#include <USBKit.h>
 #include <stdio.h>
 #include <usb/USB_audio.h>
+#include <usb/USB_video.h>
 
 #include "usbspec_private.h"
 #include "usb-utils.h"
 
+#include "listusb.h"
+
 
 const char*
 ClassName(int classNumber) {
        switch (classNumber) {
                case 0:
                        return "Per-interface classes";
-               case 1:
+               case USB_AUDIO_DEVICE_CLASS:
                        return "Audio";
                case 2:
                        return "Communication";
@@ -45,7 +47,7 @@ ClassName(int classNumber) {
                        return "Smart card";
                case 13:
                        return "Content security";
-               case 14:
+               case USB_VIDEO_DEVICE_CLASS:
                        return "Video";
                case 15:
                        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
@@ -90,6 +143,9 @@ DumpDescriptor(const usb_generic_descriptor* descriptor,
                case USB_AUDIO_DEVICE_CLASS:
                        DumpAudioDescriptor(descriptor, subclass);
                        break;
+               case USB_VIDEO_DEVICE_CLASS:
+                       DumpVideoDescriptor(descriptor, subclass);
+                       break;
                default:
                        DumpDescriptorData(descriptor);
                        break;
@@ -105,10 +161,12 @@ DumpInterface(const BUSBInterface* interface)
 
        printf("                Class .............. 0x%02x (%s)\n",
                interface->Class(), ClassName(interface->Class()));
-       printf("                Subclass ........... 0x%02x\n",
-               interface->Subclass());
-       printf("                Protocol ........... 0x%02x\n",
-               interface->Protocol());
+       printf("                Subclass ........... 0x%02x%s\n",
+               interface->Subclass(),
+               SubclassName(interface->Class(), interface->Subclass()));
+       printf("                Protocol ........... 0x%02x%s\n",
+               interface->Protocol(), ProtocolName(interface->Class(),
+                       interface->Subclass(), interface->Protocol()));
        printf("                Interface String ... \"%s\"\n",
                interface->InterfaceString());
 
@@ -190,10 +248,13 @@ DumpInfo(BUSBDevice& device, bool verbose)
        printf("[Device /dev/bus/usb%s]\n", device.Location());
        printf("    Class .................. 0x%02x (%s)\n", device.Class(),
                ClassName(device.Class()));
-       printf("    Subclass ............... 0x%02x\n", device.Subclass());
-       printf("    Protocol ............... 0x%02x\n", device.Protocol());
+       printf("    Subclass ............... 0x%02x%s\n", device.Subclass(),
+               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("    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());
        if (vendorName != NULL)
                printf(" (%s)", vendorName);
diff --git a/src/bin/listusb/listusb.h b/src/bin/listusb/listusb.h
index 27ae00a..cdc2740 100644
--- a/src/bin/listusb/listusb.h
+++ b/src/bin/listusb/listusb.h
@@ -11,8 +11,13 @@
 #define LISTUSB_H
 
 
+#include <USBKit.h>
+
+
 void DumpDescriptorData(const usb_generic_descriptor* descriptor);
+
 void DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int 
subclass);
+void DumpVideoDescriptor(const usb_generic_descriptor* descriptor, int 
subclass);
 
 
 #endif /* !LISTUSB_H */
diff --git a/src/bin/listusb/usb_audio.cpp b/src/bin/listusb/usb_audio.cpp
index 58c11eb..7102502 100644
--- a/src/bin/listusb/usb_audio.cpp
+++ b/src/bin/listusb/usb_audio.cpp
@@ -19,10 +19,12 @@ void
 DumpAudioCSInterfaceDescriptorHeader(
        const usb_audiocontrol_header_descriptor* descriptor)
 {
+       printf("                    Type .............. 0x%02x\n",
+               descriptor->descriptor_type);
        printf("                    Subtype ........... 0x%02x (Header)\n",
                descriptor->descriptor_subtype);
-       printf("                    bcdADC Release date 0x%04x\n",
-               descriptor->bcd_release_no);
+       printf("                    ADC Release ....... %d.%d\n",
+               descriptor->bcd_release_no >> 8, descriptor->bcd_release_no & 
0xFF);
        printf("                    Total Length ...... %u\n",
                descriptor->r1.total_length);
        printf("                    Interfaces ........ ");
@@ -81,7 +83,7 @@ DumpChannelConfig(uint32 wChannelConfig)
 }
 
 
-const char*
+static const char*
 TerminalTypeName(uint16 terminalType)
 {
        switch (terminalType) {
@@ -138,6 +140,8 @@ void
 DumpAudioCSInterfaceDescriptorInputTerminal(
        const usb_audio_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",
@@ -164,6 +168,8 @@ void
 DumpAudioCSInterfaceDescriptorOutputTerminal(
        const usb_audio_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",
@@ -184,6 +190,8 @@ void
 DumpAudioCSInterfaceDescriptorMixerUnit(
        const usb_audio_mixer_unit_descriptor* descriptor)
 {
+       printf("                    Type .............. 0x%02x\n",
+               descriptor->descriptor_type);
        printf("                    Subtype ........... 0x%02x (Mixer Unit)\n",
                descriptor->descriptor_subtype);
        printf("                    Unit ID ........... %u\n",
@@ -222,6 +230,8 @@ void
 DumpAudioCSInterfaceDescriptorSelectorUnit(
        const usb_audio_selector_unit_descriptor* descriptor)
 {
+       printf("                    Type .............. 0x%02x\n",
+               descriptor->descriptor_type);
        printf("                    Subtype ........... 0x%02x (Selector 
Unit)\n",
                descriptor->descriptor_subtype);
        printf("                    Unit ID ........... %u\n",
@@ -275,6 +285,8 @@ void
 DumpAudioCSInterfaceDescriptorFeatureUnit(
        const usb_audio_feature_unit_descriptor* descriptor)
 {
+       printf("                    Type .............. 0x%02x\n",
+               descriptor->descriptor_type);
        printf("                    Subtype ........... 0x%02x (Feature 
Unit)\n",
                descriptor->descriptor_subtype);
        printf("                    Unit ID ........... %u\n",
@@ -316,6 +328,8 @@ void
 DumpAudioCSInterfaceDescriptorAssociated(
        const usb_generic_descriptor* descriptor)
 {
+       printf("                    Type .............. 0x%02x\n",
+               descriptor->descriptor_type);
        printf("                    Subtype ........... 0x%02x (Associate 
Interface)\n",
                (uint8)descriptor->data[0]);
        printf("                    Interface ......... %u\n",
@@ -324,6 +338,7 @@ DumpAudioCSInterfaceDescriptorAssociated(
        printf("                    Data .............. ");
        for (uint8 i = 0; i < descriptor->length - 2; i++)
                printf("%02x ", descriptor->data[i]);
+       printf("\n");
 }
 
 
diff --git a/src/bin/listusb/usb_video.cpp b/src/bin/listusb/usb_video.cpp
new file mode 100644
index 0000000..bab6996
--- /dev/null
+++ b/src/bin/listusb/usb_video.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2016, Adrien Destugues, pulkomandy@xxxxxxxxxxxxx
+ * 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;
+       }
+}
+

############################################################################

Revision:    hrev50651
Commit:      12431ebff49970922ce0125bac58784467ecb39b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=12431ebff499
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Wed Nov  2 14:23:14 2016 UTC

listusb: dump video streams from UVC devices.

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/usb/USB_video.h 
b/headers/os/drivers/usb/USB_video.h
index 064e33a..2c3fb00 100644
--- a/headers/os/drivers/usb/USB_video.h
+++ b/headers/os/drivers/usb/USB_video.h
@@ -52,6 +52,30 @@ enum { // Video Class-Specific VideoControl Interface 
descriptor subtypes
 };
 
 
+enum { // Video Class-Specific VideoStreaming Interface descriptor subtypes
+       USB_VIDEO_VS_UNDEFINED                                          = 0x00,
+       USB_VIDEO_VS_INPUT_HEADER                                       = 0x01,
+       USB_VIDEO_VS_OUTPUT_HEADER                                      = 0x02,
+       USB_VIDEO_VS_STILL_IMAGE_FRAME                          = 0x03,
+       USB_VIDEO_VS_FORMAT_UNCOMPRESSED                        = 0x04,
+       USB_VIDEO_VS_FRAME_UNCOMPRESSED                         = 0x05,
+       USB_VIDEO_VS_FORMAT_MJPEG                                       = 0x06,
+       USB_VIDEO_VS_FRAME_MJPEG                                        = 0x07,
+       USB_VIDEO_VS_FORMAT_MPEG2TS                                     = 0x0a,
+       USB_VIDEO_VS_FORMAT_DV                                          = 0x0c,
+       USB_VIDEO_VS_COLORFORMAT                                        = 0x0d,
+       USB_VIDEO_VS_FORMAT_FRAME_BASED                         = 0x10,
+       USB_VIDEO_VS_FRAME_FRAME_BASED                          = 0x11,
+       USB_VIDEO_VS_FORMAT_STREAM_BASED                        = 0x12,
+       USB_VIDEO_VS_FORMAT_H264                                        = 0x13,
+       USB_VIDEO_VS_FRAME_H264                                         = 0x14,
+       USB_VIDEO_VS_FORMAT_H264_SIMULCAST                      = 0x15,
+       USB_VIDEO_VS_FORMAT_VP8                                         = 0x16,
+       USB_VIDEO_VS_FRAME_VP8                                          = 0x17,
+       USB_VIDEO_VS_FORMAT_VP8_SIMULCAST                       = 0x18,
+};
+
+
 enum {
        // USB Terminal Types
        USB_VIDEO_VENDOR_USB_IO                                         = 0x100,
@@ -72,6 +96,14 @@ enum {
 };
 
 
+enum {
+       EP_SUBTYPE_UNDEFINED                                            = 0x00,
+       EP_SUBTYPE_GENERAL                                                      
= 0x01,
+       EP_SUBTYPE_ENDPOINT                                                     
= 0x02,
+       EP_SUBTYPE_INTERRUPT                                            = 0x03,
+};
+
+
 // Class Specific Video Control Interface Header
 // 1.5: Table 3-3 p.48
 typedef struct {
@@ -139,4 +171,28 @@ typedef struct {
 } _PACKED usb_video_processing_unit_descriptor;
 
 
+struct usb_video_frame_descriptor {
+       uint8   length;
+       uint8   descriptor_type;
+       uint8   descriptor_subtype;
+       uint8   frame_index;
+       uint8   capabilities;
+       uint16  width;
+       uint16  height;
+       uint32  min_bit_rate;
+       uint32  max_bit_rate;
+       uint32  max_video_frame_buffer_size;
+       uint32  default_frame_interval;
+       uint8   frame_interval_type;
+       union {
+               struct {
+                       uint32  min_frame_interval;
+                       uint32  max_frame_tnterval;
+                       uint32  frame_interval_step;
+               } continuous;
+               uint32  discrete_frame_intervals[0];
+       };
+} _PACKED;
+
+
 #endif /* !USB_VIDEO_H */
diff --git a/src/bin/listusb/usb_video.cpp b/src/bin/listusb/usb_video.cpp
index bab6996..89a1559 100644
--- a/src/bin/listusb/usb_video.cpp
+++ b/src/bin/listusb/usb_video.cpp
@@ -275,7 +275,239 @@ DumpVideoControlCSInterfaceDescriptor(const 
usb_generic_descriptor* descriptor)
 
 
 void
-DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor);
+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++)
+       {
+               // FIXME these are reverse-endian compared to everything else.
+               // Is my webcam wrong, or is it some quirk in the spec?
+               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);
+       }
+       // TODO if frame__interval_type is 0, dump continuous frame intervals
+}
+
+
+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;
+               default:
+                       DumpDescriptorData(descriptor);
+                       break;
+       }
+}
+
+
 
 void
 DumpVideoDescriptor(const usb_generic_descriptor* descriptor, int subclass)
@@ -286,6 +518,9 @@ DumpVideoDescriptor(const usb_generic_descriptor* 
descriptor, int subclass)
                                case USB_VIDEO_CS_INTERFACE:
                                        
DumpVideoControlCSInterfaceDescriptor(descriptor);
                                        break;
+                               case USB_VIDEO_CS_ENDPOINT:
+                                       
DumpVideoControlCSEndpointDescriptor(descriptor);
+                                       break;
                                default:
                                        DumpDescriptorData(descriptor);
                                        break;
@@ -294,7 +529,7 @@ DumpVideoDescriptor(const usb_generic_descriptor* 
descriptor, int subclass)
                case USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS:
                        switch (descriptor->descriptor_type) {
                                case USB_VIDEO_CS_INTERFACE:
-                                       
DumpAudioStreamCSInterfaceDescriptor(descriptor);
+                                       
DumpVideoStreamCSInterfaceDescriptor(descriptor);
                                        break;
                                default:
                                        DumpDescriptorData(descriptor);


Other related posts:

  • » [haiku-commits] haiku: hrev50651 - src/bin/listusb src/bin headers/os/drivers/usb - pulkomandy