USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Tue Nov 15 09:16:25 2011 +0000
Revision:
9:9c343b9ee6d8
Parent:
8:534fd41d8cc7
Child:
10:cf8fd2b6ca23
ok, will try to protect disk

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