Miha Bokan / Mbed 2 deprecated FRDM-KL46Z-LAB2_C

Dependencies:   MMA8451Q USBDevice mbed

Committer:
mdestroyer
Date:
Mon May 12 12:14:48 2014 +0000
Revision:
0:22a7d22635fa
Spremenil ime lab1 v lab2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mdestroyer 0:22a7d22635fa 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
mdestroyer 0:22a7d22635fa 2 *
mdestroyer 0:22a7d22635fa 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
mdestroyer 0:22a7d22635fa 4 * and associated documentation files (the "Software"), to deal in the Software without
mdestroyer 0:22a7d22635fa 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
mdestroyer 0:22a7d22635fa 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
mdestroyer 0:22a7d22635fa 7 * Software is furnished to do so, subject to the following conditions:
mdestroyer 0:22a7d22635fa 8 *
mdestroyer 0:22a7d22635fa 9 * The above copyright notice and this permission notice shall be included in all copies or
mdestroyer 0:22a7d22635fa 10 * substantial portions of the Software.
mdestroyer 0:22a7d22635fa 11 *
mdestroyer 0:22a7d22635fa 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
mdestroyer 0:22a7d22635fa 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
mdestroyer 0:22a7d22635fa 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
mdestroyer 0:22a7d22635fa 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
mdestroyer 0:22a7d22635fa 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
mdestroyer 0:22a7d22635fa 17 */
mdestroyer 0:22a7d22635fa 18
mdestroyer 0:22a7d22635fa 19 #include "stdint.h"
mdestroyer 0:22a7d22635fa 20 #include "USBMSD.h"
mdestroyer 0:22a7d22635fa 21
mdestroyer 0:22a7d22635fa 22 #define DISK_OK 0x00
mdestroyer 0:22a7d22635fa 23 #define NO_INIT 0x01
mdestroyer 0:22a7d22635fa 24 #define NO_DISK 0x02
mdestroyer 0:22a7d22635fa 25 #define WRITE_PROTECT 0x04
mdestroyer 0:22a7d22635fa 26
mdestroyer 0:22a7d22635fa 27 #define CBW_Signature 0x43425355
mdestroyer 0:22a7d22635fa 28 #define CSW_Signature 0x53425355
mdestroyer 0:22a7d22635fa 29
mdestroyer 0:22a7d22635fa 30 // SCSI Commands
mdestroyer 0:22a7d22635fa 31 #define TEST_UNIT_READY 0x00
mdestroyer 0:22a7d22635fa 32 #define REQUEST_SENSE 0x03
mdestroyer 0:22a7d22635fa 33 #define FORMAT_UNIT 0x04
mdestroyer 0:22a7d22635fa 34 #define INQUIRY 0x12
mdestroyer 0:22a7d22635fa 35 #define MODE_SELECT6 0x15
mdestroyer 0:22a7d22635fa 36 #define MODE_SENSE6 0x1A
mdestroyer 0:22a7d22635fa 37 #define START_STOP_UNIT 0x1B
mdestroyer 0:22a7d22635fa 38 #define MEDIA_REMOVAL 0x1E
mdestroyer 0:22a7d22635fa 39 #define READ_FORMAT_CAPACITIES 0x23
mdestroyer 0:22a7d22635fa 40 #define READ_CAPACITY 0x25
mdestroyer 0:22a7d22635fa 41 #define READ10 0x28
mdestroyer 0:22a7d22635fa 42 #define WRITE10 0x2A
mdestroyer 0:22a7d22635fa 43 #define VERIFY10 0x2F
mdestroyer 0:22a7d22635fa 44 #define READ12 0xA8
mdestroyer 0:22a7d22635fa 45 #define WRITE12 0xAA
mdestroyer 0:22a7d22635fa 46 #define MODE_SELECT10 0x55
mdestroyer 0:22a7d22635fa 47 #define MODE_SENSE10 0x5A
mdestroyer 0:22a7d22635fa 48
mdestroyer 0:22a7d22635fa 49 // MSC class specific requests
mdestroyer 0:22a7d22635fa 50 #define MSC_REQUEST_RESET 0xFF
mdestroyer 0:22a7d22635fa 51 #define MSC_REQUEST_GET_MAX_LUN 0xFE
mdestroyer 0:22a7d22635fa 52
mdestroyer 0:22a7d22635fa 53 #define DEFAULT_CONFIGURATION (1)
mdestroyer 0:22a7d22635fa 54
mdestroyer 0:22a7d22635fa 55 // max packet size
mdestroyer 0:22a7d22635fa 56 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK
mdestroyer 0:22a7d22635fa 57
mdestroyer 0:22a7d22635fa 58 // CSW Status
mdestroyer 0:22a7d22635fa 59 enum Status {
mdestroyer 0:22a7d22635fa 60 CSW_PASSED,
mdestroyer 0:22a7d22635fa 61 CSW_FAILED,
mdestroyer 0:22a7d22635fa 62 CSW_ERROR,
mdestroyer 0:22a7d22635fa 63 };
mdestroyer 0:22a7d22635fa 64
mdestroyer 0:22a7d22635fa 65
mdestroyer 0:22a7d22635fa 66 USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) {
mdestroyer 0:22a7d22635fa 67 stage = READ_CBW;
mdestroyer 0:22a7d22635fa 68 memset((void *)&cbw, 0, sizeof(CBW));
mdestroyer 0:22a7d22635fa 69 memset((void *)&csw, 0, sizeof(CSW));
mdestroyer 0:22a7d22635fa 70 page = NULL;
mdestroyer 0:22a7d22635fa 71 }
mdestroyer 0:22a7d22635fa 72
mdestroyer 0:22a7d22635fa 73 USBMSD::~USBMSD() {
mdestroyer 0:22a7d22635fa 74 disconnect();
mdestroyer 0:22a7d22635fa 75 }
mdestroyer 0:22a7d22635fa 76
mdestroyer 0:22a7d22635fa 77
mdestroyer 0:22a7d22635fa 78 // Called in ISR context to process a class specific request
mdestroyer 0:22a7d22635fa 79 bool USBMSD::USBCallback_request(void) {
mdestroyer 0:22a7d22635fa 80
mdestroyer 0:22a7d22635fa 81 bool success = false;
mdestroyer 0:22a7d22635fa 82 CONTROL_TRANSFER * transfer = getTransferPtr();
mdestroyer 0:22a7d22635fa 83 static uint8_t maxLUN[1] = {0};
mdestroyer 0:22a7d22635fa 84
mdestroyer 0:22a7d22635fa 85 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
mdestroyer 0:22a7d22635fa 86 switch (transfer->setup.bRequest) {
mdestroyer 0:22a7d22635fa 87 case MSC_REQUEST_RESET:
mdestroyer 0:22a7d22635fa 88 reset();
mdestroyer 0:22a7d22635fa 89 success = true;
mdestroyer 0:22a7d22635fa 90 break;
mdestroyer 0:22a7d22635fa 91 case MSC_REQUEST_GET_MAX_LUN:
mdestroyer 0:22a7d22635fa 92 transfer->remaining = 1;
mdestroyer 0:22a7d22635fa 93 transfer->ptr = maxLUN;
mdestroyer 0:22a7d22635fa 94 transfer->direction = DEVICE_TO_HOST;
mdestroyer 0:22a7d22635fa 95 success = true;
mdestroyer 0:22a7d22635fa 96 break;
mdestroyer 0:22a7d22635fa 97 default:
mdestroyer 0:22a7d22635fa 98 break;
mdestroyer 0:22a7d22635fa 99 }
mdestroyer 0:22a7d22635fa 100 }
mdestroyer 0:22a7d22635fa 101
mdestroyer 0:22a7d22635fa 102 return success;
mdestroyer 0:22a7d22635fa 103 }
mdestroyer 0:22a7d22635fa 104
mdestroyer 0:22a7d22635fa 105
mdestroyer 0:22a7d22635fa 106 bool USBMSD::connect(bool blocking) {
mdestroyer 0:22a7d22635fa 107 //disk initialization
mdestroyer 0:22a7d22635fa 108 if (disk_status() & NO_INIT) {
mdestroyer 0:22a7d22635fa 109 if (disk_initialize()) {
mdestroyer 0:22a7d22635fa 110 return false;
mdestroyer 0:22a7d22635fa 111 }
mdestroyer 0:22a7d22635fa 112 }
mdestroyer 0:22a7d22635fa 113
mdestroyer 0:22a7d22635fa 114 // get number of blocks
mdestroyer 0:22a7d22635fa 115 BlockCount = disk_sectors();
mdestroyer 0:22a7d22635fa 116
mdestroyer 0:22a7d22635fa 117 // get memory size
mdestroyer 0:22a7d22635fa 118 MemorySize = disk_size();
mdestroyer 0:22a7d22635fa 119
mdestroyer 0:22a7d22635fa 120 if (BlockCount > 0) {
mdestroyer 0:22a7d22635fa 121 BlockSize = MemorySize / BlockCount;
mdestroyer 0:22a7d22635fa 122 if (BlockSize != 0) {
mdestroyer 0:22a7d22635fa 123 free(page);
mdestroyer 0:22a7d22635fa 124 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t));
mdestroyer 0:22a7d22635fa 125 if (page == NULL)
mdestroyer 0:22a7d22635fa 126 return false;
mdestroyer 0:22a7d22635fa 127 }
mdestroyer 0:22a7d22635fa 128 } else {
mdestroyer 0:22a7d22635fa 129 return false;
mdestroyer 0:22a7d22635fa 130 }
mdestroyer 0:22a7d22635fa 131
mdestroyer 0:22a7d22635fa 132 //connect the device
mdestroyer 0:22a7d22635fa 133 USBDevice::connect(blocking);
mdestroyer 0:22a7d22635fa 134 return true;
mdestroyer 0:22a7d22635fa 135 }
mdestroyer 0:22a7d22635fa 136
mdestroyer 0:22a7d22635fa 137 void USBMSD::disconnect() {
mdestroyer 0:22a7d22635fa 138 //De-allocate MSD page size:
mdestroyer 0:22a7d22635fa 139 free(page);
mdestroyer 0:22a7d22635fa 140 page = NULL;
mdestroyer 0:22a7d22635fa 141 USBDevice::disconnect();
mdestroyer 0:22a7d22635fa 142 }
mdestroyer 0:22a7d22635fa 143
mdestroyer 0:22a7d22635fa 144 void USBMSD::reset() {
mdestroyer 0:22a7d22635fa 145 stage = READ_CBW;
mdestroyer 0:22a7d22635fa 146 }
mdestroyer 0:22a7d22635fa 147
mdestroyer 0:22a7d22635fa 148
mdestroyer 0:22a7d22635fa 149 // Called in ISR context called when a data is received
mdestroyer 0:22a7d22635fa 150 bool USBMSD::EP2_OUT_callback() {
mdestroyer 0:22a7d22635fa 151 uint32_t size = 0;
mdestroyer 0:22a7d22635fa 152 uint8_t buf[MAX_PACKET_SIZE_EPBULK];
mdestroyer 0:22a7d22635fa 153 readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 154 switch (stage) {
mdestroyer 0:22a7d22635fa 155 // the device has to decode the CBW received
mdestroyer 0:22a7d22635fa 156 case READ_CBW:
mdestroyer 0:22a7d22635fa 157 CBWDecode(buf, size);
mdestroyer 0:22a7d22635fa 158 break;
mdestroyer 0:22a7d22635fa 159
mdestroyer 0:22a7d22635fa 160 // the device has to receive data from the host
mdestroyer 0:22a7d22635fa 161 case PROCESS_CBW:
mdestroyer 0:22a7d22635fa 162 switch (cbw.CB[0]) {
mdestroyer 0:22a7d22635fa 163 case WRITE10:
mdestroyer 0:22a7d22635fa 164 case WRITE12:
mdestroyer 0:22a7d22635fa 165 memoryWrite(buf, size);
mdestroyer 0:22a7d22635fa 166 break;
mdestroyer 0:22a7d22635fa 167 case VERIFY10:
mdestroyer 0:22a7d22635fa 168 memoryVerify(buf, size);
mdestroyer 0:22a7d22635fa 169 break;
mdestroyer 0:22a7d22635fa 170 }
mdestroyer 0:22a7d22635fa 171 break;
mdestroyer 0:22a7d22635fa 172
mdestroyer 0:22a7d22635fa 173 // an error has occured: stall endpoint and send CSW
mdestroyer 0:22a7d22635fa 174 default:
mdestroyer 0:22a7d22635fa 175 stallEndpoint(EPBULK_OUT);
mdestroyer 0:22a7d22635fa 176 csw.Status = CSW_ERROR;
mdestroyer 0:22a7d22635fa 177 sendCSW();
mdestroyer 0:22a7d22635fa 178 break;
mdestroyer 0:22a7d22635fa 179 }
mdestroyer 0:22a7d22635fa 180
mdestroyer 0:22a7d22635fa 181 //reactivate readings on the OUT bulk endpoint
mdestroyer 0:22a7d22635fa 182 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 183 return true;
mdestroyer 0:22a7d22635fa 184 }
mdestroyer 0:22a7d22635fa 185
mdestroyer 0:22a7d22635fa 186 // Called in ISR context when a data has been transferred
mdestroyer 0:22a7d22635fa 187 bool USBMSD::EP2_IN_callback() {
mdestroyer 0:22a7d22635fa 188 switch (stage) {
mdestroyer 0:22a7d22635fa 189
mdestroyer 0:22a7d22635fa 190 // the device has to send data to the host
mdestroyer 0:22a7d22635fa 191 case PROCESS_CBW:
mdestroyer 0:22a7d22635fa 192 switch (cbw.CB[0]) {
mdestroyer 0:22a7d22635fa 193 case READ10:
mdestroyer 0:22a7d22635fa 194 case READ12:
mdestroyer 0:22a7d22635fa 195 memoryRead();
mdestroyer 0:22a7d22635fa 196 break;
mdestroyer 0:22a7d22635fa 197 }
mdestroyer 0:22a7d22635fa 198 break;
mdestroyer 0:22a7d22635fa 199
mdestroyer 0:22a7d22635fa 200 //the device has to send a CSW
mdestroyer 0:22a7d22635fa 201 case SEND_CSW:
mdestroyer 0:22a7d22635fa 202 sendCSW();
mdestroyer 0:22a7d22635fa 203 break;
mdestroyer 0:22a7d22635fa 204
mdestroyer 0:22a7d22635fa 205 // the host has received the CSW -> we wait a CBW
mdestroyer 0:22a7d22635fa 206 case WAIT_CSW:
mdestroyer 0:22a7d22635fa 207 stage = READ_CBW;
mdestroyer 0:22a7d22635fa 208 break;
mdestroyer 0:22a7d22635fa 209
mdestroyer 0:22a7d22635fa 210 // an error has occured
mdestroyer 0:22a7d22635fa 211 default:
mdestroyer 0:22a7d22635fa 212 stallEndpoint(EPBULK_IN);
mdestroyer 0:22a7d22635fa 213 sendCSW();
mdestroyer 0:22a7d22635fa 214 break;
mdestroyer 0:22a7d22635fa 215 }
mdestroyer 0:22a7d22635fa 216 return true;
mdestroyer 0:22a7d22635fa 217 }
mdestroyer 0:22a7d22635fa 218
mdestroyer 0:22a7d22635fa 219
mdestroyer 0:22a7d22635fa 220 void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) {
mdestroyer 0:22a7d22635fa 221
mdestroyer 0:22a7d22635fa 222 if ((addr + size) > MemorySize) {
mdestroyer 0:22a7d22635fa 223 size = MemorySize - addr;
mdestroyer 0:22a7d22635fa 224 stage = ERROR;
mdestroyer 0:22a7d22635fa 225 stallEndpoint(EPBULK_OUT);
mdestroyer 0:22a7d22635fa 226 }
mdestroyer 0:22a7d22635fa 227
mdestroyer 0:22a7d22635fa 228 // we fill an array in RAM of 1 block before writing it in memory
mdestroyer 0:22a7d22635fa 229 for (int i = 0; i < size; i++)
mdestroyer 0:22a7d22635fa 230 page[addr%BlockSize + i] = buf[i];
mdestroyer 0:22a7d22635fa 231
mdestroyer 0:22a7d22635fa 232 // if the array is filled, write it in memory
mdestroyer 0:22a7d22635fa 233 if (!((addr + size)%BlockSize)) {
mdestroyer 0:22a7d22635fa 234 if (!(disk_status() & WRITE_PROTECT)) {
mdestroyer 0:22a7d22635fa 235 disk_write(page, addr/BlockSize);
mdestroyer 0:22a7d22635fa 236 }
mdestroyer 0:22a7d22635fa 237 }
mdestroyer 0:22a7d22635fa 238
mdestroyer 0:22a7d22635fa 239 addr += size;
mdestroyer 0:22a7d22635fa 240 length -= size;
mdestroyer 0:22a7d22635fa 241 csw.DataResidue -= size;
mdestroyer 0:22a7d22635fa 242
mdestroyer 0:22a7d22635fa 243 if ((!length) || (stage != PROCESS_CBW)) {
mdestroyer 0:22a7d22635fa 244 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED;
mdestroyer 0:22a7d22635fa 245 sendCSW();
mdestroyer 0:22a7d22635fa 246 }
mdestroyer 0:22a7d22635fa 247 }
mdestroyer 0:22a7d22635fa 248
mdestroyer 0:22a7d22635fa 249 void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) {
mdestroyer 0:22a7d22635fa 250 uint32_t n;
mdestroyer 0:22a7d22635fa 251
mdestroyer 0:22a7d22635fa 252 if ((addr + size) > MemorySize) {
mdestroyer 0:22a7d22635fa 253 size = MemorySize - addr;
mdestroyer 0:22a7d22635fa 254 stage = ERROR;
mdestroyer 0:22a7d22635fa 255 stallEndpoint(EPBULK_OUT);
mdestroyer 0:22a7d22635fa 256 }
mdestroyer 0:22a7d22635fa 257
mdestroyer 0:22a7d22635fa 258 // beginning of a new block -> load a whole block in RAM
mdestroyer 0:22a7d22635fa 259 if (!(addr%BlockSize))
mdestroyer 0:22a7d22635fa 260 disk_read(page, addr/BlockSize);
mdestroyer 0:22a7d22635fa 261
mdestroyer 0:22a7d22635fa 262 // info are in RAM -> no need to re-read memory
mdestroyer 0:22a7d22635fa 263 for (n = 0; n < size; n++) {
mdestroyer 0:22a7d22635fa 264 if (page[addr%BlockSize + n] != buf[n]) {
mdestroyer 0:22a7d22635fa 265 memOK = false;
mdestroyer 0:22a7d22635fa 266 break;
mdestroyer 0:22a7d22635fa 267 }
mdestroyer 0:22a7d22635fa 268 }
mdestroyer 0:22a7d22635fa 269
mdestroyer 0:22a7d22635fa 270 addr += size;
mdestroyer 0:22a7d22635fa 271 length -= size;
mdestroyer 0:22a7d22635fa 272 csw.DataResidue -= size;
mdestroyer 0:22a7d22635fa 273
mdestroyer 0:22a7d22635fa 274 if ( !length || (stage != PROCESS_CBW)) {
mdestroyer 0:22a7d22635fa 275 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED;
mdestroyer 0:22a7d22635fa 276 sendCSW();
mdestroyer 0:22a7d22635fa 277 }
mdestroyer 0:22a7d22635fa 278 }
mdestroyer 0:22a7d22635fa 279
mdestroyer 0:22a7d22635fa 280
mdestroyer 0:22a7d22635fa 281 bool USBMSD::inquiryRequest (void) {
mdestroyer 0:22a7d22635fa 282 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
mdestroyer 0:22a7d22635fa 283 36 - 4, 0x80, 0x00, 0x00,
mdestroyer 0:22a7d22635fa 284 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G',
mdestroyer 0:22a7d22635fa 285 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ',
mdestroyer 0:22a7d22635fa 286 '1', '.', '0', ' ',
mdestroyer 0:22a7d22635fa 287 };
mdestroyer 0:22a7d22635fa 288 if (!write(inquiry, sizeof(inquiry))) {
mdestroyer 0:22a7d22635fa 289 return false;
mdestroyer 0:22a7d22635fa 290 }
mdestroyer 0:22a7d22635fa 291 return true;
mdestroyer 0:22a7d22635fa 292 }
mdestroyer 0:22a7d22635fa 293
mdestroyer 0:22a7d22635fa 294
mdestroyer 0:22a7d22635fa 295 bool USBMSD::readFormatCapacity() {
mdestroyer 0:22a7d22635fa 296 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
mdestroyer 0:22a7d22635fa 297 (uint8_t)((BlockCount >> 24) & 0xff),
mdestroyer 0:22a7d22635fa 298 (uint8_t)((BlockCount >> 16) & 0xff),
mdestroyer 0:22a7d22635fa 299 (uint8_t)((BlockCount >> 8) & 0xff),
mdestroyer 0:22a7d22635fa 300 (uint8_t)((BlockCount >> 0) & 0xff),
mdestroyer 0:22a7d22635fa 301
mdestroyer 0:22a7d22635fa 302 0x02,
mdestroyer 0:22a7d22635fa 303 (uint8_t)((BlockSize >> 16) & 0xff),
mdestroyer 0:22a7d22635fa 304 (uint8_t)((BlockSize >> 8) & 0xff),
mdestroyer 0:22a7d22635fa 305 (uint8_t)((BlockSize >> 0) & 0xff),
mdestroyer 0:22a7d22635fa 306 };
mdestroyer 0:22a7d22635fa 307 if (!write(capacity, sizeof(capacity))) {
mdestroyer 0:22a7d22635fa 308 return false;
mdestroyer 0:22a7d22635fa 309 }
mdestroyer 0:22a7d22635fa 310 return true;
mdestroyer 0:22a7d22635fa 311 }
mdestroyer 0:22a7d22635fa 312
mdestroyer 0:22a7d22635fa 313
mdestroyer 0:22a7d22635fa 314 bool USBMSD::readCapacity (void) {
mdestroyer 0:22a7d22635fa 315 uint8_t capacity[] = {
mdestroyer 0:22a7d22635fa 316 (uint8_t)(((BlockCount - 1) >> 24) & 0xff),
mdestroyer 0:22a7d22635fa 317 (uint8_t)(((BlockCount - 1) >> 16) & 0xff),
mdestroyer 0:22a7d22635fa 318 (uint8_t)(((BlockCount - 1) >> 8) & 0xff),
mdestroyer 0:22a7d22635fa 319 (uint8_t)(((BlockCount - 1) >> 0) & 0xff),
mdestroyer 0:22a7d22635fa 320
mdestroyer 0:22a7d22635fa 321 (uint8_t)((BlockSize >> 24) & 0xff),
mdestroyer 0:22a7d22635fa 322 (uint8_t)((BlockSize >> 16) & 0xff),
mdestroyer 0:22a7d22635fa 323 (uint8_t)((BlockSize >> 8) & 0xff),
mdestroyer 0:22a7d22635fa 324 (uint8_t)((BlockSize >> 0) & 0xff),
mdestroyer 0:22a7d22635fa 325 };
mdestroyer 0:22a7d22635fa 326 if (!write(capacity, sizeof(capacity))) {
mdestroyer 0:22a7d22635fa 327 return false;
mdestroyer 0:22a7d22635fa 328 }
mdestroyer 0:22a7d22635fa 329 return true;
mdestroyer 0:22a7d22635fa 330 }
mdestroyer 0:22a7d22635fa 331
mdestroyer 0:22a7d22635fa 332 bool USBMSD::write (uint8_t * buf, uint16_t size) {
mdestroyer 0:22a7d22635fa 333
mdestroyer 0:22a7d22635fa 334 if (size >= cbw.DataLength) {
mdestroyer 0:22a7d22635fa 335 size = cbw.DataLength;
mdestroyer 0:22a7d22635fa 336 }
mdestroyer 0:22a7d22635fa 337 stage = SEND_CSW;
mdestroyer 0:22a7d22635fa 338
mdestroyer 0:22a7d22635fa 339 if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) {
mdestroyer 0:22a7d22635fa 340 return false;
mdestroyer 0:22a7d22635fa 341 }
mdestroyer 0:22a7d22635fa 342
mdestroyer 0:22a7d22635fa 343 csw.DataResidue -= size;
mdestroyer 0:22a7d22635fa 344 csw.Status = CSW_PASSED;
mdestroyer 0:22a7d22635fa 345 return true;
mdestroyer 0:22a7d22635fa 346 }
mdestroyer 0:22a7d22635fa 347
mdestroyer 0:22a7d22635fa 348
mdestroyer 0:22a7d22635fa 349 bool USBMSD::modeSense6 (void) {
mdestroyer 0:22a7d22635fa 350 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
mdestroyer 0:22a7d22635fa 351 if (!write(sense6, sizeof(sense6))) {
mdestroyer 0:22a7d22635fa 352 return false;
mdestroyer 0:22a7d22635fa 353 }
mdestroyer 0:22a7d22635fa 354 return true;
mdestroyer 0:22a7d22635fa 355 }
mdestroyer 0:22a7d22635fa 356
mdestroyer 0:22a7d22635fa 357 void USBMSD::sendCSW() {
mdestroyer 0:22a7d22635fa 358 csw.Signature = CSW_Signature;
mdestroyer 0:22a7d22635fa 359 writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 360 stage = WAIT_CSW;
mdestroyer 0:22a7d22635fa 361 }
mdestroyer 0:22a7d22635fa 362
mdestroyer 0:22a7d22635fa 363 bool USBMSD::requestSense (void) {
mdestroyer 0:22a7d22635fa 364 uint8_t request_sense[] = {
mdestroyer 0:22a7d22635fa 365 0x70,
mdestroyer 0:22a7d22635fa 366 0x00,
mdestroyer 0:22a7d22635fa 367 0x05, // Sense Key: illegal request
mdestroyer 0:22a7d22635fa 368 0x00,
mdestroyer 0:22a7d22635fa 369 0x00,
mdestroyer 0:22a7d22635fa 370 0x00,
mdestroyer 0:22a7d22635fa 371 0x00,
mdestroyer 0:22a7d22635fa 372 0x0A,
mdestroyer 0:22a7d22635fa 373 0x00,
mdestroyer 0:22a7d22635fa 374 0x00,
mdestroyer 0:22a7d22635fa 375 0x00,
mdestroyer 0:22a7d22635fa 376 0x00,
mdestroyer 0:22a7d22635fa 377 0x30,
mdestroyer 0:22a7d22635fa 378 0x01,
mdestroyer 0:22a7d22635fa 379 0x00,
mdestroyer 0:22a7d22635fa 380 0x00,
mdestroyer 0:22a7d22635fa 381 0x00,
mdestroyer 0:22a7d22635fa 382 0x00,
mdestroyer 0:22a7d22635fa 383 };
mdestroyer 0:22a7d22635fa 384
mdestroyer 0:22a7d22635fa 385 if (!write(request_sense, sizeof(request_sense))) {
mdestroyer 0:22a7d22635fa 386 return false;
mdestroyer 0:22a7d22635fa 387 }
mdestroyer 0:22a7d22635fa 388
mdestroyer 0:22a7d22635fa 389 return true;
mdestroyer 0:22a7d22635fa 390 }
mdestroyer 0:22a7d22635fa 391
mdestroyer 0:22a7d22635fa 392 void USBMSD::fail() {
mdestroyer 0:22a7d22635fa 393 csw.Status = CSW_FAILED;
mdestroyer 0:22a7d22635fa 394 sendCSW();
mdestroyer 0:22a7d22635fa 395 }
mdestroyer 0:22a7d22635fa 396
mdestroyer 0:22a7d22635fa 397
mdestroyer 0:22a7d22635fa 398 void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) {
mdestroyer 0:22a7d22635fa 399 if (size == sizeof(cbw)) {
mdestroyer 0:22a7d22635fa 400 memcpy((uint8_t *)&cbw, buf, size);
mdestroyer 0:22a7d22635fa 401 if (cbw.Signature == CBW_Signature) {
mdestroyer 0:22a7d22635fa 402 csw.Tag = cbw.Tag;
mdestroyer 0:22a7d22635fa 403 csw.DataResidue = cbw.DataLength;
mdestroyer 0:22a7d22635fa 404 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) {
mdestroyer 0:22a7d22635fa 405 fail();
mdestroyer 0:22a7d22635fa 406 } else {
mdestroyer 0:22a7d22635fa 407 switch (cbw.CB[0]) {
mdestroyer 0:22a7d22635fa 408 case TEST_UNIT_READY:
mdestroyer 0:22a7d22635fa 409 testUnitReady();
mdestroyer 0:22a7d22635fa 410 break;
mdestroyer 0:22a7d22635fa 411 case REQUEST_SENSE:
mdestroyer 0:22a7d22635fa 412 requestSense();
mdestroyer 0:22a7d22635fa 413 break;
mdestroyer 0:22a7d22635fa 414 case INQUIRY:
mdestroyer 0:22a7d22635fa 415 inquiryRequest();
mdestroyer 0:22a7d22635fa 416 break;
mdestroyer 0:22a7d22635fa 417 case MODE_SENSE6:
mdestroyer 0:22a7d22635fa 418 modeSense6();
mdestroyer 0:22a7d22635fa 419 break;
mdestroyer 0:22a7d22635fa 420 case READ_FORMAT_CAPACITIES:
mdestroyer 0:22a7d22635fa 421 readFormatCapacity();
mdestroyer 0:22a7d22635fa 422 break;
mdestroyer 0:22a7d22635fa 423 case READ_CAPACITY:
mdestroyer 0:22a7d22635fa 424 readCapacity();
mdestroyer 0:22a7d22635fa 425 break;
mdestroyer 0:22a7d22635fa 426 case READ10:
mdestroyer 0:22a7d22635fa 427 case READ12:
mdestroyer 0:22a7d22635fa 428 if (infoTransfer()) {
mdestroyer 0:22a7d22635fa 429 if ((cbw.Flags & 0x80)) {
mdestroyer 0:22a7d22635fa 430 stage = PROCESS_CBW;
mdestroyer 0:22a7d22635fa 431 memoryRead();
mdestroyer 0:22a7d22635fa 432 } else {
mdestroyer 0:22a7d22635fa 433 stallEndpoint(EPBULK_OUT);
mdestroyer 0:22a7d22635fa 434 csw.Status = CSW_ERROR;
mdestroyer 0:22a7d22635fa 435 sendCSW();
mdestroyer 0:22a7d22635fa 436 }
mdestroyer 0:22a7d22635fa 437 }
mdestroyer 0:22a7d22635fa 438 break;
mdestroyer 0:22a7d22635fa 439 case WRITE10:
mdestroyer 0:22a7d22635fa 440 case WRITE12:
mdestroyer 0:22a7d22635fa 441 if (infoTransfer()) {
mdestroyer 0:22a7d22635fa 442 if (!(cbw.Flags & 0x80)) {
mdestroyer 0:22a7d22635fa 443 stage = PROCESS_CBW;
mdestroyer 0:22a7d22635fa 444 } else {
mdestroyer 0:22a7d22635fa 445 stallEndpoint(EPBULK_IN);
mdestroyer 0:22a7d22635fa 446 csw.Status = CSW_ERROR;
mdestroyer 0:22a7d22635fa 447 sendCSW();
mdestroyer 0:22a7d22635fa 448 }
mdestroyer 0:22a7d22635fa 449 }
mdestroyer 0:22a7d22635fa 450 break;
mdestroyer 0:22a7d22635fa 451 case VERIFY10:
mdestroyer 0:22a7d22635fa 452 if (!(cbw.CB[1] & 0x02)) {
mdestroyer 0:22a7d22635fa 453 csw.Status = CSW_PASSED;
mdestroyer 0:22a7d22635fa 454 sendCSW();
mdestroyer 0:22a7d22635fa 455 break;
mdestroyer 0:22a7d22635fa 456 }
mdestroyer 0:22a7d22635fa 457 if (infoTransfer()) {
mdestroyer 0:22a7d22635fa 458 if (!(cbw.Flags & 0x80)) {
mdestroyer 0:22a7d22635fa 459 stage = PROCESS_CBW;
mdestroyer 0:22a7d22635fa 460 memOK = true;
mdestroyer 0:22a7d22635fa 461 } else {
mdestroyer 0:22a7d22635fa 462 stallEndpoint(EPBULK_IN);
mdestroyer 0:22a7d22635fa 463 csw.Status = CSW_ERROR;
mdestroyer 0:22a7d22635fa 464 sendCSW();
mdestroyer 0:22a7d22635fa 465 }
mdestroyer 0:22a7d22635fa 466 }
mdestroyer 0:22a7d22635fa 467 break;
mdestroyer 0:22a7d22635fa 468 case MEDIA_REMOVAL:
mdestroyer 0:22a7d22635fa 469 csw.Status = CSW_PASSED;
mdestroyer 0:22a7d22635fa 470 sendCSW();
mdestroyer 0:22a7d22635fa 471 break;
mdestroyer 0:22a7d22635fa 472 default:
mdestroyer 0:22a7d22635fa 473 fail();
mdestroyer 0:22a7d22635fa 474 break;
mdestroyer 0:22a7d22635fa 475 }
mdestroyer 0:22a7d22635fa 476 }
mdestroyer 0:22a7d22635fa 477 }
mdestroyer 0:22a7d22635fa 478 }
mdestroyer 0:22a7d22635fa 479 }
mdestroyer 0:22a7d22635fa 480
mdestroyer 0:22a7d22635fa 481 void USBMSD::testUnitReady (void) {
mdestroyer 0:22a7d22635fa 482
mdestroyer 0:22a7d22635fa 483 if (cbw.DataLength != 0) {
mdestroyer 0:22a7d22635fa 484 if ((cbw.Flags & 0x80) != 0) {
mdestroyer 0:22a7d22635fa 485 stallEndpoint(EPBULK_IN);
mdestroyer 0:22a7d22635fa 486 } else {
mdestroyer 0:22a7d22635fa 487 stallEndpoint(EPBULK_OUT);
mdestroyer 0:22a7d22635fa 488 }
mdestroyer 0:22a7d22635fa 489 }
mdestroyer 0:22a7d22635fa 490
mdestroyer 0:22a7d22635fa 491 csw.Status = CSW_PASSED;
mdestroyer 0:22a7d22635fa 492 sendCSW();
mdestroyer 0:22a7d22635fa 493 }
mdestroyer 0:22a7d22635fa 494
mdestroyer 0:22a7d22635fa 495
mdestroyer 0:22a7d22635fa 496 void USBMSD::memoryRead (void) {
mdestroyer 0:22a7d22635fa 497 uint32_t n;
mdestroyer 0:22a7d22635fa 498
mdestroyer 0:22a7d22635fa 499 n = (length > MAX_PACKET) ? MAX_PACKET : length;
mdestroyer 0:22a7d22635fa 500
mdestroyer 0:22a7d22635fa 501 if ((addr + n) > MemorySize) {
mdestroyer 0:22a7d22635fa 502 n = MemorySize - addr;
mdestroyer 0:22a7d22635fa 503 stage = ERROR;
mdestroyer 0:22a7d22635fa 504 }
mdestroyer 0:22a7d22635fa 505
mdestroyer 0:22a7d22635fa 506 // we read an entire block
mdestroyer 0:22a7d22635fa 507 if (!(addr%BlockSize))
mdestroyer 0:22a7d22635fa 508 disk_read(page, addr/BlockSize);
mdestroyer 0:22a7d22635fa 509
mdestroyer 0:22a7d22635fa 510 // write data which are in RAM
mdestroyer 0:22a7d22635fa 511 writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 512
mdestroyer 0:22a7d22635fa 513 addr += n;
mdestroyer 0:22a7d22635fa 514 length -= n;
mdestroyer 0:22a7d22635fa 515
mdestroyer 0:22a7d22635fa 516 csw.DataResidue -= n;
mdestroyer 0:22a7d22635fa 517
mdestroyer 0:22a7d22635fa 518 if ( !length || (stage != PROCESS_CBW)) {
mdestroyer 0:22a7d22635fa 519 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED;
mdestroyer 0:22a7d22635fa 520 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage;
mdestroyer 0:22a7d22635fa 521 }
mdestroyer 0:22a7d22635fa 522 }
mdestroyer 0:22a7d22635fa 523
mdestroyer 0:22a7d22635fa 524
mdestroyer 0:22a7d22635fa 525 bool USBMSD::infoTransfer (void) {
mdestroyer 0:22a7d22635fa 526 uint32_t n;
mdestroyer 0:22a7d22635fa 527
mdestroyer 0:22a7d22635fa 528 // Logical Block Address of First Block
mdestroyer 0:22a7d22635fa 529 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0);
mdestroyer 0:22a7d22635fa 530
mdestroyer 0:22a7d22635fa 531 addr = n * BlockSize;
mdestroyer 0:22a7d22635fa 532
mdestroyer 0:22a7d22635fa 533 // Number of Blocks to transfer
mdestroyer 0:22a7d22635fa 534 switch (cbw.CB[0]) {
mdestroyer 0:22a7d22635fa 535 case READ10:
mdestroyer 0:22a7d22635fa 536 case WRITE10:
mdestroyer 0:22a7d22635fa 537 case VERIFY10:
mdestroyer 0:22a7d22635fa 538 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0);
mdestroyer 0:22a7d22635fa 539 break;
mdestroyer 0:22a7d22635fa 540
mdestroyer 0:22a7d22635fa 541 case READ12:
mdestroyer 0:22a7d22635fa 542 case WRITE12:
mdestroyer 0:22a7d22635fa 543 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0);
mdestroyer 0:22a7d22635fa 544 break;
mdestroyer 0:22a7d22635fa 545 }
mdestroyer 0:22a7d22635fa 546
mdestroyer 0:22a7d22635fa 547 length = n * BlockSize;
mdestroyer 0:22a7d22635fa 548
mdestroyer 0:22a7d22635fa 549 if (!cbw.DataLength) { // host requests no data
mdestroyer 0:22a7d22635fa 550 csw.Status = CSW_FAILED;
mdestroyer 0:22a7d22635fa 551 sendCSW();
mdestroyer 0:22a7d22635fa 552 return false;
mdestroyer 0:22a7d22635fa 553 }
mdestroyer 0:22a7d22635fa 554
mdestroyer 0:22a7d22635fa 555 if (cbw.DataLength != length) {
mdestroyer 0:22a7d22635fa 556 if ((cbw.Flags & 0x80) != 0) {
mdestroyer 0:22a7d22635fa 557 stallEndpoint(EPBULK_IN);
mdestroyer 0:22a7d22635fa 558 } else {
mdestroyer 0:22a7d22635fa 559 stallEndpoint(EPBULK_OUT);
mdestroyer 0:22a7d22635fa 560 }
mdestroyer 0:22a7d22635fa 561
mdestroyer 0:22a7d22635fa 562 csw.Status = CSW_FAILED;
mdestroyer 0:22a7d22635fa 563 sendCSW();
mdestroyer 0:22a7d22635fa 564 return false;
mdestroyer 0:22a7d22635fa 565 }
mdestroyer 0:22a7d22635fa 566
mdestroyer 0:22a7d22635fa 567 return true;
mdestroyer 0:22a7d22635fa 568 }
mdestroyer 0:22a7d22635fa 569
mdestroyer 0:22a7d22635fa 570
mdestroyer 0:22a7d22635fa 571
mdestroyer 0:22a7d22635fa 572
mdestroyer 0:22a7d22635fa 573
mdestroyer 0:22a7d22635fa 574 // Called in ISR context
mdestroyer 0:22a7d22635fa 575 // Set configuration. Return false if the
mdestroyer 0:22a7d22635fa 576 // configuration is not supported.
mdestroyer 0:22a7d22635fa 577 bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) {
mdestroyer 0:22a7d22635fa 578 if (configuration != DEFAULT_CONFIGURATION) {
mdestroyer 0:22a7d22635fa 579 return false;
mdestroyer 0:22a7d22635fa 580 }
mdestroyer 0:22a7d22635fa 581
mdestroyer 0:22a7d22635fa 582 // Configure endpoints > 0
mdestroyer 0:22a7d22635fa 583 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 584 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 585
mdestroyer 0:22a7d22635fa 586 //activate readings
mdestroyer 0:22a7d22635fa 587 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
mdestroyer 0:22a7d22635fa 588 return true;
mdestroyer 0:22a7d22635fa 589 }
mdestroyer 0:22a7d22635fa 590
mdestroyer 0:22a7d22635fa 591
mdestroyer 0:22a7d22635fa 592 uint8_t * USBMSD::stringIinterfaceDesc() {
mdestroyer 0:22a7d22635fa 593 static uint8_t stringIinterfaceDescriptor[] = {
mdestroyer 0:22a7d22635fa 594 0x08, //bLength
mdestroyer 0:22a7d22635fa 595 STRING_DESCRIPTOR, //bDescriptorType 0x03
mdestroyer 0:22a7d22635fa 596 'M',0,'S',0,'D',0 //bString iInterface - MSD
mdestroyer 0:22a7d22635fa 597 };
mdestroyer 0:22a7d22635fa 598 return stringIinterfaceDescriptor;
mdestroyer 0:22a7d22635fa 599 }
mdestroyer 0:22a7d22635fa 600
mdestroyer 0:22a7d22635fa 601 uint8_t * USBMSD::stringIproductDesc() {
mdestroyer 0:22a7d22635fa 602 static uint8_t stringIproductDescriptor[] = {
mdestroyer 0:22a7d22635fa 603 0x12, //bLength
mdestroyer 0:22a7d22635fa 604 STRING_DESCRIPTOR, //bDescriptorType 0x03
mdestroyer 0:22a7d22635fa 605 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio
mdestroyer 0:22a7d22635fa 606 };
mdestroyer 0:22a7d22635fa 607 return stringIproductDescriptor;
mdestroyer 0:22a7d22635fa 608 }
mdestroyer 0:22a7d22635fa 609
mdestroyer 0:22a7d22635fa 610
mdestroyer 0:22a7d22635fa 611 uint8_t * USBMSD::configurationDesc() {
mdestroyer 0:22a7d22635fa 612 static uint8_t configDescriptor[] = {
mdestroyer 0:22a7d22635fa 613
mdestroyer 0:22a7d22635fa 614 // Configuration 1
mdestroyer 0:22a7d22635fa 615 9, // bLength
mdestroyer 0:22a7d22635fa 616 2, // bDescriptorType
mdestroyer 0:22a7d22635fa 617 LSB(9 + 9 + 7 + 7), // wTotalLength
mdestroyer 0:22a7d22635fa 618 MSB(9 + 9 + 7 + 7),
mdestroyer 0:22a7d22635fa 619 0x01, // bNumInterfaces
mdestroyer 0:22a7d22635fa 620 0x01, // bConfigurationValue: 0x01 is used to select this configuration
mdestroyer 0:22a7d22635fa 621 0x00, // iConfiguration: no string to describe this configuration
mdestroyer 0:22a7d22635fa 622 0xC0, // bmAttributes
mdestroyer 0:22a7d22635fa 623 100, // bMaxPower, device power consumption is 100 mA
mdestroyer 0:22a7d22635fa 624
mdestroyer 0:22a7d22635fa 625 // Interface 0, Alternate Setting 0, MSC Class
mdestroyer 0:22a7d22635fa 626 9, // bLength
mdestroyer 0:22a7d22635fa 627 4, // bDescriptorType
mdestroyer 0:22a7d22635fa 628 0x00, // bInterfaceNumber
mdestroyer 0:22a7d22635fa 629 0x00, // bAlternateSetting
mdestroyer 0:22a7d22635fa 630 0x02, // bNumEndpoints
mdestroyer 0:22a7d22635fa 631 0x08, // bInterfaceClass
mdestroyer 0:22a7d22635fa 632 0x06, // bInterfaceSubClass
mdestroyer 0:22a7d22635fa 633 0x50, // bInterfaceProtocol
mdestroyer 0:22a7d22635fa 634 0x04, // iInterface
mdestroyer 0:22a7d22635fa 635
mdestroyer 0:22a7d22635fa 636 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
mdestroyer 0:22a7d22635fa 637 7, // bLength
mdestroyer 0:22a7d22635fa 638 5, // bDescriptorType
mdestroyer 0:22a7d22635fa 639 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress
mdestroyer 0:22a7d22635fa 640 0x02, // bmAttributes (0x02=bulk)
mdestroyer 0:22a7d22635fa 641 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
mdestroyer 0:22a7d22635fa 642 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
mdestroyer 0:22a7d22635fa 643 0, // bInterval
mdestroyer 0:22a7d22635fa 644
mdestroyer 0:22a7d22635fa 645 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
mdestroyer 0:22a7d22635fa 646 7, // bLength
mdestroyer 0:22a7d22635fa 647 5, // bDescriptorType
mdestroyer 0:22a7d22635fa 648 PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress
mdestroyer 0:22a7d22635fa 649 0x02, // bmAttributes (0x02=bulk)
mdestroyer 0:22a7d22635fa 650 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB)
mdestroyer 0:22a7d22635fa 651 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB)
mdestroyer 0:22a7d22635fa 652 0 // bInterval
mdestroyer 0:22a7d22635fa 653 };
mdestroyer 0:22a7d22635fa 654 return configDescriptor;
mdestroyer 0:22a7d22635fa 655 }