listusb: decode USB-CDC descriptors

Change-Id: I36ea15fee28b27332a8092a98a302c22b41ae060
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5225
Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com>
This commit is contained in:
PulkoMandy 2022-04-18 12:52:19 +02:00 committed by waddlesplash
parent 6c02429697
commit 581013b8e3
2 changed files with 225 additions and 1 deletions

View File

@ -5,6 +5,7 @@
// Reference: http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
#define USB_COMMUNICATION_DEVICE_CLASS 0x02
#define USB_COMMUNICATION_WIRELESS_DEVICE_CLASS 0xe0
#define USB_CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define USB_CDC_CLASS_VERSION 0x0101

View File

@ -12,6 +12,7 @@
#include <String.h>
#include <stdio.h>
#include <usb/USB_audio.h>
#include <usb/USB_cdc.h>
#include <usb/USB_video.h>
#include "usbspec_private.h"
@ -129,16 +130,234 @@ ProtocolName(int classNumber, int subclass, int protocol)
}
case 0xE0:
if (subclass == 0x01 && protocol == 0x01)
return " (Bluetooth)";
return " (Bluetooth control)";
if (subclass == 0x01 && protocol == 0x02)
return " (UWB Radio)";
if (subclass == 0x01 && protocol == 0x03)
return " (RNDIS control)";
if (subclass == 0x01 && protocol == 0x04)
return " (Bluetooth AMP)";
if (subclass == 0x02 && protocol == 0x01)
return " (Host wire adapter)";
if (subclass == 0x02 && protocol == 0x02)
return " (Device wire adapter)";
if (subclass == 0x02 && protocol == 0x03)
return " (Device wire isochronous)";
case 0xEF:
if (subclass == 0x01 && protocol == 0x01)
return " (Microsoft Active Sync)";
if (subclass == 0x01 && protocol == 0x02)
return " (Palm Sync)";
if (subclass == 0x02 && protocol == 0x01)
return " (Interface Association)";
if (subclass == 0x02 && protocol == 0x02)
return " (Wire adapter multifunction peripheral)";
if (subclass == 0x03 && protocol == 0x01)
return " (Cable based association framework)";
if (subclass == 0x04 && protocol == 0x01)
return " (RNDIS Ethernet)";
if (subclass == 0x04 && protocol == 0x02)
return " (RNDIS Wifi)";
if (subclass == 0x04 && protocol == 0x03)
return " (RNDIS WiMAX)";
if (subclass == 0x04 && protocol == 0x04)
return " (RNDIS WWAN)";
if (subclass == 0x04 && protocol == 0x05)
return " (RNDIS raw IPv4)";
if (subclass == 0x04 && protocol == 0x06)
return " (RNDIS raw IPv6)";
if (subclass == 0x04 && protocol == 0x07)
return " (RNDIS GPRS)";
if (subclass == 0x05 && protocol == 0x00)
return " (USB3 vision control)";
if (subclass == 0x05 && protocol == 0x01)
return " (USB3 vision event)";
if (subclass == 0x05 && protocol == 0x02)
return " (USB3 vision streaming)";
if (subclass == 0x06 && protocol == 0x01)
return " (STEP)";
if (subclass == 0x06 && protocol == 0x02)
return " (STEP RAW)";
if (subclass == 0x07 && protocol == 0x01)
return " (DVB Command Interface in IAD)";
if (subclass == 0x07 && protocol == 0x02)
return " (DVB Command Interface in interface descriptor)";
if (subclass == 0x07 && protocol == 0x03)
return " (Media interface in interface descriptor)";
break;
}
return "";
}
void
DumpCDCDescriptor(const usb_generic_descriptor* descriptor, int subclass)
{
if (descriptor->descriptor_type == 0x24) {
printf(" Type ............. CDC interface descriptor\n");
printf(" Subtype .......... ");
switch (descriptor->data[0]) {
case USB_CDC_HEADER_FUNCTIONAL_DESCRIPTOR:
printf("Header\n");
printf(" CDC Version ...... %x.%x\n",
descriptor->data[2], descriptor->data[1]);
return;
case USB_CDC_CM_FUNCTIONAL_DESCRIPTOR:
{
printf("Call management\n");
const usb_cdc_cm_functional_descriptor* cmDesc
= (const usb_cdc_cm_functional_descriptor*)descriptor;
printf(" Capabilities ..... ");
bool somethingPrinted = false;
if (cmDesc->capabilities & USB_CDC_CM_DOES_CALL_MANAGEMENT != 0) {
printf("Call management");
somethingPrinted = true;
}
if (cmDesc->capabilities & USB_CDC_CM_OVER_DATA_INTERFACE != 0) {
if (somethingPrinted)
printf(", ");
printf("Over data interface");
somethingPrinted = true;
}
if (!somethingPrinted)
printf("None");
printf("\n");
printf(" Data interface ... %d\n", cmDesc->data_interface);
return;
}
case USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR:
{
printf("Abstract control management\n");
const usb_cdc_acm_functional_descriptor* acmDesc
= (const usb_cdc_acm_functional_descriptor*)descriptor;
printf(" Capabilities ..... ");
bool somethingPrinted = false;
if (acmDesc->capabilities & USB_CDC_ACM_HAS_COMM_FEATURES != 0) {
printf("Communication features");
somethingPrinted = true;
}
if (acmDesc->capabilities & USB_CDC_ACM_HAS_LINE_CONTROL != 0) {
if (somethingPrinted)
printf(", ");
printf("Line control");
somethingPrinted = true;
}
if (acmDesc->capabilities & USB_CDC_ACM_HAS_SEND_BREAK != 0) {
if (somethingPrinted)
printf(", ");
printf("Send break");
somethingPrinted = true;
}
if (acmDesc->capabilities & USB_CDC_ACM_HAS_NETWORK_CONNECTION != 0) {
if (somethingPrinted)
printf(", ");
printf("Network connection");
somethingPrinted = true;
}
if (!somethingPrinted)
printf("None");
printf("\n");
return;
}
case 0x03:
printf("Direct line management\n");
break;
case 0x04:
printf("Telephone ringer management\n");
break;
case 0x05:
printf("Telephone call and line state reporting\n");
break;
case USB_CDC_UNION_FUNCTIONAL_DESCRIPTOR:
printf("Union\n");
printf(" Control interface %d\n", descriptor->data[1]);
for (int32 i = 2; i < descriptor->length - 2; i++)
printf(" Subordinate ..... %d\n", descriptor->data[i]);
return;
case 0x07:
printf("Country selection\n");
break;
case 0x08:
printf("Telephone operational mode\n");
break;
case 0x09:
printf("USB Terminal\n");
break;
case 0x0A:
printf("Network channel\n");
break;
case 0x0B:
printf("Protocol init\n");
break;
case 0x0C:
printf("Extension unit\n");
break;
case 0x0D:
printf("Multi-channel management\n");
break;
case 0x0E:
printf("CAPI control\n");
break;
case 0x0F:
printf("Ethernet\n");
break;
case 0x10:
printf("ATM\n");
break;
case 0x11:
printf("Wireless handset\n");
break;
case 0x12:
printf("Mobile direct line\n");
break;
case 0x13:
printf("Mobile direct line detail\n");
break;
case 0x14:
printf("Device management\n");
break;
case 0x15:
printf("Object Exchange\n");
break;
case 0x16:
printf("Command set\n");
break;
case 0x17:
printf("Command set detail\n");
break;
case 0x18:
printf("Telephone control\n");
break;
case 0x19:
printf("Object Exchange service identifier\n");
break;
case 0x1A:
printf("NCM\n");
break;
default:
printf("0x%02x\n", descriptor->data[0]);
}
printf(" Data ............. ");
// len includes len and descriptor_type field
// start at i = 1 because we already dumped the first byte as subtype
for (int32 i = 1; i < descriptor->length - 2; i++)
printf("%02x ", descriptor->data[i]);
printf("\n");
return;
}
#if 0
if (descriptor->descriptor_type == 0x25) {
printf(" Type ............. CDC endpoint descriptor\n",
return;
}
#endif
DumpDescriptorData(descriptor);
}
void
DumpDescriptorData(const usb_generic_descriptor* descriptor)
{
@ -164,6 +383,10 @@ DumpDescriptor(const usb_generic_descriptor* descriptor,
case USB_VIDEO_DEVICE_CLASS:
DumpVideoDescriptor(descriptor, subclass);
break;
case USB_COMMUNICATION_DEVICE_CLASS:
case USB_COMMUNICATION_WIRELESS_DEVICE_CLASS:
DumpCDCDescriptor(descriptor, subclass);
break;
default:
DumpDescriptorData(descriptor);
break;