2

I'm working on a simple USB audio input device based on the Microchip/Atmel ATSAMD21. The descriptors identify it as a single channel microphone with a single feature unit for volume control. As I understood the feedback endpoint is not mandatory so I have not implemented the feedback/synchronization mechanism yet.

typedef struct ConfigDesc {
USB_ConfigurationDescriptor Config;

USB_InterfaceDescriptor AUDIO_control_interface;
AUDIO_HeaderDescriptor AUDIO_header;
AUDIO_InputTerminalDescriptor AUDIO_input_terminal_descriptor;    
AUDIO_FeatureUnit_1CH AUDIO_feature_unit_1;
AUDIO_OutputTerminalDescriptor AUDIO_output_terminal_descriptor;
/*AUDIO_ControlSelectorUnit AUDIO_control_selector_unit;*/



USB_InterfaceDescriptor AUDIO_audio_streaming_interface_1;
USB_InterfaceDescriptor AUDIO_audio_streaming_interface_2;
AUDIO_GeneralDescriptor AUDIO_mic_general;

AUDIO_MicType1Descriptor AUDIO_mic_type1;

USB_ISocEndpointDescriptor AUDIO_mic_endpoint;

AUDIO_IsocDataEndpoint AUDIO_mic_isoc;

}  __attribute__((packed)) ConfigDesc;

(Detailed descriptors at the bottom) I have implemented the functions to handle class specific requests (Only the GET/SET requests for the FeatureUnit but after debugging and logging I didn't come across any other class specific requests.) For As soon as the device gets a request to SET_INTERFACE interface-1, alternate interface-1, it starts to transmit a buffer of 64 bytes (32 PCM16 values) continuously. When connected to a Windows 10 PC, the device enumerates as a microphone without any issue (shows up under recording devices) and I was able to record a snippet of audio using the ksstudio. But every attempt to open from any high level application failed. Audacity, for an example gives an error -9999-Unanticipated host error.

enter image description here

__attribute__((__aligned__(4))) const ConfigDesc configuration_descriptor = {
.Config = {
    .bLength = sizeof(USB_ConfigurationDescriptor),
    .bDescriptorType = USB_DTYPE_Configuration,
    .wTotalLength  = sizeof(ConfigDesc),
    .bNumInterfaces = 2,
    .bConfigurationValue = 1,
    .iConfiguration = 0,
    .bmAttributes = USB_CONFIG_ATTR_BUSPOWERED,
    .bMaxPower = USB_CONFIG_POWER_MA(500)
},
.AUDIO_control_interface = {
    .bLength = 9,//sizeof(USB_InterfaceDescriptor),
    .bDescriptorType = 0x04,//USB_DTYPE_Interface,
    .bInterfaceNumber = 0,//INTERFACE_AUDIO_CONTROL,
    .bAlternateSetting = 0,
    .bNumEndpoints = 0,
    .bInterfaceClass = 0x01,//AUDIO_INTERFACE_CLASS, //Audio
    .bInterfaceSubClass = 0x01,//AUDIO_INTERFACE_SUBCLASS_CONTROL, //Audio
    .bInterfaceProtocol = 0,
    .iInterface = 0,
    
},
.AUDIO_header =
{
    .bLength = 9,//sizeof(AUDIO_HeaderDescriptor),
    .bDescriptorType = 0x24,//USB_DTYPE_CSInterface,
    .bDescriptorSubType = 1, //HEDADER subtype,
    .bcdADC = 0x0100,//**
    .wTotalLength = 55, //43//Total size of class specific descriptors
    .bInCollction = 0x01, //Number of streaming interfaces
    .baInterfaceNr = 0x01,//INTERFACE_AUDIO_STREAMING, //AudioStreaming interface 1 belongs tothis AudioControl interface.
},
.AUDIO_input_terminal_descriptor = 
{
    .bLength = 0x0c, //sizeof(AUDIO_InputTerminalDescriptor),
    .bDescriptorType = 0x24, //USB_DTYPE_CSInterface,
    .bDescriptorSubType = 0x02,//USB_AUDIO_DType_INPUT_TERMINAL, 
    .bTerminalID = 0x01,
    .wTerminalType = 0x0201, //Microphone
    .bAssocTerminal = 0, 
    .bNrChannels = 1,
    .wChannelConfig = 0x0001,
    .iChannelNames = 0,
    .iTerminal = 0
},
.AUDIO_output_terminal_descriptor =
{
    .bLength = 0x09, //sizeof(AUDIO_OutputTerminalDescriptor),
    .bDescriptorType = 0x24,//USB_DTYPE_CSInterface,
    .bDescriptorSubType = 0x03, //USB_AUDIO_DType_OUTPUT_TERMINAL,
    .bTerminalID = 3,
    .wTerminalType = 0x0101, //USB Streaming
    .bAssocTerminal = 0,
    .bSourceID = 2, //input terminal
    .iTerminal = 0,
},
/*
.AUDIO_control_selector_unit = 
{
    .bLength = 0x7,
    .bDescriptorType = 0x24,
    .bDescriptorSubType = 0x05,
    .bUnitID = 0x08,
    .bNrInPins = 0x01,
    .baSourceID_1 = 0x0A,
    .iSelector = 0x00
},
*/
.AUDIO_feature_unit_1 = 
{
    .bLength = 0x09, //sizeof(AUDIO_FeatureUnit_1CH),
    .bDescriptorType = 0x24,//USB_DTYPE_CSInterface,
    .bDescriptorSubType = 0x06, //USB_AUDIO_DType_FEATURE_UNIT,
    .bUnitID = 0x02,
    .bSourceID = 0x01,
    .bControlSize = 0x01,
    .bmaControlsMaster = 0x02, //supports  volume controls
    .bmaControls_0 = 0x2,
    .iFeature = 0,
},



.AUDIO_audio_streaming_interface_1 = 
{
    .bLength = 0x09,//sizeof(USB_InterfaceDescriptor),
    .bDescriptorType = 0x04,//USB_DTYPE_Interface,
    .bInterfaceNumber = 0x01,//INTERFACE_AUDIO_STREAMING,
    .bAlternateSetting = 0,
    .bNumEndpoints = 0,
    .bInterfaceClass = 0x01,//AUDIO_INTERFACE_CLASS,
    .bInterfaceSubClass = 0x02,//AUDIO_INTERFACE_SUBCLASS_STREAMING,
    .bInterfaceProtocol = 0,
    .iInterface = 0
},

.AUDIO_audio_streaming_interface_2 =
{
    .bLength = 0x09,//sizeof(USB_InterfaceDescriptor),
    .bDescriptorType = 0x04,//USB_DTYPE_Interface,
    .bInterfaceNumber = 0x01,//INTERFACE_AUDIO_STREAMING,
    .bAlternateSetting = 1,
    .bNumEndpoints = 1,
    .bInterfaceClass = 0x01,//AUDIO_INTERFACE_CLASS,
    .bInterfaceSubClass = 0x02,//AUDIO_INTERFACE_SUBCLASS_STREAMING,
    .bInterfaceProtocol = 0,
    .iInterface = 0
},
.AUDIO_mic_general = 
{
    .bLength = 0x07,// sizeof(AUDIO_GeneralDescriptor),
    .bDescriptorType = 0x24,//USB_DTYPE_CSInterface,
    .bDescriptorSubType = 1,
    .bTerminalLink = 0x03,
    .bDelay = 1,
    .wFormatTag = 0x0001, //PCM
},
.AUDIO_mic_type1 = 
{
    .bLength = sizeof(AUDIO_MicType1Descriptor),
    .bDescriptorType = 0x24,//USB_DTYPE_CSInterface,
    .bDescriptorSubType = 0x02, //FORMAT_TYPE subtype
    .bFormatType = 0x01, //FORMAT_TYPE_1
    .bNrChannels = 1,
    .bSubFrameSize = 0x02, //2bytes per audio subframe
    .bBitResolution = 16, //16 bits per sample,
    .bSamFreqType = 0x01, //1 sampling freq supported
    //.tSamFreq1 = {0x40, 0x1f, 0x00}, //8000Hz
    .tSamFreq1 = {0x80,  0xbb, 0x00}, //48000Hz

},


.AUDIO_mic_endpoint = 
{
    .bLength = 0x09, //sizeof(USB_ISocEndpointDescriptor),
    .bDescriptorType = 0x05, //USB_DTYPE_Endpoint,
    .bEndpointAddress = USB_EP_AUDIO_MIC,
    .bmAttributes = 9, //Isochronous, not shared
    .wMaxPacketSize = USB_MIC_EP_SIZE,
    .bInterval = 1,
    .bRefresh = 0,
    .bSyncAddress = 0,
    
},

.AUDIO_mic_isoc = 
{
    .bLength = 0x07,//sizeof (AUDIO_IsocDataEndpoint),
    .bDescriptorType = 0x25,// USB_AUDIO_DType_CS_ENDPOINT,
    .bDescriptorSubType = 0x01,
    .bmAttributes = 1,
    .bLockDelayUnits=0,
    .wLockDelay = 0
},
};

Is there any other information I need to provide in the descriptors in order for the high level applications to use this device? Or any requests I might not be handling?

Update: I tried the same device on MacOS, I was able to open the device like a normal microphone on Audacity/Voice recorder and record a snippet of data. It seems like the windows usbaudio.sys behaves differently. Any pointers would be helpful.

Update 2: I made some changes to the device. Made it USB2 compliant, added a CDC class in addition to the Audio and used InterfaceAssociationDescriptors to precede those descriptors. I can't point as to why, but this solved the issue of not being opened from high level applications; I can now open and record from audacity.

chamod
  • 516
  • 8
  • 23

0 Answers0