Webcam Server.

Dependencies:   uvchost FatFileSystem mbed HTTPServer NetServicesMin

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers msc.cpp Source File

msc.cpp

00001 #include "msc.h"
00002 //#define __DEBUG
00003 #include "mydbg.h"
00004 #include "Utils.h"
00005 
00006 //#define WRITE_PROTECT
00007 
00008 msc::msc(const char* name, int drive): FATFileSystem(name)
00009 {
00010     DBG("drive=%d\n", drive);
00011     m_name = name;
00012     m_drive = drive;
00013     DBG_ASSERT(sizeof(CBW) == 31);
00014     DBG_ASSERT(sizeof(CSW) == 13);
00015     m_numBlocks = 0;
00016     m_BlockSize = 0;
00017     m_lun = 0;
00018     m_interface = 0;
00019     m_pDev = NULL;
00020     m_pEpBulkIn = NULL;
00021     m_pEpBulkOut = NULL;
00022 }
00023 
00024 int msc::disk_initialize()
00025 {
00026     DBG("m_BlockSize=%d\n", m_BlockSize);
00027     if (m_BlockSize != 512) {
00028         return 1;
00029     }
00030     return 0;    
00031 }
00032 
00033 int msc::disk_write(const char *buffer, int block_number)
00034 {
00035     DBG("buffer=%p block_number=%d\n", buffer, block_number);
00036     int ret = MS_BulkSend(block_number, 1, (uint8_t*)buffer);
00037     if (ret >= 0) {
00038         return 0;
00039     }
00040     return 1;
00041 }
00042 
00043 int msc::disk_read(char *buffer, int block_number)
00044 {
00045     DBG("buffer=%p block_number=%d\n", buffer, block_number);
00046     int ret = MS_BulkRecv(block_number, 1, (uint8_t*)buffer);
00047     if (ret >= 0) {
00048         return 0;
00049     }
00050     return 1;
00051 }    
00052 
00053 int msc::disk_status()
00054 {
00055     DBG("\n");
00056     return 0;
00057 }
00058 
00059 int msc::disk_sync()
00060 {
00061     DBG("\n");
00062     return 0;
00063 }
00064 
00065 int msc::disk_sectors()
00066 {
00067     DBG("m_numBlocks=%d\n", m_numBlocks);
00068     return m_numBlocks;
00069 }
00070 
00071 int msc::setup(int timeout)
00072 {
00073     for(int i = 0; i < 2; i++) {
00074         m_pDev = m_pHost->getDeviceByClass(0x08, m_drive); // USB Mass Storage Class
00075         if (m_pDev || i > 0) {
00076             break;
00077         }
00078         UsbErr rc = Usb_poll();
00079         if (rc == USBERR_PROCESSING) {
00080             VERBOSE("%p USBERR_PROCESSING\n", this);
00081             return -1;
00082         }
00083     }
00084     DBG("m_pDev=%p\n", m_pDev);
00085     if (m_pDev == NULL) {
00086         VERBOSE("%p MSC DISK(%d) NOT FOUND\n", this, m_drive);
00087         return -1;
00088     }
00089     DBG_ASSERT(m_pDev);
00090 
00091     ParseConfiguration();
00092     
00093     GetMaxLUN();
00094 
00095     int retry = 0;
00096     Timer t;
00097     t.start();
00098     t.reset();
00099     while(t.read_ms() < timeout) {
00100         DBG("retry=%d t=%d\n", retry, t.read_ms());
00101         if (retry > 80) {
00102             return -1;
00103         }
00104         int rc = TestUnitReady();
00105         DBG("TestUnitReady(): %d\n", rc);
00106         if (rc == USBERR_OK) {
00107             DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus);
00108             if (m_CSW.bCSWStatus == 0x00) {
00109                 break;
00110             }
00111         }
00112         GetSenseInfo();
00113         retry++;
00114         wait_ms(50);
00115     }
00116     if (t.read_ms() >= timeout) {
00117         return -1;
00118     }
00119     ReadCapacity();
00120     Inquire();
00121     return 0;
00122 }
00123 void msc::_test()
00124 {
00125     ReadCapacity();
00126 
00127     char buf[512];
00128     for(int block = 0; block < m_numBlocks; block++) {
00129     DBG("block=%d\n", block);
00130         disk_read(buf, block);    
00131     }
00132     exit(1);
00133 }
00134 
00135 int msc::ParseConfiguration()
00136 {
00137   UsbErr rc;
00138   uint8_t ConfigDesc[9];
00139   int index = 0;
00140   DBG_ASSERT(m_pDev);
00141   rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc));
00142   DBG_ASSERT(rc == USBERR_OK);
00143   DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc));
00144   DBG_ASSERT(ConfigDesc[0] == 9);
00145   DBG_ASSERT(ConfigDesc[1] == 0x02);
00146   int wTotalLength = *((uint16_t*)&ConfigDesc[2]);
00147   DBG("TotalLength: %d\n", wTotalLength);
00148   int bConfigValue = ConfigDesc[5];
00149   DBG_ASSERT(bConfigValue == 1);
00150   DBG("ConfigValue: %d\n", bConfigValue);
00151   DBG("MaxPower: %d mA\n", ConfigDesc[8]*2);   
00152 
00153   uint8_t* buf = new uint8_t[wTotalLength];
00154   DBG_ASSERT(buf);
00155   rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
00156   DBG_ASSERT(rc == USBERR_OK);
00157   DBG_ASSERT(ConfigDesc[1] == 0x02);
00158   for (int pos = 0; pos < wTotalLength; pos += buf[pos]) {
00159       DBG_BYTES("CFG", buf+pos, buf[pos]);
00160       int type = buf[pos+1];
00161       if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04
00162         DBG("InterfaceNumber: %d\n", buf[pos+2]);
00163         DBG("AlternateSetting: %d\n", buf[pos+3]);
00164         DBG("NumEndpoint: %d\n", buf[pos+4]);
00165         DBG("InterfaceClass: %02X\n", buf[pos+5]);
00166         DBG("InterfaceSubClass: %02X\n", buf[pos+6]);
00167         DBG("InterfaceProtocol: %02X\n", buf[pos+7]);
00168         DBG_ASSERT(buf[pos+6] == 0x06); // SCSI
00169         DBG_ASSERT(buf[pos+7] == 0x50); // bulk only
00170       } 
00171       if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) {
00172           DBG_ASSERT(buf[pos] == 7);
00173           uint8_t att = buf[pos+3];
00174           if (att == 2) { // bulk
00175               uint8_t ep = buf[pos+2];
00176               bool dir = ep & 0x80; // true=IN
00177               uint16_t size = LE16(buf+pos+4);
00178               DBG("EndpointAddress: %02X\n", ep);
00179               DBG("Attribute: %02X\n", att);
00180               DBG("MaxPacketSize: %d\n", size); 
00181               UsbEndpoint* pEp = new UsbEndpoint(m_pDev, ep, dir, USB_BULK, size);
00182               DBG_ASSERT(pEp);
00183               if (dir) {
00184                   m_pEpBulkIn = pEp;
00185               } else {
00186                   m_pEpBulkOut = pEp;
00187               } 
00188           }
00189       }
00190   }
00191   delete[] buf;
00192   DBG_ASSERT(m_pEpBulkIn);
00193   DBG_ASSERT(m_pEpBulkOut);
00194   return 0;   
00195 }
00196 
00197 int msc::BulkOnlyMassStorageReset()
00198 {
00199     DBG_ASSERT(m_pDev);
00200     UsbErr rc = m_pDev->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); 
00201     DBG_ASSERT(rc == USBERR_OK);
00202     return rc;
00203 }
00204 
00205 int msc::GetMaxLUN()
00206 {
00207     DBG_ASSERT(m_interface == 0);
00208     uint8_t temp[1];
00209     DBG_ASSERT(m_pDev);
00210     UsbErr rc = m_pDev->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp)); 
00211     DBG_ASSERT(rc == USBERR_OK);
00212     DBG_BYTES("GetMaxLUN", temp, sizeof(temp));
00213     m_MaxLUN = temp[0];
00214     DBG_ASSERT(m_MaxLUN <= 15);
00215     return rc;
00216 }
00217 
00218 
00219 int msc::TestUnitReady()
00220 {
00221     const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00};
00222     m_CBW.dCBWDataTraansferLength = 0;
00223     m_CBW.bmCBWFlags = 0x00;
00224     CommandTransport(cdb, sizeof(cdb));
00225     StatusTransport();
00226     return 0;
00227 }
00228 
00229 int msc::GetSenseInfo()
00230 {
00231     const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00};
00232     m_CBW.dCBWDataTraansferLength = 18;
00233     m_CBW.bmCBWFlags = 0x80; // data In
00234     CommandTransport(cdb, sizeof(cdb));
00235 
00236     uint8_t buf[18];
00237     _bulkRecv(buf, sizeof(buf));
00238     DBG_HEX(buf, sizeof(buf));
00239 
00240     StatusTransport();
00241     DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
00242     return 0;
00243 }
00244 
00245 int msc::ReadCapacity()
00246 {
00247     const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00, 
00248                                                0x00, 0x00, 0x00, 0x00, 0x00};
00249     m_CBW.dCBWDataTraansferLength = 8;
00250     m_CBW.bmCBWFlags = 0x80; // data In
00251     CommandTransport(cdb, sizeof(cdb));
00252 
00253     uint8_t buf[8];
00254     int rc = _bulkRecv(buf, sizeof(buf));
00255     DBG_ASSERT(rc >= 0);
00256     DBG_HEX(buf, sizeof(buf));
00257 
00258     StatusTransport();
00259     DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
00260     
00261     m_numBlocks = BE32(buf);
00262     m_BlockSize = BE32(buf+4);
00263     DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize);
00264     DBG_ASSERT(m_BlockSize == 512);
00265     DBG_ASSERT(m_numBlocks > 0);
00266     return 0;
00267 }
00268 
00269 int msc::Inquire()
00270 {
00271     const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00};
00272     m_CBW.dCBWDataTraansferLength = 36;
00273     m_CBW.bmCBWFlags = 0x80; // data In
00274     CommandTransport(cdb, sizeof(cdb));
00275 
00276     uint8_t buf[36];
00277     _bulkRecv(buf, sizeof(buf));
00278     DBG_HEX(buf, sizeof(buf));
00279 
00280     StatusTransport();
00281     return 0;
00282 }
00283 
00284 int msc::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
00285 {
00286     DBG_ASSERT(m_BlockSize == 512);
00287     DBG_ASSERT(num_blocks == 1);
00288     DBG_ASSERT(user_buffer);
00289     uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00, 
00290                                    0x00, 0x00, 0x00, 0x00, 0x00};
00291     BE32(block_number, cdb+2);
00292     BE16(num_blocks, cdb+7);
00293     uint32_t len = m_BlockSize * num_blocks;
00294     DBG_ASSERT(len <= 512);
00295     m_CBW.dCBWDataTraansferLength = len;
00296     m_CBW.bmCBWFlags = 0x80; // data In
00297     CommandTransport(cdb, sizeof(cdb));
00298 
00299     int ret = _bulkRecv(user_buffer, len);
00300     //DBG_HEX(user_buffer, len);
00301 
00302     StatusTransport();
00303     DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
00304     return ret;
00305 }
00306 
00307 int msc::MS_BulkSend(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
00308 {
00309 #ifdef WRITE_PROTECT
00310     return 0;
00311 #else
00312     DBG_ASSERT(num_blocks == 1);
00313     DBG_ASSERT(user_buffer);
00314     uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00, 
00315                                     0x00, 0x00, 0x00, 0x00, 0x00};
00316     BE32(block_number, cdb+2);
00317     BE16(num_blocks, cdb+7);
00318     uint32_t len = m_BlockSize * num_blocks;
00319     DBG_ASSERT(len <= 512);
00320     m_CBW.dCBWDataTraansferLength = len;
00321     m_CBW.bmCBWFlags = 0x00; // data Out
00322     CommandTransport(cdb, sizeof(cdb));
00323 
00324     int ret = _bulkSend(user_buffer, len);
00325     //DBG_HEX(user_buffer, len);
00326 
00327     StatusTransport();
00328     DBG_ASSERT(m_CSW.bCSWStatus == 0x00);
00329     return ret;
00330 #endif //WRITE_PROTECT    
00331 }
00332 
00333 int msc::CommandTransport(const uint8_t* cdb, int size)
00334 {
00335     DBG_ASSERT(cdb);
00336     DBG_ASSERT(size >= 6);
00337     DBG_ASSERT(size <= 16);
00338     m_CBW.bCBWLUN = m_lun;
00339     m_CBW.bCBWCBLength = size;
00340     memcpy(m_CBW.CBWCB, cdb, size);
00341 
00342     m_CBW.dCBWSignature = 0x43425355;
00343     m_CBW.dCBWTag = m_tag++;
00344     m_CBW.bCBWLUN = 0;
00345     //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW));
00346     int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW));
00347     return rc;
00348 }
00349 
00350 int msc::StatusTransport()
00351 {
00352     DBG_ASSERT(sizeof(CSW) == 13);
00353     int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW));
00354     //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW));
00355     DBG_ASSERT(m_CSW.dCSWSignature == 0x53425355);
00356     DBG_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag);
00357     DBG_ASSERT(m_CSW.dCSWDataResidue == 0);
00358     return rc;
00359 }
00360 
00361 int msc::_bulkRecv(uint8_t* buf, int size)
00362 {
00363     UsbErr rc = m_pEpBulkIn->transfer(buf, size);
00364     DBG_ASSERT(rc == USBERR_PROCESSING);
00365     while(m_pEpBulkIn->status() == USBERR_PROCESSING){
00366         wait_us(1);
00367     }
00368     int ret = m_pEpBulkIn->status();
00369     if (ret >= 0) {
00370         return ret;
00371     }
00372     DBG("buf=%p size=%d ret=%d\n", buf, size, ret);
00373     return ret;
00374 }
00375 
00376 int msc::_bulkSend(uint8_t* buf, int size)
00377 {
00378     DBG_ASSERT(m_pEpBulkOut);
00379     UsbErr rc = m_pEpBulkOut->transfer(buf, size);
00380     DBG_ASSERT(rc == USBERR_PROCESSING);
00381     while(m_pEpBulkOut->status() == USBERR_PROCESSING){
00382         wait_us(1);
00383     }
00384     int ret = m_pEpBulkOut->status();
00385     if (ret >= 0) {
00386         return ret;
00387     }
00388     DBG("buf=%p size=%d ret=%d\n", buf, size, ret);
00389     return ret;
00390 }