USB Device Library
Dependents: DipCortex-ADC-USB DipCortex-USB-CDC DipCortex-USB-EEProm WiFiDip-UsbKitchenSink ... more
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 stage = READ_CBW; 00068 memset((void *)&cbw, 0, sizeof(CBW)); 00069 memset((void *)&csw, 0, sizeof(CSW)); 00070 page = NULL; 00071 } 00072 00073 USBMSD::~USBMSD() { 00074 disconnect(); 00075 } 00076 00077 00078 // Called in ISR context to process a class specific request 00079 bool USBMSD::USBCallback_request(void) { 00080 00081 bool success = false; 00082 CONTROL_TRANSFER * transfer = getTransferPtr(); 00083 static uint8_t maxLUN[1] = {0}; 00084 00085 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { 00086 switch (transfer->setup.bRequest) { 00087 case MSC_REQUEST_RESET: 00088 reset(); 00089 success = true; 00090 break; 00091 case MSC_REQUEST_GET_MAX_LUN: 00092 transfer->remaining = 1; 00093 transfer->ptr = maxLUN; 00094 transfer->direction = DEVICE_TO_HOST; 00095 success = true; 00096 break; 00097 default: 00098 break; 00099 } 00100 } 00101 00102 return success; 00103 } 00104 00105 00106 bool USBMSD::connect() { 00107 00108 //disk initialization 00109 if (disk_status() & NO_INIT) { 00110 if (disk_initialize()) { 00111 return false; 00112 } 00113 } 00114 00115 // get number of blocks 00116 BlockCount = disk_sectors(); 00117 00118 // get memory size 00119 MemorySize = disk_size(); 00120 00121 if (BlockCount > 0) { 00122 BlockSize = MemorySize / BlockCount; 00123 if (BlockSize != 0) { 00124 free(page); 00125 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); 00126 if (page == NULL) 00127 return false; 00128 } 00129 } else { 00130 return false; 00131 } 00132 00133 //connect the device 00134 USBDevice::connect(); 00135 return true; 00136 } 00137 00138 void USBMSD::disconnect() { 00139 //De-allocate MSD page size: 00140 free(page); 00141 page = NULL; 00142 USBDevice::disconnect(); 00143 } 00144 00145 void USBMSD::reset() { 00146 stage = READ_CBW; 00147 } 00148 00149 00150 // Called in ISR context called when a data is received 00151 bool USBMSD::EP2_OUT_callback() { 00152 uint32_t size = 0; 00153 uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00154 readEP(EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); 00155 switch (stage) { 00156 // the device has to decode the CBW received 00157 case READ_CBW: 00158 CBWDecode(buf, size); 00159 break; 00160 00161 // the device has to receive data from the host 00162 case PROCESS_CBW: 00163 switch (cbw.CB[0]) { 00164 case WRITE10: 00165 case WRITE12: 00166 memoryWrite(buf, size); 00167 break; 00168 case VERIFY10: 00169 memoryVerify(buf, size); 00170 break; 00171 } 00172 break; 00173 00174 // an error has occured: stall endpoint and send CSW 00175 default: 00176 stallEndpoint(EPBULK_OUT); 00177 csw.Status = CSW_ERROR; 00178 sendCSW(); 00179 break; 00180 } 00181 00182 //reactivate readings on the OUT bulk endpoint 00183 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00184 return true; 00185 } 00186 00187 // Called in ISR context when a data has been transferred 00188 bool USBMSD::EP2_IN_callback() { 00189 switch (stage) { 00190 00191 // the device has to send data to the host 00192 case PROCESS_CBW: 00193 switch (cbw.CB[0]) { 00194 case READ10: 00195 case READ12: 00196 memoryRead(); 00197 break; 00198 } 00199 break; 00200 00201 //the device has to send a CSW 00202 case SEND_CSW: 00203 sendCSW(); 00204 break; 00205 00206 // the host has received the CSW -> we wait a CBW 00207 case WAIT_CSW: 00208 stage = READ_CBW; 00209 break; 00210 00211 // an error has occured 00212 default: 00213 stallEndpoint(EPBULK_IN); 00214 sendCSW(); 00215 break; 00216 } 00217 return true; 00218 } 00219 00220 00221 void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) { 00222 00223 if ((addr + size) > MemorySize) { 00224 size = MemorySize - addr; 00225 stage = ERROR; 00226 stallEndpoint(EPBULK_OUT); 00227 } 00228 00229 // we fill an array in RAM of 1 block before writing it in memory 00230 for (int i = 0; i < size; i++) 00231 page[addr%BlockSize + i] = buf[i]; 00232 00233 // if the array is filled, write it in memory 00234 if (!((addr + size)%BlockSize)) { 00235 if (!(disk_status() & WRITE_PROTECT)) { 00236 disk_write(page, addr/BlockSize); 00237 } 00238 } 00239 00240 addr += size; 00241 length -= size; 00242 csw.DataResidue -= size; 00243 00244 if ((!length) || (stage != PROCESS_CBW)) { 00245 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00246 sendCSW(); 00247 } 00248 } 00249 00250 void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) { 00251 uint32_t n; 00252 00253 if ((addr + size) > MemorySize) { 00254 size = MemorySize - addr; 00255 stage = ERROR; 00256 stallEndpoint(EPBULK_OUT); 00257 } 00258 00259 // beginning of a new block -> load a whole block in RAM 00260 if (!(addr%BlockSize)) 00261 disk_read(page, addr/BlockSize); 00262 00263 // info are in RAM -> no need to re-read memory 00264 for (n = 0; n < size; n++) { 00265 if (page[addr%BlockSize + n] != buf[n]) { 00266 memOK = false; 00267 break; 00268 } 00269 } 00270 00271 addr += size; 00272 length -= size; 00273 csw.DataResidue -= size; 00274 00275 if ( !length || (stage != PROCESS_CBW)) { 00276 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00277 sendCSW(); 00278 } 00279 } 00280 00281 00282 bool USBMSD::inquiryRequest (void) { 00283 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00284 36 - 4, 0x80, 0x00, 0x00, 00285 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00286 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00287 '1', '.', '0', ' ', 00288 }; 00289 if (!write(inquiry, sizeof(inquiry))) { 00290 return false; 00291 } 00292 return true; 00293 } 00294 00295 00296 bool USBMSD::readFormatCapacity() { 00297 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00298 (uint8_t)((BlockCount >> 24) & 0xff), 00299 (uint8_t)((BlockCount >> 16) & 0xff), 00300 (uint8_t)((BlockCount >> 8) & 0xff), 00301 (uint8_t)((BlockCount >> 0) & 0xff), 00302 00303 0x02, 00304 (uint8_t)((BlockSize >> 16) & 0xff), 00305 (uint8_t)((BlockSize >> 8) & 0xff), 00306 (uint8_t)((BlockSize >> 0) & 0xff), 00307 }; 00308 if (!write(capacity, sizeof(capacity))) { 00309 return false; 00310 } 00311 return true; 00312 } 00313 00314 00315 bool USBMSD::readCapacity (void) { 00316 uint8_t capacity[] = { 00317 (uint8_t)(((BlockCount - 1) >> 24) & 0xff), 00318 (uint8_t)(((BlockCount - 1) >> 16) & 0xff), 00319 (uint8_t)(((BlockCount - 1) >> 8) & 0xff), 00320 (uint8_t)(((BlockCount - 1) >> 0) & 0xff), 00321 00322 (uint8_t)((BlockSize >> 24) & 0xff), 00323 (uint8_t)((BlockSize >> 16) & 0xff), 00324 (uint8_t)((BlockSize >> 8) & 0xff), 00325 (uint8_t)((BlockSize >> 0) & 0xff), 00326 }; 00327 if (!write(capacity, sizeof(capacity))) { 00328 return false; 00329 } 00330 return true; 00331 } 00332 00333 bool USBMSD::write (uint8_t * buf, uint16_t size) { 00334 00335 if (size >= cbw.DataLength) { 00336 size = cbw.DataLength; 00337 } 00338 stage = SEND_CSW; 00339 00340 if (!writeNB(EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { 00341 return false; 00342 } 00343 00344 csw.DataResidue -= size; 00345 csw.Status = CSW_PASSED; 00346 return true; 00347 } 00348 00349 00350 bool USBMSD::modeSense6 (void) { 00351 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00352 if (!write(sense6, sizeof(sense6))) { 00353 return false; 00354 } 00355 return true; 00356 } 00357 00358 void USBMSD::sendCSW() { 00359 csw.Signature = CSW_Signature; 00360 writeNB(EPBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); 00361 stage = WAIT_CSW; 00362 } 00363 00364 bool USBMSD::requestSense (void) { 00365 uint8_t request_sense[] = { 00366 0x70, 00367 0x00, 00368 0x05, // Sense Key: illegal request 00369 0x00, 00370 0x00, 00371 0x00, 00372 0x00, 00373 0x0A, 00374 0x00, 00375 0x00, 00376 0x00, 00377 0x00, 00378 0x30, 00379 0x01, 00380 0x00, 00381 0x00, 00382 0x00, 00383 0x00, 00384 }; 00385 00386 if (!write(request_sense, sizeof(request_sense))) { 00387 return false; 00388 } 00389 00390 return true; 00391 } 00392 00393 void USBMSD::fail() { 00394 csw.Status = CSW_FAILED; 00395 sendCSW(); 00396 } 00397 00398 00399 void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) { 00400 if (size == sizeof(cbw)) { 00401 memcpy((uint8_t *)&cbw, buf, size); 00402 if (cbw.Signature == CBW_Signature) { 00403 csw.Tag = cbw.Tag; 00404 csw.DataResidue = cbw.DataLength; 00405 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { 00406 fail(); 00407 } else { 00408 switch (cbw.CB[0]) { 00409 case TEST_UNIT_READY: 00410 testUnitReady(); 00411 break; 00412 case REQUEST_SENSE: 00413 requestSense(); 00414 break; 00415 case INQUIRY: 00416 inquiryRequest(); 00417 break; 00418 case MODE_SENSE6: 00419 modeSense6(); 00420 break; 00421 case READ_FORMAT_CAPACITIES: 00422 readFormatCapacity(); 00423 break; 00424 case READ_CAPACITY: 00425 readCapacity(); 00426 break; 00427 case READ10: 00428 case READ12: 00429 if (infoTransfer()) { 00430 if ((cbw.Flags & 0x80)) { 00431 stage = PROCESS_CBW; 00432 memoryRead(); 00433 } else { 00434 stallEndpoint(EPBULK_OUT); 00435 csw.Status = CSW_ERROR; 00436 sendCSW(); 00437 } 00438 } 00439 break; 00440 case WRITE10: 00441 case WRITE12: 00442 if (infoTransfer()) { 00443 if (!(cbw.Flags & 0x80)) { 00444 stage = PROCESS_CBW; 00445 } else { 00446 stallEndpoint(EPBULK_IN); 00447 csw.Status = CSW_ERROR; 00448 sendCSW(); 00449 } 00450 } 00451 break; 00452 case VERIFY10: 00453 if (!(cbw.CB[1] & 0x02)) { 00454 csw.Status = CSW_PASSED; 00455 sendCSW(); 00456 break; 00457 } 00458 if (infoTransfer()) { 00459 if (!(cbw.Flags & 0x80)) { 00460 stage = PROCESS_CBW; 00461 memOK = true; 00462 } else { 00463 stallEndpoint(EPBULK_IN); 00464 csw.Status = CSW_ERROR; 00465 sendCSW(); 00466 } 00467 } 00468 break; 00469 case MEDIA_REMOVAL: 00470 csw.Status = CSW_PASSED; 00471 sendCSW(); 00472 break; 00473 default: 00474 fail(); 00475 break; 00476 } 00477 } 00478 } 00479 } 00480 } 00481 00482 void USBMSD::testUnitReady (void) { 00483 00484 if (cbw.DataLength != 0) { 00485 if ((cbw.Flags & 0x80) != 0) { 00486 stallEndpoint(EPBULK_IN); 00487 } else { 00488 stallEndpoint(EPBULK_OUT); 00489 } 00490 } 00491 00492 csw.Status = CSW_PASSED; 00493 sendCSW(); 00494 } 00495 00496 00497 void USBMSD::memoryRead (void) { 00498 uint32_t n; 00499 00500 n = (length > MAX_PACKET) ? MAX_PACKET : length; 00501 00502 if ((addr + n) > MemorySize) { 00503 n = MemorySize - addr; 00504 stage = ERROR; 00505 } 00506 00507 // we read an entire block 00508 if (!(addr%BlockSize)) 00509 disk_read(page, addr/BlockSize); 00510 00511 // write data which are in RAM 00512 writeNB(EPBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); 00513 00514 addr += n; 00515 length -= n; 00516 00517 csw.DataResidue -= n; 00518 00519 if ( !length || (stage != PROCESS_CBW)) { 00520 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00521 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; 00522 } 00523 } 00524 00525 00526 bool USBMSD::infoTransfer (void) { 00527 uint32_t n; 00528 00529 // Logical Block Address of First Block 00530 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); 00531 00532 addr = n * BlockSize; 00533 00534 // Number of Blocks to transfer 00535 switch (cbw.CB[0]) { 00536 case READ10: 00537 case WRITE10: 00538 case VERIFY10: 00539 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); 00540 break; 00541 00542 case READ12: 00543 case WRITE12: 00544 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); 00545 break; 00546 } 00547 00548 length = n * BlockSize; 00549 00550 if (!cbw.DataLength) { // host requests no data 00551 csw.Status = CSW_FAILED; 00552 sendCSW(); 00553 return false; 00554 } 00555 00556 if (cbw.DataLength != length) { 00557 if ((cbw.Flags & 0x80) != 0) { 00558 stallEndpoint(EPBULK_IN); 00559 } else { 00560 stallEndpoint(EPBULK_OUT); 00561 } 00562 00563 csw.Status = CSW_FAILED; 00564 sendCSW(); 00565 return false; 00566 } 00567 00568 return true; 00569 } 00570 00571 00572 00573 00574 00575 // Called in ISR context 00576 // Set configuration. Return false if the 00577 // configuration is not supported. 00578 bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) { 00579 if (configuration != DEFAULT_CONFIGURATION) { 00580 return false; 00581 } 00582 00583 // Configure endpoints > 0 00584 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK); 00585 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00586 00587 //activate readings 00588 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00589 return true; 00590 } 00591 00592 00593 uint8_t * USBMSD::stringIinterfaceDesc() { 00594 static uint8_t stringIinterfaceDescriptor[] = { 00595 0x08, //bLength 00596 STRING_DESCRIPTOR, //bDescriptorType 0x03 00597 'M',0,'S',0,'D',0 //bString iInterface - MSD 00598 }; 00599 return stringIinterfaceDescriptor; 00600 } 00601 00602 uint8_t * USBMSD::stringIproductDesc() { 00603 static uint8_t stringIproductDescriptor[] = { 00604 0x12, //bLength 00605 STRING_DESCRIPTOR, //bDescriptorType 0x03 00606 'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio 00607 }; 00608 return stringIproductDescriptor; 00609 } 00610 00611 00612 uint8_t * USBMSD::configurationDesc() { 00613 static uint8_t configDescriptor[] = { 00614 00615 // Configuration 1 00616 9, // bLength 00617 2, // bDescriptorType 00618 LSB(9 + 9 + 7 + 7), // wTotalLength 00619 MSB(9 + 9 + 7 + 7), 00620 0x01, // bNumInterfaces 00621 0x01, // bConfigurationValue: 0x01 is used to select this configuration 00622 0x00, // iConfiguration: no string to describe this configuration 00623 0xC0, // bmAttributes 00624 100, // bMaxPower, device power consumption is 100 mA 00625 00626 // Interface 0, Alternate Setting 0, MSC Class 00627 9, // bLength 00628 4, // bDescriptorType 00629 0x00, // bInterfaceNumber 00630 0x00, // bAlternateSetting 00631 0x02, // bNumEndpoints 00632 0x08, // bInterfaceClass 00633 0x06, // bInterfaceSubClass 00634 0x50, // bInterfaceProtocol 00635 0x04, // iInterface 00636 00637 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00638 7, // bLength 00639 5, // bDescriptorType 00640 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress 00641 0x02, // bmAttributes (0x02=bulk) 00642 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00643 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00644 0, // bInterval 00645 00646 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00647 7, // bLength 00648 5, // bDescriptorType 00649 PHY_TO_DESC(EPBULK_OUT), // bEndpointAddress 00650 0x02, // bmAttributes (0x02=bulk) 00651 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00652 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00653 0 // bInterval 00654 }; 00655 return configDescriptor; 00656 }
Generated on Mon Jul 18 2022 01:00:17 by 1.7.2