619 řádky
26 KiB
C++
619 řádky
26 KiB
C++
|
/* Copyright (c) 2010-2011 mbed.org, MIT License
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||
|
* and associated documentation files (the "Software"), to deal in the Software without
|
||
|
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
|
||
|
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in all copies or
|
||
|
* substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||
|
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include "stdint.h"
|
||
|
#include "USBAudio.h"
|
||
|
#include "USBAudio_Types.h"
|
||
|
|
||
|
|
||
|
|
||
|
USBAudio::USBAudio(uint32_t frequency_in, uint8_t channel_nb_in, uint32_t frequency_out, uint8_t channel_nb_out, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
|
||
|
mute = 0;
|
||
|
volCur = 0x0080;
|
||
|
volMin = 0x0000;
|
||
|
volMax = 0x0100;
|
||
|
volRes = 0x0004;
|
||
|
available = false;
|
||
|
|
||
|
FREQ_IN = frequency_in;
|
||
|
FREQ_OUT = frequency_out;
|
||
|
|
||
|
this->channel_nb_in = channel_nb_in;
|
||
|
this->channel_nb_out = channel_nb_out;
|
||
|
|
||
|
// stereo -> *2, mono -> *1
|
||
|
PACKET_SIZE_ISO_IN = (FREQ_IN / 500) * channel_nb_in;
|
||
|
PACKET_SIZE_ISO_OUT = (FREQ_OUT / 500) * channel_nb_out;
|
||
|
|
||
|
// STEREO -> left and right
|
||
|
channel_config_in = (channel_nb_in == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
|
||
|
channel_config_out = (channel_nb_out == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
|
||
|
|
||
|
SOF_handler = false;
|
||
|
|
||
|
buf_stream_out = NULL;
|
||
|
buf_stream_in = NULL;
|
||
|
|
||
|
interruptOUT = false;
|
||
|
writeIN = false;
|
||
|
interruptIN = false;
|
||
|
available = false;
|
||
|
|
||
|
volume = 0;
|
||
|
|
||
|
// connect the device
|
||
|
USBDevice::connect();
|
||
|
}
|
||
|
|
||
|
bool USBAudio::read(uint8_t * buf) {
|
||
|
buf_stream_in = buf;
|
||
|
SOF_handler = false;
|
||
|
while (!available || !SOF_handler);
|
||
|
available = false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool USBAudio::readNB(uint8_t * buf) {
|
||
|
buf_stream_in = buf;
|
||
|
SOF_handler = false;
|
||
|
while (!SOF_handler);
|
||
|
if (available) {
|
||
|
available = false;
|
||
|
buf_stream_in = NULL;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool USBAudio::readWrite(uint8_t * buf_read, uint8_t * buf_write) {
|
||
|
buf_stream_in = buf_read;
|
||
|
SOF_handler = false;
|
||
|
writeIN = false;
|
||
|
if (interruptIN) {
|
||
|
USBDevice::writeNB(EP3IN, buf_write, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
|
||
|
} else {
|
||
|
buf_stream_out = buf_write;
|
||
|
}
|
||
|
while (!available);
|
||
|
if (interruptIN) {
|
||
|
while (!writeIN);
|
||
|
}
|
||
|
while (!SOF_handler);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool USBAudio::write(uint8_t * buf) {
|
||
|
writeIN = false;
|
||
|
SOF_handler = false;
|
||
|
if (interruptIN) {
|
||
|
USBDevice::writeNB(EP3IN, buf, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
|
||
|
} else {
|
||
|
buf_stream_out = buf;
|
||
|
}
|
||
|
while (!SOF_handler);
|
||
|
if (interruptIN) {
|
||
|
while (!writeIN);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
float USBAudio::getVolume() {
|
||
|
return (mute) ? 0.0 : volume;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool USBAudio::EPISO_OUT_callback() {
|
||
|
uint32_t size = 0;
|
||
|
interruptOUT = true;
|
||
|
if (buf_stream_in != NULL) {
|
||
|
readEP(EP3OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN);
|
||
|
available = true;
|
||
|
buf_stream_in = NULL;
|
||
|
}
|
||
|
readStart(EP3OUT, PACKET_SIZE_ISO_IN);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool USBAudio::EPISO_IN_callback() {
|
||
|
interruptIN = true;
|
||
|
writeIN = true;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Called in ISR context on each start of frame
|
||
|
void USBAudio::SOF(int frameNumber) {
|
||
|
uint32_t size = 0;
|
||
|
|
||
|
if (!interruptOUT) {
|
||
|
// read the isochronous endpoint
|
||
|
if (buf_stream_in != NULL) {
|
||
|
if (USBDevice::readEP_NB(EP3OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN)) {
|
||
|
if (size) {
|
||
|
available = true;
|
||
|
readStart(EP3OUT, PACKET_SIZE_ISO_IN);
|
||
|
buf_stream_in = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!interruptIN) {
|
||
|
// write if needed
|
||
|
if (buf_stream_out != NULL) {
|
||
|
USBDevice::writeNB(EP3IN, (uint8_t *)buf_stream_out, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
|
||
|
buf_stream_out = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SOF_handler = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Called in ISR context
|
||
|
// Set configuration. Return false if the configuration is not supported.
|
||
|
bool USBAudio::USBCallback_setConfiguration(uint8_t configuration) {
|
||
|
if (configuration != DEFAULT_CONFIGURATION) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Configure isochronous endpoint
|
||
|
realiseEndpoint(EP3OUT, PACKET_SIZE_ISO_IN, ISOCHRONOUS);
|
||
|
realiseEndpoint(EP3IN, PACKET_SIZE_ISO_OUT, ISOCHRONOUS);
|
||
|
|
||
|
// activate readings on this endpoint
|
||
|
readStart(EP3OUT, PACKET_SIZE_ISO_IN);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Called in ISR context
|
||
|
// Set alternate setting. Return false if the alternate setting is not supported
|
||
|
bool USBAudio::USBCallback_setInterface(uint16_t interface, uint8_t alternate) {
|
||
|
if (interface == 0 && alternate == 0) {
|
||
|
return true;
|
||
|
}
|
||
|
if (interface == 1 && (alternate == 0 || alternate == 1)) {
|
||
|
return true;
|
||
|
}
|
||
|
if (interface == 2 && (alternate == 0 || alternate == 1)) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Called in ISR context
|
||
|
// Called by USBDevice on Endpoint0 request
|
||
|
// This is used to handle extensions to standard requests and class specific requests.
|
||
|
// Return true if class handles this request
|
||
|
bool USBAudio::USBCallback_request() {
|
||
|
bool success = false;
|
||
|
CONTROL_TRANSFER * transfer = getTransferPtr();
|
||
|
|
||
|
// Process class-specific requests
|
||
|
if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
|
||
|
|
||
|
// Feature Unit: Interface = 0, ID = 2
|
||
|
if (transfer->setup.wIndex == 0x0200) {
|
||
|
|
||
|
// Master Channel
|
||
|
if ((transfer->setup.wValue & 0xff) == 0) {
|
||
|
|
||
|
switch (transfer->setup.wValue >> 8) {
|
||
|
case MUTE_CONTROL:
|
||
|
switch (transfer->setup.bRequest) {
|
||
|
case REQUEST_GET_CUR:
|
||
|
transfer->remaining = 1;
|
||
|
transfer->ptr = &mute;
|
||
|
transfer->direction = DEVICE_TO_HOST;
|
||
|
success = true;
|
||
|
break;
|
||
|
|
||
|
case REQUEST_SET_CUR:
|
||
|
transfer->remaining = 1;
|
||
|
transfer->notify = true;
|
||
|
transfer->direction = HOST_TO_DEVICE;
|
||
|
success = true;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case VOLUME_CONTROL:
|
||
|
switch (transfer->setup.bRequest) {
|
||
|
case REQUEST_GET_CUR:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->ptr = (uint8_t *)&volCur;
|
||
|
transfer->direction = DEVICE_TO_HOST;
|
||
|
success = true;
|
||
|
break;
|
||
|
case REQUEST_GET_MIN:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->ptr = (uint8_t *)&volMin;
|
||
|
transfer->direction = DEVICE_TO_HOST;
|
||
|
success = true;
|
||
|
break;
|
||
|
case REQUEST_GET_MAX:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->ptr = (uint8_t *)&volMax;
|
||
|
transfer->direction = DEVICE_TO_HOST;
|
||
|
success = true;
|
||
|
break;
|
||
|
case REQUEST_GET_RES:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->ptr = (uint8_t *)&volRes;
|
||
|
transfer->direction = DEVICE_TO_HOST;
|
||
|
success = true;
|
||
|
break;
|
||
|
|
||
|
case REQUEST_SET_CUR:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->notify = true;
|
||
|
transfer->direction = HOST_TO_DEVICE;
|
||
|
success = true;
|
||
|
break;
|
||
|
case REQUEST_SET_MIN:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->notify = true;
|
||
|
transfer->direction = HOST_TO_DEVICE;
|
||
|
success = true;
|
||
|
break;
|
||
|
case REQUEST_SET_MAX:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->notify = true;
|
||
|
transfer->direction = HOST_TO_DEVICE;
|
||
|
success = true;
|
||
|
break;
|
||
|
case REQUEST_SET_RES:
|
||
|
transfer->remaining = 2;
|
||
|
transfer->notify = true;
|
||
|
transfer->direction = HOST_TO_DEVICE;
|
||
|
success = true;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Called in ISR context when a data OUT stage has been performed
|
||
|
void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {
|
||
|
if ((length == 1) || (length == 2)) {
|
||
|
uint16_t data = (length == 1) ? *buf : *((uint16_t *)buf);
|
||
|
CONTROL_TRANSFER * transfer = getTransferPtr();
|
||
|
switch (transfer->setup.wValue >> 8) {
|
||
|
case MUTE_CONTROL:
|
||
|
switch (transfer->setup.bRequest) {
|
||
|
case REQUEST_SET_CUR:
|
||
|
mute = data & 0xff;
|
||
|
updateVol.call();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case VOLUME_CONTROL:
|
||
|
switch (transfer->setup.bRequest) {
|
||
|
case REQUEST_SET_CUR:
|
||
|
volCur = data;
|
||
|
volume = (float)volCur/(float)volMax;
|
||
|
updateVol.call();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
|
||
|
+ (5 * INTERFACE_DESCRIPTOR_LENGTH) \
|
||
|
+ (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1) \
|
||
|
+ (2 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \
|
||
|
+ (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \
|
||
|
+ (2 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \
|
||
|
+ (2 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \
|
||
|
+ (2 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \
|
||
|
+ (2 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \
|
||
|
+ (2 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) )
|
||
|
|
||
|
#define TOTAL_CONTROL_INTF_LENGTH (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1 + \
|
||
|
2*INPUT_TERMINAL_DESCRIPTOR_LENGTH + \
|
||
|
FEATURE_UNIT_DESCRIPTOR_LENGTH + \
|
||
|
2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
|
||
|
|
||
|
uint8_t * USBAudio::configurationDesc() {
|
||
|
static uint8_t configDescriptor[] = {
|
||
|
// Configuration 1
|
||
|
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
|
||
|
CONFIGURATION_DESCRIPTOR, // bDescriptorType
|
||
|
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
|
||
|
MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
|
||
|
0x03, // bNumInterfaces
|
||
|
DEFAULT_CONFIGURATION, // bConfigurationValue
|
||
|
0x00, // iConfiguration
|
||
|
0x80, // bmAttributes
|
||
|
50, // bMaxPower
|
||
|
|
||
|
// Interface 0, Alternate Setting 0, Audio Control
|
||
|
INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR, // bDescriptorType
|
||
|
0x00, // bInterfaceNumber
|
||
|
0x00, // bAlternateSetting
|
||
|
0x00, // bNumEndpoints
|
||
|
AUDIO_CLASS, // bInterfaceClass
|
||
|
SUBCLASS_AUDIOCONTROL, // bInterfaceSubClass
|
||
|
0x00, // bInterfaceProtocol
|
||
|
0x00, // iInterface
|
||
|
|
||
|
|
||
|
// Audio Control Interface
|
||
|
CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1,// bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
CONTROL_HEADER, // bDescriptorSubtype
|
||
|
LSB(0x0100), // bcdADC (LSB)
|
||
|
MSB(0x0100), // bcdADC (MSB)
|
||
|
LSB(TOTAL_CONTROL_INTF_LENGTH), // wTotalLength
|
||
|
MSB(TOTAL_CONTROL_INTF_LENGTH), // wTotalLength
|
||
|
0x02, // bInCollection
|
||
|
0x01, // baInterfaceNr
|
||
|
0x02, // baInterfaceNr
|
||
|
|
||
|
// Audio Input Terminal (Speaker)
|
||
|
INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
CONTROL_INPUT_TERMINAL, // bDescriptorSubtype
|
||
|
0x01, // bTerminalID
|
||
|
LSB(TERMINAL_USB_STREAMING), // wTerminalType
|
||
|
MSB(TERMINAL_USB_STREAMING), // wTerminalType
|
||
|
0x00, // bAssocTerminal
|
||
|
channel_nb_in, // bNrChannels
|
||
|
(uint8_t)(LSB(channel_config_in)), // wChannelConfig
|
||
|
(uint8_t)(MSB(channel_config_in)), // wChannelConfig
|
||
|
0x00, // iChannelNames
|
||
|
0x00, // iTerminal
|
||
|
|
||
|
// Audio Feature Unit (Speaker)
|
||
|
FEATURE_UNIT_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
CONTROL_FEATURE_UNIT, // bDescriptorSubtype
|
||
|
0x02, // bUnitID
|
||
|
0x01, // bSourceID
|
||
|
0x01, // bControlSize
|
||
|
CONTROL_MUTE |
|
||
|
CONTROL_VOLUME, // bmaControls(0)
|
||
|
0x00, // bmaControls(1)
|
||
|
0x00, // iTerminal
|
||
|
|
||
|
// Audio Output Terminal (Speaker)
|
||
|
OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype
|
||
|
0x03, // bTerminalID
|
||
|
LSB(TERMINAL_SPEAKER), // wTerminalType
|
||
|
MSB(TERMINAL_SPEAKER), // wTerminalType
|
||
|
0x00, // bAssocTerminal
|
||
|
0x02, // bSourceID
|
||
|
0x00, // iTerminal
|
||
|
|
||
|
|
||
|
// Audio Input Terminal (Microphone)
|
||
|
INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
CONTROL_INPUT_TERMINAL, // bDescriptorSubtype
|
||
|
0x04, // bTerminalID
|
||
|
LSB(TERMINAL_MICROPHONE), // wTerminalType
|
||
|
MSB(TERMINAL_MICROPHONE), // wTerminalType
|
||
|
0x00, // bAssocTerminal
|
||
|
channel_nb_out, // bNrChannels
|
||
|
(uint8_t)(LSB(channel_config_out)), // wChannelConfig
|
||
|
(uint8_t)(MSB(channel_config_out)), // wChannelConfig
|
||
|
0x00, // iChannelNames
|
||
|
0x00, // iTerminal
|
||
|
|
||
|
// Audio Output Terminal (Microphone)
|
||
|
OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype
|
||
|
0x05, // bTerminalID
|
||
|
LSB(TERMINAL_USB_STREAMING), // wTerminalType
|
||
|
MSB(TERMINAL_USB_STREAMING), // wTerminalType
|
||
|
0x00, // bAssocTerminal
|
||
|
0x04, // bSourceID
|
||
|
0x00, // iTerminal
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
|
||
|
INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR, // bDescriptorType
|
||
|
0x01, // bInterfaceNumber
|
||
|
0x00, // bAlternateSetting
|
||
|
0x00, // bNumEndpoints
|
||
|
AUDIO_CLASS, // bInterfaceClass
|
||
|
SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
|
||
|
0x00, // bInterfaceProtocol
|
||
|
0x00, // iInterface
|
||
|
|
||
|
// Interface 1, Alternate Setting 1, Audio Streaming - Operational
|
||
|
INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR, // bDescriptorType
|
||
|
0x01, // bInterfaceNumber
|
||
|
0x01, // bAlternateSetting
|
||
|
0x01, // bNumEndpoints
|
||
|
AUDIO_CLASS, // bInterfaceClass
|
||
|
SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
|
||
|
0x00, // bInterfaceProtocol
|
||
|
0x00, // iInterface
|
||
|
|
||
|
// Audio Streaming Interface
|
||
|
STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
STREAMING_GENERAL, // bDescriptorSubtype
|
||
|
0x01, // bTerminalLink
|
||
|
0x00, // bDelay
|
||
|
LSB(FORMAT_PCM), // wFormatTag
|
||
|
MSB(FORMAT_PCM), // wFormatTag
|
||
|
|
||
|
// Audio Type I Format
|
||
|
FORMAT_TYPE_I_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
STREAMING_FORMAT_TYPE, // bDescriptorSubtype
|
||
|
FORMAT_TYPE_I, // bFormatType
|
||
|
channel_nb_in, // bNrChannels
|
||
|
0x02, // bSubFrameSize
|
||
|
16, // bBitResolution
|
||
|
0x01, // bSamFreqType
|
||
|
(uint8_t)(LSB(FREQ_IN)), // tSamFreq
|
||
|
(uint8_t)((FREQ_IN >> 8) & 0xff), // tSamFreq
|
||
|
(uint8_t)((FREQ_IN >> 16) & 0xff), // tSamFreq
|
||
|
|
||
|
// Endpoint - Standard Descriptor
|
||
|
ENDPOINT_DESCRIPTOR_LENGTH + 2, // bLength
|
||
|
ENDPOINT_DESCRIPTOR, // bDescriptorType
|
||
|
PHY_TO_DESC(EPISO_OUT), // bEndpointAddress
|
||
|
E_ISOCHRONOUS, // bmAttributes
|
||
|
(uint8_t)(LSB(PACKET_SIZE_ISO_IN)), // wMaxPacketSize
|
||
|
(uint8_t)(MSB(PACKET_SIZE_ISO_IN)), // wMaxPacketSize
|
||
|
0x01, // bInterval
|
||
|
0x00, // bRefresh
|
||
|
0x00, // bSynchAddress
|
||
|
|
||
|
// Endpoint - Audio Streaming
|
||
|
STREAMING_ENDPOINT_DESCRIPTOR_LENGTH, // bLength
|
||
|
ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
ENDPOINT_GENERAL, // bDescriptor
|
||
|
0x00, // bmAttributes
|
||
|
0x00, // bLockDelayUnits
|
||
|
LSB(0x0000), // wLockDelay
|
||
|
MSB(0x0000), // wLockDelay
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
|
||
|
INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR, // bDescriptorType
|
||
|
0x02, // bInterfaceNumber
|
||
|
0x00, // bAlternateSetting
|
||
|
0x00, // bNumEndpoints
|
||
|
AUDIO_CLASS, // bInterfaceClass
|
||
|
SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
|
||
|
0x00, // bInterfaceProtocol
|
||
|
0x00, // iInterface
|
||
|
|
||
|
// Interface 1, Alternate Setting 1, Audio Streaming - Operational
|
||
|
INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR, // bDescriptorType
|
||
|
0x02, // bInterfaceNumber
|
||
|
0x01, // bAlternateSetting
|
||
|
0x01, // bNumEndpoints
|
||
|
AUDIO_CLASS, // bInterfaceClass
|
||
|
SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
|
||
|
0x00, // bInterfaceProtocol
|
||
|
0x00, // iInterface
|
||
|
|
||
|
// Audio Streaming Interface
|
||
|
STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
SUBCLASS_AUDIOCONTROL, // bDescriptorSubtype
|
||
|
0x05, // bTerminalLink (output terminal microphone)
|
||
|
0x01, // bDelay
|
||
|
0x01, // wFormatTag
|
||
|
0x00, // wFormatTag
|
||
|
|
||
|
// Audio Type I Format
|
||
|
FORMAT_TYPE_I_DESCRIPTOR_LENGTH, // bLength
|
||
|
INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
SUBCLASS_AUDIOSTREAMING, // bDescriptorSubtype
|
||
|
FORMAT_TYPE_I, // bFormatType
|
||
|
channel_nb_out, // bNrChannels
|
||
|
0x02, // bSubFrameSize
|
||
|
0x10, // bBitResolution
|
||
|
0x01, // bSamFreqType
|
||
|
(uint8_t)(LSB(FREQ_OUT)), // tSamFreq
|
||
|
(uint8_t)((FREQ_OUT >> 8) & 0xff), // tSamFreq
|
||
|
(uint8_t)((FREQ_OUT >> 16) & 0xff), // tSamFreq
|
||
|
|
||
|
// Endpoint - Standard Descriptor
|
||
|
ENDPOINT_DESCRIPTOR_LENGTH + 2, // bLength
|
||
|
ENDPOINT_DESCRIPTOR, // bDescriptorType
|
||
|
PHY_TO_DESC(EPISO_IN), // bEndpointAddress
|
||
|
E_ISOCHRONOUS, // bmAttributes
|
||
|
(uint8_t)(LSB(PACKET_SIZE_ISO_OUT)), // wMaxPacketSize
|
||
|
(uint8_t)(MSB(PACKET_SIZE_ISO_OUT)), // wMaxPacketSize
|
||
|
0x01, // bInterval
|
||
|
0x00, // bRefresh
|
||
|
0x00, // bSynchAddress
|
||
|
|
||
|
// Endpoint - Audio Streaming
|
||
|
STREAMING_ENDPOINT_DESCRIPTOR_LENGTH, // bLength
|
||
|
ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType
|
||
|
ENDPOINT_GENERAL, // bDescriptor
|
||
|
0x00, // bmAttributes
|
||
|
0x00, // bLockDelayUnits
|
||
|
LSB(0x0000), // wLockDelay
|
||
|
MSB(0x0000), // wLockDelay
|
||
|
|
||
|
// Terminator
|
||
|
0 // bLength
|
||
|
};
|
||
|
return configDescriptor;
|
||
|
}
|
||
|
|
||
|
uint8_t * USBAudio::stringIinterfaceDesc() {
|
||
|
static uint8_t stringIinterfaceDescriptor[] = {
|
||
|
0x0c, //bLength
|
||
|
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||
|
'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
|
||
|
};
|
||
|
return stringIinterfaceDescriptor;
|
||
|
}
|
||
|
|
||
|
uint8_t * USBAudio::stringIproductDesc() {
|
||
|
static uint8_t stringIproductDescriptor[] = {
|
||
|
0x16, //bLength
|
||
|
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||
|
'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
|
||
|
};
|
||
|
return stringIproductDescriptor;
|
||
|
}
|