USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Wed Nov 30 17:50:35 2011 +0000
Revision:
12:a12eb1fc05f3
Parent:
11:a26e7b7a1221
demo for chris OK

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