From 3199c071c5d97b37b7e2beed9f59b8922156c9a8 Mon Sep 17 00:00:00 2001 From: tendrils Date: Sat, 10 Apr 2021 07:29:09 +1200 Subject: [PATCH] Add MIDI device class support --- usb/usbview/dispaud.c | 302 ++++++++++++++++++++++++++++++++++++++++-- usb/usbview/display.c | 4 +- usb/usbview/usbdesc.h | 108 ++++++++++++++- usb/usbview/uvcview.h | 4 +- 4 files changed, 405 insertions(+), 13 deletions(-) diff --git a/usb/usbview/dispaud.c b/usb/usbview/dispaud.c index 66115dd89..35d08fc27 100644 --- a/usb/usbview/dispaud.c +++ b/usb/usbview/dispaud.c @@ -264,8 +264,8 @@ DisplayASGeneral ( ); BOOL -DisplayCSEndpoint ( - PUSB_AUDIO_ENDPOINT_DESCRIPTOR EndpointDesc +DisplayAudioStreamingEndpoint ( + PUSB_AUDIO_AS_ENDPOINT_DESCRIPTOR EndpointDesc ); BOOL @@ -278,6 +278,37 @@ DisplayASFormatSpecific ( PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc ); +BOOL +DisplayMSInterfaceHeader ( + PUSB_AUDIO_MS_INTERFACE_HEADER_DESCRIPTOR HeaderDesc +); + +BOOL +DisplayMSMIDIInJack ( + PUSB_AUDIO_MS_MIDI_IN_JACK_DESCRIPTOR JackDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +); + +BOOL +DisplayMSMIDIOutJack ( + PUSB_AUDIO_MS_MIDI_OUT_JACK_DESCRIPTOR JackDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +); + +BOOL +DisplayMSElement ( + PUSB_AUDIO_MS_ELEMENT_DESCRIPTOR ElementDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +); + +BOOL +DisplayMidiStreamingEndpoint( + PUSB_AUDIO_MS_ENDPOINT_DESCRIPTOR EndpointDesc +); + VOID DisplayBytes ( PUCHAR Data, @@ -311,12 +342,16 @@ DisplayChannelConfig ( bInterfaceSubClass - The SubClass of the Interface containing the descriptor + info - The device which supplied the descriptor + *****************************************************************************/ BOOL DisplayAudioDescriptor ( PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc, - UCHAR bInterfaceSubClass + UCHAR bInterfaceSubClass, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState ) { switch (CommonDesc->bDescriptorType) @@ -374,13 +409,39 @@ DisplayAudioDescriptor ( } break; + case USB_AUDIO_SUBCLASS_MIDISTREAMING: + switch (CommonDesc->bDescriptorSubtype) + { + case USB_AUDIO_CS_INTERFACE_MS_HEADER: + return DisplayMSInterfaceHeader((PUSB_AUDIO_MS_INTERFACE_HEADER_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_CS_INTERFACE_MIDI_IN_JACK: + return DisplayMSMIDIInJack((PUSB_AUDIO_MS_MIDI_IN_JACK_DESCRIPTOR)CommonDesc, StringDescs, LatestDevicePowerState); + + case USB_AUDIO_CS_INTERFACE_MIDI_OUT_JACK: + return DisplayMSMIDIOutJack((PUSB_AUDIO_MS_MIDI_OUT_JACK_DESCRIPTOR)CommonDesc, StringDescs, LatestDevicePowerState); + + case USB_AUDIO_CS_INTERFACE_ELEMENT: + return DisplayMSElement((PUSB_AUDIO_MS_ELEMENT_DESCRIPTOR)CommonDesc, StringDescs, LatestDevicePowerState); + default: + break; + } + break; + default: break; } break; case USB_AUDIO_CS_ENDPOINT: - return DisplayCSEndpoint((PUSB_AUDIO_ENDPOINT_DESCRIPTOR)CommonDesc); + switch (bInterfaceSubClass) + { + case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: + return DisplayAudioStreamingEndpoint((PUSB_AUDIO_AS_ENDPOINT_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_SUBCLASS_MIDISTREAMING: + return DisplayMidiStreamingEndpoint((PUSB_AUDIO_MS_ENDPOINT_DESCRIPTOR)CommonDesc); + } default: break; @@ -1025,18 +1086,18 @@ DisplayASGeneral ( /***************************************************************************** - DisplayCSEndpoint() + DisplayAudioStreamingEndpoint() *****************************************************************************/ BOOL -DisplayCSEndpoint ( - PUSB_AUDIO_ENDPOINT_DESCRIPTOR EndpointDesc +DisplayAudioStreamingEndpoint ( + PUSB_AUDIO_AS_ENDPOINT_DESCRIPTOR EndpointDesc ) { PCHAR pStr = NULL; - if (EndpointDesc->bLength != sizeof(USB_AUDIO_ENDPOINT_DESCRIPTOR)) + if (EndpointDesc->bLength != sizeof(USB_AUDIO_AS_ENDPOINT_DESCRIPTOR)) { OOPS(); return FALSE; @@ -1256,6 +1317,231 @@ DisplayASFormatSpecific ( return TRUE; } +BOOL +DisplayMSInterfaceHeader( + PUSB_AUDIO_MS_INTERFACE_HEADER_DESCRIPTOR HeaderDesc +) +{ + AppendTextBuffer("\r\n ===>MIDI Streaming Interface Header Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + HeaderDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X (CS_INTERFACE)\r\n", + HeaderDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X (MS_HEADER)\r\n", + HeaderDesc->bDescriptorSubtype); + + AppendTextBuffer("bcdMSC: 0x%04X\r\n", + HeaderDesc->bcdMSC); + + AppendTextBuffer("wTotalLength: 0x%04X\r\n", + HeaderDesc->wTotalLength); + return TRUE; +} + +PCHAR +DescribeMidiJackType( + UCHAR JackType +) +{ + if (JackType == USB_AUDIO_MS_JACK_TYPE_EMBEDDED) + { + return "EMBEDDED"; + } + if (JackType == USB_AUDIO_MS_JACK_TYPE_EXTERNAL) + { + return "EXTERNAL"; + } + return "JACK_TYPE_UNDEFINED"; +} + +BOOL +DisplayMSMIDIInJack( + PUSB_AUDIO_MS_MIDI_IN_JACK_DESCRIPTOR JackDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +) +{ + AppendTextBuffer("\r\n ===>MIDI IN Jack Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + JackDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X (CS_INTERFACE)\r\n", + JackDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X (MIDI_IN_JACK)\r\n", + JackDesc->bDescriptorSubtype); + + AppendTextBuffer("bJackType: 0x%02X (%s)\r\n", + JackDesc->bJackType, + DescribeMidiJackType(JackDesc->bJackType)); + + AppendTextBuffer("bJackID: 0x%02X\r\n", + JackDesc->bJackType); + + if (JackDesc->iJack) + { + DisplayStringDescriptor(JackDesc->iJack, StringDescs, LatestDevicePowerState); + } + return TRUE; +} + +BOOL +DisplayMSMIDIOutJack( + PUSB_AUDIO_MS_MIDI_OUT_JACK_DESCRIPTOR JackDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +) +{ + UCHAR i, iJack; + PUSB_AUDIO_MS_MIDI_OUT_JACK_PIN_DESCRIPTOR PinDesc = (PUSB_AUDIO_MS_MIDI_OUT_JACK_PIN_DESCRIPTOR)(JackDesc + 1); + + AppendTextBuffer("\r\n ===>MIDI OUT Jack Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + JackDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X (CS_INTERFACE)\r\n", + JackDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X (MIDI_OUT_JACK)\r\n", + JackDesc->bDescriptorSubtype); + + AppendTextBuffer("bJackType: 0x%02X (%s)\r\n", + JackDesc->bJackType, + DescribeMidiJackType(JackDesc->bJackType)); + + AppendTextBuffer("bJackID: 0x%02X\r\n", + JackDesc->bJackID); + + AppendTextBuffer("bNrInputPins: 0x%02X\r\n", + JackDesc->bNrInputPins); + + for (i = 0; i < JackDesc->bNrInputPins; i++) + { + AppendTextBuffer("baSourceID(%d): 0x%02X\r\n", + i + 1, PinDesc->baSourceID); + + AppendTextBuffer("baSourcePin(%d): 0x%02X\r\n", + i + 1, PinDesc->baSourcePin); + + PinDesc++; + } + + iJack = *((UCHAR *)PinDesc); + + if (iJack) + { + DisplayStringDescriptor(iJack, StringDescs, LatestDevicePowerState); + } + return TRUE; +} + +BOOL +DisplayMSElement( + PUSB_AUDIO_MS_ELEMENT_DESCRIPTOR ElementDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +) +{ + UCHAR i, iElement; + PUSB_AUDIO_MS_ELEMENT_SOURCE_DESCRIPTOR SourceDesc = (PUSB_AUDIO_MS_ELEMENT_SOURCE_DESCRIPTOR)(ElementDesc + 1); + PUSB_AUDIO_MS_ELEMENT_FOOTER_DESCRIPTOR FooterDesc; + + AppendTextBuffer("\r\n ===>MIDI Element Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + ElementDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X (CS_INTERFACE)\r\n", + ElementDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X (ELEMENT)\r\n", + ElementDesc->bDescriptorSubtype); + + AppendTextBuffer("bElementID: 0x%02X\r\n", + ElementDesc->bElementID); + + AppendTextBuffer("bNrInputPins: 0x%02X\r\n", + ElementDesc->bNrInputPins); + + for (i = 0; i < ElementDesc->bNrInputPins; i++) + { + AppendTextBuffer("baSourceID(%d): 0x%02X\r\n", + i, SourceDesc->baSourceID); + + AppendTextBuffer("baSourcePin(%d): 0x%02X\r\n", + i, SourceDesc->baSourcePin); + + SourceDesc++; + } + + FooterDesc = (PUSB_AUDIO_MS_ELEMENT_FOOTER_DESCRIPTOR) SourceDesc; + + AppendTextBuffer("bNrOutputPins: 0x%02X\r\n", + FooterDesc->bNrOutputPins); + + AppendTextBuffer("bInTerminalLink: 0x%02X\r\n", + FooterDesc->bInTerminalLink); + + AppendTextBuffer("bOutTerminalLink: 0x%02X\r\n", + FooterDesc->bOutTerminalLink); + + AppendTextBuffer("bElCapsSize: 0x%02X\r\n", + FooterDesc->bInTerminalLink); + + FooterDesc++; + iElement = *((UCHAR*)FooterDesc); + + if (iElement) + { + DisplayStringDescriptor(iElement, StringDescs, LatestDevicePowerState); + } + return TRUE; +} + +BOOL +DisplayMidiStreamingEndpoint( + PUSB_AUDIO_MS_ENDPOINT_DESCRIPTOR EndpointDesc +) +{ + UCHAR i, *j; + if (EndpointDesc->bLength < sizeof(USB_AUDIO_MS_ENDPOINT_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>MIDI Streaming Class Specific Audio Data Endpoint Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + EndpointDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X (CS_ENDPOINT)\r\n", + EndpointDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X (EP_GENERAL)\r\n", + EndpointDesc->bDescriptorSubtype); + + AppendTextBuffer("bNumEmbMIDIJack: 0x%02X\r\n", + EndpointDesc->bNumEmbMIDIJack); + + j = (PUCHAR)(EndpointDesc + 1); + + for (i = 0; i < EndpointDesc->bNumEmbMIDIJack; i++) + { + AppendTextBuffer("baAssocJackID(%d): 0x%02X\r\n", + i + 1, + *(j + i)); + + } + + return TRUE; +} + /***************************************************************************** DisplayBytes() diff --git a/usb/usbview/display.c b/usb/usbview/display.c index f27d32c9e..f86ad7586 100644 --- a/usb/usbview/display.c +++ b/usb/usbview/display.c @@ -2159,7 +2159,9 @@ DisplayConfigDesc ( case USB_DEVICE_CLASS_AUDIO: displayUnknown = ! DisplayAudioDescriptor( (PUSB_AUDIO_COMMON_DESCRIPTOR)commonDesc, - bInterfaceSubClass); + bInterfaceSubClass, + StringDescs, + info->DeviceInfoNode != NULL ? info->DeviceInfoNode->LatestDevicePowerState : PowerDeviceUnspecified); break; case USB_DEVICE_CLASS_VIDEO: diff --git a/usb/usbview/usbdesc.h b/usb/usbview/usbdesc.h index 23420cfe2..e9a72a4a2 100644 --- a/usb/usbview/usbdesc.h +++ b/usb/usbview/usbdesc.h @@ -134,6 +134,39 @@ Revision History: #define USB_AUDIO_PROCESS_CHORUS 0x05 #define USB_AUDIO_PROCESS_DYNRANGECOMP 0x06 +// A.8 Audio Class-Specific Endpoint Descriptor Subtypes +// +#define USB_AUDIO_CS_ENDPOINT_UNDEFINED 0x00 +#define USB_AUDIO_CS_ENDPOINT_GENERAL 0x01 + +// +// USB Device Class Definition for MIDI Devices +// Appendix A. Audio Device Class Codes: MIDIStreaming +// + +// A.1 MS Class-Specific Interface Descriptor Subtypes +// +#define USB_AUDIO_CS_INTERFACE_MS_UNDEFINED 0x00 +#define USB_AUDIO_CS_INTERFACE_MS_HEADER 0x01 +#define USB_AUDIO_CS_INTERFACE_MIDI_IN_JACK 0x02 +#define USB_AUDIO_CS_INTERFACE_MIDI_OUT_JACK 0x03 +#define USB_AUDIO_CS_INTERFACE_ELEMENT 0x04 + +// A.2 MS Class-Specific Endpoint Descriptor Subtypes +// +#define USB_AUDIO_CS_EP_MS_UNDEFINED 0x00 +#define USB_AUDIO_CS_EP_MS_GENERAL 0x01 + +// A.3 MS MIDI IN and OUT Jack Types +// +#define USB_AUDIO_MS_JACK_TYPE_UNDEFINED 0x00 +#define USB_AUDIO_MS_JACK_TYPE_EMBEDDED 0x01 +#define USB_AUDIO_MS_JACK_TYPE_EXTERNAL 0x02 + +// A.5.1 Endpoint Control Selectors +// +#define USB_AUDIO_CS_EP_CONTROL_MS_UNDEFINED 0x00 +#define USB_AUDIO_CS_EP_ASSOCIATION_CONTROL 0x01 /***************************************************************************** T Y P E D E F S @@ -339,15 +372,84 @@ typedef struct _USB_AUDIO_GENERAL_DESCRIPTOR { // 4.6.1.2 Class-Specific AS Endpoint Descriptor // -typedef struct _USB_AUDIO_ENDPOINT_DESCRIPTOR { +typedef struct _USB_AUDIO_AS_ENDPOINT_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; UCHAR bDescriptorSubtype; UCHAR bmAttributes; UCHAR bLockDelayUnits; USHORT wLockDelay; -} USB_AUDIO_ENDPOINT_DESCRIPTOR, -*PUSB_AUDIO_ENDPOINT_DESCRIPTOR; +} USB_AUDIO_AS_ENDPOINT_DESCRIPTOR, +*PUSB_AUDIO_AS_ENDPOINT_DESCRIPTOR; + +// +// USB Device Class Definition for MIDI Devices +// +typedef struct _USB_AUDIO_MS_INTERFACE_HEADER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + USHORT bcdMSC; + USHORT wTotalLength; +} USB_AUDIO_MS_INTERFACE_HEADER_DESCRIPTOR, +*PUSB_AUDIO_MS_INTERFACE_HEADER_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_MIDI_IN_JACK_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bJackType; + UCHAR bJackID; + UCHAR iJack; +} USB_AUDIO_MS_MIDI_IN_JACK_DESCRIPTOR, +*PUSB_AUDIO_MS_MIDI_IN_JACK_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_MIDI_OUT_JACK_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bJackType; + UCHAR bJackID; + UCHAR bNrInputPins; +} USB_AUDIO_MS_MIDI_OUT_JACK_DESCRIPTOR, +*PUSB_AUDIO_MS_MIDI_OUT_JACK_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_MIDI_OUT_JACK_PIN_DESCRIPTOR { + UCHAR baSourceID; + UCHAR baSourcePin; +} USB_AUDIO_MS_MIDI_OUT_JACK_PIN_DESCRIPTOR, +*PUSB_AUDIO_MS_MIDI_OUT_JACK_PIN_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_ELEMENT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bElementID; + UCHAR bNrInputPins; +} USB_AUDIO_MS_ELEMENT_DESCRIPTOR, +*PUSB_AUDIO_MS_ELEMENT_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_ELEMENT_SOURCE_DESCRIPTOR { + UCHAR baSourceID; + UCHAR baSourcePin; +} USB_AUDIO_MS_ELEMENT_SOURCE_DESCRIPTOR, +*PUSB_AUDIO_MS_ELEMENT_SOURCE_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_ELEMENT_FOOTER_DESCRIPTOR { + UCHAR bNrOutputPins; + UCHAR bInTerminalLink; + UCHAR bOutTerminalLink; + UCHAR bElCapsSize; +} USB_AUDIO_MS_ELEMENT_FOOTER_DESCRIPTOR, +*PUSB_AUDIO_MS_ELEMENT_FOOTER_DESCRIPTOR; + +typedef struct _USB_AUDIO_MS_ENDPOINT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bNumEmbMIDIJack; +} USB_AUDIO_MS_ENDPOINT_DESCRIPTOR, +*PUSB_AUDIO_MS_ENDPOINT_DESCRIPTOR; // // USB Device Class Definition for Audio Data Formats diff --git a/usb/usbview/uvcview.h b/usb/usbview/uvcview.h index 6f7424624..2db5b1451 100644 --- a/usb/usbview/uvcview.h +++ b/usb/usbview/uvcview.h @@ -651,7 +651,9 @@ VOID FreeDeviceProperties( BOOL DisplayAudioDescriptor ( PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc, - UCHAR bInterfaceSubClass + UCHAR bInterfaceSubClass, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState ); //