USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Tue Dec 06 12:07:12 2011 +0000
Revision:
14:757226626acb
protection enabled when usb cable plugged. filesystem has no access when plugged

Who changed what in which revision?

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