USB Serial application

Fork of USBSerial_HelloWorld by Samuel Mokrani

Committer:
Zaitsev
Date:
Tue Jan 10 20:42:26 2017 +0000
Revision:
10:41552d038a69
USB Serial bi-directional bridge

Who changed what in which revision?

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