Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBMSD.cpp Source File

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 }