USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Mon Nov 14 12:08:32 2011 +0000
Revision:
7:6494da2a5c60
Child:
8:534fd41d8cc7
will try to use ChaNFSSD

Who changed what in which revision?

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