Modified USBDevice mainly for debug of serial port communications. It is unfinished and should not be used - use the main branch.

Dependents:   FinalProject

Fork of USBDevice by mbed official

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