video streaming using websocket. but,streaming is very slower than 0.1fps.

Dependencies:   BaseUsbHost EthernetInterface WebSocketClient mbed-rtos mbed

Fork of BaseUsbHost_example by Norimasa Okamoto

viewer

Revision:
0:2a9734a95d55
Child:
1:80205a2de336
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.cpp	Tue Dec 04 13:39:57 2012 +0000
@@ -0,0 +1,388 @@
+// UsbFlashDrive.cpp 2012/12/4
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#define DEBUG
+#include "BaseUsbHostDebug.h"
+#define TEST
+#include "BaseUsbHostTest.h"
+
+#include "UsbFlashDrive.h"
+
+//#define WRITE_PROTECT
+
+int LE16(const uint8_t* d)
+{
+    return d[0] | (d[1] << 8);
+}
+
+uint32_t BE32(uint8_t* d)
+{
+    return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+void BE16(uint32_t n, uint8_t* d)
+{
+    d[0] = (uint8_t)(n >> 8);
+    d[1] = (uint8_t)n;
+}
+
+void BE32(uint32_t n, uint8_t* d)
+{
+    d[0] = (uint8_t)(n >> 24);
+    d[1] = (uint8_t)(n >> 16);
+    d[2] = (uint8_t)(n >> 8);
+    d[3] = (uint8_t)n;
+}
+
+UsbFlashDrive::UsbFlashDrive(const char* name, ControlEp* ctlEp): FATFileSystem(name)
+{
+    m_name = name;
+    
+    if (ctlEp == NULL) { // root hub
+        DBG_OHCI(LPC_USB->HcRhPortStatus1);
+        TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200);
+        m_ctlEp = new ControlEp();
+        TEST_ASSERT_TRUE(m_ctlEp);
+    } else {
+        m_ctlEp = ctlEp;
+    }
+
+    TEST_ASSERT(sizeof(CBW) == 31);
+    TEST_ASSERT(sizeof(CSW) == 13);
+
+    m_numBlocks = 0;
+    m_BlockSize = 0;
+    m_lun = 0;
+    m_interface = 0;
+    m_pEpBulkIn = NULL;
+    m_pEpBulkOut = NULL;
+    
+    ParseConfiguration();
+    int rc = m_ctlEp->SetConfiguration(1);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    GetMaxLUN();
+    setup();
+}
+
+int UsbFlashDrive::disk_initialize()
+{
+    //DBG("m_BlockSize=%d\n", m_BlockSize);
+    if (m_BlockSize != 512) {
+        return 1;
+    }
+    return 0;    
+}
+
+int UsbFlashDrive::disk_write(const uint8_t* buffer, uint64_t sector)
+{
+    m_report_disk_write++;
+    //DBG("buffer=%p block_number=%d\n", buffer, sector);
+    int ret = MS_BulkSend(sector, 1, buffer);
+    if (ret >= 0) {
+        return 0;
+    }
+    return 1;
+}
+
+int UsbFlashDrive::disk_read(uint8_t* buffer, uint64_t sector)
+{
+    m_report_disk_read++;
+    //DBG("buffer=%p block_number=%d\n", buffer, sector);
+    int ret = MS_BulkRecv(sector, 1, buffer);
+    if (ret >= 0) {
+        return 0;
+    }
+    return 1;
+}    
+
+int UsbFlashDrive::disk_status()
+{
+    m_report_disk_status++;
+    return 0;
+}
+
+int UsbFlashDrive::disk_sync()
+{
+    m_report_disk_sync++;
+    return 0;
+}
+
+uint64_t UsbFlashDrive::disk_sectors()
+{
+    DBG("m_numBlocks=%d\n", m_numBlocks);
+    return m_numBlocks;
+}
+
+int UsbFlashDrive::setup(int timeout)
+{
+
+    int retry = 0;
+    Timer t;
+    t.start();
+    t.reset();
+    while(t.read_ms() < timeout) {
+        DBG("retry=%d t=%d\n", retry, t.read_ms());
+        if (retry > 80) {
+            return -1;
+        }
+        int rc = TestUnitReady();
+        DBG("TestUnitReady(): %d\n", rc);
+        if (rc == USB_OK) {
+            DBG("m_CSW.bCSWStatus: %02X\n", m_CSW.bCSWStatus);
+            if (m_CSW.bCSWStatus == 0x00) {
+                break;
+            }
+        }
+        GetSenseInfo();
+        retry++;
+        wait_ms(50);
+    }
+    if (t.read_ms() >= timeout) {
+        return -1;
+    }
+    ReadCapacity();
+    Inquire();
+    return 0;
+}
+
+int UsbFlashDrive::ParseConfiguration()
+{
+  int rc;
+  uint8_t ConfigDesc[9];
+  int index = 0;
+  TEST_ASSERT(m_ctlEp);
+  rc = m_ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc));
+  TEST_ASSERT(rc == USB_OK);
+  DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc));
+  TEST_ASSERT(ConfigDesc[0] == 9);
+  TEST_ASSERT(ConfigDesc[1] == 0x02);
+  int wTotalLength = *((uint16_t*)&ConfigDesc[2]);
+  DBG("TotalLength: %d\n", wTotalLength);
+  int bConfigValue = ConfigDesc[5];
+  TEST_ASSERT(bConfigValue == 1);
+  DBG("ConfigValue: %d\n", bConfigValue);
+  DBG("MaxPower: %d mA\n", ConfigDesc[8]*2);   
+
+  uint8_t* buf = new uint8_t[wTotalLength];
+  TEST_ASSERT(buf);
+  rc = m_ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
+  TEST_ASSERT(rc == USB_OK);
+  TEST_ASSERT(ConfigDesc[1] == 0x02);
+  for (int pos = 0; pos < wTotalLength; pos += buf[pos]) {
+      DBG_BYTES("CFG", buf+pos, buf[pos]);
+      int type = buf[pos+1];
+      if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04
+        DBG("InterfaceNumber: %d\n", buf[pos+2]);
+        DBG("AlternateSetting: %d\n", buf[pos+3]);
+        DBG("NumEndpoint: %d\n", buf[pos+4]);
+        DBG("InterfaceClass: %02X\n", buf[pos+5]);
+        DBG("InterfaceSubClass: %02X\n", buf[pos+6]);
+        DBG("InterfaceProtocol: %02X\n", buf[pos+7]);
+        TEST_ASSERT(buf[pos+6] == 0x06); // SCSI
+        TEST_ASSERT(buf[pos+7] == 0x50); // bulk only
+      } 
+      if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) {
+          TEST_ASSERT(buf[pos] == 7);
+          uint8_t att = buf[pos+3];
+          if (att == 2) { // bulk
+              uint8_t ep = buf[pos+2];
+              bool dir = ep & 0x80; // true=IN
+              uint16_t size = LE16(buf+pos+4);
+              DBG("EndpointAddress: %02X\n", ep);
+              DBG("Attribute: %02X\n", att);
+              DBG("MaxPacketSize: %d\n", size); 
+              BulkEp* pEp = new BulkEp(m_ctlEp->GetAddr(), ep, size);
+              TEST_ASSERT(pEp);
+              if (dir) {
+                  m_pEpBulkIn = pEp;
+              } else {
+                  m_pEpBulkOut = pEp;
+              } 
+          }
+      }
+  }
+  delete[] buf;
+  TEST_ASSERT(m_pEpBulkIn);
+  TEST_ASSERT(m_pEpBulkOut);
+  return 0;   
+}
+
+int UsbFlashDrive::BulkOnlyMassStorageReset()
+{
+    TEST_ASSERT(m_ctlEp);
+    int rc = m_ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); 
+    TEST_ASSERT(rc == USB_OK);
+    return rc;
+}
+
+int UsbFlashDrive::GetMaxLUN()
+{
+    TEST_ASSERT(m_interface == 0);
+    uint8_t temp[1];
+    TEST_ASSERT(m_ctlEp);
+    int rc = m_ctlEp->controlReceive(0xa1, 0xfe, 0x0000, m_interface, temp, sizeof(temp)); 
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GetMaxLUN", temp, sizeof(temp));
+    m_MaxLUN = temp[0];
+    TEST_ASSERT(m_MaxLUN <= 15);
+    return rc;
+}
+
+
+int UsbFlashDrive::TestUnitReady()
+{
+    const uint8_t cdb[6] = {SCSI_CMD_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00};
+    m_CBW.dCBWDataTraansferLength = 0;
+    m_CBW.bmCBWFlags = 0x00;
+    CommandTransport(cdb, sizeof(cdb));
+    StatusTransport();
+    return 0;
+}
+
+int UsbFlashDrive::GetSenseInfo()
+{
+    const uint8_t cdb[6] = {SCSI_CMD_REQUEST_SENSE, 0x00, 0x00, 0x00, 18, 0x00};
+    m_CBW.dCBWDataTraansferLength = 18;
+    m_CBW.bmCBWFlags = 0x80; // data In
+    CommandTransport(cdb, sizeof(cdb));
+
+    uint8_t buf[18];
+    _bulkRecv(buf, sizeof(buf));
+    DBG_HEX(buf, sizeof(buf));
+
+    StatusTransport();
+    TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+    return 0;
+}
+
+int UsbFlashDrive::ReadCapacity()
+{
+    const uint8_t cdb[10] = {SCSI_CMD_READ_CAPACITY, 0x00, 0x00, 0x00, 0x00, 
+                                               0x00, 0x00, 0x00, 0x00, 0x00};
+    m_CBW.dCBWDataTraansferLength = 8;
+    m_CBW.bmCBWFlags = 0x80; // data In
+    CommandTransport(cdb, sizeof(cdb));
+
+    uint8_t buf[8];
+    int rc = _bulkRecv(buf, sizeof(buf));
+    TEST_ASSERT(rc >= 0);
+    DBG_HEX(buf, sizeof(buf));
+
+    StatusTransport();
+    TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+    
+    m_numBlocks = BE32(buf);
+    m_BlockSize = BE32(buf+4);
+    DBG("m_numBlocks=%d m_BlockSize=%d\n", m_numBlocks, m_BlockSize);
+    TEST_ASSERT(m_BlockSize == 512);
+    TEST_ASSERT(m_numBlocks > 0);
+    return 0;
+}
+
+int UsbFlashDrive::Inquire()
+{
+    const uint8_t cdb[6] = {SCSI_CMD_INQUIRY, 0x00, 0x00, 0x00, 36, 0x00};
+    m_CBW.dCBWDataTraansferLength = 36;
+    m_CBW.bmCBWFlags = 0x80; // data In
+    CommandTransport(cdb, sizeof(cdb));
+
+    uint8_t buf[36];
+    int rc = _bulkRecv(buf, sizeof(buf));
+    TEST_ASSERT(rc >= 0);
+    DBG_HEX(buf, sizeof(buf));
+
+    StatusTransport();
+    return 0;
+}
+
+int UsbFlashDrive::MS_BulkRecv(uint32_t block_number, int num_blocks, uint8_t* user_buffer)
+{
+    TEST_ASSERT(m_BlockSize == 512);
+    TEST_ASSERT(num_blocks == 1);
+    TEST_ASSERT(user_buffer);
+    uint8_t cdb[10] = {SCSI_CMD_READ_10, 0x00, 0x00, 0x00, 0x00, 
+                                   0x00, 0x00, 0x00, 0x00, 0x00};
+    BE32(block_number, cdb+2);
+    BE16(num_blocks, cdb+7);
+    uint32_t len = m_BlockSize * num_blocks;
+    TEST_ASSERT(len <= 512);
+    m_CBW.dCBWDataTraansferLength = len;
+    m_CBW.bmCBWFlags = 0x80; // data In
+    CommandTransport(cdb, sizeof(cdb));
+
+    int ret = _bulkRecv(user_buffer, len);
+    //DBG_HEX(user_buffer, len);
+
+    StatusTransport();
+    TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+    return ret;
+}
+
+int UsbFlashDrive::MS_BulkSend(uint32_t block_number, int num_blocks, const uint8_t* user_buffer)
+{
+#ifdef WRITE_PROTECT
+    return 0;
+#else
+    TEST_ASSERT(num_blocks == 1);
+    TEST_ASSERT(user_buffer);
+    uint8_t cdb[10] = {SCSI_CMD_WRITE_10, 0x00, 0x00, 0x00, 0x00, 
+                                    0x00, 0x00, 0x00, 0x00, 0x00};
+    BE32(block_number, cdb+2);
+    BE16(num_blocks, cdb+7);
+    uint32_t len = m_BlockSize * num_blocks;
+    TEST_ASSERT(len <= 512);
+    m_CBW.dCBWDataTraansferLength = len;
+    m_CBW.bmCBWFlags = 0x00; // data Out
+    CommandTransport(cdb, sizeof(cdb));
+
+    int ret = _bulkSend(user_buffer, len);
+    //DBG_HEX(user_buffer, len);
+
+    StatusTransport();
+    TEST_ASSERT(m_CSW.bCSWStatus == 0x00);
+    return ret;
+#endif //WRITE_PROTECT    
+}
+
+int UsbFlashDrive::CommandTransport(const uint8_t* cdb, int size)
+{
+    TEST_ASSERT(cdb);
+    TEST_ASSERT(size >= 6);
+    TEST_ASSERT(size <= 16);
+    m_CBW.bCBWLUN = m_lun;
+    m_CBW.bCBWCBLength = size;
+    memcpy(m_CBW.CBWCB, cdb, size);
+
+    m_CBW.dCBWSignature = 0x43425355;
+    m_CBW.dCBWTag = m_tag++;
+    m_CBW.bCBWLUN = 0;
+    //DBG_HEX((uint8_t*)&m_CBW, sizeof(CBW));
+    int rc = _bulkSend((uint8_t*)&m_CBW, sizeof(CBW));
+    return rc;
+}
+
+int UsbFlashDrive::StatusTransport()
+{
+    TEST_ASSERT(sizeof(CSW) == 13);
+    int rc = _bulkRecv((uint8_t*)&m_CSW, sizeof(CSW));
+    //DBG_HEX((uint8_t*)&m_CSW, sizeof(CSW));
+    TEST_ASSERT(m_CSW.dCSWSignature == 0x53425355);
+    TEST_ASSERT(m_CSW.dCSWTag == m_CBW.dCBWTag);
+    TEST_ASSERT(m_CSW.dCSWDataResidue == 0);
+    return rc;
+}
+
+int UsbFlashDrive::_bulkRecv(uint8_t* buf, int size)
+{
+    TEST_ASSERT(m_pEpBulkIn);
+    int ret = m_pEpBulkIn->read(buf, size);
+    return ret;
+}
+
+int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size)
+{
+    TEST_ASSERT(m_pEpBulkOut);
+    int ret = m_pEpBulkOut->write(buf, size);
+    return ret;
+}