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.
Dependencies: ChaNFSSD mbed ChaNFS
USBCDCMSC.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 "USBCDCMSC.h" 00021 #include "USBBusInterface.h" 00022 00023 static uint8_t cdc_line_coding[7]= {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08}; 00024 00025 #define DEFAULT_CONFIGURATION (1) 00026 00027 #define CDC_SET_LINE_CODING 0x20 00028 #define CDC_GET_LINE_CODING 0x21 00029 #define CDC_SET_CONTROL_LINE_STATE 0x22 00030 #define CDC_SEND_BREAK 0x23 00031 00032 #define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK 00033 00034 00035 00036 #define DISK_OK 0x00 00037 #define NO_INIT 0x01 00038 #define NO_DISK 0x02 00039 #define WRITE_PROTECT 0x04 00040 00041 #define CBW_Signature 0x43425355 00042 #define CSW_Signature 0x53425355 00043 00044 // SCSI Commands 00045 #define TEST_UNIT_READY 0x00 00046 #define REQUEST_SENSE 0x03 00047 #define FORMAT_UNIT 0x04 00048 #define INQUIRY 0x12 00049 #define MODE_SELECT6 0x15 00050 #define MODE_SENSE6 0x1A 00051 #define START_STOP_UNIT 0x1B 00052 #define MEDIA_REMOVAL 0x1E 00053 #define READ_FORMAT_CAPACITIES 0x23 00054 #define READ_CAPACITY 0x25 00055 #define READ10 0x28 00056 #define WRITE10 0x2A 00057 #define VERIFY10 0x2F 00058 #define READ12 0xA8 00059 #define WRITE12 0xAA 00060 #define MODE_SELECT10 0x55 00061 #define MODE_SENSE10 0x5A 00062 00063 // MSC class specific requests 00064 #define MSC_REQUEST_RESET 0xFF 00065 #define MSC_REQUEST_GET_MAX_LUN 0xFE 00066 00067 #define DEFAULT_CONFIGURATION (1) 00068 00069 // max packet size 00070 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK 00071 00072 // CSW Status 00073 enum Status { 00074 CSW_PASSED, 00075 CSW_FAILED, 00076 CSW_ERROR, 00077 }; 00078 00079 00080 USBCDCMSC::USBCDCMSC(SDFileSystem *sd, uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release), cdcbuf(128), _sd(sd) { 00081 cdcbreak = 0; 00082 _status = NO_INIT; 00083 connect(); 00084 // USBDevice::connect(); 00085 USBHAL::connect(); 00086 } 00087 00088 bool USBCDCMSC::USBCallback_request(void) { 00089 /* Called in ISR context */ 00090 00091 bool success = false; 00092 CONTROL_TRANSFER * transfer = getTransferPtr(); 00093 static uint8_t maxLUN[1] = {0}; 00094 00095 /* Process class-specific requests */ 00096 00097 if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { 00098 switch (transfer->setup.bRequest) { 00099 case CDC_GET_LINE_CODING: 00100 transfer->remaining = 7; 00101 transfer->ptr = cdc_line_coding; 00102 transfer->direction = DEVICE_TO_HOST; 00103 success = true; 00104 break; 00105 case CDC_SET_LINE_CODING: 00106 transfer->remaining = 7; 00107 success = true; 00108 break; 00109 case CDC_SET_CONTROL_LINE_STATE: 00110 success = true; 00111 break; 00112 case CDC_SEND_BREAK: 00113 cdcbreak = 1; 00114 success = true; 00115 break; 00116 case MSC_REQUEST_RESET: 00117 reset(); 00118 success = true; 00119 break; 00120 case MSC_REQUEST_GET_MAX_LUN: 00121 transfer->remaining = 1; 00122 transfer->ptr = maxLUN; 00123 transfer->direction = DEVICE_TO_HOST; 00124 success = true; 00125 break; 00126 default: 00127 break; 00128 } 00129 } 00130 00131 return success; 00132 } 00133 00134 00135 // Called in ISR context 00136 // Set configuration. Return false if the 00137 // configuration is not supported. 00138 bool USBCDCMSC::USBCallback_setConfiguration(uint8_t configuration) { 00139 if (configuration != DEFAULT_CONFIGURATION) { 00140 return false; 00141 } 00142 00143 // Configure endpoints > 0 00144 addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT); 00145 addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK); 00146 addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00147 00148 // Configure endpoints > 0 00149 addEndpoint(MSDBULK_IN, MAX_PACKET_SIZE_MSDBULK); 00150 addEndpoint(MSDBULK_OUT, MAX_PACKET_SIZE_MSDBULK); 00151 00152 // We activate the endpoint to be able to recceive data 00153 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00154 00155 //activate readings 00156 readStart(MSDBULK_OUT, MAX_PACKET_SIZE_MSDBULK); 00157 return true; 00158 } 00159 00160 bool USBCDCMSC::send(uint8_t * buffer, uint16_t size) { 00161 return USBDevice::write(EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE); 00162 } 00163 00164 bool USBCDCMSC::readEP(uint8_t * buffer, uint16_t * size) { 00165 if (!USBDevice::readEP(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE)) 00166 return false; 00167 if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE)) 00168 return false; 00169 return true; 00170 } 00171 00172 bool USBCDCMSC::readEP_NB(uint8_t * buffer, uint16_t * size) { 00173 if (!USBDevice::readEP_NB(EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE)) 00174 return false; 00175 if (!readStart(EPBULK_OUT, MAX_CDC_REPORT_SIZE)) 00176 return false; 00177 return true; 00178 } 00179 00180 00181 uint8_t * USBCDCMSC::deviceDesc() { 00182 static uint8_t deviceDescriptor[] = { 00183 18, // bLength 00184 1, // bDescriptorType 00185 0x10, 0x01, // bcdUSB 00186 0xef, // bDeviceClass 00187 0x02, // bDeviceSubClass 00188 0x01, // bDeviceProtocol 00189 MAX_PACKET_SIZE_EP0, // bMaxPacketSize0 00190 LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor 00191 LSB(PRODUCT_ID), MSB(PRODUCT_ID),// idProduct 00192 0x00, 0x01, // bcdDevice 00193 1, // iManufacturer 00194 2, // iProduct 00195 3, // iSerialNumber 00196 1 // bNumConfigurations 00197 }; 00198 return deviceDescriptor; 00199 } 00200 00201 uint8_t * USBCDCMSC::stringIinterfaceDesc() { 00202 static uint8_t stringIinterfaceDescriptor[] = { 00203 0x0e, 00204 STRING_DESCRIPTOR, 00205 'C',0,'D',0,'C',0,'M',0,'S',0,'C',0, 00206 }; 00207 return stringIinterfaceDescriptor; 00208 } 00209 00210 uint8_t * USBCDCMSC::stringIproductDesc() { 00211 static uint8_t stringIproductDescriptor[] = { 00212 0x1c, 00213 STRING_DESCRIPTOR, 00214 'C',0,'D',0,'C',0,'M',0,'S',0,'C',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 00215 }; 00216 return stringIproductDescriptor; 00217 } 00218 00219 00220 uint8_t * USBCDCMSC::configurationDesc() { 00221 static uint8_t configDescriptor[] = { 00222 9, // bLength; 00223 2, // bDescriptorType; 00224 LSB(0x62), // wTotalLength 00225 MSB(0x62), 00226 3, // bNumInterfaces 00227 1, // bConfigurationValue 00228 0, // iConfiguration 00229 0xc0, // bmAttributes 00230 50, // bMaxPower 00231 00232 // IAD 00233 // 0x08, 0x0B, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 00234 0x08, 0x0B, 0x00, 0x02, 0x02, 0x02, 0x01, 0x00, 00235 00236 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 00237 9, // bLength 00238 4, // bDescriptorType 00239 0, // bInterfaceNumber 00240 0, // bAlternateSetting 00241 1, // bNumEndpoints 00242 0x02, // bInterfaceClass 00243 0x02, // bInterfaceSubClass 00244 0x01, // bInterfaceProtocol 00245 0, // iInterface 00246 00247 // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 00248 5, // bFunctionLength 00249 0x24, // bDescriptorType 00250 0x00, // bDescriptorSubtype 00251 0x10, 0x01, // bcdCDC 00252 00253 // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 00254 5, // bFunctionLength 00255 0x24, // bDescriptorType 00256 0x01, // bDescriptorSubtype 00257 0x03, // bmCapabilities 00258 1, // bDataInterface 00259 00260 // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 00261 4, // bFunctionLength 00262 0x24, // bDescriptorType 00263 0x02, // bDescriptorSubtype 00264 0x06, // bmCapabilities 00265 00266 // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 00267 5, // bFunctionLength 00268 0x24, // bDescriptorType 00269 0x06, // bDescriptorSubtype 00270 0, // bMasterInterface 00271 1, // bSlaveInterface0 00272 00273 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00274 ENDPOINT_DESCRIPTOR_LENGTH, // bLength 00275 ENDPOINT_DESCRIPTOR, // bDescriptorType 00276 PHY_TO_DESC(EPINT_IN), // bEndpointAddress 00277 E_INTERRUPT, // bmAttributes (0x03=intr) 00278 LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB) 00279 MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) 00280 16, // bInterval 00281 00282 00283 00284 00285 // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 00286 9, // bLength 00287 4, // bDescriptorType 00288 1, // bInterfaceNumber 00289 0, // bAlternateSetting 00290 2, // bNumEndpoints 00291 0x0A, // bInterfaceClass 00292 0x00, // bInterfaceSubClass 00293 0x00, // bInterfaceProtocol 00294 0, // iInterface 00295 00296 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00297 7, // bLength 00298 5, // bDescriptorType 00299 PHY_TO_DESC(EPBULK_IN), // bEndpointAddress 00300 0x02, // bmAttributes (0x02=bulk) 00301 LSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (LSB) 00302 MSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (MSB) 00303 0, // bInterval 00304 00305 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00306 7, // bLength 00307 5, // bDescriptorType 00308 PHY_TO_DESC(EPBULK_OUT),// bEndpointAddress 00309 0x02, // bmAttributes (0x02=bulk) 00310 LSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (LSB) 00311 MSB(MAX_PACKET_SIZE_EPBULK), // wMaxPacketSize (MSB) 00312 0, // bInterval 00313 00314 // Interface 2, Alternate Setting 0, MSC Class 00315 9, // bLength 00316 4, // bDescriptorType 00317 0x02, // bInterfaceNumber 00318 0x00, // bAlternateSetting 00319 0x02, // bNumEndpoints 00320 0x08, // bInterfaceClass 00321 0x06, // bInterfaceSubClass 00322 0x50, // bInterfaceProtocol 00323 0x04, // iInterface 00324 00325 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00326 7, // bLength 00327 5, // bDescriptorType 00328 PHY_TO_DESC(MSDBULK_IN), // bEndpointAddress 00329 0x02, // bmAttributes (0x02=bulk) 00330 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00331 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00332 0, // bInterval 00333 00334 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 00335 7, // bLength 00336 5, // bDescriptorType 00337 PHY_TO_DESC(MSDBULK_OUT), // bEndpointAddress 00338 0x02, // bmAttributes (0x02=bulk) 00339 LSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (LSB) 00340 MSB(MAX_PACKET_SIZE_EPBULK),// wMaxPacketSize (MSB) 00341 0 // bInterval 00342 }; 00343 return configDescriptor; 00344 } 00345 00346 int USBCDCMSC::_putc(int c) { 00347 send((uint8_t *)&c, 1); 00348 return 1; 00349 } 00350 00351 int USBCDCMSC::_getc() { 00352 uint8_t c; 00353 while (cdcbuf.isEmpty()); 00354 cdcbuf.dequeue(&c); 00355 return c; 00356 } 00357 00358 00359 bool USBCDCMSC::writeBlock(uint8_t * buf, uint16_t size) { 00360 if(size > MAX_PACKET_SIZE_EPBULK) { 00361 return false; 00362 } 00363 if(!send(buf, size)) { 00364 return false; 00365 } 00366 return true; 00367 } 00368 00369 00370 00371 bool USBCDCMSC::EP2_OUT_callback() { 00372 uint8_t c[65]; 00373 uint16_t size = 0; 00374 00375 //we read the packet received and put it on the circular buffer 00376 readEP(c, &size); 00377 for (int i = 0; i < size; i++) { 00378 cdcbuf.queue(c[i]); 00379 } 00380 00381 //call a potential handler 00382 rx.call(); 00383 00384 // We reactivate the endpoint to receive next characters 00385 readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00386 return true; 00387 } 00388 00389 uint8_t USBCDCMSC::available() { 00390 return cdcbuf.available(); 00391 } 00392 00393 00394 bool USBCDCMSC::connect() { 00395 00396 //disk initialization 00397 if (disk_status() & NO_INIT) { 00398 if (disk_initialize()) { 00399 return false; 00400 } 00401 } 00402 00403 // get number of blocks 00404 BlockCount = disk_sectors(); 00405 00406 // get memory size 00407 MemorySize = disk_size(); 00408 00409 if (BlockCount >= 0) { 00410 BlockSize = MemorySize / BlockCount; 00411 if (BlockSize != 0) { 00412 page = (uint8_t *)malloc(BlockSize * sizeof(uint8_t)); 00413 if (page == NULL) 00414 return false; 00415 } 00416 } else { 00417 return false; 00418 } 00419 00420 //connect the device 00421 // USBDevice::connect(); 00422 return true; 00423 } 00424 00425 00426 void USBCDCMSC::reset() { 00427 stage = READ_CBW; 00428 } 00429 00430 00431 // Called in ISR context called when a data is received 00432 bool USBCDCMSC::EP5_OUT_callback() { 00433 uint16_t size = 0; 00434 uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00435 USBDevice::readEP(MSDBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK); 00436 switch (stage) { 00437 // the device has to decode the CBW received 00438 case READ_CBW: 00439 CBWDecode(buf, size); 00440 break; 00441 00442 // the device has to receive data from the host 00443 case PROCESS_CBW: 00444 switch (cbw.CB[0]) { 00445 case WRITE10: 00446 case WRITE12: 00447 memoryWrite(buf, size); 00448 break; 00449 case VERIFY10: 00450 memoryVerify(buf, size); 00451 break; 00452 } 00453 break; 00454 00455 // an error has occured: stall endpoint and send CSW 00456 default: 00457 stallEndpoint(MSDBULK_OUT); 00458 csw.Status = CSW_ERROR; 00459 sendCSW(); 00460 break; 00461 } 00462 00463 //reactivate readings on the OUT bulk endpoint 00464 readStart(MSDBULK_OUT, MAX_PACKET_SIZE_EPBULK); 00465 return true; 00466 } 00467 00468 // Called in ISR context when a data has been transferred 00469 bool USBCDCMSC::EP5_IN_callback() { 00470 switch (stage) { 00471 00472 // the device has to send data to the host 00473 case PROCESS_CBW: 00474 switch (cbw.CB[0]) { 00475 case READ10: 00476 case READ12: 00477 memoryRead(); 00478 break; 00479 } 00480 break; 00481 00482 //the device has to send a CSW 00483 case SEND_CSW: 00484 sendCSW(); 00485 break; 00486 00487 // an error has occured 00488 case ERROR: 00489 stallEndpoint(MSDBULK_IN); 00490 sendCSW(); 00491 break; 00492 00493 // the host has received the CSW -> we wait a CBW 00494 case WAIT_CSW: 00495 stage = READ_CBW; 00496 break; 00497 } 00498 return true; 00499 } 00500 00501 00502 void USBCDCMSC::memoryWrite (uint8_t * buf, uint16_t size) { 00503 00504 if ((addr + size) > MemorySize) { 00505 size = MemorySize - addr; 00506 stage = ERROR; 00507 stallEndpoint(MSDBULK_OUT); 00508 } 00509 00510 // we fill an array in RAM of 1 block before writing it in memory 00511 for (int i = 0; i < size; i++) 00512 page[addr%BlockSize + i] = buf[i]; 00513 00514 // if the array is filled, write it in memory 00515 if (!((addr + size)%BlockSize)) { 00516 if (!(disk_status() & WRITE_PROTECT)) { 00517 disk_write((const char *)page, addr/BlockSize); 00518 } 00519 } 00520 00521 addr += size; 00522 length -= size; 00523 csw.DataResidue -= size; 00524 00525 if ((!length) || (stage != PROCESS_CBW)) { 00526 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00527 sendCSW(); 00528 } 00529 } 00530 00531 void USBCDCMSC::memoryVerify (uint8_t * buf, uint16_t size) { 00532 uint32_t n; 00533 00534 if ((addr + size) > MemorySize) { 00535 size = MemorySize - addr; 00536 stage = ERROR; 00537 stallEndpoint(MSDBULK_OUT); 00538 } 00539 00540 // beginning of a new block -> load a whole block in RAM 00541 if (!(addr%BlockSize)) 00542 disk_read((char *)page, addr/BlockSize); 00543 00544 // info are in RAM -> no need to re-read memory 00545 for (n = 0; n < size; n++) { 00546 if (page[addr%BlockSize + n] != buf[n]) { 00547 memOK = false; 00548 break; 00549 } 00550 } 00551 00552 addr += size; 00553 length -= size; 00554 csw.DataResidue -= size; 00555 00556 if ( !length || (stage != PROCESS_CBW)) { 00557 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00558 sendCSW(); 00559 } 00560 } 00561 00562 00563 bool USBCDCMSC::inquiryRequest (void) { 00564 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00565 36 - 4, 0x80, 0x00, 0x00, 00566 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00567 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00568 '1', '.', '0', ' ', 00569 }; 00570 if (!msd_write(inquiry, sizeof(inquiry))) { 00571 return false; 00572 } 00573 return true; 00574 } 00575 00576 00577 bool USBCDCMSC::readFormatCapacity() { 00578 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00579 (BlockCount >> 24) & 0xff, 00580 (BlockCount >> 16) & 0xff, 00581 (BlockCount >> 8) & 0xff, 00582 (BlockCount >> 0) & 0xff, 00583 00584 0x02, 00585 (BlockSize >> 16) & 0xff, 00586 (BlockSize >> 8) & 0xff, 00587 (BlockSize >> 0) & 0xff, 00588 }; 00589 if (!msd_write(capacity, sizeof(capacity))) { 00590 return false; 00591 } 00592 return true; 00593 } 00594 00595 00596 bool USBCDCMSC::readCapacity (void) { 00597 uint8_t capacity[] = { 00598 ((BlockCount - 1) >> 24) & 0xff, 00599 ((BlockCount - 1) >> 16) & 0xff, 00600 ((BlockCount - 1) >> 8) & 0xff, 00601 ((BlockCount - 1) >> 0) & 0xff, 00602 00603 (BlockSize >> 24) & 0xff, 00604 (BlockSize >> 16) & 0xff, 00605 (BlockSize >> 8) & 0xff, 00606 (BlockSize >> 0) & 0xff, 00607 }; 00608 if (!msd_write(capacity, sizeof(capacity))) { 00609 return false; 00610 } 00611 return true; 00612 } 00613 00614 bool USBCDCMSC::msd_write (uint8_t * buf, uint16_t size) { 00615 00616 if (size >= cbw.DataLength) { 00617 size = cbw.DataLength; 00618 } 00619 stage = SEND_CSW; 00620 00621 if (!writeNB(MSDBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK)) { 00622 return false; 00623 } 00624 00625 csw.DataResidue -= size; 00626 csw.Status = CSW_PASSED; 00627 return true; 00628 } 00629 00630 00631 bool USBCDCMSC::modeSense6 (void) { 00632 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00633 if (!msd_write(sense6, sizeof(sense6))) { 00634 return false; 00635 } 00636 return true; 00637 } 00638 00639 void USBCDCMSC::sendCSW() { 00640 csw.Signature = CSW_Signature; 00641 writeNB(MSDBULK_IN, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); 00642 stage = WAIT_CSW; 00643 } 00644 00645 bool USBCDCMSC::requestSense (void) { 00646 uint8_t request_sense[] = { 00647 0x70, 00648 0x00, 00649 0x05, // Sense Key: illegal request 00650 0x00, 00651 0x00, 00652 0x00, 00653 0x00, 00654 0x0A, 00655 0x00, 00656 0x00, 00657 0x00, 00658 0x00, 00659 0x30, 00660 0x01, 00661 0x00, 00662 0x00, 00663 0x00, 00664 0x00, 00665 }; 00666 00667 if (!msd_write(request_sense, sizeof(request_sense))) { 00668 return false; 00669 } 00670 00671 return true; 00672 } 00673 00674 void USBCDCMSC::fail() { 00675 csw.Status = CSW_FAILED; 00676 sendCSW(); 00677 } 00678 00679 00680 void USBCDCMSC::CBWDecode(uint8_t * buf, uint16_t size) { 00681 if (size == sizeof(cbw)) { 00682 memcpy((uint8_t *)&cbw, buf, size); 00683 if (cbw.Signature == CBW_Signature) { 00684 csw.Tag = cbw.Tag; 00685 csw.DataResidue = cbw.DataLength; 00686 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { 00687 fail(); 00688 } else { 00689 switch (cbw.CB[0]) { 00690 case TEST_UNIT_READY: 00691 testUnitReady(); 00692 break; 00693 case REQUEST_SENSE: 00694 requestSense(); 00695 break; 00696 case INQUIRY: 00697 inquiryRequest(); 00698 break; 00699 case MODE_SENSE6: 00700 modeSense6(); 00701 break; 00702 case READ_FORMAT_CAPACITIES: 00703 readFormatCapacity(); 00704 break; 00705 case READ_CAPACITY: 00706 readCapacity(); 00707 break; 00708 case READ10: 00709 case READ12: 00710 if (infoTransfer()) { 00711 if ((cbw.Flags & 0x80)) { 00712 stage = PROCESS_CBW; 00713 memoryRead(); 00714 } else { 00715 stallEndpoint(MSDBULK_OUT); 00716 csw.Status = CSW_ERROR; 00717 sendCSW(); 00718 } 00719 } 00720 break; 00721 case WRITE10: 00722 case WRITE12: 00723 if (infoTransfer()) { 00724 if (!(cbw.Flags & 0x80)) { 00725 stage = PROCESS_CBW; 00726 } else { 00727 stallEndpoint(MSDBULK_IN); 00728 csw.Status = CSW_ERROR; 00729 sendCSW(); 00730 } 00731 } 00732 break; 00733 case VERIFY10: 00734 if (!(cbw.CB[1] & 0x02)) { 00735 csw.Status = CSW_PASSED; 00736 sendCSW(); 00737 break; 00738 } 00739 if (infoTransfer()) { 00740 if (!(cbw.Flags & 0x80)) { 00741 stage = PROCESS_CBW; 00742 memOK = true; 00743 } else { 00744 stallEndpoint(MSDBULK_IN); 00745 csw.Status = CSW_ERROR; 00746 sendCSW(); 00747 } 00748 } 00749 break; 00750 default: 00751 fail(); 00752 break; 00753 } 00754 } 00755 } 00756 } 00757 } 00758 00759 void USBCDCMSC::testUnitReady (void) { 00760 00761 if (cbw.DataLength != 0) { 00762 if ((cbw.Flags & 0x80) != 0) { 00763 stallEndpoint(MSDBULK_IN); 00764 } else { 00765 stallEndpoint(MSDBULK_OUT); 00766 } 00767 } 00768 00769 csw.Status = CSW_PASSED; 00770 sendCSW(); 00771 } 00772 00773 00774 void USBCDCMSC::memoryRead (void) { 00775 uint32_t n; 00776 00777 n = (length > MAX_PACKET) ? MAX_PACKET : length; 00778 00779 if ((addr + n) > MemorySize) { 00780 n = MemorySize - addr; 00781 stage = ERROR; 00782 } 00783 00784 // we read an entire block 00785 if (!(addr%BlockSize)) 00786 disk_read((char *)page, addr/BlockSize); 00787 00788 // write data which are in RAM 00789 writeNB(MSDBULK_IN, &page[addr%BlockSize], n, MAX_PACKET_SIZE_EPBULK); 00790 00791 addr += n; 00792 length -= n; 00793 00794 csw.DataResidue -= n; 00795 00796 if ( !length || (stage != PROCESS_CBW)) { 00797 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00798 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; 00799 } 00800 } 00801 00802 00803 bool USBCDCMSC::infoTransfer (void) { 00804 uint32_t n; 00805 00806 // Logical Block Address of First Block 00807 n = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); 00808 00809 addr = n * BlockSize; 00810 00811 // Number of Blocks to transfer 00812 switch (cbw.CB[0]) { 00813 case READ10: 00814 case WRITE10: 00815 case VERIFY10: 00816 n = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); 00817 break; 00818 00819 case READ12: 00820 case WRITE12: 00821 n = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); 00822 break; 00823 } 00824 00825 length = n * BlockSize; 00826 00827 if (!cbw.DataLength) { // host requests no data 00828 csw.Status = CSW_FAILED; 00829 sendCSW(); 00830 return false; 00831 } 00832 00833 if (cbw.DataLength != length) { 00834 if ((cbw.Flags & 0x80) != 0) { 00835 stallEndpoint(MSDBULK_IN); 00836 } else { 00837 stallEndpoint(MSDBULK_OUT); 00838 } 00839 00840 csw.Status = CSW_FAILED; 00841 sendCSW(); 00842 return false; 00843 } 00844 00845 return true; 00846 } 00847 00848 int USBCDCMSC::isBreak () { 00849 int ret = cdcbreak; 00850 cdcbreak = 0; 00851 return ret; 00852 } 00853 00854 int USBCDCMSC::disk_initialize() { 00855 if (_sd->disk_initialize()) { 00856 _status |= NO_DISK; 00857 return 1; 00858 } else { 00859 _status = DISK_OK; 00860 return 0; 00861 } 00862 } 00863 00864 int USBCDCMSC::disk_write(const char *buffer, int block_number) { 00865 return _sd->disk_write(buffer, block_number); 00866 } 00867 00868 int USBCDCMSC::disk_read(char *buffer, int block_number) { 00869 return _sd->disk_read(buffer, block_number); 00870 } 00871 00872 int USBCDCMSC::disk_status() { 00873 return _status; 00874 } 00875 00876 int USBCDCMSC::disk_sectors() { 00877 return _sd->disk_sectors(); 00878 } 00879 int USBCDCMSC::disk_size() { 00880 return _sd->disk_sectors() * 512; 00881 }
Generated on Wed Jul 13 2022 11:42:57 by
1.7.2