1 /* Copyright (c) 2010-2011 mbed.org, MIT License
3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4 * and associated documentation files (the "Software"), to deal in the Software without
5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
7 * Software is furnished to do so, subject to the following conditions:
9 * The above copyright notice and this permission notice shall be included in all copies or
10 * substantial portions of the Software.
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 #include "USBBusInterface.h"
22 #include "USBAudio_Types.h"
26 USBAudio::USBAudio(uint32_t frequency
, uint8_t channel_nb
, uint16_t vendor_id
, uint16_t product_id
, uint16_t product_release
): USBDevice(vendor_id
, product_id
, product_release
) {
36 this->channel_nb
= channel_nb
;
38 // stereo -> *2, mono -> *1
39 PACKET_SIZE_ISO
= (FREQ
/ 500) * channel_nb
;
41 // STEREO -> left and right
42 channel_config
= (channel_nb
== 1) ? CHANNEL_M
: CHANNEL_L
+ CHANNEL_R
;
52 bool USBAudio::read(uint8_t * buf
) {
60 bool USBAudio::readNB(uint8_t * buf
) {
74 float USBAudio::getVolume() {
75 return (mute
) ? 0.0 : (float)volCur
/(float)volMax
;
79 // Called in ISR context on each start of frame
80 void USBAudio::SOF(int frameNumber
) {
83 // read the isochronous endpoint
84 if (buf_stream
!= NULL
) {
85 USBDevice::readEP_NB(EP3OUT
, buf_stream
, &size
, PACKET_SIZE_ISO
);
88 // if we read something, modify the flag "available"
89 available
= (size
) ? true : false;
91 // activate readings on the isochronous
92 readStart(EP3OUT
, PACKET_SIZE_ISO
);
98 // Called in ISR context
99 // Set configuration. Return false if the configuration is not supported.
100 bool USBAudio::USBCallback_setConfiguration(uint8_t configuration
) {
101 if (configuration
!= DEFAULT_CONFIGURATION
) {
105 // Configure isochronous endpoint
106 realiseEndpoint(EP3OUT
, PACKET_SIZE_ISO
, ISOCHRONOUS
);
108 // activate readings on this endpoint
109 readStart(EP3OUT
, PACKET_SIZE_ISO
);
114 // Called in ISR context
115 // Set alternate setting. Return false if the alternate setting is not supported
116 bool USBAudio::USBCallback_setInterface(uint16_t interface
, uint8_t alternate
) {
117 if (interface
== 0 && alternate
== 0) {
120 if (interface
== 1 && (alternate
== 0 || alternate
== 1)) {
128 // Called in ISR context
129 // Called by USBDevice on Endpoint0 request
130 // This is used to handle extensions to standard requests and class specific requests.
131 // Return true if class handles this request
132 bool USBAudio::USBCallback_request() {
133 bool success
= false;
134 CONTROL_TRANSFER
* transfer
= getTransferPtr();
136 // Process class-specific requests
137 if (transfer
->setup
.bmRequestType
.Type
== CLASS_TYPE
) {
139 // Feature Unit: Interface = 0, ID = 2
140 if (transfer
->setup
.wIndex
== 0x0200) {
143 if ((transfer
->setup
.wValue
& 0xff) == 0) {
145 switch (transfer
->setup
.wValue
>> 8) {
147 switch (transfer
->setup
.bRequest
) {
148 case REQUEST_GET_CUR
:
149 transfer
->remaining
= 1;
150 transfer
->ptr
= &mute
;
151 transfer
->direction
= DEVICE_TO_HOST
;
155 case REQUEST_SET_CUR
:
156 transfer
->remaining
= 1;
157 transfer
->notify
= true;
158 transfer
->direction
= HOST_TO_DEVICE
;
166 switch (transfer
->setup
.bRequest
) {
167 case REQUEST_GET_CUR
:
168 transfer
->remaining
= 2;
169 transfer
->ptr
= (uint8_t *)&volCur
;
170 transfer
->direction
= DEVICE_TO_HOST
;
173 case REQUEST_GET_MIN
:
174 transfer
->remaining
= 2;
175 transfer
->ptr
= (uint8_t *)&volMin
;
176 transfer
->direction
= DEVICE_TO_HOST
;
179 case REQUEST_GET_MAX
:
180 transfer
->remaining
= 2;
181 transfer
->ptr
= (uint8_t *)&volMax
;
182 transfer
->direction
= DEVICE_TO_HOST
;
185 case REQUEST_GET_RES
:
186 transfer
->remaining
= 2;
187 transfer
->ptr
= (uint8_t *)&volRes
;
188 transfer
->direction
= DEVICE_TO_HOST
;
192 case REQUEST_SET_CUR
:
193 transfer
->remaining
= 2;
194 transfer
->notify
= true;
195 transfer
->direction
= HOST_TO_DEVICE
;
198 case REQUEST_SET_MIN
:
199 transfer
->remaining
= 2;
200 transfer
->notify
= true;
201 transfer
->direction
= HOST_TO_DEVICE
;
204 case REQUEST_SET_MAX
:
205 transfer
->remaining
= 2;
206 transfer
->notify
= true;
207 transfer
->direction
= HOST_TO_DEVICE
;
210 case REQUEST_SET_RES
:
211 transfer
->remaining
= 2;
212 transfer
->notify
= true;
213 transfer
->direction
= HOST_TO_DEVICE
;
228 // Called in ISR context when a data OUT stage has been performed
229 void USBAudio::USBCallback_requestCompleted(uint8_t * buf
, uint16_t length
) {
230 uint16_t data
= *((uint16_t *)buf
);
231 CONTROL_TRANSFER
* transfer
= getTransferPtr();
232 switch (transfer
->setup
.wValue
>> 8) {
234 switch (transfer
->setup
.bRequest
) {
235 case REQUEST_SET_CUR
:
244 switch (transfer
->setup
.bRequest
) {
245 case REQUEST_SET_CUR
:
260 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
261 + (3 * INTERFACE_DESCRIPTOR_LENGTH) \
262 + (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH) \
263 + (1 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \
264 + (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \
265 + (1 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \
266 + (1 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \
267 + (1 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \
268 + (1 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \
269 + (1 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) )
271 #define TOTAL_CONTROL_INTF_LENGTH (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + \
272 INPUT_TERMINAL_DESCRIPTOR_LENGTH + \
273 FEATURE_UNIT_DESCRIPTOR_LENGTH + \
274 OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
276 uint8_t * USBAudio::configurationDesc() {
277 static uint8_t configDescriptor
[] = {
279 CONFIGURATION_DESCRIPTOR_LENGTH
, // bLength
280 CONFIGURATION_DESCRIPTOR
, // bDescriptorType
281 LSB(TOTAL_DESCRIPTOR_LENGTH
), // wTotalLength (LSB)
282 MSB(TOTAL_DESCRIPTOR_LENGTH
), // wTotalLength (MSB)
283 0x02, // bNumInterfaces
284 DEFAULT_CONFIGURATION
, // bConfigurationValue
285 0x00, // iConfiguration
286 0x80, // bmAttributes
289 // Interface 0, Alternate Setting 0, Audio Control
290 INTERFACE_DESCRIPTOR_LENGTH
, // bLength
291 INTERFACE_DESCRIPTOR
, // bDescriptorType
292 0x00, // bInterfaceNumber
293 0x00, // bAlternateSetting
294 0x00, // bNumEndpoints
295 AUDIO_CLASS
, // bInterfaceClass
296 SUBCLASS_AUDIOCONTROL
, // bInterfaceSubClass
297 0x00, // bInterfaceProtocol
301 // Audio Control Interface
302 CONTROL_INTERFACE_DESCRIPTOR_LENGTH
, // bLength
303 INTERFACE_DESCRIPTOR_TYPE
, // bDescriptorType
304 CONTROL_HEADER
, // bDescriptorSubtype
305 LSB(0x0100), // bcdADC (LSB)
306 MSB(0x0100), // bcdADC (MSB)
307 LSB(TOTAL_CONTROL_INTF_LENGTH
), // wTotalLength
308 MSB(TOTAL_CONTROL_INTF_LENGTH
), // wTotalLength
309 0x01, // bInCollection
310 0x01, // baInterfaceNr
312 // Audio Input Terminal
313 INPUT_TERMINAL_DESCRIPTOR_LENGTH
, // bLength
314 INTERFACE_DESCRIPTOR_TYPE
, // bDescriptorType
315 CONTROL_INPUT_TERMINAL
, // bDescriptorSubtype
317 LSB(TERMINAL_USB_STREAMING
), // wTerminalType
318 MSB(TERMINAL_USB_STREAMING
), // wTerminalType
319 0x00, // bAssocTerminal
320 channel_nb
, // bNrChannels
321 LSB(channel_config
), // wChannelConfig
322 MSB(channel_config
), // wChannelConfig
323 0x00, // iChannelNames
326 // Audio Feature Unit
327 FEATURE_UNIT_DESCRIPTOR_LENGTH
, // bLength
328 INTERFACE_DESCRIPTOR_TYPE
, // bDescriptorType
329 CONTROL_FEATURE_UNIT
, // bDescriptorSubtype
332 0x01, // bControlSize
334 CONTROL_VOLUME
, // bmaControls(0)
335 0x00, // bmaControls(1)
338 // Audio Output Terminal
339 OUTPUT_TERMINAL_DESCRIPTOR_LENGTH
, // bLength
340 INTERFACE_DESCRIPTOR_TYPE
, // bDescriptorType
341 CONTROL_OUTPUT_TERMINAL
, // bDescriptorSubtype
343 LSB(TERMINAL_SPEAKER
), // wTerminalType
344 MSB(TERMINAL_SPEAKER
), // wTerminalType
345 0x00, // bAssocTerminal
350 // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
351 INTERFACE_DESCRIPTOR_LENGTH
, // bLength
352 INTERFACE_DESCRIPTOR
, // bDescriptorType
353 0x01, // bInterfaceNumber
354 0x00, // bAlternateSetting
355 0x00, // bNumEndpoints
356 AUDIO_CLASS
, // bInterfaceClass
357 SUBCLASS_AUDIOSTREAMING
, // bInterfaceSubClass
358 0x00, // bInterfaceProtocol
361 // Interface 1, Alternate Setting 1, Audio Streaming - Operational
362 INTERFACE_DESCRIPTOR_LENGTH
, // bLength
363 INTERFACE_DESCRIPTOR
, // bDescriptorType
364 0x01, // bInterfaceNumber
365 0x01, // bAlternateSetting
366 0x01, // bNumEndpoints
367 AUDIO_CLASS
, // bInterfaceClass
368 SUBCLASS_AUDIOSTREAMING
, // bInterfaceSubClass
369 0x00, // bInterfaceProtocol
372 // Audio Streaming Interface
373 STREAMING_INTERFACE_DESCRIPTOR_LENGTH
, // bLength
374 INTERFACE_DESCRIPTOR_TYPE
, // bDescriptorType
375 STREAMING_GENERAL
, // bDescriptorSubtype
376 0x01, // bTerminalLink
378 LSB(FORMAT_PCM
), // wFormatTag
379 MSB(FORMAT_PCM
), // wFormatTag
381 // Audio Type I Format
382 FORMAT_TYPE_I_DESCRIPTOR_LENGTH
, // bLength
383 INTERFACE_DESCRIPTOR_TYPE
, // bDescriptorType
384 STREAMING_FORMAT_TYPE
, // bDescriptorSubtype
385 FORMAT_TYPE_I
, // bFormatType
386 channel_nb
, // bNrChannels
387 0x02, // bSubFrameSize
388 16, // bBitResolution
389 0x01, // bSamFreqType
390 LSB(FREQ
), // tSamFreq
391 (FREQ
>> 8) & 0xff, // tSamFreq
392 (FREQ
>> 16) & 0xff, // tSamFreq
394 // Endpoint - Standard Descriptor
395 ENDPOINT_DESCRIPTOR_LENGTH
+ 2, // bLength
396 ENDPOINT_DESCRIPTOR
, // bDescriptorType
397 PHY_TO_DESC(EPISO_OUT
), // bEndpointAddress
398 E_ISOCHRONOUS
, // bmAttributes
399 LSB(PACKET_SIZE_ISO
), // wMaxPacketSize
400 MSB(PACKET_SIZE_ISO
), // wMaxPacketSize
403 0x00, // bSynchAddress
405 // Endpoint - Audio Streaming
406 STREAMING_ENDPOINT_DESCRIPTOR_LENGTH
, // bLength
407 ENDPOINT_DESCRIPTOR_TYPE
, // bDescriptorType
408 ENDPOINT_GENERAL
, // bDescriptor
409 0x00, // bmAttributes
410 0x00, // bLockDelayUnits
411 LSB(0x0000), // wLockDelay
412 MSB(0x0000), // wLockDelay
417 return configDescriptor
;
420 uint8_t * USBAudio::stringIinterfaceDesc() {
421 static uint8_t stringIinterfaceDescriptor
[] = {
423 STRING_DESCRIPTOR
, //bDescriptorType 0x03
424 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
426 return stringIinterfaceDescriptor
;
429 uint8_t * USBAudio::stringIproductDesc() {
430 static uint8_t stringIproductDescriptor
[] = {
432 STRING_DESCRIPTOR
, //bDescriptorType 0x03
433 'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
435 return stringIproductDescriptor
;