USBDevice with Nucleo 32L476RG support

Dependents:   ObCP_ENSMM_V2020_Test_Accelero

Committer:
jimbaud
Date:
Wed Sep 30 11:26:16 2020 +0000
Revision:
72:14a22343c610
Parent:
70:2c525a50f1b6
USBDevice with Nucleo 32L476RG support

Who changed what in which revision?

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