Suga koubou / Mbed 2 deprecated USB_CDC_MSD_Hello

Dependencies:   ChaNFSSD mbed ChaNFS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBCDCMSC.cpp Source File

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 }