BaseUsbHost example program

Dependencies:   BaseUsbHost FATFileSystem mbed mbed-rtos

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Wed Dec 05 13:25:18 2012 +0000
Parent:
0:2a9734a95d55
Child:
2:c10029b87439
Commit message:
add LifeCamVX700

Changed in this revision

BaseJpegDecode.lib Show annotated file Show diff for this revision Revisions of this file
BaseUsbHost.lib Show annotated file Show diff for this revision Revisions of this file
LifeCamVX700.cpp Show annotated file Show diff for this revision Revisions of this file
LifeCamVX700.h Show annotated file Show diff for this revision Revisions of this file
LogitechC270/LogitechC270.cpp Show annotated file Show diff for this revision Revisions of this file
LogitechC270/LogitechC270.h Show annotated file Show diff for this revision Revisions of this file
UsbFlashDrive/UsbFlashDrive.cpp Show annotated file Show diff for this revision Revisions of this file
UsbFlashDrive/UsbFlashDrive.h Show annotated file Show diff for this revision Revisions of this file
UsbMouseHost/UsbMouseHost.cpp Show annotated file Show diff for this revision Revisions of this file
UsbMouseHost/UsbMouseHost.h Show annotated file Show diff for this revision Revisions of this file
example1_LogitechC270.cpp Show annotated file Show diff for this revision Revisions of this file
example1_UsbFlashDrive.cpp Show annotated file Show diff for this revision Revisions of this file
example1_UsbMouseHost.cpp Show annotated file Show diff for this revision Revisions of this file
example2_LifeCamVX700.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BaseJpegDecode.lib	Tue Dec 04 13:39:57 2012 +0000
+++ b/BaseJpegDecode.lib	Wed Dec 05 13:25:18 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/va009039/code/BaseJpegDecode/#a7547692071d
+http://mbed.org/users/va009039/code/BaseJpegDecode/#e243fa781e5c
--- a/BaseUsbHost.lib	Tue Dec 04 13:39:57 2012 +0000
+++ b/BaseUsbHost.lib	Wed Dec 05 13:25:18 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/va009039/code/BaseUsbHost/#b7d6879637a8
+http://mbed.org/users/va009039/code/BaseUsbHost/#3b7bc4f87a61
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LifeCamVX700.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -0,0 +1,128 @@
+// LifeCamVX700.cpp 2012/12/5
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#define DEBUG
+#include "BaseUsbHostDebug.h"
+#define TEST
+#include "BaseUsbHostTest.h"
+#include "LifeCamVX700.h"
+
+LifeCamVX700::LifeCamVX700(int frameIndex, uint32_t interval, ControlEp* ctlEp)
+{
+    uint8_t buf[26];
+    
+    if (ctlEp == NULL) { // root hub
+        DBG_OHCI(LPC_USB->HcRhPortStatus1);
+        TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200);
+        ctlEp = new ControlEp();
+        TEST_ASSERT_TRUE(ctlEp);
+    }
+    bool r = check(ctlEp);
+    TEST_ASSERT(r);
+    m_ctlEp = ctlEp;
+    
+    int addr = m_ctlEp->GetAddr();
+    m_isoEp = new IsochronousEp(addr, VX700_EN, VX700_MPS);
+    TEST_ASSERT_TRUE(m_isoEp);
+
+    int rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_INFO Prob", buf, 1);
+
+    rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, 26);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_DEF Probe", buf, 26);
+
+    rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, 26);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_MIN Probe", buf, 26);
+
+    rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, 26);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_MAX Probe", buf, 26);
+
+    rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, 26);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_CUR Probe", buf, 26);
+
+    memset(buf, 0, 26);
+    buf[2] = VX700_MJPEG;
+    buf[3] = frameIndex;
+    *reinterpret_cast<uint32_t*>(buf+4) = interval;
+    
+    DBG_BYTES("SET_CUR Commit", buf, 26);
+    rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, 26);
+    TEST_ASSERT(rc == USB_OK);
+
+    rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, 26);
+    TEST_ASSERT(rc == USB_OK);
+    TEST_ASSERT_EQUAL(buf[2], VX700_MJPEG);
+    TEST_ASSERT_EQUAL(buf[3], frameIndex);
+    TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
+    DBG_BYTES("GET_CUR Commit", buf, 26);
+
+    int cfg;
+    rc = m_ctlEp->GetConfiguration(&cfg);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("config: %d\n", cfg);
+
+    rc = m_ctlEp->SetConfiguration(1);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+
+    rc = m_ctlEp->GetConfiguration(&cfg);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("config: %d\n", cfg);
+    TEST_ASSERT_EQUAL(cfg, 1);
+
+    int alt;
+    rc = m_ctlEp->GetInterface(1, &alt);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("alt: %d\n", alt);
+
+    rc = m_ctlEp->SetInterfaceAlternate(1, VX700_IF_ALT); // alt=1 packet size = 192
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+
+    rc = m_ctlEp->GetInterface(1, &alt);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("alt: %d\n", alt);
+    TEST_ASSERT_EQUAL(alt, 1);
+
+    for(int i = 0; i < 16; i++) {
+        report_cc_count[i] = 0;
+        report_ps_cc_count[i] = 0;
+    }
+  
+    LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable
+    LPC_USB->HcControl |= OR_CONTROL_IE;  // IsochronousEnable
+}
+
+bool LifeCamVX700::check(ControlEp* ctlEp)
+{
+    if (ctlEp == NULL) {
+        return false;
+    }
+    uint8_t buf[18];
+    int r = ctlEp->GetDescriptor(1, 0, buf, 8);
+    if (r != USB_OK) {
+        return false;
+    }
+    DBG_HEX(buf, 8);
+    const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01,0x40};
+    if (memcmp(buf, desc, sizeof(desc)) != 0) {
+        return false;
+    }
+    r = ctlEp->GetDescriptor(1, 0, buf, 18);
+    if (r != USB_OK) {
+        return false;
+    }
+    DBG_HEX(buf, 18);
+    uint16_t vid = *reinterpret_cast<uint16_t*>(buf+8);
+    uint16_t pid = *reinterpret_cast<uint16_t*>(buf+10);
+    DBG("VID PID: %04X %04X\n", vid, pid);
+    if (vid == VX700_VID && pid == VX700_PID) {
+        return true;
+    }
+    return false;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LifeCamVX700.h	Wed Dec 05 13:25:18 2012 +0000
@@ -0,0 +1,25 @@
+// LifeCamVX700.h 2012/12/5
+#ifndef LIFECAM_VX700_H
+#define LIFECAM_VX700_H
+
+#define VX700_VID 0x045e
+#define VX700_PID 0x074a
+
+#define VX700_160x120 5
+#define VX700_176x144 4
+#define VX700_320x240 3
+#define VX700_352x288 2
+#define VX700_640x480 1
+
+#define VX700_MJPEG 1
+
+#define VX700_EN  0x81
+#define VX700_MPS  128
+#define VX700_IF_ALT 1 
+
+class LifeCamVX700 : public BaseUvc{
+public:
+    LifeCamVX700(int frameIndex = VX700_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL);
+    static bool check(ControlEp* ctlEp);
+};
+#endif //LIFECAM_VX700_H
--- a/LogitechC270/LogitechC270.cpp	Tue Dec 04 13:39:57 2012 +0000
+++ b/LogitechC270/LogitechC270.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -1,4 +1,4 @@
-// LogitechC270.cpp 2012/12/4
+// LogitechC270.cpp 2012/12/5
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -8,30 +8,22 @@
 #include "BaseUsbHostTest.h"
 #include "LogitechC270.h"
 
-LogitechC270::LogitechC270(int frame, uint32_t interval, ControlEp* ctlEp)
+LogitechC270::LogitechC270(int frameIndex, uint32_t interval, ControlEp* ctlEp)
 {
     uint8_t buf[26];
     
     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;
+        ctlEp = new ControlEp();
+        TEST_ASSERT_TRUE(ctlEp);
     }
-
-    int r = m_ctlEp->GetDescriptor(1, 0, buf, 18);
-    TEST_ASSERT(r == USB_OK);
-    DBG_HEX(buf, 18);
-    vid = *reinterpret_cast<uint16_t*>(buf+8);
-    pid = *reinterpret_cast<uint16_t*>(buf+10);
-    DBG("VID PID: %04X %04X\n", vid, pid);
-    TEST_ASSERT(vid == 0x046d && pid == 0x0825);
+    bool r = check(ctlEp);
+    TEST_ASSERT(r);
+    m_ctlEp = ctlEp;
+    
     int addr = m_ctlEp->GetAddr();
-    DBG("addr: %d\n", addr);
-
-    m_isoEp = new IsochronousEp(addr, 0x81, 192);
+    m_isoEp = new IsochronousEp(addr, C270_EN, C270_MPS);
     TEST_ASSERT_TRUE(m_isoEp);
 
     int rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1);
@@ -56,7 +48,7 @@
 
     memset(buf, 0, 26);
     buf[2] = C270_MJPEG;
-    buf[3] = frame;
+    buf[3] = frameIndex;
     *reinterpret_cast<uint32_t*>(buf+4) = interval;
     
     DBG_BYTES("SET_CUR Commit", buf, 26);
@@ -66,7 +58,7 @@
     rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, 26);
     TEST_ASSERT(rc == USB_OK);
     TEST_ASSERT_EQUAL(buf[2], C270_MJPEG);
-    TEST_ASSERT_EQUAL(buf[3], frame);
+    TEST_ASSERT_EQUAL(buf[3], frameIndex);
     TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
     DBG_BYTES("GET_CUR Commit", buf, 26);
 
@@ -88,7 +80,7 @@
     TEST_ASSERT_EQUAL(rc, USB_OK);
     DBG("alt: %d\n", alt);
 
-    rc = m_ctlEp->SetInterfaceAlternate(1, 1); // alt=1 packet size = 192
+    rc = m_ctlEp->SetInterfaceAlternate(1, C270_IF_ALT); // alt=1 packet size = 192
     TEST_ASSERT_EQUAL(rc, USB_OK);
 
     rc = m_ctlEp->GetInterface(1, &alt);
@@ -105,53 +97,32 @@
     LPC_USB->HcControl |= OR_CONTROL_IE;  // IsochronousEnable
 }
 
-void LogitechC270::poll()
+bool LogitechC270::check(ControlEp* ctlEp)
 {
-    HCITD* itd = m_isoEp->read();
-    if (itd) {
-        uint8_t cc = itd->Control>>28;
-        report_cc_count[cc]++;
-        if (cc == 0) { // ConditionCode
-            //DBG_ITD(itd);
-            uint16_t frame = itd->Control & 0xffff;
-            uint8_t* buf = const_cast<uint8_t*>(itd->buf); 
-            int mps = m_isoEp->m_PacketSize;
-            for(int i = 0; i < m_isoEp->m_FrameCount; i++) {
-                uint16_t pswn = itd->OffsetPSW[i];
-                cc = pswn>>12;
-                if (cc == 0 || cc == 9) {
-                    int len = pswn & 0x7ff;
-                    onResult(frame, buf, len);
-               }
-               report_ps_cc_count[cc]++;
-               buf += mps;
-                frame++;
-            }
-        }
-        m_isoEp->delete_HCTD(reinterpret_cast<HCTD*>(itd));
+    if (ctlEp == NULL) {
+        return false;
+    }
+    uint8_t buf[18];
+    int r = ctlEp->GetDescriptor(1, 0, buf, 8);
+    if (r != USB_OK) {
+        return false;
+    }
+    DBG_HEX(buf, 8);
+    const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01,0x40};
+    if (memcmp(buf, desc, sizeof(desc)) != 0) {
+        return false;
     }
+    r = ctlEp->GetDescriptor(1, 0, buf, 18);
+    if (r != USB_OK) {
+        return false;
+    }
+    DBG_HEX(buf, 18);
+    uint16_t vid = *reinterpret_cast<uint16_t*>(buf+8);
+    uint16_t pid = *reinterpret_cast<uint16_t*>(buf+10);
+    DBG("VID PID: %04X %04X\n", vid, pid);
+    if (vid == C270_VID && pid == C270_PID) {
+        return true;
+    }
+    return false;
 }
 
-int LogitechC270::Control(int req, int cs, int index, uint8_t* buf, int size)
-{
-    TEST_ASSERT(m_ctlEp);
-    int rc;
-    if (req == SET_CUR) {    
-        rc = m_ctlEp->controlSend(
-                    USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 
-                    req, cs<<8, index, buf, size);
-        return rc;
-    }
-    rc = m_ctlEp->controlReceive(
-                USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 
-                req, cs<<8, index, buf, size);
-    return rc;
-}
-
-void LogitechC270::onResult(uint16_t frame, uint8_t* buf, int len)
-{
-  if(m_pCbItem && m_pCbMeth)
-    (m_pCbItem->*m_pCbMeth)(frame, buf, len);
-  else if(m_pCb)
-    m_pCb(frame, buf, len);
-}
--- a/LogitechC270/LogitechC270.h	Tue Dec 04 13:39:57 2012 +0000
+++ b/LogitechC270/LogitechC270.h	Wed Dec 05 13:25:18 2012 +0000
@@ -1,6 +1,10 @@
+// LogitechC270.h 2012/12/5
 #ifndef LOGITECH_C270_H
 #define LOGITECH_C270_H
 
+#define C270_VID 0x046d
+#define C270_PID 0x0825
+
 #define C270_160x120 2
 #define C270_176x144 3
 #define C270_320x176 4
@@ -14,64 +18,16 @@
 #define C270_800x448 11
 #define C270_800x600 12
 
-#define _30FPS  333333
-#define _25FPS  400000
-#define _20FPS  500000
-#define _15FPS  666666
-#define _10FPS 1000000
-#define _5FPS  2000000
-
 #define C270_MJPEG 2
 #define C270_YUV2  1
 
-#define SET_CUR  0x01
-#define GET_CUR  0x81
-#define GET_MIN  0x82
-#define GET_MAX  0x83
-#define GET_RES  0x84
-#define GET_LEN  0x85
-#define GET_INFO 0x86
-#define GET_DEF  0x87
+#define C270_EN  0x81
+#define C270_MPS  192
+#define C270_IF_ALT 1 
 
-#define VS_PROBE_CONTROL  0x01
-#define VS_COMMIT_CONTROL 0x02
-
-class LogitechC270 {
+class LogitechC270 : public BaseUvc {
 public:
-    LogitechC270(int frame = C270_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL);
-    void poll();
-    int Control(int req, int cs, int index, uint8_t* buf, int size);
-    uint16_t vid;
-    uint16_t pid;
-    ControlEp* m_ctlEp;
-    IsochronousEp* m_isoEp;
-    uint32_t report_cc_count[16];  // ConditionCode
-    uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode
-    // callback
-    void onResult(uint16_t frame, uint8_t* buf, int len);
-    void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
-    {
-        m_pCb = pMethod;
-        m_pCbItem = NULL;
-        m_pCbMeth = NULL;
-    }
-    
-    class CDummy;
-    template<class T> 
-    void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) )
-    {
-        m_pCb = NULL;
-        m_pCbItem = (CDummy*) pItem;
-        m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod;
-    }
-    void clearOnResult()
-    {
-        m_pCb = NULL;
-        m_pCbItem = NULL;
-        m_pCbMeth = NULL;
-    }
-    CDummy* m_pCbItem;
-    void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int);
-    void (*m_pCb)(uint16_t, uint8_t*, int);
+    LogitechC270(int frameIndex = C270_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL);
+    static bool check(ControlEp* ctlEp);
 };
 #endif //LOGITECH_C270_H
--- a/UsbFlashDrive/UsbFlashDrive.cpp	Tue Dec 04 13:39:57 2012 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -1,4 +1,4 @@
-// UsbFlashDrive.cpp 2012/12/4
+// UsbFlashDrive.cpp 2012/12/5
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -42,10 +42,8 @@
     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;
+        ctlEp = new ControlEp();
+        TEST_ASSERT_TRUE(ctlEp);
     }
 
     TEST_ASSERT(sizeof(CBW) == 31);
@@ -58,11 +56,30 @@
     m_pEpBulkIn = NULL;
     m_pEpBulkOut = NULL;
     
-    ParseConfiguration();
-    int rc = m_ctlEp->SetConfiguration(1);
+    ParseConfiguration(ctlEp);
+    int rc = ctlEp->SetConfiguration(1);
     TEST_ASSERT_EQUAL(rc, USB_OK);
-    GetMaxLUN();
-    setup();
+    GetMaxLUN(ctlEp);
+    setup(ctlEp);
+}
+
+bool UsbFlashDrive::check(ControlEp* ctlEp)
+{
+    if (ctlEp == NULL) {
+        return false;
+    }
+    uint8_t buf[8];
+    int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, sizeof(buf));
+    if (rc != USB_OK) {
+        return false;
+    }
+    DBG_BYTES("ConfigDescriptor 8bytes", buf, sizeof(buf));
+    TEST_ASSERT(buf[0] == 9);
+    TEST_ASSERT(buf[1] == 0x02);
+    if (buf[4] != 0x01) {
+        return false;
+    }    
+    return true;
 }
 
 int UsbFlashDrive::disk_initialize()
@@ -114,7 +131,7 @@
     return m_numBlocks;
 }
 
-int UsbFlashDrive::setup(int timeout)
+int UsbFlashDrive::setup(ControlEp* ctlEp, int timeout)
 {
 
     int retry = 0;
@@ -146,13 +163,13 @@
     return 0;
 }
 
-int UsbFlashDrive::ParseConfiguration()
+int UsbFlashDrive::ParseConfiguration(ControlEp* ctlEp)
 {
+  TEST_ASSERT(ctlEp);
   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));
+  rc = 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);
@@ -166,7 +183,7 @@
 
   uint8_t* buf = new uint8_t[wTotalLength];
   TEST_ASSERT(buf);
-  rc = m_ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
+  rc = 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]) {
@@ -192,7 +209,7 @@
               DBG("EndpointAddress: %02X\n", ep);
               DBG("Attribute: %02X\n", att);
               DBG("MaxPacketSize: %d\n", size); 
-              BulkEp* pEp = new BulkEp(m_ctlEp->GetAddr(), ep, size);
+              BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), ep, size);
               TEST_ASSERT(pEp);
               if (dir) {
                   m_pEpBulkIn = pEp;
@@ -208,20 +225,20 @@
   return 0;   
 }
 
-int UsbFlashDrive::BulkOnlyMassStorageReset()
+int UsbFlashDrive::BulkOnlyMassStorageReset(ControlEp* ctlEp)
 {
-    TEST_ASSERT(m_ctlEp);
-    int rc = m_ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); 
+    TEST_ASSERT(ctlEp);
+    int rc = ctlEp->controlReceive(0x21, 0xff, 0x0000, m_interface, NULL, 0); 
     TEST_ASSERT(rc == USB_OK);
     return rc;
 }
 
-int UsbFlashDrive::GetMaxLUN()
+int UsbFlashDrive::GetMaxLUN(ControlEp* ctlEp)
 {
+    TEST_ASSERT(ctlEp);
     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)); 
+    int rc = 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];
@@ -376,13 +393,13 @@
 int UsbFlashDrive::_bulkRecv(uint8_t* buf, int size)
 {
     TEST_ASSERT(m_pEpBulkIn);
-    int ret = m_pEpBulkIn->read(buf, size);
+    int ret = m_pEpBulkIn->bulkReceive(buf, size);
     return ret;
 }
 
 int UsbFlashDrive::_bulkSend(const uint8_t* buf, int size)
 {
     TEST_ASSERT(m_pEpBulkOut);
-    int ret = m_pEpBulkOut->write(buf, size);
+    int ret = m_pEpBulkOut->bulkSend(buf, size);
     return ret;
 }
--- a/UsbFlashDrive/UsbFlashDrive.h	Tue Dec 04 13:39:57 2012 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.h	Wed Dec 05 13:25:18 2012 +0000
@@ -1,4 +1,4 @@
-// usbFlashDrive.h 2012/12/4
+// usbFlashDrive.h 2012/12/5
 #ifndef USB_FLASH_DRIVE_H
 #define USB_FLASH_DRIVE_H
 
@@ -33,18 +33,18 @@
 class UsbFlashDrive : public FATFileSystem {
 public:
     UsbFlashDrive(const char* name, ControlEp* ctlEp = NULL);
+    static bool check(ControlEp* ctlEp);
     virtual int disk_initialize();
     virtual int disk_write(const uint8_t* buffer, uint64_t sector);
     virtual int disk_read(uint8_t* buffer, uint64_t sector);    
     virtual int disk_status();
     virtual int disk_sync();
     virtual uint64_t disk_sectors();
-
-    int setup(int timeout = 9000);
 private:
-    int ParseConfiguration();
-    int BulkOnlyMassStorageReset();
-    int GetMaxLUN();
+    int setup(ControlEp* ctlEp, int timeout = 9000);
+    int ParseConfiguration(ControlEp* ctlEp);
+    int BulkOnlyMassStorageReset(ControlEp* ctlEp);
+    int GetMaxLUN(ControlEp* ctlEp);
     int ReadCapacity();
     int GetSenseInfo();
     int TestUnitReady();
@@ -65,7 +65,7 @@
     uint32_t m_tag;
     CBW m_CBW;
     CSW m_CSW;
-    ControlEp* m_ctlEp;
+    // endpoint
     BulkEp* m_pEpBulkIn;
     BulkEp* m_pEpBulkOut;
     // report
--- a/UsbMouseHost/UsbMouseHost.cpp	Tue Dec 04 13:39:57 2012 +0000
+++ b/UsbMouseHost/UsbMouseHost.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -1,8 +1,8 @@
-// UsbMouseHost.cpp
+// UsbMouseHost.cpp 2012/12/5
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-//#define DEBUG
+#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
@@ -16,24 +16,41 @@
         if (LPC_USB->HcRhPortStatus1 & 0x200) {
             lowSpeed = 1;
         }
-        m_ctlEp = new ControlEp(lowSpeed);
-        TEST_ASSERT_TRUE(m_ctlEp);
-    } else {
-        m_ctlEp = ctlEp;
+        ctlEp = new ControlEp(lowSpeed);
+        TEST_ASSERT_TRUE(ctlEp);
     }
-
-    int rc = m_ctlEp->SetConfiguration(1);
+    bool r = check(ctlEp);
+    TEST_ASSERT(r);
+ 
+    int rc = ctlEp->SetConfiguration(1);
     TEST_ASSERT_EQUAL(rc, USB_OK);
 
-    int addr = m_ctlEp->GetAddr();
-    int lowSpeed = m_ctlEp->GetLowSpeed();
+    int addr = ctlEp->GetAddr();
+    int lowSpeed = ctlEp->GetLowSpeed();
     m_intEp = new InterruptEp(addr, 0x81, 8, lowSpeed);
     TEST_ASSERT_TRUE(m_intEp);
 }
 
+bool UsbMouseHost::check(ControlEp* ctlEp)
+{
+    if (ctlEp == NULL) {
+        return false;
+    }
+    uint8_t buf[8];
+    int r = ctlEp->GetDescriptor(1, 0, buf, 8);
+    if (r != USB_OK) {
+        return false;
+    }
+    DBG_HEX(buf, 8);
+    if (buf[4] != 0x00) { // HID ?
+        return false;
+    }    
+    return true;
+}
+
 int UsbMouseHost::read(uint32_t* status, int millisec)
 {
-    int rc = m_intEp->read(reinterpret_cast<uint8_t*>(status), 4, millisec);
+    int rc = m_intEp->interruptReceive(reinterpret_cast<uint8_t*>(status), 4, millisec);
     if (rc < 0) { // error?
         *status = 0x00000000;
         return rc;
--- a/UsbMouseHost/UsbMouseHost.h	Tue Dec 04 13:39:57 2012 +0000
+++ b/UsbMouseHost/UsbMouseHost.h	Wed Dec 05 13:25:18 2012 +0000
@@ -1,12 +1,13 @@
-// UsbMouseHost.h
+// UsbMouseHost.h 2012/12/5
 #ifndef USB_MOUSE_HOST_H
 #define USB_MOUSE_HOST_H
 
 class UsbMouseHost {
 public:
     UsbMouseHost(ControlEp* ctlEp = NULL);
+    static bool check(ControlEp* ctlEp);
     int read(uint32_t* status, int millisec=osWaitForever);
-    ControlEp* m_ctlEp;
+    //ControlEp* m_ctlEp;
     InterruptEp* m_intEp;
 };
 
--- a/example1_LogitechC270.cpp	Tue Dec 04 13:39:57 2012 +0000
+++ b/example1_LogitechC270.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -100,8 +100,8 @@
             }
         }
         term.locate(0, y);
-        term.printf("Cr:(%d,%d)[width=%d height=%d yblock=%d %u %u]\n", 
-            calc->x_center, calc->y_center, calc->width, calc->height, calc->yblock, calc->EOI_count, t.read_ms()/1000);
+        term.printf("Cr:(%d,%d)[width=%d height=%d yblock=%d %u]\n", 
+            calc->x_center, calc->y_center, calc->width, calc->height, calc->yblock, calc->EOI_count);
         term.printf("[CC:"); 
         for(int i = 0; i < 16; i++) {
             term.printf(" %u", cam->report_cc_count[i]); 
@@ -131,14 +131,15 @@
     UsbHub* hub = new UsbHub();
     TEST_ASSERT_TRUE(hub);
 
-    for(int i = 0; i < 4; i++) {
-        if (hub->PortEp[i]) {
-            if (hub->PortEp[i]->DeviceClass == 0x02) {  
-                ctlEp = hub->PortEp[i];
-                break;
-            }
+    for(int i = 0; i < MAX_HUB_PORT; i++) {
+        if (LogitechC270::check(hub->PortEp[i])) {
+            ctlEp = hub->PortEp[i];
+            break;
         }
     }
+    if (ctlEp == NULL) {
+        error("LogitechC270 not found\n");
+    }
     
     cam = new LogitechC270(C270_160x120, _15FPS, ctlEp); 
     TEST_ASSERT_TRUE(cam);
--- a/example1_UsbFlashDrive.cpp	Tue Dec 04 13:39:57 2012 +0000
+++ b/example1_UsbFlashDrive.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -26,25 +26,39 @@
     TEST_ASSERT_TRUE(hub);
 
     for(int i = 0; i < MAX_HUB_PORT; i++) {
-        if (hub->PortEp[i]) {
-            if (hub->PortEp[i]->DeviceClass == 0x01) {  
-                ctlEp = hub->PortEp[i];
-                break;
-            }
+        if (UsbFlashDrive::check(hub->PortEp[i])) {
+            ctlEp = hub->PortEp[i];
+            break;
         }
     }
+    if (ctlEp == NULL) {
+        error("USB Flash Drive not found\n");
+    }
+    TEST_ASSERT(ctlEp);
 
     drive = new UsbFlashDrive("usb", ctlEp);
     TEST_ASSERT(drive);
 
-
-    const int file_size = 1024*256;
-    printf("USB FLASH DRIVE read/write file size: %d bytes\n", file_size);
+    const int size_table[] = {
+        1024*1,
+        1024*2,
+        1024*4,
+        1024*8,
+        1024*16,
+        1024*32,
+        1024*64,
+        1024*128,
+        1204*256,
+        1204*512,
+    };
+    
+    printf("USB FLASH DRIVE read/write test\n");
     
     char path[32];
     int size;
     Timer t;
     for(int n = 0; n <= 9; n++) {
+        int file_size = size_table[n];
         sprintf(path, "/usb/test%d.txt", n);
         FILE* fp = fopen(path, "wb");
         size = 0;
--- a/example1_UsbMouseHost.cpp	Tue Dec 04 13:39:57 2012 +0000
+++ b/example1_UsbMouseHost.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -25,16 +25,18 @@
     UsbHub* hub = new UsbHub();
     TEST_ASSERT_TRUE(hub);
 
-    for(int i = 0; i < 4; i++) {
-        ctlEp = hub->PortEp[i];
-        if (ctlEp) {
+    for(int i = 0; i < MAX_HUB_PORT; i++) {
+        if (UsbMouseHost::check(hub->PortEp[i])) {
+            ctlEp = hub->PortEp[i];
             break;
         }
     }
+    if (ctlEp == NULL) {
+        error("USB Mouse not found\n");
+    }
 
     mouse = new UsbMouseHost(ctlEp);
     TEST_ASSERT(mouse);
-
  
     while(1) {
         uint32_t status;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example2_LifeCamVX700.cpp	Wed Dec 05 13:25:18 2012 +0000
@@ -0,0 +1,144 @@
+#if 0
+// example2_LifeCamVX700.cpp
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#define DEBUG
+#include "BaseUsbHostDebug.h"
+#define TEST
+#include "BaseUsbHostTest.h"
+#include "LifeCamVX700.h"
+#include "BaseJpegDecode.h"
+#include "Terminal.h"
+
+// LifeCamVX700
+#define WIDTH  160
+#define HEIGHT 120
+
+#define THRESHOLD 200
+
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+Terminal term(USBTX, USBRX);
+
+class JpegDecode : public BaseJpegDecode {
+public:
+    uint32_t EOI_count;
+    int8_t m_buf[WIDTH/8*HEIGHT/8];
+    bool mode_CbCr;
+    JpegDecode() {
+        mode_CbCr = false;
+        EOI_count = 0;
+        memset(m_buf, 0, sizeof(m_buf));
+    }
+    virtual void outputDC(int mcu, int block, int value) {
+        if (mcu >= (WIDTH/16*HEIGHT/8)) {
+            return;
+        }
+        if (mode_CbCr) {
+            if (block == 2 || block == 3) {
+                value *= qt[1][0];
+                value /= 16;
+                m_buf[mcu*2+block-2] = value;
+            }
+        } else {
+            if (block == 0 || block == 1) {
+                value *= qt[0][0];
+                value /= 16;
+                m_buf[mcu*2+block] = value;
+            }
+        }
+    }
+    virtual void outputAC(int mcu, int block, int scan, int value){};
+    virtual void outputMARK(uint8_t c){
+        if (c == 0xd9) { // EOI
+            EOI_count++;
+            led3 = !led3;
+        }
+    };
+};
+
+JpegDecode* decode = NULL;
+void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len)
+{
+    if (decode) {
+        decode->input(buf+12, len-12);
+    }
+    if (buf[1]&1) { // FID
+        led1 = !led1;
+    }
+}
+
+BaseUsbHost *UsbHost;
+UsbHub* hub;
+ControlEp* ctlEp = NULL;
+LifeCamVX700* cam;
+
+void display_thread(void const *args) {
+    term.cls();
+    int n = 0;
+    while(1) {
+        int y;
+        for(y = 0; y < HEIGHT/8; y++) {
+            term.locate(0, y);
+            for(int x = 0; x < WIDTH/8; x++) {
+                int value = decode->m_buf[y*WIDTH/8+x];
+                term.printf("%+3d,", value);
+            }
+        }
+        term.locate(0, y);
+        term.printf("[%s width=%d height=%d yblock=%d %u]\n", decode->mode_CbCr ? "CbCr": "Y0Y1",  
+            decode->width, decode->height, decode->yblock, decode->EOI_count);
+        term.printf("[CC:"); 
+        for(int i = 0; i < 16; i++) {
+            term.printf(" %u", cam->report_cc_count[i]); 
+        }
+        term.printf("]\n"); 
+        term.printf("[PS:"); 
+        for(int i = 0; i < 16; i++) {
+            term.printf(" %u", cam->report_ps_cc_count[i]); 
+        }
+        term.printf("]\n"); 
+        Thread::wait(200);
+        //Thread::signal_wait(1, 2000);
+        led2 = !led2;
+        if (n++ > (20000/200)) {
+            n = 0;
+            decode->mode_CbCr = !decode->mode_CbCr;
+        }
+    }
+}
+
+int main() {
+    term.baud(921600);
+    term.printf("%s\n", __FILE__);
+
+    decode = new JpegDecode;
+    TEST_ASSERT(decode);
+
+    UsbHost = new BaseUsbHost;
+    TEST_ASSERT_TRUE(UsbHost);
+
+    UsbHub* hub = new UsbHub();
+    TEST_ASSERT_TRUE(hub);
+
+    for(int i = 0; i < MAX_HUB_PORT; i++) {
+        if (LifeCamVX700::check(hub->PortEp[i])) {
+            ctlEp = hub->PortEp[i];
+            break;
+        }
+    }
+    if (ctlEp == NULL) {
+        error("LifeCamVX700 not found\n");
+    }
+    
+    cam = new LifeCamVX700(VX700_160x120, _5FPS, ctlEp); 
+    TEST_ASSERT_TRUE(cam);
+    cam->setOnResult(callback_motion_jpeg);
+
+    Thread thread(display_thread, NULL, osPriorityBelowNormal);
+ 
+    while(1) {
+        cam->poll();
+    }
+}
+#endif