BaseUsbHost example program

Dependencies:   BaseUsbHost FATFileSystem mbed mbed-rtos

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UsbFlashDrive.cpp Source File

UsbFlashDrive.cpp

00001 // UsbFlashDrive.cpp 2013/1/25
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 #include "BaseUsbHost.h"
00005 //#define DEBUG
00006 #include "BaseUsbHostDebug.h"
00007 #define TEST
00008 #include "BaseUsbHostTest.h"
00009 #include "UsbFlashDrive.h"
00010 
00011 //#define WRITE_PROTECT
00012 
00013 
00014 uint32_t BE32(uint8_t* d)
00015 {
00016     return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
00017 }
00018 
00019 void BE16(uint32_t n, uint8_t* d)
00020 {
00021     d[0] = (uint8_t)(n >> 8);
00022     d[1] = (uint8_t)n;
00023 }
00024 
00025 void BE32(uint32_t n, uint8_t* d)
00026 {
00027     d[0] = (uint8_t)(n >> 24);
00028     d[1] = (uint8_t)(n >> 16);
00029     d[2] = (uint8_t)(n >> 8);
00030     d[3] = (uint8_t)n;
00031 }
00032 
00033 UsbFlashDrive::UsbFlashDrive(const char* name, ControlEp* ctlEp): FATFileSystem(name)
00034 {
00035     m_name = name;
00036     
00037     if (ctlEp == NULL) { // root hub
00038         DBG_OHCI(LPC_USB->HcRhPortStatus1);
00039         TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200);
00040         ctlEp = new ControlEp();
00041         TEST_ASSERT_TRUE(ctlEp);
00042     }
00043 
00044     CTASSERT(sizeof(CBW) == 31);
00045     CTASSERT(sizeof(CSW) == 13);
00046     TEST_ASSERT(sizeof(CBW) == 31);
00047     TEST_ASSERT(sizeof(CSW) == 13);
00048 
00049     m_numBlocks = 0;
00050     m_BlockSize = 0;
00051     m_lun = 0;
00052     m_interface = 0;
00053     m_pEpBulkIn = NULL;
00054     m_pEpBulkOut = NULL;
00055     
00056     ParseConfiguration(ctlEp);
00057     int rc = ctlEp->SetConfiguration(1);
00058     TEST_ASSERT_EQUAL(rc, USB_OK);
00059     GetMaxLUN(ctlEp);
00060     setup(ctlEp);
00061 }
00062 
00063 bool UsbFlashDrive::check(ControlEp* ctlEp)
00064 {
00065     if (ctlEp == NULL) {
00066         return false;
00067     }
00068     CTASSERT(sizeof(StandardDeviceDescriptor) == 18);
00069     CTASSERT(sizeof(StandardConfigurationDescriptor) == 9);
00070     CTASSERT(sizeof(StandardInterfaceDescriptor) == 9);
00071     TEST_ASSERT(sizeof(StandardDeviceDescriptor) == 18);
00072     TEST_ASSERT(sizeof(StandardConfigurationDescriptor) == 9);
00073     TEST_ASSERT(sizeof(StandardInterfaceDescriptor) == 9);
00074 
00075     StandardDeviceDescriptor desc;
00076     int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, reinterpret_cast<uint8_t*>(&desc), sizeof(StandardDeviceDescriptor));
00077     if (rc != USB_OK) {
00078         return false;
00079     }
00080     if (desc.bDeviceClass == 8) {
00081         return true;
00082     } else if (desc.bDeviceClass != 0x00) {
00083         return false;
00084     }
00085     uint8_t temp[4];
00086     rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp));
00087     if (rc != USB_OK) {
00088         return false;
00089     }
00090     StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp);
00091     uint8_t* buf = new uint8_t[cfg->wTotalLength];
00092     
00093     rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength);
00094     if (rc != USB_OK) {
00095         return false;
00096     }
00097     DBG_HEX(buf, cfg->wTotalLength);
00098     bool ret = false;
00099     for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) {
00100         StandardInterfaceDescriptor* desc = reinterpret_cast<StandardInterfaceDescriptor*>(buf+pos);
00101         if (desc->bDescriptorType == 4) { // interface ?
00102             if (desc->bInterfaceClass == 8 && desc->bInterfaceSubClass == 6 && desc->bInterfaceProtocol == 0x50) {
00103                 ret = true;
00104             }
00105             break;
00106         }
00107     }
00108     delete[] buf;
00109     return ret;
00110 }
00111 
00112 int UsbFlashDrive::disk_initialize()
00113 {
00114     //DBG("m_BlockSize=%d\n", m_BlockSize);
00115     if (m_BlockSize != 512) {
00116         return 1;
00117     }
00118     return 0;    
00119 }
00120 
00121 int UsbFlashDrive::disk_write(const uint8_t* buffer, uint64_t sector)
00122 {
00123     m_report_disk_write++;
00124     //DBG("buffer=%p block_number=%d\n", buffer, sector);
00125     int ret = MS_BulkSend(sector, 1, buffer);
00126     if (ret >= 0) {
00127         return 0;
00128     }
00129     return 1;
00130 }
00131 
00132 int UsbFlashDrive::disk_read(uint8_t* buffer, uint64_t sector)
00133 {
00134     m_report_disk_read++;
00135     //DBG("buffer=%p block_number=%d\n", buffer, sector);
00136     int ret = MS_BulkRecv(sector, 1, buffer);
00137     if (ret >= 0) {
00138         return 0;
00139     }
00140     return 1;
00141 }    
00142 
00143 int UsbFlashDrive::disk_status()
00144 {
00145     m_report_disk_status++;
00146     return 0;
00147 }
00148 
00149 int UsbFlashDrive::disk_sync()
00150 {
00151     m_report_disk_sync++;
00152     return 0;
00153 }
00154 
00155 uint64_t UsbFlashDrive::disk_sectors()
00156 {
00157     DBG("m_numBlocks=%d\n", m_numBlocks);
00158     return m_numBlocks;
00159 }
00160 
00161 int UsbFlashDrive::setup(ControlEp* ctlEp, int timeout)
00162 {
00163 
00164     int retry = 0;
00165     Timer t;
00166     t.start();
00167     t.reset();
00168     while(t.read_ms() < timeout) {
00169         DBG("retry=%d t=%d\n", retry, t.read_ms());
00170         if (retry > 80) {
00171             return -1;
00172         }
00173         int rc = TestUnitReady();
00174         DBG("TestUnitReady(): %d\n", rc);
00175         if (rc == USB_OK) {
00176             DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus);
00177             if (m_CSW.bCSWStatus == 0x00) {
00178                 break;
00179             }
00180         }
00181         GetSenseInfo();
00182         retry++;
00183         wait_ms(50);
00184     }
00185     if (t.read_ms() >= timeout) {
00186         return -1;
00187     }
00188     ReadCapacity();
00189     Inquire();
00190     return 0;
00191 }
00192 
00193 int UsbFlashDrive::ParseConfiguration(ControlEp* ctlEp)
00194 {
00195     TEST_ASSERT(ctlEp);
00196     TEST_ASSERT(sizeof(StandardEndpointDescriptor) == 7);
00197     uint8_t temp[4];
00198     int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp));
00199     if (rc != USB_OK) {
00200         return rc;
00201     }
00202     StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp);
00203     uint8_t* buf = new uint8_t[cfg->wTotalLength];
00204     rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength);
00205     if (rc != USB_OK) {
00206         return rc;
00207     }
00208     DBG_HEX(buf, cfg->wTotalLength);
00209     for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) {
00210         StandardEndpointDescriptor* desc = reinterpret_cast<StandardEndpointDescriptor*>(buf+pos);
00211         if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) {
00212             if (desc->bmAttributes == 2) { // bulk
00213                 BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), desc->bEndpointAddress, desc->wMaxPacketSize);
00214                 if (desc->bEndpointAddress & 0x80) {
00215                     m_pEpBulkIn = pEp;
00216                 } else {
00217                     m_pEpBulkOut = pEp;
00218                 }
00219             }
00220         }
00221     }
00222     delete[] buf;
00223     if (m_pEpBulkIn && m_pEpBulkOut) {
00224         return USB_OK;
00225     }
00226     return USB_ERROR;    
00227 }
00228 
00229 int UsbFlashDrive::BulkOnlyMassStorageReset(ControlEp* ctlEp)
00230 {
00231     TEST_ASSERT(ctlEp);
00232     int rc = ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); 
00233     TEST_ASSERT(rc == USB_OK);
00234     return rc;
00235 }
00236 
00237 int UsbFlashDrive::GetMaxLUN(ControlEp* ctlEp)
00238 {
00239     TEST_ASSERT(ctlEp);
00240     TEST_ASSERT(m_interface == 0);
00241     uint8_t temp[1];
00242     int rc = ctlEp->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp)); 
00243     TEST_ASSERT(rc == USB_OK);
00244     DBG_BYTES("GetMaxLUN", temp, sizeof(temp));
00245     m_MaxLUN = temp[0];
00246     TEST_ASSERT(m_MaxLUN <= 15);
00247     return rc;
00248 }
00249 
00250 
00251 int UsbFlashDrive::TestUnitReady()
00252 {
00253     const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00};
00254     m_CBW.dCBWDataTraansferLength = 0;
00255     m_CBW.bmCBWFlags = 0x00;
00256     CommandTransport(cdb, sizeof(cdb));
00257     StatusTransport();
00258     return 0;
00259 }
00260 
00261 int UsbFlashDrive::GetSenseInfo()
00262 {
00263     const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00};
00264     m_CBW.dCBWDataTraansferLength = 18;
00265     m_CBW.bmCBWFlags = 0x80; // data In
00266     CommandTransport(cdb, sizeof(cdb));
00267 
00268     uint8_t buf[18];
00269     _bulkRecv(buf, sizeof(buf));
00270     DBG_HEX(buf, sizeof(buf));
00271 
00272     StatusTransport();
00273     TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
00274     return 0;
00275 }
00276 
00277 int UsbFlashDrive::ReadCapacity()
00278 {
00279     const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00, 
00280                                                0x00, 0x00, 0x00, 0x00, 0x00};
00281     m_CBW.dCBWDataTraansferLength = 8;
00282     m_CBW.bmCBWFlags = 0x80; // data In
00283     CommandTransport(cdb, sizeof(cdb));
00284 
00285     uint8_t buf[8];
00286     int rc = _bulkRecv(buf, sizeof(buf));
00287     TEST_ASSERT(rc >= 0);
00288     DBG_HEX(buf, sizeof(buf));
00289 
00290     StatusTransport();
00291     TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
00292     
00293     m_numBlocks = BE32(buf);
00294     m_BlockSize = BE32(buf+4);
00295     DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize);
00296     TEST_ASSERT(m_BlockSize == 512);
00297     TEST_ASSERT(m_numBlocks > 0);
00298     return 0;
00299 }
00300 
00301 int UsbFlashDrive::Inquire()
00302 {
00303     const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00};
00304     m_CBW.dCBWDataTraansferLength = 36;
00305     m_CBW.bmCBWFlags = 0x80; // data In
00306     CommandTransport(cdb, sizeof(cdb));
00307 
00308     uint8_t buf[36];
00309     int rc = _bulkRecv(buf, sizeof(buf));
00310     TEST_ASSERT(rc >= 0);
00311     DBG_HEX(buf, sizeof(buf));
00312 
00313     StatusTransport();
00314     return 0;
00315 }
00316 
00317 int UsbFlashDrive::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
00318 {
00319     TEST_ASSERT(m_BlockSize == 512);
00320     TEST_ASSERT(num_blocks == 1);
00321     TEST_ASSERT(user_buffer);
00322     uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00, 
00323                                    0x00, 0x00, 0x00, 0x00, 0x00};
00324     BE32(block_number, cdb+2);
00325     BE16(num_blocks, cdb+7);
00326     uint32_t len = m_BlockSize * num_blocks;
00327     TEST_ASSERT(len <= 512);
00328     m_CBW.dCBWDataTraansferLength = len;
00329     m_CBW.bmCBWFlags = 0x80; // data In
00330     CommandTransport(cdb, sizeof(cdb));
00331 
00332     int ret = _bulkRecv(user_buffer, len);
00333     //DBG_HEX(user_buffer, len);
00334 
00335     StatusTransport();
00336     TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
00337     return ret;
00338 }
00339 
00340 int UsbFlashDrive::MS_BulkSend(uint32_t block_number, int num_blocks, const uint8_t* user_buffer)
00341 {
00342 #ifdef WRITE_PROTECT
00343     return 0;
00344 #else
00345     TEST_ASSERT(num_blocks == 1);
00346     TEST_ASSERT(user_buffer);
00347     uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00, 
00348                                     0x00, 0x00, 0x00, 0x00, 0x00};
00349     BE32(block_number, cdb+2);
00350     BE16(num_blocks, cdb+7);
00351     uint32_t len = m_BlockSize * num_blocks;
00352     TEST_ASSERT(len <= 512);
00353     m_CBW.dCBWDataTraansferLength = len;
00354     m_CBW.bmCBWFlags = 0x00; // data Out
00355     CommandTransport(cdb, sizeof(cdb));
00356 
00357     int ret = _bulkSend(user_buffer, len);
00358     //DBG_HEX(user_buffer, len);
00359 
00360     StatusTransport();
00361     TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
00362     return ret;
00363 #endif //WRITE_PROTECT    
00364 }
00365 
00366 int UsbFlashDrive::CommandTransport(const uint8_t* cdb, int size)
00367 {
00368     TEST_ASSERT(cdb);
00369     TEST_ASSERT(size >= 6);
00370     TEST_ASSERT(size <= 16);
00371     m_CBW.bCBWLUN = m_lun;
00372     m_CBW.bCBWCBLength = size;
00373     memcpy(m_CBW.CBWCB, cdb, size);
00374 
00375     m_CBW.dCBWSignature = 0x43425355;
00376     m_CBW.dCBWTag = m_tag++;
00377     m_CBW.bCBWLUN = 0;
00378     //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW));
00379     int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW));
00380     return rc;
00381 }
00382 
00383 int UsbFlashDrive::StatusTransport()
00384 {
00385     TEST_ASSERT(sizeof(CSW) == 13);
00386     int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW));
00387     //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW));
00388     TEST_ASSERT(m_CSW.dCSWSignature == 0x53425355);
00389     TEST_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag);
00390     TEST_ASSERT(m_CSW.dCSWDataResidue == 0);
00391     return rc;
00392 }
00393 
00394 int UsbFlashDrive::_bulkRecv(uint8_t* buf, int size)
00395 {
00396     TEST_ASSERT(m_pEpBulkIn);
00397     int ret = m_pEpBulkIn->bulkReceive(buf, size);
00398     return ret;
00399 }
00400 
00401 int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size)
00402 {
00403     TEST_ASSERT(m_pEpBulkOut);
00404     int ret = m_pEpBulkOut->bulkSend(buf, size);
00405     return ret;
00406 }