USBDevice stack

Dependents:   erg USBSerial_HelloWorld Slingshot SuperScanner ... more

Committer:
samux
Date:
Wed May 30 18:28:11 2012 +0000
Revision:
0:140cdf8e2d60

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 0:140cdf8e2d60 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
samux 0:140cdf8e2d60 2 *
samux 0:140cdf8e2d60 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 0:140cdf8e2d60 4 * and associated documentation files (the "Software"), to deal in the Software without
samux 0:140cdf8e2d60 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
samux 0:140cdf8e2d60 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
samux 0:140cdf8e2d60 7 * Software is furnished to do so, subject to the following conditions:
samux 0:140cdf8e2d60 8 *
samux 0:140cdf8e2d60 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 0:140cdf8e2d60 10 * substantial portions of the Software.
samux 0:140cdf8e2d60 11 *
samux 0:140cdf8e2d60 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 0:140cdf8e2d60 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 0:140cdf8e2d60 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 0:140cdf8e2d60 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 0:140cdf8e2d60 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 0:140cdf8e2d60 17 */
samux 0:140cdf8e2d60 18
samux 0:140cdf8e2d60 19 #include "stdint.h"
samux 0:140cdf8e2d60 20 #include "USBAudio.h"
samux 0:140cdf8e2d60 21 #include "USBAudio_Types.h"
samux 0:140cdf8e2d60 22
samux 0:140cdf8e2d60 23
samux 0:140cdf8e2d60 24
samux 0:140cdf8e2d60 25 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) {
samux 0:140cdf8e2d60 26 mute = 0;
samux 0:140cdf8e2d60 27 volCur = 0x0080;
samux 0:140cdf8e2d60 28 volMin = 0x0000;
samux 0:140cdf8e2d60 29 volMax = 0x0100;
samux 0:140cdf8e2d60 30 volRes = 0x0004;
samux 0:140cdf8e2d60 31 available = false;
samux 0:140cdf8e2d60 32
samux 0:140cdf8e2d60 33 FREQ_IN = frequency_in;
samux 0:140cdf8e2d60 34 FREQ_OUT = frequency_out;
samux 0:140cdf8e2d60 35
samux 0:140cdf8e2d60 36 this->channel_nb_in = channel_nb_in;
samux 0:140cdf8e2d60 37 this->channel_nb_out = channel_nb_out;
samux 0:140cdf8e2d60 38
samux 0:140cdf8e2d60 39 // stereo -> *2, mono -> *1
samux 0:140cdf8e2d60 40 PACKET_SIZE_ISO_IN = (FREQ_IN / 500) * channel_nb_in;
samux 0:140cdf8e2d60 41 PACKET_SIZE_ISO_OUT = (FREQ_OUT / 500) * channel_nb_out;
samux 0:140cdf8e2d60 42
samux 0:140cdf8e2d60 43 // STEREO -> left and right
samux 0:140cdf8e2d60 44 channel_config_in = (channel_nb_in == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
samux 0:140cdf8e2d60 45 channel_config_out = (channel_nb_out == 1) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
samux 0:140cdf8e2d60 46
samux 0:140cdf8e2d60 47 SOF_handler = false;
samux 0:140cdf8e2d60 48
samux 0:140cdf8e2d60 49 buf_stream_out = NULL;
samux 0:140cdf8e2d60 50 buf_stream_in = NULL;
samux 0:140cdf8e2d60 51
samux 0:140cdf8e2d60 52 interruptOUT = false;
samux 0:140cdf8e2d60 53 writeIN = false;
samux 0:140cdf8e2d60 54 interruptIN = false;
samux 0:140cdf8e2d60 55 available = false;
samux 0:140cdf8e2d60 56
samux 0:140cdf8e2d60 57 volume = 0;
samux 0:140cdf8e2d60 58
samux 0:140cdf8e2d60 59 // connect the device
samux 0:140cdf8e2d60 60 USBDevice::connect();
samux 0:140cdf8e2d60 61 }
samux 0:140cdf8e2d60 62
samux 0:140cdf8e2d60 63 bool USBAudio::read(uint8_t * buf) {
samux 0:140cdf8e2d60 64 buf_stream_in = buf;
samux 0:140cdf8e2d60 65 SOF_handler = false;
samux 0:140cdf8e2d60 66 while (!available || !SOF_handler);
samux 0:140cdf8e2d60 67 available = false;
samux 0:140cdf8e2d60 68 return true;
samux 0:140cdf8e2d60 69 }
samux 0:140cdf8e2d60 70
samux 0:140cdf8e2d60 71 bool USBAudio::readNB(uint8_t * buf) {
samux 0:140cdf8e2d60 72 buf_stream_in = buf;
samux 0:140cdf8e2d60 73 SOF_handler = false;
samux 0:140cdf8e2d60 74 while (!SOF_handler);
samux 0:140cdf8e2d60 75 if (available) {
samux 0:140cdf8e2d60 76 available = false;
samux 0:140cdf8e2d60 77 buf_stream_in = NULL;
samux 0:140cdf8e2d60 78 return true;
samux 0:140cdf8e2d60 79 }
samux 0:140cdf8e2d60 80 return false;
samux 0:140cdf8e2d60 81 }
samux 0:140cdf8e2d60 82
samux 0:140cdf8e2d60 83 bool USBAudio::readWrite(uint8_t * buf_read, uint8_t * buf_write) {
samux 0:140cdf8e2d60 84 buf_stream_in = buf_read;
samux 0:140cdf8e2d60 85 SOF_handler = false;
samux 0:140cdf8e2d60 86 writeIN = false;
samux 0:140cdf8e2d60 87 if (interruptIN) {
samux 0:140cdf8e2d60 88 USBDevice::writeNB(EP3IN, buf_write, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
samux 0:140cdf8e2d60 89 } else {
samux 0:140cdf8e2d60 90 buf_stream_out = buf_write;
samux 0:140cdf8e2d60 91 }
samux 0:140cdf8e2d60 92 while (!available);
samux 0:140cdf8e2d60 93 if (interruptIN) {
samux 0:140cdf8e2d60 94 while (!writeIN);
samux 0:140cdf8e2d60 95 }
samux 0:140cdf8e2d60 96 while (!SOF_handler);
samux 0:140cdf8e2d60 97 return true;
samux 0:140cdf8e2d60 98 }
samux 0:140cdf8e2d60 99
samux 0:140cdf8e2d60 100
samux 0:140cdf8e2d60 101 bool USBAudio::write(uint8_t * buf) {
samux 0:140cdf8e2d60 102 writeIN = false;
samux 0:140cdf8e2d60 103 SOF_handler = false;
samux 0:140cdf8e2d60 104 if (interruptIN) {
samux 0:140cdf8e2d60 105 USBDevice::writeNB(EP3IN, buf, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
samux 0:140cdf8e2d60 106 } else {
samux 0:140cdf8e2d60 107 buf_stream_out = buf;
samux 0:140cdf8e2d60 108 }
samux 0:140cdf8e2d60 109 while (!SOF_handler);
samux 0:140cdf8e2d60 110 if (interruptIN) {
samux 0:140cdf8e2d60 111 while (!writeIN);
samux 0:140cdf8e2d60 112 }
samux 0:140cdf8e2d60 113 return true;
samux 0:140cdf8e2d60 114 }
samux 0:140cdf8e2d60 115
samux 0:140cdf8e2d60 116
samux 0:140cdf8e2d60 117 float USBAudio::getVolume() {
samux 0:140cdf8e2d60 118 return (mute) ? 0.0 : volume;
samux 0:140cdf8e2d60 119 }
samux 0:140cdf8e2d60 120
samux 0:140cdf8e2d60 121
samux 0:140cdf8e2d60 122 bool USBAudio::EP3_OUT_callback() {
samux 0:140cdf8e2d60 123 uint32_t size = 0;
samux 0:140cdf8e2d60 124 interruptOUT = true;
samux 0:140cdf8e2d60 125 if (buf_stream_in != NULL) {
samux 0:140cdf8e2d60 126 readEP(EP3OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN);
samux 0:140cdf8e2d60 127 available = true;
samux 0:140cdf8e2d60 128 buf_stream_in = NULL;
samux 0:140cdf8e2d60 129 }
samux 0:140cdf8e2d60 130 readStart(EP3OUT, PACKET_SIZE_ISO_IN);
samux 0:140cdf8e2d60 131 return false;
samux 0:140cdf8e2d60 132 }
samux 0:140cdf8e2d60 133
samux 0:140cdf8e2d60 134
samux 0:140cdf8e2d60 135 bool USBAudio::EP3_IN_callback() {
samux 0:140cdf8e2d60 136 interruptIN = true;
samux 0:140cdf8e2d60 137 writeIN = true;
samux 0:140cdf8e2d60 138 return true;
samux 0:140cdf8e2d60 139 }
samux 0:140cdf8e2d60 140
samux 0:140cdf8e2d60 141
samux 0:140cdf8e2d60 142
samux 0:140cdf8e2d60 143 // Called in ISR context on each start of frame
samux 0:140cdf8e2d60 144 void USBAudio::SOF(int frameNumber) {
samux 0:140cdf8e2d60 145 uint32_t size = 0;
samux 0:140cdf8e2d60 146
samux 0:140cdf8e2d60 147 if (!interruptOUT) {
samux 0:140cdf8e2d60 148 // read the isochronous endpoint
samux 0:140cdf8e2d60 149 if (buf_stream_in != NULL) {
samux 0:140cdf8e2d60 150 if (USBDevice::readEP_NB(EP3OUT, (uint8_t *)buf_stream_in, &size, PACKET_SIZE_ISO_IN)) {
samux 0:140cdf8e2d60 151 if (size) {
samux 0:140cdf8e2d60 152 available = true;
samux 0:140cdf8e2d60 153 readStart(EP3OUT, PACKET_SIZE_ISO_IN);
samux 0:140cdf8e2d60 154 buf_stream_in = NULL;
samux 0:140cdf8e2d60 155 }
samux 0:140cdf8e2d60 156 }
samux 0:140cdf8e2d60 157 }
samux 0:140cdf8e2d60 158 }
samux 0:140cdf8e2d60 159
samux 0:140cdf8e2d60 160 if (!interruptIN) {
samux 0:140cdf8e2d60 161 // write if needed
samux 0:140cdf8e2d60 162 if (buf_stream_out != NULL) {
samux 0:140cdf8e2d60 163 USBDevice::writeNB(EP3IN, (uint8_t *)buf_stream_out, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
samux 0:140cdf8e2d60 164 buf_stream_out = NULL;
samux 0:140cdf8e2d60 165 }
samux 0:140cdf8e2d60 166 }
samux 0:140cdf8e2d60 167
samux 0:140cdf8e2d60 168 SOF_handler = true;
samux 0:140cdf8e2d60 169 }
samux 0:140cdf8e2d60 170
samux 0:140cdf8e2d60 171
samux 0:140cdf8e2d60 172 // Called in ISR context
samux 0:140cdf8e2d60 173 // Set configuration. Return false if the configuration is not supported.
samux 0:140cdf8e2d60 174 bool USBAudio::USBCallback_setConfiguration(uint8_t configuration) {
samux 0:140cdf8e2d60 175 if (configuration != DEFAULT_CONFIGURATION) {
samux 0:140cdf8e2d60 176 return false;
samux 0:140cdf8e2d60 177 }
samux 0:140cdf8e2d60 178
samux 0:140cdf8e2d60 179 // Configure isochronous endpoint
samux 0:140cdf8e2d60 180 realiseEndpoint(EP3OUT, PACKET_SIZE_ISO_IN, ISOCHRONOUS);
samux 0:140cdf8e2d60 181 realiseEndpoint(EP3IN, PACKET_SIZE_ISO_OUT, ISOCHRONOUS);
samux 0:140cdf8e2d60 182
samux 0:140cdf8e2d60 183 // activate readings on this endpoint
samux 0:140cdf8e2d60 184 readStart(EP3OUT, PACKET_SIZE_ISO_IN);
samux 0:140cdf8e2d60 185 return true;
samux 0:140cdf8e2d60 186 }
samux 0:140cdf8e2d60 187
samux 0:140cdf8e2d60 188
samux 0:140cdf8e2d60 189 // Called in ISR context
samux 0:140cdf8e2d60 190 // Set alternate setting. Return false if the alternate setting is not supported
samux 0:140cdf8e2d60 191 bool USBAudio::USBCallback_setInterface(uint16_t interface, uint8_t alternate) {
samux 0:140cdf8e2d60 192 if (interface == 0 && alternate == 0) {
samux 0:140cdf8e2d60 193 return true;
samux 0:140cdf8e2d60 194 }
samux 0:140cdf8e2d60 195 if (interface == 1 && (alternate == 0 || alternate == 1)) {
samux 0:140cdf8e2d60 196 return true;
samux 0:140cdf8e2d60 197 }
samux 0:140cdf8e2d60 198 if (interface == 2 && (alternate == 0 || alternate == 1)) {
samux 0:140cdf8e2d60 199 return true;
samux 0:140cdf8e2d60 200 }
samux 0:140cdf8e2d60 201 return false;
samux 0:140cdf8e2d60 202 }
samux 0:140cdf8e2d60 203
samux 0:140cdf8e2d60 204
samux 0:140cdf8e2d60 205
samux 0:140cdf8e2d60 206 // Called in ISR context
samux 0:140cdf8e2d60 207 // Called by USBDevice on Endpoint0 request
samux 0:140cdf8e2d60 208 // This is used to handle extensions to standard requests and class specific requests.
samux 0:140cdf8e2d60 209 // Return true if class handles this request
samux 0:140cdf8e2d60 210 bool USBAudio::USBCallback_request() {
samux 0:140cdf8e2d60 211 bool success = false;
samux 0:140cdf8e2d60 212 CONTROL_TRANSFER * transfer = getTransferPtr();
samux 0:140cdf8e2d60 213
samux 0:140cdf8e2d60 214 // Process class-specific requests
samux 0:140cdf8e2d60 215 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
samux 0:140cdf8e2d60 216
samux 0:140cdf8e2d60 217 // Feature Unit: Interface = 0, ID = 2
samux 0:140cdf8e2d60 218 if (transfer->setup.wIndex == 0x0200) {
samux 0:140cdf8e2d60 219
samux 0:140cdf8e2d60 220 // Master Channel
samux 0:140cdf8e2d60 221 if ((transfer->setup.wValue & 0xff) == 0) {
samux 0:140cdf8e2d60 222
samux 0:140cdf8e2d60 223 switch (transfer->setup.wValue >> 8) {
samux 0:140cdf8e2d60 224 case MUTE_CONTROL:
samux 0:140cdf8e2d60 225 switch (transfer->setup.bRequest) {
samux 0:140cdf8e2d60 226 case REQUEST_GET_CUR:
samux 0:140cdf8e2d60 227 transfer->remaining = 1;
samux 0:140cdf8e2d60 228 transfer->ptr = &mute;
samux 0:140cdf8e2d60 229 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 230 success = true;
samux 0:140cdf8e2d60 231 break;
samux 0:140cdf8e2d60 232
samux 0:140cdf8e2d60 233 case REQUEST_SET_CUR:
samux 0:140cdf8e2d60 234 transfer->remaining = 1;
samux 0:140cdf8e2d60 235 transfer->notify = true;
samux 0:140cdf8e2d60 236 transfer->direction = HOST_TO_DEVICE;
samux 0:140cdf8e2d60 237 success = true;
samux 0:140cdf8e2d60 238 break;
samux 0:140cdf8e2d60 239 default:
samux 0:140cdf8e2d60 240 break;
samux 0:140cdf8e2d60 241 }
samux 0:140cdf8e2d60 242 break;
samux 0:140cdf8e2d60 243 case VOLUME_CONTROL:
samux 0:140cdf8e2d60 244 switch (transfer->setup.bRequest) {
samux 0:140cdf8e2d60 245 case REQUEST_GET_CUR:
samux 0:140cdf8e2d60 246 transfer->remaining = 2;
samux 0:140cdf8e2d60 247 transfer->ptr = (uint8_t *)&volCur;
samux 0:140cdf8e2d60 248 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 249 success = true;
samux 0:140cdf8e2d60 250 break;
samux 0:140cdf8e2d60 251 case REQUEST_GET_MIN:
samux 0:140cdf8e2d60 252 transfer->remaining = 2;
samux 0:140cdf8e2d60 253 transfer->ptr = (uint8_t *)&volMin;
samux 0:140cdf8e2d60 254 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 255 success = true;
samux 0:140cdf8e2d60 256 break;
samux 0:140cdf8e2d60 257 case REQUEST_GET_MAX:
samux 0:140cdf8e2d60 258 transfer->remaining = 2;
samux 0:140cdf8e2d60 259 transfer->ptr = (uint8_t *)&volMax;
samux 0:140cdf8e2d60 260 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 261 success = true;
samux 0:140cdf8e2d60 262 break;
samux 0:140cdf8e2d60 263 case REQUEST_GET_RES:
samux 0:140cdf8e2d60 264 transfer->remaining = 2;
samux 0:140cdf8e2d60 265 transfer->ptr = (uint8_t *)&volRes;
samux 0:140cdf8e2d60 266 transfer->direction = DEVICE_TO_HOST;
samux 0:140cdf8e2d60 267 success = true;
samux 0:140cdf8e2d60 268 break;
samux 0:140cdf8e2d60 269
samux 0:140cdf8e2d60 270 case REQUEST_SET_CUR:
samux 0:140cdf8e2d60 271 transfer->remaining = 2;
samux 0:140cdf8e2d60 272 transfer->notify = true;
samux 0:140cdf8e2d60 273 transfer->direction = HOST_TO_DEVICE;
samux 0:140cdf8e2d60 274 success = true;
samux 0:140cdf8e2d60 275 break;
samux 0:140cdf8e2d60 276 case REQUEST_SET_MIN:
samux 0:140cdf8e2d60 277 transfer->remaining = 2;
samux 0:140cdf8e2d60 278 transfer->notify = true;
samux 0:140cdf8e2d60 279 transfer->direction = HOST_TO_DEVICE;
samux 0:140cdf8e2d60 280 success = true;
samux 0:140cdf8e2d60 281 break;
samux 0:140cdf8e2d60 282 case REQUEST_SET_MAX:
samux 0:140cdf8e2d60 283 transfer->remaining = 2;
samux 0:140cdf8e2d60 284 transfer->notify = true;
samux 0:140cdf8e2d60 285 transfer->direction = HOST_TO_DEVICE;
samux 0:140cdf8e2d60 286 success = true;
samux 0:140cdf8e2d60 287 break;
samux 0:140cdf8e2d60 288 case REQUEST_SET_RES:
samux 0:140cdf8e2d60 289 transfer->remaining = 2;
samux 0:140cdf8e2d60 290 transfer->notify = true;
samux 0:140cdf8e2d60 291 transfer->direction = HOST_TO_DEVICE;
samux 0:140cdf8e2d60 292 success = true;
samux 0:140cdf8e2d60 293 break;
samux 0:140cdf8e2d60 294 }
samux 0:140cdf8e2d60 295 break;
samux 0:140cdf8e2d60 296 default:
samux 0:140cdf8e2d60 297 break;
samux 0:140cdf8e2d60 298 }
samux 0:140cdf8e2d60 299 }
samux 0:140cdf8e2d60 300 }
samux 0:140cdf8e2d60 301 }
samux 0:140cdf8e2d60 302 return success;
samux 0:140cdf8e2d60 303 }
samux 0:140cdf8e2d60 304
samux 0:140cdf8e2d60 305
samux 0:140cdf8e2d60 306 // Called in ISR context when a data OUT stage has been performed
samux 0:140cdf8e2d60 307 void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {
samux 0:140cdf8e2d60 308 if ((length == 1) || (length == 2)) {
samux 0:140cdf8e2d60 309 uint16_t data = (length == 1) ? *buf : *((uint16_t *)buf);
samux 0:140cdf8e2d60 310 CONTROL_TRANSFER * transfer = getTransferPtr();
samux 0:140cdf8e2d60 311 switch (transfer->setup.wValue >> 8) {
samux 0:140cdf8e2d60 312 case MUTE_CONTROL:
samux 0:140cdf8e2d60 313 switch (transfer->setup.bRequest) {
samux 0:140cdf8e2d60 314 case REQUEST_SET_CUR:
samux 0:140cdf8e2d60 315 mute = data & 0xff;
samux 0:140cdf8e2d60 316 updateVol.call();
samux 0:140cdf8e2d60 317 break;
samux 0:140cdf8e2d60 318 default:
samux 0:140cdf8e2d60 319 break;
samux 0:140cdf8e2d60 320 }
samux 0:140cdf8e2d60 321 break;
samux 0:140cdf8e2d60 322 case VOLUME_CONTROL:
samux 0:140cdf8e2d60 323 switch (transfer->setup.bRequest) {
samux 0:140cdf8e2d60 324 case REQUEST_SET_CUR:
samux 0:140cdf8e2d60 325 volCur = data;
samux 0:140cdf8e2d60 326 volume = (float)volCur/(float)volMax;
samux 0:140cdf8e2d60 327 updateVol.call();
samux 0:140cdf8e2d60 328 break;
samux 0:140cdf8e2d60 329 default:
samux 0:140cdf8e2d60 330 break;
samux 0:140cdf8e2d60 331 }
samux 0:140cdf8e2d60 332 break;
samux 0:140cdf8e2d60 333 default:
samux 0:140cdf8e2d60 334 break;
samux 0:140cdf8e2d60 335 }
samux 0:140cdf8e2d60 336 }
samux 0:140cdf8e2d60 337 }
samux 0:140cdf8e2d60 338
samux 0:140cdf8e2d60 339
samux 0:140cdf8e2d60 340
samux 0:140cdf8e2d60 341 #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 342 + (5 * INTERFACE_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 343 + (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1) \
samux 0:140cdf8e2d60 344 + (2 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 345 + (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 346 + (2 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 347 + (2 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 348 + (2 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \
samux 0:140cdf8e2d60 349 + (2 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \
samux 0:140cdf8e2d60 350 + (2 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) )
samux 0:140cdf8e2d60 351
samux 0:140cdf8e2d60 352 #define TOTAL_CONTROL_INTF_LENGTH (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1 + \
samux 0:140cdf8e2d60 353 2*INPUT_TERMINAL_DESCRIPTOR_LENGTH + \
samux 0:140cdf8e2d60 354 FEATURE_UNIT_DESCRIPTOR_LENGTH + \
samux 0:140cdf8e2d60 355 2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
samux 0:140cdf8e2d60 356
samux 0:140cdf8e2d60 357 uint8_t * USBAudio::configurationDesc() {
samux 0:140cdf8e2d60 358 static uint8_t configDescriptor[] = {
samux 0:140cdf8e2d60 359 // Configuration 1
samux 0:140cdf8e2d60 360 CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 361 CONFIGURATION_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 362 LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
samux 0:140cdf8e2d60 363 MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
samux 0:140cdf8e2d60 364 0x03, // bNumInterfaces
samux 0:140cdf8e2d60 365 DEFAULT_CONFIGURATION, // bConfigurationValue
samux 0:140cdf8e2d60 366 0x00, // iConfiguration
samux 0:140cdf8e2d60 367 0x80, // bmAttributes
samux 0:140cdf8e2d60 368 50, // bMaxPower
samux 0:140cdf8e2d60 369
samux 0:140cdf8e2d60 370 // Interface 0, Alternate Setting 0, Audio Control
samux 0:140cdf8e2d60 371 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 372 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 373 0x00, // bInterfaceNumber
samux 0:140cdf8e2d60 374 0x00, // bAlternateSetting
samux 0:140cdf8e2d60 375 0x00, // bNumEndpoints
samux 0:140cdf8e2d60 376 AUDIO_CLASS, // bInterfaceClass
samux 0:140cdf8e2d60 377 SUBCLASS_AUDIOCONTROL, // bInterfaceSubClass
samux 0:140cdf8e2d60 378 0x00, // bInterfaceProtocol
samux 0:140cdf8e2d60 379 0x00, // iInterface
samux 0:140cdf8e2d60 380
samux 0:140cdf8e2d60 381
samux 0:140cdf8e2d60 382 // Audio Control Interface
samux 0:140cdf8e2d60 383 CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1,// bLength
samux 0:140cdf8e2d60 384 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 385 CONTROL_HEADER, // bDescriptorSubtype
samux 0:140cdf8e2d60 386 LSB(0x0100), // bcdADC (LSB)
samux 0:140cdf8e2d60 387 MSB(0x0100), // bcdADC (MSB)
samux 0:140cdf8e2d60 388 LSB(TOTAL_CONTROL_INTF_LENGTH), // wTotalLength
samux 0:140cdf8e2d60 389 MSB(TOTAL_CONTROL_INTF_LENGTH), // wTotalLength
samux 0:140cdf8e2d60 390 0x02, // bInCollection
samux 0:140cdf8e2d60 391 0x01, // baInterfaceNr
samux 0:140cdf8e2d60 392 0x02, // baInterfaceNr
samux 0:140cdf8e2d60 393
samux 0:140cdf8e2d60 394 // Audio Input Terminal (Speaker)
samux 0:140cdf8e2d60 395 INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 396 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 397 CONTROL_INPUT_TERMINAL, // bDescriptorSubtype
samux 0:140cdf8e2d60 398 0x01, // bTerminalID
samux 0:140cdf8e2d60 399 LSB(TERMINAL_USB_STREAMING), // wTerminalType
samux 0:140cdf8e2d60 400 MSB(TERMINAL_USB_STREAMING), // wTerminalType
samux 0:140cdf8e2d60 401 0x00, // bAssocTerminal
samux 0:140cdf8e2d60 402 channel_nb_in, // bNrChannels
samux 0:140cdf8e2d60 403 LSB(channel_config_in), // wChannelConfig
samux 0:140cdf8e2d60 404 MSB(channel_config_in), // wChannelConfig
samux 0:140cdf8e2d60 405 0x00, // iChannelNames
samux 0:140cdf8e2d60 406 0x00, // iTerminal
samux 0:140cdf8e2d60 407
samux 0:140cdf8e2d60 408 // Audio Feature Unit (Speaker)
samux 0:140cdf8e2d60 409 FEATURE_UNIT_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 410 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 411 CONTROL_FEATURE_UNIT, // bDescriptorSubtype
samux 0:140cdf8e2d60 412 0x02, // bUnitID
samux 0:140cdf8e2d60 413 0x01, // bSourceID
samux 0:140cdf8e2d60 414 0x01, // bControlSize
samux 0:140cdf8e2d60 415 CONTROL_MUTE |
samux 0:140cdf8e2d60 416 CONTROL_VOLUME, // bmaControls(0)
samux 0:140cdf8e2d60 417 0x00, // bmaControls(1)
samux 0:140cdf8e2d60 418 0x00, // iTerminal
samux 0:140cdf8e2d60 419
samux 0:140cdf8e2d60 420 // Audio Output Terminal (Speaker)
samux 0:140cdf8e2d60 421 OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 422 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 423 CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype
samux 0:140cdf8e2d60 424 0x03, // bTerminalID
samux 0:140cdf8e2d60 425 LSB(TERMINAL_SPEAKER), // wTerminalType
samux 0:140cdf8e2d60 426 MSB(TERMINAL_SPEAKER), // wTerminalType
samux 0:140cdf8e2d60 427 0x00, // bAssocTerminal
samux 0:140cdf8e2d60 428 0x02, // bSourceID
samux 0:140cdf8e2d60 429 0x00, // iTerminal
samux 0:140cdf8e2d60 430
samux 0:140cdf8e2d60 431
samux 0:140cdf8e2d60 432 // Audio Input Terminal (Microphone)
samux 0:140cdf8e2d60 433 INPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 434 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 435 CONTROL_INPUT_TERMINAL, // bDescriptorSubtype
samux 0:140cdf8e2d60 436 0x04, // bTerminalID
samux 0:140cdf8e2d60 437 LSB(TERMINAL_MICROPHONE), // wTerminalType
samux 0:140cdf8e2d60 438 MSB(TERMINAL_MICROPHONE), // wTerminalType
samux 0:140cdf8e2d60 439 0x00, // bAssocTerminal
samux 0:140cdf8e2d60 440 channel_nb_out, // bNrChannels
samux 0:140cdf8e2d60 441 LSB(channel_config_out), // wChannelConfig
samux 0:140cdf8e2d60 442 MSB(channel_config_out), // wChannelConfig
samux 0:140cdf8e2d60 443 0x00, // iChannelNames
samux 0:140cdf8e2d60 444 0x00, // iTerminal
samux 0:140cdf8e2d60 445
samux 0:140cdf8e2d60 446 // Audio Output Terminal (Microphone)
samux 0:140cdf8e2d60 447 OUTPUT_TERMINAL_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 448 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 449 CONTROL_OUTPUT_TERMINAL, // bDescriptorSubtype
samux 0:140cdf8e2d60 450 0x05, // bTerminalID
samux 0:140cdf8e2d60 451 LSB(TERMINAL_USB_STREAMING), // wTerminalType
samux 0:140cdf8e2d60 452 MSB(TERMINAL_USB_STREAMING), // wTerminalType
samux 0:140cdf8e2d60 453 0x00, // bAssocTerminal
samux 0:140cdf8e2d60 454 0x04, // bSourceID
samux 0:140cdf8e2d60 455 0x00, // iTerminal
samux 0:140cdf8e2d60 456
samux 0:140cdf8e2d60 457
samux 0:140cdf8e2d60 458
samux 0:140cdf8e2d60 459
samux 0:140cdf8e2d60 460
samux 0:140cdf8e2d60 461
samux 0:140cdf8e2d60 462 // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
samux 0:140cdf8e2d60 463 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 464 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 465 0x01, // bInterfaceNumber
samux 0:140cdf8e2d60 466 0x00, // bAlternateSetting
samux 0:140cdf8e2d60 467 0x00, // bNumEndpoints
samux 0:140cdf8e2d60 468 AUDIO_CLASS, // bInterfaceClass
samux 0:140cdf8e2d60 469 SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
samux 0:140cdf8e2d60 470 0x00, // bInterfaceProtocol
samux 0:140cdf8e2d60 471 0x00, // iInterface
samux 0:140cdf8e2d60 472
samux 0:140cdf8e2d60 473 // Interface 1, Alternate Setting 1, Audio Streaming - Operational
samux 0:140cdf8e2d60 474 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 475 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 476 0x01, // bInterfaceNumber
samux 0:140cdf8e2d60 477 0x01, // bAlternateSetting
samux 0:140cdf8e2d60 478 0x01, // bNumEndpoints
samux 0:140cdf8e2d60 479 AUDIO_CLASS, // bInterfaceClass
samux 0:140cdf8e2d60 480 SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
samux 0:140cdf8e2d60 481 0x00, // bInterfaceProtocol
samux 0:140cdf8e2d60 482 0x00, // iInterface
samux 0:140cdf8e2d60 483
samux 0:140cdf8e2d60 484 // Audio Streaming Interface
samux 0:140cdf8e2d60 485 STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 486 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 487 STREAMING_GENERAL, // bDescriptorSubtype
samux 0:140cdf8e2d60 488 0x01, // bTerminalLink
samux 0:140cdf8e2d60 489 0x00, // bDelay
samux 0:140cdf8e2d60 490 LSB(FORMAT_PCM), // wFormatTag
samux 0:140cdf8e2d60 491 MSB(FORMAT_PCM), // wFormatTag
samux 0:140cdf8e2d60 492
samux 0:140cdf8e2d60 493 // Audio Type I Format
samux 0:140cdf8e2d60 494 FORMAT_TYPE_I_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 495 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 496 STREAMING_FORMAT_TYPE, // bDescriptorSubtype
samux 0:140cdf8e2d60 497 FORMAT_TYPE_I, // bFormatType
samux 0:140cdf8e2d60 498 channel_nb_in, // bNrChannels
samux 0:140cdf8e2d60 499 0x02, // bSubFrameSize
samux 0:140cdf8e2d60 500 16, // bBitResolution
samux 0:140cdf8e2d60 501 0x01, // bSamFreqType
samux 0:140cdf8e2d60 502 LSB(FREQ_IN), // tSamFreq
samux 0:140cdf8e2d60 503 (FREQ_IN >> 8) & 0xff, // tSamFreq
samux 0:140cdf8e2d60 504 (FREQ_IN >> 16) & 0xff, // tSamFreq
samux 0:140cdf8e2d60 505
samux 0:140cdf8e2d60 506 // Endpoint - Standard Descriptor
samux 0:140cdf8e2d60 507 ENDPOINT_DESCRIPTOR_LENGTH + 2, // bLength
samux 0:140cdf8e2d60 508 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 509 PHY_TO_DESC(EPISO_OUT), // bEndpointAddress
samux 0:140cdf8e2d60 510 E_ISOCHRONOUS, // bmAttributes
samux 0:140cdf8e2d60 511 LSB(PACKET_SIZE_ISO_IN), // wMaxPacketSize
samux 0:140cdf8e2d60 512 MSB(PACKET_SIZE_ISO_IN), // wMaxPacketSize
samux 0:140cdf8e2d60 513 0x01, // bInterval
samux 0:140cdf8e2d60 514 0x00, // bRefresh
samux 0:140cdf8e2d60 515 0x00, // bSynchAddress
samux 0:140cdf8e2d60 516
samux 0:140cdf8e2d60 517 // Endpoint - Audio Streaming
samux 0:140cdf8e2d60 518 STREAMING_ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 519 ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 520 ENDPOINT_GENERAL, // bDescriptor
samux 0:140cdf8e2d60 521 0x00, // bmAttributes
samux 0:140cdf8e2d60 522 0x00, // bLockDelayUnits
samux 0:140cdf8e2d60 523 LSB(0x0000), // wLockDelay
samux 0:140cdf8e2d60 524 MSB(0x0000), // wLockDelay
samux 0:140cdf8e2d60 525
samux 0:140cdf8e2d60 526
samux 0:140cdf8e2d60 527
samux 0:140cdf8e2d60 528
samux 0:140cdf8e2d60 529
samux 0:140cdf8e2d60 530
samux 0:140cdf8e2d60 531
samux 0:140cdf8e2d60 532 // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
samux 0:140cdf8e2d60 533 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 534 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 535 0x02, // bInterfaceNumber
samux 0:140cdf8e2d60 536 0x00, // bAlternateSetting
samux 0:140cdf8e2d60 537 0x00, // bNumEndpoints
samux 0:140cdf8e2d60 538 AUDIO_CLASS, // bInterfaceClass
samux 0:140cdf8e2d60 539 SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
samux 0:140cdf8e2d60 540 0x00, // bInterfaceProtocol
samux 0:140cdf8e2d60 541 0x00, // iInterface
samux 0:140cdf8e2d60 542
samux 0:140cdf8e2d60 543 // Interface 1, Alternate Setting 1, Audio Streaming - Operational
samux 0:140cdf8e2d60 544 INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 545 INTERFACE_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 546 0x02, // bInterfaceNumber
samux 0:140cdf8e2d60 547 0x01, // bAlternateSetting
samux 0:140cdf8e2d60 548 0x01, // bNumEndpoints
samux 0:140cdf8e2d60 549 AUDIO_CLASS, // bInterfaceClass
samux 0:140cdf8e2d60 550 SUBCLASS_AUDIOSTREAMING, // bInterfaceSubClass
samux 0:140cdf8e2d60 551 0x00, // bInterfaceProtocol
samux 0:140cdf8e2d60 552 0x00, // iInterface
samux 0:140cdf8e2d60 553
samux 0:140cdf8e2d60 554 // Audio Streaming Interface
samux 0:140cdf8e2d60 555 STREAMING_INTERFACE_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 556 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 557 SUBCLASS_AUDIOCONTROL, // bDescriptorSubtype
samux 0:140cdf8e2d60 558 0x05, // bTerminalLink (output terminal microphone)
samux 0:140cdf8e2d60 559 0x01, // bDelay
samux 0:140cdf8e2d60 560 0x01, // wFormatTag
samux 0:140cdf8e2d60 561 0x00, // wFormatTag
samux 0:140cdf8e2d60 562
samux 0:140cdf8e2d60 563 // Audio Type I Format
samux 0:140cdf8e2d60 564 FORMAT_TYPE_I_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 565 INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 566 SUBCLASS_AUDIOSTREAMING, // bDescriptorSubtype
samux 0:140cdf8e2d60 567 FORMAT_TYPE_I, // bFormatType
samux 0:140cdf8e2d60 568 channel_nb_out, // bNrChannels
samux 0:140cdf8e2d60 569 0x02, // bSubFrameSize
samux 0:140cdf8e2d60 570 0x10, // bBitResolution
samux 0:140cdf8e2d60 571 0x01, // bSamFreqType
samux 0:140cdf8e2d60 572 LSB(FREQ_OUT), // tSamFreq
samux 0:140cdf8e2d60 573 (FREQ_OUT >> 8) & 0xff, // tSamFreq
samux 0:140cdf8e2d60 574 (FREQ_OUT >> 16) & 0xff, // tSamFreq
samux 0:140cdf8e2d60 575
samux 0:140cdf8e2d60 576 // Endpoint - Standard Descriptor
samux 0:140cdf8e2d60 577 ENDPOINT_DESCRIPTOR_LENGTH + 2, // bLength
samux 0:140cdf8e2d60 578 ENDPOINT_DESCRIPTOR, // bDescriptorType
samux 0:140cdf8e2d60 579 PHY_TO_DESC(EPISO_IN), // bEndpointAddress
samux 0:140cdf8e2d60 580 E_ISOCHRONOUS, // bmAttributes
samux 0:140cdf8e2d60 581 LSB(PACKET_SIZE_ISO_OUT), // wMaxPacketSize
samux 0:140cdf8e2d60 582 MSB(PACKET_SIZE_ISO_OUT), // wMaxPacketSize
samux 0:140cdf8e2d60 583 0x01, // bInterval
samux 0:140cdf8e2d60 584 0x00, // bRefresh
samux 0:140cdf8e2d60 585 0x00, // bSynchAddress
samux 0:140cdf8e2d60 586
samux 0:140cdf8e2d60 587 // Endpoint - Audio Streaming
samux 0:140cdf8e2d60 588 STREAMING_ENDPOINT_DESCRIPTOR_LENGTH, // bLength
samux 0:140cdf8e2d60 589 ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType
samux 0:140cdf8e2d60 590 ENDPOINT_GENERAL, // bDescriptor
samux 0:140cdf8e2d60 591 0x00, // bmAttributes
samux 0:140cdf8e2d60 592 0x00, // bLockDelayUnits
samux 0:140cdf8e2d60 593 LSB(0x0000), // wLockDelay
samux 0:140cdf8e2d60 594 MSB(0x0000), // wLockDelay
samux 0:140cdf8e2d60 595
samux 0:140cdf8e2d60 596 // Terminator
samux 0:140cdf8e2d60 597 0 // bLength
samux 0:140cdf8e2d60 598 };
samux 0:140cdf8e2d60 599 return configDescriptor;
samux 0:140cdf8e2d60 600 }
samux 0:140cdf8e2d60 601
samux 0:140cdf8e2d60 602 uint8_t * USBAudio::stringIinterfaceDesc() {
samux 0:140cdf8e2d60 603 static uint8_t stringIinterfaceDescriptor[] = {
samux 0:140cdf8e2d60 604 0x0c, //bLength
samux 0:140cdf8e2d60 605 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 0:140cdf8e2d60 606 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
samux 0:140cdf8e2d60 607 };
samux 0:140cdf8e2d60 608 return stringIinterfaceDescriptor;
samux 0:140cdf8e2d60 609 }
samux 0:140cdf8e2d60 610
samux 0:140cdf8e2d60 611 uint8_t * USBAudio::stringIproductDesc() {
samux 0:140cdf8e2d60 612 static uint8_t stringIproductDescriptor[] = {
samux 0:140cdf8e2d60 613 0x16, //bLength
samux 0:140cdf8e2d60 614 STRING_DESCRIPTOR, //bDescriptorType 0x03
samux 0:140cdf8e2d60 615 'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
samux 0:140cdf8e2d60 616 };
samux 0:140cdf8e2d60 617 return stringIproductDescriptor;
samux 0:140cdf8e2d60 618 }