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