cleanup before merging
[clinton/Smoothieware.git] / gcc4mbed / samples / MSTest / USBDevice / USBAudio / USBAudio.cpp
1 /* Copyright (c) 2010-2011 mbed.org, MIT License
2 *
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:
8 *
9 * The above copyright notice and this permission notice shall be included in all copies or
10 * substantial portions of the Software.
11 *
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.
17 */
18
19 #include "stdint.h"
20 #include "USBAudio.h"
21 #include "USBBusInterface.h"
22 #include "USBAudio_Types.h"
23
24
25
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) {
27 mute = 0;
28 volCur = 0x0080;
29 volMin = 0x0000;
30 volMax = 0x0100;
31 volRes = 0x0004;
32 available = false;
33
34 FREQ = frequency;
35
36 this->channel_nb = channel_nb;
37
38 // stereo -> *2, mono -> *1
39 PACKET_SIZE_ISO = (FREQ / 500) * channel_nb;
40
41 // STEREO -> left and right
42 channel_config = (channel_nb == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
43
44 SOF_handler = false;
45
46 buf_stream = NULL;
47
48 // connect the device
49 USBDevice::connect();
50 }
51
52 bool USBAudio::read(uint8_t * buf) {
53 buf_stream = buf;
54 while (!available);
55 available = false;
56 buf_stream = NULL;
57 return true;
58 }
59
60 bool USBAudio::readNB(uint8_t * buf) {
61 buf_stream = buf;
62 SOF_handler = false;
63 while (!SOF_handler);
64 if (available) {
65 available = false;
66 buf_stream = NULL;
67 return true;
68 }
69 buf_stream = NULL;
70 return false;
71 }
72
73
74 float USBAudio::getVolume() {
75 return (mute) ? 0.0 : (float)volCur/(float)volMax;
76 }
77
78
79 // Called in ISR context on each start of frame
80 void USBAudio::SOF(int frameNumber) {
81 uint16_t size = 0;
82
83 // read the isochronous endpoint
84 if (buf_stream != NULL) {
85 USBDevice::readEP_NB(EP3OUT, buf_stream, &size, PACKET_SIZE_ISO);
86 }
87
88 // if we read something, modify the flag "available"
89 available = (size) ? true : false;
90
91 // activate readings on the isochronous
92 readStart(EP3OUT, PACKET_SIZE_ISO);
93
94 SOF_handler = true;
95 }
96
97
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) {
102 return false;
103 }
104
105 // Configure isochronous endpoint
106 realiseEndpoint(EP3OUT, PACKET_SIZE_ISO, ISOCHRONOUS);
107
108 // activate readings on this endpoint
109 readStart(EP3OUT, PACKET_SIZE_ISO);
110 return true;
111 }
112
113
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) {
118 return true;
119 }
120 if (interface == 1 && (alternate == 0 || alternate == 1)) {
121 return true;
122 }
123 return false;
124 }
125
126
127
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();
135
136 // Process class-specific requests
137 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
138
139 // Feature Unit: Interface = 0, ID = 2
140 if (transfer->setup.wIndex == 0x0200) {
141
142 // Master Channel
143 if ((transfer->setup.wValue & 0xff) == 0) {
144
145 switch (transfer->setup.wValue >> 8) {
146 case MUTE_CONTROL:
147 switch (transfer->setup.bRequest) {
148 case REQUEST_GET_CUR:
149 transfer->remaining = 1;
150 transfer->ptr = &mute;
151 transfer->direction = DEVICE_TO_HOST;
152 success = true;
153 break;
154
155 case REQUEST_SET_CUR:
156 transfer->remaining = 1;
157 transfer->notify = true;
158 transfer->direction = HOST_TO_DEVICE;
159 success = true;
160 break;
161 default:
162 break;
163 }
164 break;
165 case VOLUME_CONTROL:
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;
171 success = true;
172 break;
173 case REQUEST_GET_MIN:
174 transfer->remaining = 2;
175 transfer->ptr = (uint8_t *)&volMin;
176 transfer->direction = DEVICE_TO_HOST;
177 success = true;
178 break;
179 case REQUEST_GET_MAX:
180 transfer->remaining = 2;
181 transfer->ptr = (uint8_t *)&volMax;
182 transfer->direction = DEVICE_TO_HOST;
183 success = true;
184 break;
185 case REQUEST_GET_RES:
186 transfer->remaining = 2;
187 transfer->ptr = (uint8_t *)&volRes;
188 transfer->direction = DEVICE_TO_HOST;
189 success = true;
190 break;
191
192 case REQUEST_SET_CUR:
193 transfer->remaining = 2;
194 transfer->notify = true;
195 transfer->direction = HOST_TO_DEVICE;
196 success = true;
197 break;
198 case REQUEST_SET_MIN:
199 transfer->remaining = 2;
200 transfer->notify = true;
201 transfer->direction = HOST_TO_DEVICE;
202 success = true;
203 break;
204 case REQUEST_SET_MAX:
205 transfer->remaining = 2;
206 transfer->notify = true;
207 transfer->direction = HOST_TO_DEVICE;
208 success = true;
209 break;
210 case REQUEST_SET_RES:
211 transfer->remaining = 2;
212 transfer->notify = true;
213 transfer->direction = HOST_TO_DEVICE;
214 success = true;
215 break;
216 }
217 break;
218 default:
219 break;
220 }
221 }
222 }
223 }
224 return success;
225 }
226
227
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) {
233 case MUTE_CONTROL:
234 switch (transfer->setup.bRequest) {
235 case REQUEST_SET_CUR:
236 mute = data & 0xff;
237 updateVol.call();
238 break;
239 default:
240 break;
241 }
242 break;
243 case VOLUME_CONTROL:
244 switch (transfer->setup.bRequest) {
245 case REQUEST_SET_CUR:
246 volCur = data;
247 updateVol.call();
248 break;
249 default:
250 break;
251 }
252 break;
253 default:
254 break;
255 }
256 }
257
258
259
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) )
270
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)
275
276 uint8_t * USBAudio::configurationDesc() {
277 static uint8_t configDescriptor[] = {
278 // Configuration 1
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
287 50, // bMaxPower
288
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
298 0x00, // iInterface
299
300
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
311
312 // Audio Input Terminal
313 INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
314 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
315 CONTROL_INPUT_TERMINAL, // bDescriptorSubtype
316 0x01, // bTerminalID
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
324 0x00, // iTerminal
325
326 // Audio Feature Unit
327 FEATURE_UNIT_DESCRIPTOR_LENGTH, // bLength
328 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
329 CONTROL_FEATURE_UNIT, // bDescriptorSubtype
330 0x02, // bUnitID
331 0x01, // bSourceID
332 0x01, // bControlSize
333 CONTROL_MUTE |
334 CONTROL_VOLUME, // bmaControls(0)
335 0x00, // bmaControls(1)
336 0x00, // iTerminal
337
338 // Audio Output Terminal
339 OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
340 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
341 CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype
342 0x03, // bTerminalID
343 LSB(TERMINAL_SPEAKER), // wTerminalType
344 MSB(TERMINAL_SPEAKER), // wTerminalType
345 0x00, // bAssocTerminal
346 0x02, // bSourceID
347 0x00, // iTerminal
348
349
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
359 0x00, // iInterface
360
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
370 0x00, // iInterface
371
372 // Audio Streaming Interface
373 STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength
374 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
375 STREAMING_GENERAL, // bDescriptorSubtype
376 0x01, // bTerminalLink
377 0x00, // bDelay
378 LSB(FORMAT_PCM), // wFormatTag
379 MSB(FORMAT_PCM), // wFormatTag
380
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
393
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
401 0x01, // bInterval
402 0x00, // bRefresh
403 0x00, // bSynchAddress
404
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
413
414 // Terminator
415 0 // bLength
416 };
417 return configDescriptor;
418 }
419
420 uint8_t * USBAudio::stringIinterfaceDesc() {
421 static uint8_t stringIinterfaceDescriptor[] = {
422 0x0c, //bLength
423 STRING_DESCRIPTOR, //bDescriptorType 0x03
424 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
425 };
426 return stringIinterfaceDescriptor;
427 }
428
429 uint8_t * USBAudio::stringIproductDesc() {
430 static uint8_t stringIproductDescriptor[] = {
431 0x16, //bLength
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
434 };
435 return stringIproductDescriptor;
436 }