usb device

Committer:
ppo
Date:
Sat May 14 17:24:10 2022 +0000
Revision:
0:c1e89c49eae5
commit

Who changed what in which revision?

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