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