Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie 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 <stdlib.h> 00021 #include <cstring> 00022 #include <cstdio> 00023 00024 #include "USBMSD.h" 00025 00026 #include "descriptor_msc.h" 00027 00028 #include "Kernel.h" 00029 00030 #include "platform_memory.h" 00031 00032 #define DISK_OK 0x00 00033 #define NO_INIT 0x01 00034 #define NO_DISK 0x02 00035 #define WRITE_PROTECT 0x04 00036 00037 #define CBW_Signature 0x43425355 00038 #define CSW_Signature 0x53425355 00039 00040 // SCSI Commands 00041 #define TEST_UNIT_READY 0x00 00042 #define REQUEST_SENSE 0x03 00043 #define FORMAT_UNIT 0x04 00044 #define INQUIRY 0x12 00045 #define MODE_SELECT6 0x15 00046 #define MODE_SENSE6 0x1A 00047 #define START_STOP_UNIT 0x1B 00048 #define MEDIA_REMOVAL 0x1E 00049 #define READ_FORMAT_CAPACITIES 0x23 00050 #define READ_CAPACITY 0x25 00051 #define READ10 0x28 00052 #define WRITE10 0x2A 00053 #define VERIFY10 0x2F 00054 #define READ12 0xA8 00055 #define WRITE12 0xAA 00056 #define MODE_SELECT10 0x55 00057 #define MODE_SENSE10 0x5A 00058 00059 // MSC class specific requests 00060 #define MSC_REQUEST_RESET 0xFF 00061 #define MSC_REQUEST_GET_MAX_LUN 0xFE 00062 00063 #define STARTSTOP_STOPMOTOR 0x0 00064 #define STARTSTOP_STARTMOTOR 0x1 00065 #define STARTSTOP_EJECT 0x2 00066 #define STARTSTOP_LOAD 0x3 00067 00068 #define DEFAULT_CONFIGURATION (1) 00069 00070 // max packet size 00071 #define MAX_PACKET MAX_PACKET_SIZE_EPBULK 00072 00073 // #define iprintf(...) THEKERNEL->streams->printf(__VA_ARGS__) 00074 #define iprintf(...) do { } while (0) 00075 00076 // CSW Status 00077 enum Status { 00078 CSW_PASSED, 00079 CSW_FAILED, 00080 CSW_ERROR, 00081 }; 00082 00083 USBMSD::USBMSD(USB *u, MSD_Disk *d) { 00084 this->usb = u; 00085 this->disk = d; 00086 00087 MSC_Interface = { 00088 DL_INTERFACE, // bLength 00089 DT_INTERFACE, // bDescType 00090 0, // bInterfaceNumber - filled out by USB during attach() 00091 0, // bAlternateSetting 00092 2, // bNumEndpoints 00093 UC_MASS_STORAGE, // bInterfaceClass 00094 MSC_SUBCLASS_SCSI, // bInterfaceSubClass 00095 MSC_PROTOCOL_BULK_ONLY, // bInterfaceProtocol 00096 0, // iInterface 00097 0, 0, 0, // dummy padding 00098 this, // callback 00099 }; 00100 00101 MSC_BulkIn = { 00102 DL_ENDPOINT, // bLength 00103 DT_ENDPOINT, // bDescType 00104 EP_DIR_IN, // bEndpointAddress - we provide direction, index is filled out by USB during attach() 00105 EA_BULK, // bmAttributes 00106 MAX_PACKET_SIZE_EPBULK, // wMaxPacketSize 00107 0, // bInterval 00108 0, // dummy padding 00109 this, // endpoint callback 00110 }; 00111 MSC_BulkOut = { 00112 DL_ENDPOINT, // bLength 00113 DT_ENDPOINT, // bDescType 00114 EP_DIR_OUT, // bEndpointAddress - we provide direction, index is filled out by USB during attach() 00115 EA_BULK, // bmAttributes 00116 MAX_PACKET_SIZE_EPBULK, // wMaxPacketSize 00117 0, // bInterval 00118 0, // dummy padding 00119 this, // endpoint callback 00120 }; 00121 00122 // because gcc-4.6 won't let us simply do MSC_Description = usbstring("Smoothie MSD") 00123 usbdesc_string_l(13) us = usbstring("Smoothie MSD"); 00124 memcpy(&MSC_Description, &us, sizeof(MSC_Description)); 00125 00126 usb->addInterface(&MSC_Interface); 00127 00128 usb->addEndpoint(&MSC_BulkIn); 00129 usb->addEndpoint(&MSC_BulkOut); 00130 00131 MSC_Interface.iInterface = 00132 usb->addString(&MSC_Description); 00133 } 00134 00135 // Called in ISR context to process a class specific request 00136 bool USBMSD::USBEvent_Request(CONTROL_TRANSFER &transfer) 00137 { 00138 iprintf("MSD:Control: "); 00139 bool success = false; 00140 // CONTROL_TRANSFER * transfer = getTransferPtr(); 00141 static uint8_t maxLUN[1] = {0}; 00142 00143 if (transfer.setup.bmRequestType.Type == CLASS_TYPE) { 00144 switch (transfer.setup.bRequest) { 00145 case MSC_REQUEST_RESET: 00146 // iprintf("MSC:Req Reset\n"); 00147 reset(); 00148 success = true; 00149 break; 00150 case MSC_REQUEST_GET_MAX_LUN: 00151 // iprintf("MSC:Req Get_Max_Lun\n"); 00152 transfer.remaining = 1; 00153 transfer.ptr = maxLUN; 00154 transfer.direction = DEVICE_TO_HOST; 00155 success = true; 00156 break; 00157 default: 00158 break; 00159 } 00160 } 00161 iprintf("%d\n", success?1:0); 00162 00163 return success; 00164 } 00165 00166 bool USBMSD::USBEvent_RequestComplete(CONTROL_TRANSFER &transfer, uint8_t *buf, uint32_t length) 00167 { 00168 return true; 00169 } 00170 00171 bool USBMSD::connect() 00172 { 00173 BlockCount = 0; 00174 00175 //disk initialization 00176 if (disk->disk_status() & NO_INIT) { 00177 if (disk->disk_initialize()) { 00178 return false; 00179 } 00180 } 00181 00182 // get number of blocks 00183 BlockCount = disk->disk_sectors(); 00184 00185 // get memory size 00186 // MemorySize = disk->disk_size(); 00187 BlockSize = disk->disk_blocksize(); 00188 00189 if ((BlockCount > 0) && (BlockSize != 0)) { 00190 page = (uint8_t*) AHB0.alloc(BlockSize); 00191 if (page == NULL) 00192 return false; 00193 } else { 00194 return false; 00195 } 00196 00197 return true; 00198 } 00199 00200 00201 void USBMSD::reset() { 00202 stage = READ_CBW; 00203 usb->endpointSetInterrupt(MSC_BulkOut.bEndpointAddress, true); 00204 usb->endpointSetInterrupt(MSC_BulkIn.bEndpointAddress, false); 00205 } 00206 00207 00208 // Called in ISR context called when a data is received 00209 // bool USBMSD::EP2_OUT_callback() { 00210 bool USBMSD::USBEvent_EPOut(uint8_t bEP, uint8_t bEPStatus) { 00211 uint32_t size = 0; 00212 // uint8_t buf[MAX_PACKET_SIZE_EPBULK]; 00213 usb->readEP(MSC_BulkOut.bEndpointAddress, buffer, &size, MAX_PACKET_SIZE_EPBULK); 00214 iprintf("MSD:EPOut:Read %lu\n", size); 00215 switch (stage) { 00216 // the device has to decode the CBW received 00217 case READ_CBW: 00218 CBWDecode(buffer, size); 00219 break; 00220 00221 // the device has to receive data from the host 00222 case PROCESS_CBW: 00223 switch (cbw.CB[0]) { 00224 case WRITE10: 00225 case WRITE12: 00226 memoryWrite(buffer, size); 00227 break; 00228 case VERIFY10: 00229 memoryVerify(buffer, size); 00230 break; 00231 } 00232 break; 00233 00234 // an error has occured: stall endpoint and send CSW 00235 default: 00236 usb->stallEndpoint(MSC_BulkOut.bEndpointAddress); 00237 csw.Status = CSW_ERROR; 00238 sendCSW(); 00239 break; 00240 } 00241 00242 //reactivate readings on the OUT bulk endpoint 00243 usb->readStart(MSC_BulkOut.bEndpointAddress, MAX_PACKET_SIZE_EPBULK); 00244 return true; 00245 } 00246 00247 // Called in ISR context when a data has been transferred 00248 // bool USBMSD::EP2_IN_callback() { 00249 bool USBMSD::USBEvent_EPIn(uint8_t bEP, uint8_t bEPStatus) { 00250 uint8_t _stage = stage; 00251 if (stage != 2) 00252 iprintf("MSD:In:S%d,G:", stage); 00253 00254 bool gotMoreData = false; 00255 00256 switch (stage) { 00257 // not sure 00258 case READ_CBW: // stage 0 00259 gotMoreData = false; 00260 break; 00261 00262 // the device has to send data to the host 00263 case PROCESS_CBW: // stage 2 00264 gotMoreData = false; 00265 switch (cbw.CB[0]) { 00266 case READ10: 00267 case READ12: 00268 memoryRead(); 00269 gotMoreData = true; 00270 break; 00271 } 00272 break; 00273 00274 //the device has to send a CSW 00275 case SEND_CSW: // stage 3 00276 sendCSW(); 00277 gotMoreData = true; 00278 break; 00279 00280 // an error has occured 00281 case ERROR: // stage 1 00282 usb->stallEndpoint(MSC_BulkIn.bEndpointAddress); 00283 sendCSW(); 00284 gotMoreData = false; 00285 break; 00286 00287 // the host has received the CSW -> we wait a CBW 00288 case WAIT_CSW: // stage 4 00289 stage = READ_CBW; 00290 gotMoreData = false; 00291 break; 00292 } 00293 00294 if (_stage != 2) 00295 iprintf("%d\n", gotMoreData?1:0); 00296 00297 return gotMoreData; 00298 } 00299 00300 void USBMSD::memoryWrite (uint8_t * buf, uint16_t size) { 00301 00302 if (lba > BlockCount) { 00303 size = (BlockCount - lba) * BlockSize + addr_in_block; 00304 stage = ERROR; 00305 usb->stallEndpoint(MSC_BulkOut.bEndpointAddress); 00306 } 00307 00308 // we fill an array in RAM of 1 block before writing it in memory 00309 for (int i = 0; i < size; i++) 00310 page[addr_in_block + i] = buf[i]; 00311 00312 // if the array is filled, write it in memory 00313 if ((addr_in_block + size) >= BlockSize) { 00314 if (!(disk->disk_status() & WRITE_PROTECT)) { 00315 disk->disk_write((const char *)page, lba); 00316 } 00317 } 00318 00319 addr_in_block += size; 00320 length -= size; 00321 csw.DataResidue -= size; 00322 if (addr_in_block >= BlockSize) 00323 { 00324 addr_in_block = 0; 00325 lba++; 00326 } 00327 00328 if ((!length) || (stage != PROCESS_CBW)) { 00329 csw.Status = (stage == ERROR) ? CSW_FAILED : CSW_PASSED; 00330 sendCSW(); 00331 } 00332 } 00333 00334 void USBMSD::memoryVerify (uint8_t * buf, uint16_t size) { 00335 uint32_t n; 00336 00337 if (lba > BlockCount) { 00338 size = (BlockCount - lba) * BlockSize + addr_in_block; 00339 stage = ERROR; 00340 usb->stallEndpoint(MSC_BulkOut.bEndpointAddress); 00341 } 00342 00343 // beginning of a new block -> load a whole block in RAM 00344 if (addr_in_block == 0) 00345 disk->disk_read((char *)page, lba); 00346 00347 // info are in RAM -> no need to re-read memory 00348 for (n = 0; n < size; n++) { 00349 if (page[addr_in_block + n] != buf[n]) { 00350 memOK = false; 00351 break; 00352 } 00353 } 00354 00355 addr_in_block += size; 00356 length -= size; 00357 csw.DataResidue -= size; 00358 00359 if (addr_in_block >= BlockSize) 00360 { 00361 addr_in_block = 0; 00362 lba++; 00363 } 00364 00365 if ( !length || (stage != PROCESS_CBW)) { 00366 csw.Status = (memOK && (stage == PROCESS_CBW)) ? CSW_PASSED : CSW_FAILED; 00367 sendCSW(); 00368 } 00369 } 00370 00371 00372 bool USBMSD::inquiryRequest (void) { 00373 uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01, 00374 36 - 4, 0x00, 0x00, 0x01, 00375 'M', 'B', 'E', 'D', '.', 'O', 'R', 'G', 00376 'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ', 00377 '1', '.', '0', ' ', 00378 }; 00379 00380 if (BlockCount == 0) 00381 inquiry[0] = 0x20; // PERIPHERAL_QUALIFIER = 1 : "A peripheral device is not connected, however usually we do support this type of peripheral" 00382 00383 if (!write(inquiry, sizeof(inquiry))) { 00384 return false; 00385 } 00386 return true; 00387 } 00388 00389 00390 bool USBMSD::readFormatCapacity() { 00391 uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08, 00392 (uint8_t) ((BlockCount >> 24) & 0xff), 00393 (uint8_t) ((BlockCount >> 16) & 0xff), 00394 (uint8_t) ((BlockCount >> 8) & 0xff), 00395 (uint8_t) ((BlockCount >> 0) & 0xff), 00396 00397 0x02, 00398 (uint8_t) ((BlockSize >> 16) & 0xff), 00399 (uint8_t) ((BlockSize >> 8) & 0xff), 00400 (uint8_t) ((BlockSize >> 0) & 0xff), 00401 }; 00402 if (!write(capacity, sizeof(capacity))) { 00403 return false; 00404 } 00405 return true; 00406 } 00407 00408 00409 bool USBMSD::readCapacity (void) { 00410 uint8_t capacity[] = { 00411 (uint8_t) (((BlockCount - 1) >> 24) & 0xff), 00412 (uint8_t) (((BlockCount - 1) >> 16) & 0xff), 00413 (uint8_t) (((BlockCount - 1) >> 8) & 0xff), 00414 (uint8_t) (((BlockCount - 1) >> 0) & 0xff), 00415 00416 (uint8_t) ((BlockSize >> 24) & 0xff), 00417 (uint8_t) ((BlockSize >> 16) & 0xff), 00418 (uint8_t) ((BlockSize >> 8) & 0xff), 00419 (uint8_t) ((BlockSize >> 0) & 0xff), 00420 }; 00421 if (!write(capacity, sizeof(capacity))) { 00422 return false; 00423 } 00424 return true; 00425 } 00426 00427 bool USBMSD::write (uint8_t * buf, uint16_t size) { 00428 if (size >= cbw.DataLength) { 00429 size = cbw.DataLength; 00430 } 00431 stage = SEND_CSW; 00432 00433 // iprintf("MSD:write: %u bytes\n", size); 00434 00435 if (!usb->writeNB(MSC_BulkIn.bEndpointAddress, buf, size, MAX_PACKET_SIZE_EPBULK)) { 00436 return false; 00437 } 00438 00439 // iprintf("MSD:write OK, sending CSW\n"); 00440 00441 csw.DataResidue -= size; 00442 csw.Status = CSW_PASSED; 00443 00444 usb->endpointSetInterrupt(MSC_BulkIn.bEndpointAddress, true); 00445 00446 return true; 00447 } 00448 00449 00450 bool USBMSD::modeSense6 (void) { 00451 uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 }; 00452 if (!write(sense6, sizeof(sense6))) { 00453 return false; 00454 } 00455 return true; 00456 } 00457 00458 void USBMSD::sendCSW() { 00459 csw.Signature = CSW_Signature; 00460 // iprintf("MSD:SendCSW:\n\tSignature : %lu\n\tTag : %lu\n\tDataResidue: %lu\n\tStatus : %u\n", csw.Signature, csw.Tag, csw.DataResidue, csw.Status); 00461 usb->writeNB(MSC_BulkIn.bEndpointAddress, (uint8_t *)&csw, sizeof(CSW), MAX_PACKET_SIZE_EPBULK); 00462 stage = WAIT_CSW; 00463 usb->endpointSetInterrupt(MSC_BulkIn.bEndpointAddress, true); 00464 } 00465 00466 bool USBMSD::requestSense (void) { 00467 uint8_t request_sense[] = { 00468 0x70, 00469 0x00, 00470 0x05, // Sense Key: illegal request 00471 0x00, 00472 0x00, 00473 0x00, 00474 0x00, 00475 0x0A, 00476 0x00, 00477 0x00, 00478 0x00, 00479 0x00, 00480 0x30, 00481 0x01, 00482 0x00, 00483 0x00, 00484 0x00, 00485 0x00, 00486 }; 00487 00488 if (BlockCount == 0) 00489 { 00490 request_sense[ 2] = 0x02; // Not Ready 00491 request_sense[12] = 0x3A; // Medium not present 00492 request_sense[13] = 0x00; // No known reason 00493 } 00494 00495 if (!write(request_sense, sizeof(request_sense))) { 00496 return false; 00497 } 00498 00499 return true; 00500 } 00501 00502 void USBMSD::fail() { 00503 csw.Status = CSW_FAILED; 00504 sendCSW(); 00505 } 00506 00507 void USBMSD::CBWDecode(uint8_t * buf, uint16_t size) { 00508 if (size == sizeof(cbw)) { 00509 memcpy((uint8_t *)&cbw, buf, size); 00510 if (cbw.Signature == CBW_Signature) { 00511 csw.Tag = cbw.Tag; 00512 csw.DataResidue = cbw.DataLength; 00513 if ((cbw.CBLength < 1) || (cbw.CBLength > 16) ) { 00514 iprintf("MSD:Got CBW 0x%02X with invalid CBLength\n", cbw.CB[0]); 00515 fail(); 00516 } else { 00517 iprintf("MSD:Got CBW 0x%02X with datalength %lu\n", cbw.CB[0], cbw.DataLength); 00518 switch (cbw.CB[0]) { 00519 case TEST_UNIT_READY: 00520 testUnitReady(); 00521 break; 00522 case REQUEST_SENSE: 00523 requestSense(); 00524 break; 00525 case INQUIRY: 00526 inquiryRequest(); 00527 break; 00528 case MODE_SENSE6: 00529 modeSense6(); 00530 break; 00531 case READ_FORMAT_CAPACITIES: 00532 readFormatCapacity(); 00533 break; 00534 case READ_CAPACITY: 00535 readCapacity(); 00536 break; 00537 case READ10: 00538 case READ12: 00539 // iprintf("MSD:READ10\n"); 00540 if (infoTransfer()) { 00541 if ((cbw.Flags & 0x80)) { 00542 iprintf("MSD: Read %lu blocks from LBA %lu\n", blocks, lba); 00543 stage = PROCESS_CBW; 00544 // memoryRead(); 00545 usb->endpointSetInterrupt(MSC_BulkIn.bEndpointAddress, true); 00546 } else { 00547 usb->stallEndpoint(MSC_BulkOut.bEndpointAddress); 00548 csw.Status = CSW_ERROR; 00549 sendCSW(); 00550 } 00551 } 00552 break; 00553 case WRITE10: 00554 case WRITE12: 00555 if (infoTransfer()) { 00556 if (!(cbw.Flags & 0x80)) { 00557 iprintf("MSD: Write %lu blocks from LBA %lu\n", blocks, lba); 00558 stage = PROCESS_CBW; 00559 } else { 00560 usb->stallEndpoint(MSC_BulkIn.bEndpointAddress); 00561 csw.Status = CSW_ERROR; 00562 sendCSW(); 00563 } 00564 } 00565 break; 00566 case VERIFY10: 00567 if (!(cbw.CB[1] & 0x02)) { 00568 csw.Status = CSW_PASSED; 00569 sendCSW(); 00570 break; 00571 } 00572 if (infoTransfer()) { 00573 if (!(cbw.Flags & 0x80)) { 00574 iprintf("MSD: Verify %lu blocks from LBA %lu\n", blocks, lba); 00575 stage = PROCESS_CBW; 00576 memOK = true; 00577 } else { 00578 usb->stallEndpoint(MSC_BulkIn.bEndpointAddress); 00579 csw.Status = CSW_ERROR; 00580 sendCSW(); 00581 } 00582 } 00583 break; 00584 case START_STOP_UNIT: 00585 { 00586 switch (cbw.CB[4] & 0x03) 00587 { 00588 case STARTSTOP_STOPMOTOR: 00589 break; 00590 case STARTSTOP_STARTMOTOR: 00591 break; 00592 case STARTSTOP_EJECT: 00593 break; 00594 case STARTSTOP_LOAD: 00595 break; 00596 } 00597 csw.Status = CSW_PASSED; 00598 sendCSW(); 00599 break; 00600 } 00601 default: 00602 iprintf("MSD: Unhandled SCSI CBW 0x%02X\n", cbw.CB[0]); 00603 fail(); 00604 break; 00605 } 00606 } 00607 } 00608 else { 00609 iprintf("MSD:Got CBW 0x%02X with bad signature\n", cbw.CB[0]); 00610 } 00611 } 00612 else { 00613 iprintf("MSD:Got CBW 0x%02X with bad length: %u (%u)\n", cbw.CB[0], size, sizeof(cbw)); 00614 } 00615 } 00616 00617 void USBMSD::testUnitReady (void) { 00618 00619 if (cbw.DataLength != 0) { 00620 if ((cbw.Flags & 0x80) != 0) { 00621 usb->stallEndpoint(MSC_BulkIn.bEndpointAddress); 00622 } else { 00623 usb->stallEndpoint(MSC_BulkOut.bEndpointAddress); 00624 } 00625 } 00626 00627 if (BlockCount > 0) 00628 csw.Status = CSW_PASSED; 00629 else 00630 csw.Status = CSW_ERROR; 00631 00632 sendCSW(); 00633 } 00634 00635 void USBMSD::memoryRead (void) { 00636 uint32_t n; 00637 00638 n = (length > MAX_PACKET_SIZE_EPBULK) ? MAX_PACKET_SIZE_EPBULK : length; 00639 00640 if (lba > BlockCount) { 00641 iprintf("MSD:Attemt to read beyond end of disk! Read LBA %lu > Disk LBAs %lu\n", lba, BlockCount); 00642 n = (BlockCount - lba) * BlockSize + addr_in_block; 00643 stage = ERROR; 00644 } 00645 00646 // we read an entire block 00647 if (addr_in_block == 0) 00648 { 00649 iprintf("MSD:LBA %lu:", lba); 00650 disk->disk_read((char *)page, lba); 00651 } 00652 00653 iprintf(" %u", addr_in_block / MAX_PACKET_SIZE_EPBULK); 00654 00655 // write data which are in RAM 00656 usb->writeNB(MSC_BulkIn.bEndpointAddress, &page[addr_in_block], n, MAX_PACKET_SIZE_EPBULK); 00657 00658 addr_in_block += n; 00659 00660 length -= n; 00661 csw.DataResidue -= n; 00662 00663 if (addr_in_block >= BlockSize) 00664 { 00665 iprintf("\n"); 00666 addr_in_block = 0; 00667 lba++; 00668 } 00669 00670 if ( !length || (stage != PROCESS_CBW)) { 00671 csw.Status = (stage == PROCESS_CBW) ? CSW_PASSED : CSW_FAILED; 00672 stage = (stage == PROCESS_CBW) ? SEND_CSW : stage; 00673 } 00674 usb->endpointSetInterrupt(MSC_BulkIn.bEndpointAddress, true); 00675 } 00676 00677 bool USBMSD::infoTransfer (void) { 00678 // Logical Block Address of First Block 00679 lba = (cbw.CB[2] << 24) | (cbw.CB[3] << 16) | (cbw.CB[4] << 8) | (cbw.CB[5] << 0); 00680 00681 // addr = lba * BlockSize; 00682 00683 // Number of Blocks to transfer 00684 switch (cbw.CB[0]) { 00685 case READ10: 00686 case WRITE10: 00687 case VERIFY10: 00688 blocks = (cbw.CB[7] << 8) | (cbw.CB[8] << 0); 00689 break; 00690 00691 case READ12: 00692 case WRITE12: 00693 blocks = (cbw.CB[6] << 24) | (cbw.CB[7] << 16) | (cbw.CB[8] << 8) | (cbw.CB[9] << 0); 00694 break; 00695 } 00696 00697 if ((lba + blocks) > BlockCount) 00698 { 00699 csw.Status = CSW_FAILED; 00700 sendCSW(); 00701 return false; 00702 } 00703 00704 length = blocks * BlockSize; 00705 00706 if (!cbw.DataLength) { // host requests no data 00707 csw.Status = CSW_FAILED; 00708 sendCSW(); 00709 return false; 00710 } 00711 00712 if (cbw.DataLength != length) { 00713 if ((cbw.Flags & 0x80) != 0) { 00714 usb->stallEndpoint(MSC_BulkIn.bEndpointAddress); 00715 } else { 00716 usb->stallEndpoint(MSC_BulkOut.bEndpointAddress); 00717 } 00718 00719 csw.Status = CSW_FAILED; 00720 sendCSW(); 00721 return false; 00722 } 00723 00724 addr_in_block = 0; 00725 00726 // iprintf("MSD:transferring %lu blocks from LBA %lu.\n", blocks, lba); 00727 00728 return true; 00729 } 00730 00731 void USBMSD::on_module_loaded() 00732 { 00733 connect(); 00734 } 00735 00736 bool USBMSD::USBEvent_busReset(void) 00737 { 00738 return true; 00739 } 00740 00741 bool USBMSD::USBEvent_connectStateChanged(bool connected) 00742 { 00743 return true; 00744 } 00745 00746 bool USBMSD::USBEvent_suspendStateChanged(bool suspended) 00747 { 00748 return true; 00749 }
Generated on Tue Jul 12 2022 20:09:03 by 1.7.2