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