BaseUsbHost example program
Dependencies: BaseUsbHost FATFileSystem mbed mbed-rtos
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 }
Generated on Wed Jul 13 2022 00:00:06 by 1.7.2