Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
USBMSD.cpp
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "stdint.h" 00020 #include "USBMSD.h" 00021 00022 #define DISK_OK 0x00 00023 #define NO_INIT 0x01 00024 #define NO_DISK 0x02 00025 #define WRITE_PROTECT 0x04 00026 00027 #define CBW_Signature 0x43425355 00028 #define CSW_Signature 0x53425355 00029 00030 // SCSI Commands 00031 #define TEST_UNIT_READY 0x00 00032 #define REQUEST_SENSE 0x03 00033 #define FORMAT_UNIT 0x04 00034 #define INQUIRY 0x12 00035 #define MODE_SELECT6 0x15 00036 #define MODE_SENSE6 0x1A 00037 #define START_STOP_UNIT 0x1B 00038 #define MEDIA_REMOVAL 0x1E 00039 #define READ_FORMAT_CAPACITIES 0x23 00040 #define READ_CAPACITY 0x25 00041 #define READ10 0x28 00042 #define WRITE10 0x2A 00043 #define VERIFY10 0x2F 00044 #define READ12 0xA8 00045 #define WRITE12 0xAA 00046 #define MODE_SELECT10 0x55 00047 #define MODE_SENSE10 0x5A 00048 00049 // MSC class specific requests 00050 #define MSC_REQUEST_RESET 0xFF 00051 #define MSC_REQUEST_GET_MAX_LUN 0xFE 00052 00053 #define DEFAULT_CONFIGURATION (1) 00054 00055 // max packet size 00056 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK 00057 00058 // CSW Status 00059 enum Status { 00060 CSW_PASSED, 00061 CSW_FAILED, 00062 CSW_ERROR, 00063 }; 00064 00065 00066 USBMSD::USBMSD(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release) { 00067 } 00068 00069 00070 00071 // Called in ISR context to process a class specific request 00072 bool USBMSD::USBCallback_request(void) { 00073 00074 bool success = false; 00075 CONTROL_TRANSFER * transfer = getTransferPtr(); 00076 static uint8_t maxLUN[1] = {0}; 00077 00078 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { 00079 switch (transfer->setup.bRequest) { 00080 case MSC_REQUEST_RESET: 00081 reset(); 00082 success = true; 00083 break; 00084 case MSC_REQUEST_GET_MAX_LUN: 00085 transfer->remaining = 1; 00086 transfer->ptr = maxLUN; 00087 transfer->direction = DEVICE_TO_HOST; 00088 success = true; 00089 break; 00090 default: 00091 break; 00092 } 00093 } 00094 00095 return success; 00096 } 00097 00098 00099 bool USBMSD::connect() { 00100 00101 //disk initialization 00102 if (disk_status() & NO_INIT) { 00103 if (disk_initialize()) { 00104 return false; 00105 } 00106 } 00107 00108 // get number of blocks 00109 BlockCount = disk_sectors(); 00110 00111 // get memory size 00112 MemorySize = disk_size();//1018691584; 00113 //MemorySize = 31914983424;//1018691584; 00114 00115 if (BlockCount >= 0) { 00116 BlockSize = MemorySize / BlockCount; 00117 if (BlockSize != 0) { 00118 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); 00119 if (page == NULL) 00120 return false; 00121 } 00122 } else { 00123 return false; 00124 } 00125 00126 //connect the device 00127 USBDevice::connect(); 00128 return true; 00129 } 00130 00131 00132 void USBMSD::reset() { 00133 stage = READ_CBW; 00134 } 00135 00136 00137 // Called in ISR context called when a data is received 00138 bool USBMSD::EP2_OUT_callback() { 00139 uint16_t size = 0; 00140 uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00141 readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); 00142 switch (stage) { 00143 // the device has to decode the CBW received 00144 case READ_CBW: 00145 CBWDecode(buf, size); 00146 break; 00147 00148 // the device has to receive data from the host 00149 case PROCESS_CBW: 00150 switch (cbw.CB[0]) { 00151 case WRITE10: 00152 case WRITE12: 00153 memoryWrite(buf, size); 00154 break; 00155 case VERIFY10: 00156 memoryVerify(buf, size); 00157 break; 00158 } 00159 break; 00160 00161 // an error has occured: stall endpoint and send CSW 00162 default: 00163 stallEndpoint(EPBULK_OUT); 00164 csw.Status = CSW_ERROR; 00165 sendCSW(); 00166 break; 00167 } 00168 00169 //reactivate readings on the OUT bulk endpoint 00170 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00171 return true; 00172 } 00173 00174 // Called in ISR context when a data has been transferred 00175 bool USBMSD::EP2_IN_callback() { 00176 switch (stage) { 00177 00178 // the device has to send data to the host 00179 case PROCESS_CBW: 00180 switch (cbw.CB[0]) { 00181 case READ10: 00182 case READ12: 00183 memoryRead(); 00184 break; 00185 } 00186 break; 00187 00188 //the device has to send a CSW 00189 case SEND_CSW: 00190 sendCSW(); 00191 break; 00192 00193 // an error has occured 00194 case ERROR: 00195 stallEndpoint(EPBULK_IN); 00196 sendCSW(); 00197 break; 00198 00199 // the host has received the CSW -> we wait a CBW 00200 case WAIT_CSW: 00201 stage = READ_CBW; 00202 break; 00203 } 00204 return true; 00205 } 00206 00207 00208 void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) { 00209 00210 if ((addr + size) > MemorySize) { 00211 size = MemorySize - addr; 00212 stage = ERROR; 00213 stallEndpoint(EPBULK_OUT); 00214 } 00215 // we fill an array in RAM of 1 block before writing it in memory 00216 for (int i = 0; i < size; i++) 00217 page[addr%BlockSize + i] = buf[i]; 00218 00219 // if the array is filled, write it in memory 00220 if (!((addr + size)%BlockSize)) { 00221 if (!(disk_status() & WRITE_PROTECT)) { 00222 //disk_write((const char *)page, addr/BlockSize); 00223 disk_write((const char *)page, addr/BlockSize); 00224 } 00225 } 00226 00227 addr += size; 00228 length -= size; 00229 csw.DataResidue -= size; 00230 00231 if ((!length) || (stage != PROCESS_CBW)) { 00232 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00233 sendCSW(); 00234 } 00235 } 00236 00237 void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) { 00238 uint32_t n; 00239 00240 if ((addr + size) > MemorySize) { 00241 size = MemorySize - addr; 00242 stage = ERROR; 00243 stallEndpoint(EPBULK_OUT); 00244 } 00245 00246 // beginning of a new block -> load a whole block in RAM 00247 if (!(addr%BlockSize)) 00248 disk_read((char *)page, addr/BlockSize); 00249 00250 // info are in RAM -> no need to re-read memory 00251 for (n = 0; n < size; n++) { 00252 if (page[addr%BlockSize + n] != buf[n]) { 00253 memOK = false; 00254 break; 00255 } 00256 } 00257 00258 addr += size; 00259 length -= size; 00260 csw.DataResidue -= size; 00261 00262 if ( !length || (stage != PROCESS_CBW)) { 00263 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00264 sendCSW(); 00265 } 00266 } 00267 00268 00269 bool USBMSD::inquiryRequest (void) { 00270 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00271 36 - 4, 0x80, 0x00, 0x00, 00272 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00273 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00274 '1', '.', '0', ' ', 00275 }; 00276 if (!write(inquiry, sizeof(inquiry))) { 00277 return false; 00278 } 00279 return true; 00280 } 00281 00282 00283 bool USBMSD::readFormatCapacity() { 00284 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00285 (BlockCount >> 24) & 0xff, 00286 (BlockCount >> 16) & 0xff, 00287 (BlockCount >> 8) & 0xff, 00288 (BlockCount >> 0) & 0xff, 00289 00290 0x02, 00291 (BlockSize >> 16) & 0xff, 00292 (BlockSize >> 8) & 0xff, 00293 (BlockSize >> 0) & 0xff, 00294 }; 00295 if (!write(capacity, sizeof(capacity))) { 00296 return false; 00297 } 00298 return true; 00299 } 00300 00301 00302 bool USBMSD::readCapacity (void) { 00303 uint8_t capacity[] = { 00304 ((BlockCount - 1) >> 24) & 0xff, 00305 ((BlockCount - 1) >> 16) & 0xff, 00306 ((BlockCount - 1) >> 8) & 0xff, 00307 ((BlockCount - 1) >> 0) & 0xff, 00308 00309 (BlockSize >> 24) & 0xff, 00310 (BlockSize >> 16) & 0xff, 00311 (BlockSize >> 8) & 0xff, 00312 (BlockSize >> 0) & 0xff, 00313 }; 00314 if (!write(capacity, sizeof(capacity))) { 00315 return false; 00316 } 00317 return true; 00318 } 00319 00320 bool USBMSD::write (uint8_t * buf, uint16_t size) { 00321 00322 if (size >= cbw.DataLength) { 00323 size = cbw.DataLength; 00324 } 00325 stage = SEND_CSW; 00326 00327 if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { 00328 return false; 00329 } 00330 00331 csw.DataResidue -= size; 00332 csw.Status = CSW_PASSED; 00333 return true; 00334 } 00335 00336 00337 bool USBMSD::modeSense6 (void) { 00338 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00339 if (!write(sense6, sizeof(sense6))) { 00340 return false; 00341 } 00342 return true; 00343 } 00344 00345 void USBMSD::sendCSW() { 00346 csw.Signature = CSW_Signature; 00347 writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); 00348 stage = WAIT_CSW; 00349 } 00350 00351 bool USBMSD::requestSense (void) { 00352 uint8_t request_sense[] = { 00353 0x70, 00354 0x00, 00355 0x05, // Sense Key: illegal request 00356 0x00, 00357 0x00, 00358 0x00, 00359 0x00, 00360 0x0A, 00361 0x00, 00362 0x00, 00363 0x00, 00364 0x00, 00365 0x30, 00366 0x01, 00367 0x00, 00368 0x00, 00369 0x00, 00370 0x00, 00371 }; 00372 00373 if (!write(request_sense, sizeof(request_sense))) { 00374 return false; 00375 } 00376 00377 return true; 00378 } 00379 00380 void USBMSD::fail() { 00381 csw.Status = CSW_FAILED; 00382 sendCSW(); 00383 } 00384 00385 00386 void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) { 00387 if (size == sizeof(cbw)) { 00388 memcpy((uint8_t *)&cbw, buf, size); 00389 if (cbw.Signature == CBW_Signature) { 00390 csw.Tag = cbw.Tag; 00391 csw.DataResidue = cbw.DataLength; 00392 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { 00393 fail(); 00394 } else { 00395 switch (cbw.CB[0]) { 00396 case TEST_UNIT_READY: 00397 testUnitReady(); 00398 break; 00399 case REQUEST_SENSE: 00400 requestSense(); 00401 break; 00402 case INQUIRY: 00403 inquiryRequest(); 00404 break; 00405 case MODE_SENSE6: 00406 modeSense6(); 00407 break; 00408 case READ_FORMAT_CAPACITIES: 00409 readFormatCapacity(); 00410 break; 00411 case READ_CAPACITY: 00412 readCapacity(); 00413 break; 00414 case READ10: 00415 case READ12: 00416 if (infoTransfer()) { 00417 if ((cbw.Flags & 0x80)) { 00418 stage = PROCESS_CBW; 00419 memoryRead(); 00420 } else { 00421 stallEndpoint(EPBULK_OUT); 00422 csw.Status = CSW_ERROR; 00423 sendCSW(); 00424 } 00425 } 00426 break; 00427 case WRITE10: 00428 case WRITE12: 00429 if (infoTransfer()) { 00430 if (!(cbw.Flags & 0x80)) { 00431 stage = PROCESS_CBW; 00432 } else { 00433 stallEndpoint(EPBULK_IN); 00434 csw.Status = CSW_ERROR; 00435 sendCSW(); 00436 } 00437 } 00438 break; 00439 case VERIFY10: 00440 if (!(cbw.CB[1] & 0x02)) { 00441 csw.Status = CSW_PASSED; 00442 sendCSW(); 00443 break; 00444 } 00445 if (infoTransfer()) { 00446 if (!(cbw.Flags & 0x80)) { 00447 stage = PROCESS_CBW; 00448 memOK = true; 00449 } else { 00450 stallEndpoint(EPBULK_IN); 00451 csw.Status = CSW_ERROR; 00452 sendCSW(); 00453 } 00454 } 00455 break; 00456 default: 00457 fail(); 00458 break; 00459 } 00460 } 00461 } 00462 } 00463 } 00464 00465 void USBMSD::testUnitReady (void) { 00466 00467 if (cbw.DataLength != 0) { 00468 if ((cbw.Flags & 0x80) != 0) { 00469 stallEndpoint(EPBULK_IN); 00470 } else { 00471 stallEndpoint(EPBULK_OUT); 00472 } 00473 } 00474 00475 csw.Status = CSW_PASSED; 00476 sendCSW(); 00477 } 00478 00479 00480 void USBMSD::memoryRead (void) { 00481 uint32_t n; 00482 00483 n = (length > MAX_PACKET) ? MAX_PACKET : length; 00484 00485 if ((addr + n) > MemorySize) { 00486 n = MemorySize - addr; 00487 stage = ERROR; 00488 } 00489 00490 // we read an entire block 00491 if (!(addr%BlockSize)) 00492 disk_read((char *)page, addr/BlockSize); 00493 00494 // write data which are in RAM 00495 writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); 00496 00497 addr += n; 00498 length -= n; 00499 00500 csw.DataResidue -= n; 00501 00502 if ( !length || (stage != PROCESS_CBW)) { 00503 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00504 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; 00505 } 00506 } 00507 00508 00509 bool USBMSD::infoTransfer (void) { 00510 uint32_t n; 00511 00512 // Logical Block Address of First Block 00513 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); 00514 00515 addr = n * BlockSize; 00516 00517 // Number of Blocks to transfer 00518 switch (cbw.CB[0]) { 00519 case READ10: 00520 case WRITE10: 00521 case VERIFY10: 00522 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); 00523 break; 00524 00525 case READ12: 00526 case WRITE12: 00527 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); 00528 break; 00529 } 00530 00531 length = n * BlockSize; 00532 00533 if (!cbw.DataLength) { // host requests no data 00534 csw.Status = CSW_FAILED; 00535 sendCSW(); 00536 return false; 00537 } 00538 00539 if (cbw.DataLength != length) { 00540 if ((cbw.Flags & 0x80) != 0) { 00541 stallEndpoint(EPBULK_IN); 00542 } else { 00543 stallEndpoint(EPBULK_OUT); 00544 } 00545 00546 csw.Status = CSW_FAILED; 00547 sendCSW(); 00548 return false; 00549 } 00550 00551 return true; 00552 } 00553 00554 00555 00556 00557 00558 // Called in ISR context 00559 // Set configuration. Return false if the 00560 // configuration is not supported. 00561 bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) { 00562 if (configuration != DEFAULT_CONFIGURATION) { 00563 return false; 00564 } 00565 00566 // Configure endpoints > 0 00567 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK); 00568 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00569 00570 //activate readings 00571 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00572 return true; 00573 } 00574 00575 00576 uint8_t * USBMSD::stringIinterfaceDesc() { 00577 static uint8_t stringIinterfaceDescriptor[] = { 00578 0x08, //bLength 00579 STRING_DESCRIPTOR, //bDescriptorType 0x03 00580 'M',0,'S',0,'D',0 //bString iInterface - MSD 00581 }; 00582 return stringIinterfaceDescriptor; 00583 } 00584 00585 uint8_t * USBMSD::stringIproductDesc() { 00586 static uint8_t stringIproductDescriptor[] = { 00587 0x12, //bLength 00588 STRING_DESCRIPTOR, //bDescriptorType 0x03 00589 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio 00590 }; 00591 return stringIproductDescriptor; 00592 } 00593 00594 00595 uint8_t * USBMSD::configurationDesc() { 00596 static uint8_t configDescriptor[] = { 00597 00598 // Configuration 1 00599 9, // bLength 00600 2, // bDescriptorType 00601 LSB(9 + 9 + 7 + 7), // wTotalLength 00602 MSB(9 + 9 + 7 + 7), 00603 0x01, // bNumInterfaces 00604 0x01, // bConfigurationValue: 0x01 is used to select this configuration 00605 0x00, // iConfiguration: no string to describe this configuration 00606 0xC0, // bmAttributes 00607 100, // bMaxPower, device power consumption is 100 mA 00608 00609 // Interface 0, Alternate Setting 0, MSC Class 00610 9, // bLength 00611 4, // bDescriptorType 00612 0x00, // bInterfaceNumber 00613 0x00, // bAlternateSetting 00614 0x02, // bNumEndpoints 00615 0x08, // bInterfaceClass 00616 0x06, // bInterfaceSubClass 00617 0x50, // bInterfaceProtocol 00618 0x04, // iInterface 00619 00620 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00621 7, // bLength 00622 5, // bDescriptorType 00623 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress 00624 0x02, // bmAttributes (0x02=bulk) 00625 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00626 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00627 0, // bInterval 00628 00629 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00630 7, // bLength 00631 5, // bDescriptorType 00632 PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress 00633 0x02, // bmAttributes (0x02=bulk) 00634 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00635 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00636 0 // bInterval 00637 }; 00638 return configDescriptor; 00639 }
Generated on Wed Jul 13 2022 10:21:29 by
1.7.2