BaseUsbHost example program

Dependencies:   BaseUsbHost FATFileSystem mbed mbed-rtos

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Tue Dec 11 15:28:00 2012 +0000
Parent:
1:80205a2de336
Child:
3:6ae9a03a6145
Commit message:
add example

Changed in this revision

BaseUsbHost.lib Show annotated file Show diff for this revision Revisions of this file
LifeCamVX700.cpp Show diff for this revision Revisions of this file
LifeCamVX700.h Show diff for this revision Revisions of this file
LifeCamVX700/LifeCamVX700.cpp Show annotated file Show diff for this revision Revisions of this file
LifeCamVX700/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
MyThread/MyThread.h Show annotated file Show diff for this revision Revisions of this file
UvcCam/UvcCam.cpp Show annotated file Show diff for this revision Revisions of this file
UvcCam/UvcCam.h Show annotated file Show diff for this revision Revisions of this file
decodeMJPEG/decodeMJPEG.cpp Show annotated file Show diff for this revision Revisions of this file
decodeMJPEG/decodeMJPEG.h Show annotated file Show diff for this revision Revisions of this file
example1_LogitechC270.cpp Show diff for this revision Revisions of this file
example1_UsbFlashDrive.cpp Show diff for this revision Revisions of this file
example1_UsbMouseHost.cpp Show diff for this revision Revisions of this file
example2_LifeCamVX700.cpp Show diff for this revision Revisions of this file
example2_LogitechC270.cpp Show annotated file Show diff for this revision Revisions of this file
example_captureJPEG.cpp Show annotated file Show diff for this revision Revisions of this file
example_captureYUY2.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- a/BaseUsbHost.lib	Wed Dec 05 13:25:18 2012 +0000
+++ b/BaseUsbHost.lib	Tue Dec 11 15:28:00 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/va009039/code/BaseUsbHost/#3b7bc4f87a61
+http://mbed.org/users/va009039/code/BaseUsbHost/#fe1e62051d88
--- a/LifeCamVX700.cpp	Wed Dec 05 13:25:18 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-// 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;
-}
-
--- a/LifeCamVX700.h	Wed Dec 05 13:25:18 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-// 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LifeCamVX700/LifeCamVX700.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,99 @@
+// LifeCamVX700.cpp 2012/12/10
+#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);
+
+    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);
+    int 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);
+
+    rc = m_ctlEp->SetConfiguration(1);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+
+    int value;
+    rc = m_ctlEp->GetConfiguration(&value);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("config: %d\n", value);
+    TEST_ASSERT_EQUAL(value, 1);
+
+    rc = m_ctlEp->SetInterfaceAlternate(1, VX700_IF_ALT); // alt=1 packet size = 192
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+
+    rc = m_ctlEp->GetInterface(1, &value);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("alt: %d\n", value);
+    TEST_ASSERT_EQUAL(value, 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/LifeCamVX700.h	Tue Dec 11 15:28:00 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	Wed Dec 05 13:25:18 2012 +0000
+++ b/LogitechC270/LogitechC270.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -1,4 +1,4 @@
-// LogitechC270.cpp 2012/12/5
+// LogitechC270.cpp 2012/12/11
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -62,31 +62,30 @@
     TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
     DBG_BYTES("GET_CUR Commit", buf, 26);
 
-    int cfg;
-    rc = m_ctlEp->GetConfiguration(&cfg);
+    int value;
+    rc = m_ctlEp->GetConfiguration(&value);
     TEST_ASSERT_EQUAL(rc, USB_OK);
-    DBG("config: %d\n", cfg);
+    DBG("config: %d\n", value);
 
     rc = m_ctlEp->SetConfiguration(1);
     TEST_ASSERT_EQUAL(rc, USB_OK);
 
-    rc = m_ctlEp->GetConfiguration(&cfg);
+    rc = m_ctlEp->GetConfiguration(&value);
     TEST_ASSERT_EQUAL(rc, USB_OK);
-    DBG("config: %d\n", cfg);
-    TEST_ASSERT_EQUAL(cfg, 1);
+    DBG("config: %d\n", value);
+    TEST_ASSERT_EQUAL(value, 1);
 
-    int alt;
-    rc = m_ctlEp->GetInterface(1, &alt);
+    rc = m_ctlEp->GetInterface(1, &value);
     TEST_ASSERT_EQUAL(rc, USB_OK);
-    DBG("alt: %d\n", alt);
+    DBG("alt: %d\n", value);
 
     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);
+    rc = m_ctlEp->GetInterface(1, &value);
     TEST_ASSERT_EQUAL(rc, USB_OK);
-    DBG("alt: %d\n", alt);
-    TEST_ASSERT_EQUAL(alt, 1);
+    DBG("alt: %d\n", value);
+    TEST_ASSERT_EQUAL(value, C270_IF_ALT);
 
     for(int i = 0; i < 16; i++) {
         report_cc_count[i] = 0;
@@ -125,4 +124,3 @@
     }
     return false;
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyThread/MyThread.h	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,52 @@
+// MyThread.h 2012/12/9
+#ifndef MY_THREAD_H
+#define MY_THREAD_H
+
+#define MAGIC_WORD 0xE25A2EA5
+static void thread_handler(void const *argument);
+
+class MyThread {
+public:
+    MyThread() {
+        m_stack_size = DEFAULT_STACK_SIZE;
+        m_stack_pointer = NULL;
+    }
+    void set_stack(uint32_t stack_size=DEFAULT_STACK_SIZE, uint8_t* stack_pointer = NULL) {
+        m_stack_size = stack_size;
+        m_stack_pointer = stack_pointer;
+    }
+    virtual void run() = 0;
+    Thread* start(osPriority priority=osPriorityNormal) {
+        if (m_stack_pointer == NULL) {
+            m_stack_pointer = reinterpret_cast<uint8_t*>(malloc(m_stack_size));
+        }
+        for(int i = 0; i < m_stack_size-64; i += 4) {
+            *reinterpret_cast<uint32_t*>(m_stack_pointer+i) = MAGIC_WORD;
+        }
+        return th = new Thread(thread_handler, this, priority, m_stack_size, m_stack_pointer);
+    }
+
+    int stack_used() {
+        int i;
+        for(i = 0; i < m_stack_size; i += 4) {
+            if(*reinterpret_cast<uint32_t*>(m_stack_pointer+i) != MAGIC_WORD) {
+                break;
+            }
+        }
+        return m_stack_size - i;       
+    }
+
+    int stack_size() { return m_stack_size; }
+protected:
+    Thread* th;
+    uint32_t m_stack_size;
+    uint8_t* m_stack_pointer;
+};
+static void thread_handler(void const *argument) {
+    MyThread* th = (MyThread*)argument;
+    if (th) {
+        th->run();
+    }    
+}
+
+#endif //MY_THREAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UvcCam/UvcCam.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,566 @@
+// UvcCam.cpp 2012/12/9
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#define DEBUG
+#include "BaseUsbHostDebug.h"
+#define TEST
+#include "BaseUsbHostTest.h"
+#include "UvcCam.h"
+
+UvcCam::UvcCam(int formatIndex, int frameIndex, uint32_t interval, ControlEp* ctlEp)
+{
+    uint8_t buf[34];
+    int rc;
+    int alt;
+    int cfg2;
+    
+    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;
+    
+    UvcCfg* cfg = new UvcCfg(formatIndex, frameIndex, ctlEp);
+    TEST_ASSERT(cfg);
+
+    int param_len = 34;
+    TEST_ASSERT(cfg->bcdUVC >= 0x0100);
+    if (cfg->bcdUVC == 0x0100) { // UVC ver. 1.0
+        param_len = 26;
+    }
+    
+    int addr = m_ctlEp->GetAddr();
+    m_isoEp = new IsochronousEp(addr, cfg->bEndpointAddress, cfg->wMaxPacketSize);
+    TEST_ASSERT_TRUE(m_isoEp);
+
+//#define USE_PROBE
+
+#ifdef USE_PROBE
+    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, param_len);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_DEF Probe", buf, param_len);
+
+    rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, param_len);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_MIN Probe", buf, param_len);
+
+    rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, param_len);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_MAX Probe", buf, param_len);
+
+    rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, param_len);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_CUR Probe", buf, param_len);
+#endif // USE_PROBE
+
+    rc = Control(GET_INFO, VS_COMMIT_CONTROL, 1, buf, 1);
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("GET_INFO Commit", buf, 1);
+
+    memset(buf, 0, param_len);
+    buf[2] = cfg->FormatIndex;
+    buf[3] = cfg->FrameIndex;
+    *reinterpret_cast<uint32_t*>(buf+4) = interval;
+    
+    DBG_BYTES("SET_CUR Commit", buf, param_len);
+    rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len);
+    TEST_ASSERT(rc == USB_OK);
+
+    rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len);
+    TEST_ASSERT(rc == USB_OK);
+    TEST_ASSERT_EQUAL(buf[2], cfg->FormatIndex);
+    TEST_ASSERT_EQUAL(buf[3], cfg->FrameIndex);
+    TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
+    DBG_BYTES("GET_CUR Commit", buf, param_len);
+
+    rc = m_ctlEp->GetConfiguration(&cfg2);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("config: %d\n", cfg2);
+
+    rc = m_ctlEp->SetConfiguration(1);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+
+    rc = m_ctlEp->GetConfiguration(&cfg2);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("config: %d\n", cfg2);
+    TEST_ASSERT_EQUAL(cfg2, 1);
+
+    rc = m_ctlEp->GetInterface(cfg->bInterface, &alt);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("alt: %d\n", alt);
+
+    rc = m_ctlEp->SetInterfaceAlternate(cfg->bInterface, cfg->bAlternate);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+
+    rc = m_ctlEp->GetInterface(cfg->bInterface, &alt);
+    TEST_ASSERT_EQUAL(rc, USB_OK);
+    DBG("alt: %d\n", alt);
+    TEST_ASSERT_EQUAL(alt, cfg->bAlternate);
+    delete cfg;
+    
+    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 UvcCam::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};
+    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);
+    return true;
+}
+
+#define  DESCRIPTOR_TYPE_DEVICE        1
+#define  DESCRIPTOR_TYPE_CONFIGURATION 2
+#define  DESCRIPTOR_TYPE_STRING        3
+#define  DESCRIPTOR_TYPE_INTERFACE     4
+#define  DESCRIPTOR_TYPE_ENDPOINT      5
+
+#define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b
+
+#define DESCRIPTOR_TYPE_HID          0x21
+#define DESCRIPTOR_TYPE_REPORT       0x22
+#define DESCRIPTOR_TYPE_PHYSICAL     0x23
+#define DESCRIPTOR_TYPE_CS_INTERFACE 0x24
+#define DESCRIPTOR_TYPE_CS_ENDPOINT  0x25
+#define DESCRIPTOR_TYPE_HUB          0x29
+
+#define CLASS_AUDIO 0x02
+#define CLASS_HUB   0x09
+
+#define IF_EQ_THEN_PRINTF(A,B) if (A == B) {VERBOSE("%s\n", #A);
+#define ENDIF }
+
+#define CC_AUDIO 0x01
+#define SC_AUDIOCONTROL   0x01
+#define SC_AUDIOSTREAMING 0x02
+
+#define AC_HEADER          0x01
+#define AC_INPUT_TERMINAL  0x02
+#define AC_OUTPUT_TERMINAL 0x03
+#define AC_FEATURE_UNIT    0x06
+
+// Input Terminal Types
+#define ITT_CAMERA 0x0201
+
+static int LE16(const uint8_t* d)
+{
+    return d[0] | (d[1] << 8);
+}
+
+static int LE24(const uint8_t* d) {
+    return d[0] | (d[1]<<8) | (d[2] << 16);
+}
+
+static int LE32(const uint8_t* d) {
+    return d[0] |(d[1]<<8) | (d[2] << 16) |(d[3] << 24) ;
+}
+
+UvcCfg::UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp):wMaxPacketSize(0)
+{
+    TEST_ASSERT(ctlEp);
+    switch(formatIndex) {
+        case UVC_MJPEG: _payload = UVC_MJPEG; break;
+        case UVC_YUY2:  _payload = UVC_YUY2; break;
+        default:        _payload = UVC_MJPEG; break;
+    }
+
+    switch(frameIndex) {
+        case UVC_160x120: _width = 160; _height = 120; break;
+        case UVC_176x144: _width = 176; _height = 144; break;
+        case UVC_320x176: _width = 320; _height = 176; break;
+        case UVC_320x240: _width = 320; _height = 240; break;
+        case UVC_352x288: _width = 352; _height = 288; break;
+        case UVC_432x240: _width = 432; _height = 240; break;
+        case UVC_640x480: _width = 640; _height = 480; break;
+        case UVC_544x288: _width = 544; _height = 288; break;
+        case UVC_640x360: _width = 640; _height = 360; break;
+        case UVC_752x416: _width = 752; _height = 416; break;
+        case UVC_800x448: _width = 800; _height = 448; break;
+        case UVC_800x600: _width = 800; _height = 600; break;
+        default:          _width = 160; _height = 120; break;
+    }
+    int index = 0;
+    uint8_t temp[4];
+    int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, temp, sizeof(temp));
+    TEST_ASSERT(rc == USB_OK);
+    DBG_BYTES("Config Descriptor 4bytes", temp, sizeof(temp));
+    TEST_ASSERT(temp[0] == 9);
+    TEST_ASSERT(temp[1] == 0x02);
+    int TotalLength = LE16(temp+2);
+    DBG("TotalLength: %d\n", TotalLength);
+
+    uint8_t* buf = new uint8_t[TotalLength];
+    TEST_ASSERT(buf);
+    rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, TotalLength);
+    TEST_ASSERT(rc == USB_OK);
+    if (rc != USB_OK) {
+        delete[] buf;
+        return;
+    }
+    _parserConfigurationDescriptor(buf, TotalLength);
+    delete[] buf;
+}
+
+void UvcCfg::_parserAudioControl(uint8_t* buf, int len) {
+    int subtype = buf[2];
+    IF_EQ_THEN_PRINTF(AC_HEADER, subtype)
+    VERBOSE("ADC: %04x\n", LE16(buf+3));
+    VERBOSE("TotalLength: %d\n", LE16(buf+5));
+    VERBOSE("InCollection: %d\n", buf[7]);
+    for (int n = 1; n <= buf[7]; n++) {
+        VERBOSE("aInterfaceNr(%d): %d\n", n, buf[8+n-1]);
+    }
+    ENDIF
+    IF_EQ_THEN_PRINTF(AC_INPUT_TERMINAL, subtype)
+    VERBOSE("TerminalID: %d\n", buf[3]);
+    VERBOSE("TerminalType: %04X\n", LE16(buf+4));
+    VERBOSE("AssocTermianl: %d\n", buf[6]);
+    VERBOSE("NrChannels: %d\n", buf[7]);
+    ENDIF
+    IF_EQ_THEN_PRINTF(AC_OUTPUT_TERMINAL, subtype)
+    VERBOSE("TerminalID: %d\n", buf[3]);
+    VERBOSE("TerminalType: %04X\n", LE16(buf+4));
+    VERBOSE("AssocTermianl: %d\n", buf[6]);
+    ENDIF
+    IF_EQ_THEN_PRINTF(AC_FEATURE_UNIT, subtype)
+    VERBOSE("UnitID: %d\n", buf[3]);
+    VERBOSE("SourceID: %d\n", buf[4]);
+    VERBOSE("ControlSize: %d\n", buf[5]);
+    ENDIF
+}
+
+#define AS_GENERAL     0x01
+#define AS_FORMAT_TYPE 0x02
+
+void UvcCfg::_parserAudioStream(uint8_t* buf, int len) {
+    int subtype = buf[2];
+    IF_EQ_THEN_PRINTF(AS_GENERAL, subtype)
+    VERBOSE("TerminalLink: %d\n", buf[3]);
+    VERBOSE("Delay: %d\n", buf[4]);
+    VERBOSE("FormatTag: %04x\n", LE16(buf+5));
+    ENDIF
+    IF_EQ_THEN_PRINTF(AS_FORMAT_TYPE, subtype)
+    VERBOSE("FormatType: %d\n", buf[3]);
+    VERBOSE("NrChannels: %d\n", buf[4]);
+    VERBOSE("SubFrameSize: %d\n", buf[5]);
+    VERBOSE("BitResolution: %d\n", buf[6]);
+    VERBOSE("SamFreqType: %d\n", buf[7]);
+    VERBOSE("SamFreq(1): %d\n", LE24(buf+8));
+    ENDIF
+}
+
+#define CC_VIDEO 0x0e
+
+#define SC_VIDEOCONTROL   0x01
+#define SC_VIDEOSTREAMING 0x02
+
+#define VC_HEADER          0x01
+#define VC_INPUT_TERMINAL  0x02
+#define VC_OUTPUT_TERMINAL 0x03
+#define VC_SELECTOR_UNIT   0x04
+#define VC_PROCESSING_UNIT 0x05
+#define VC_EXTENSION_UNIT  0x06
+
+void UvcCfg::_parserVideoControl(uint8_t* buf, int len) {
+    int subtype = buf[2];
+    IF_EQ_THEN_PRINTF(VC_HEADER, subtype)
+        bcdUVC = LE16(buf+3);
+        VERBOSE("UVC: %04x\n", bcdUVC);
+        VERBOSE("TotalLength: %d\n", LE16(buf+5));
+        VERBOSE("ClockFrequency: %d\n", LE32(buf+7));
+        VERBOSE("InCollection: %d\n", buf[11]);
+        VERBOSE("aInterfaceNr(1): %d\n", buf[12]);
+    ENDIF
+    IF_EQ_THEN_PRINTF(VC_INPUT_TERMINAL, subtype)
+        VERBOSE("TerminalID: %d\n", buf[3]);
+        uint16_t tt = LE16(buf+4);
+        VERBOSE("TerminalType: %04X\n", tt);
+        VERBOSE("AssocTerminal: %d\n", buf[6]);
+        VERBOSE("Terminal: %d\n", buf[7]);
+        if (tt == ITT_CAMERA) { // camera
+            int bControlSize = buf[14];
+            VERBOSE("ControlSize: %d\n", bControlSize);
+            for(int i = 0; i < bControlSize; i++) {
+            uint8_t bControls = buf[15+i];
+                VERBOSE("Controls(%d): %02X\n", i, bControls); 
+            }
+        }
+    ENDIF
+    IF_EQ_THEN_PRINTF(VC_OUTPUT_TERMINAL, subtype)
+        VERBOSE("TerminalID: %d\n", buf[3]);
+        VERBOSE("TerminalType: %04X\n", LE16(buf+4));
+        VERBOSE("AssocTerminal: %d\n", buf[6]);
+        VERBOSE("SourceID: %d\n", buf[7]);
+        VERBOSE("Terminal: %d\n", buf[8]);
+    ENDIF
+    IF_EQ_THEN_PRINTF(VC_SELECTOR_UNIT, subtype)
+        VERBOSE("UnitID: %d\n", buf[3]);
+    ENDIF
+    IF_EQ_THEN_PRINTF(VC_PROCESSING_UNIT, subtype)
+        VERBOSE("UnitID: %d\n", buf[3]);
+        VERBOSE("SourceID: %d\n", buf[4]);
+        VERBOSE("MaxMultiplier: %d\n", LE16(buf+5));
+        VERBOSE("ControlSize: %d\n", buf[7]);
+        int pos = 8;
+        for (int n = 1; n <= buf[7]; n++) {
+            VERBOSE("Controls(%d): %02X\n", n , buf[pos]);
+            pos++;
+        }
+        VERBOSE("Processing: %d\n", buf[pos]);
+        pos++;
+        VERBOSE("VideoStanders: %02X\n", buf[pos]);
+    ENDIF
+    IF_EQ_THEN_PRINTF(VC_EXTENSION_UNIT, subtype)
+        VERBOSE("UnitID: %d\n", buf[3]);
+    ENDIF
+}
+
+#define VS_INPUT_HEADER 0x01
+#define VS_STILL_FRAME  0x03
+#define VS_FORMAT_UNCOMPRESSED 0x04
+#define VS_FRAME_UNCOMPRESSED 0x05
+#define VS_FORMAT_MJPEG 0x06
+#define VS_FRAME_MJPEG  0x07
+#define VS_COLOR_FORMAT 0x0d
+
+void UvcCfg::_parserVideoStream(uint8_t* buf, int len) {
+    int subtype = buf[2];
+    IF_EQ_THEN_PRINTF(VS_INPUT_HEADER, subtype)
+        VERBOSE("NumFormats: %d\n", buf[3]);
+        VERBOSE("TotalLength: %d\n", LE16(buf+4));
+        VERBOSE("EndpointAddress: %02X\n", buf[6]);
+        VERBOSE("Info: %02X\n", buf[7]);
+        VERBOSE("TerminalLink: %d\n", buf[8]);
+        VERBOSE("StillCaptureMethod: %d\n", buf[9]);
+        VERBOSE("TriggerSupport: %d\n", buf[10]);
+        VERBOSE("TriggerUsage: %d\n", buf[11]);
+        VERBOSE("ControlSize: %d\n", buf[12]);
+        int pos = 13;
+        for (int n = 1; n <= buf[12]; n++) {
+            VERBOSE("Controls(%d): %02X\n", n, buf[pos]);
+            pos++;
+        }
+        bEndpointAddress = buf[6];
+    ENDIF
+    IF_EQ_THEN_PRINTF(VS_STILL_FRAME, subtype)
+    VERBOSE("EndpointAdress: %02X\n", buf[3]);
+    VERBOSE("NumImageSizePatterns: %d\n", buf[4]);
+    int ptn = buf[4];
+    int pos = 5;
+    for (int n = 1; n <= ptn; n++) {
+        VERBOSE("Width(%d): %d\n", n, LE16(buf+pos));
+        VERBOSE("Height(%d): %d\n", n, LE16(buf+pos+2));
+        pos += 4;
+    }
+    VERBOSE("NumCompressPtn: %d\n", buf[pos]);
+    ptn = buf[pos++];
+    for (int n = 1; n <= ptn; n++) {
+        VERBOSE("Compress(%d): %d\n", n, buf[pos]);
+        pos++;
+    }
+    ENDIF
+    IF_EQ_THEN_PRINTF(VS_FORMAT_UNCOMPRESSED, subtype)
+        VERBOSE("FormatIndex: %d\n", buf[3]);
+        VERBOSE("NumFrameDescriptors: %d\n", buf[4]);
+        uint32_t guid = LE32(buf+5);
+        if (guid == 0x32595559) {
+            VERBOSE("GUID: YUY2\n");
+        } else if (guid == 0x3231564e) {
+            VERBOSE("GUID: NV12\n");
+        } else {
+            VERBOSE("GUID: %08x\n", guid);
+        }
+        VERBOSE("DefaultFrameIndex: %d\n", buf[22]);
+        if (_payload == UVC_YUY2) {
+            FormatIndex = buf[3];
+        }
+    ENDIF
+    IF_EQ_THEN_PRINTF(VS_FRAME_UNCOMPRESSED, subtype)
+        VERBOSE("FrameIndex: %d\n", buf[3]);
+        VERBOSE("Capabilites: %d\n", buf[4]);
+        VERBOSE("Width: %d\n", LE16(buf+5));
+        VERBOSE("Height: %d\n", LE16(buf+7));
+        VERBOSE("MinBitRate: %d\n", LE32(buf+9));
+        VERBOSE("MaxBitRate: %d\n", LE32(buf+13));
+        VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17));
+        VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21));
+        VERBOSE("FrameIntervalType: %d\n", buf[25]);
+        int it = buf[25];
+        uint32_t max_fi = 333333; // 30.0fps
+        if (it == 0) {
+            VERBOSE("FrameMinInterval: %d\n", buf[26]);
+            VERBOSE("FrameMaxInterval: %d\n", buf[30]);
+            VERBOSE("FrameIntervalStep: %d\n", buf[34]);
+        } else {
+            int pos = 26;
+            for (int n = 1; n <= it; n++) {
+                uint32_t fi = LE32(buf+pos);
+                if (fi >= max_fi) {
+                    max_fi = fi;
+                }
+                float fps = 1e+7 / fi;
+                VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps);
+                pos += 4;
+            }
+        }
+        if (_payload == UVC_YUY2) {
+            if (_width == LE16(buf+5) && _height == LE16(buf+7)) {
+                FrameIndex = buf[3];
+            }
+            if (dwFrameInterval == 0) {
+                dwFrameInterval = max_fi;
+            }
+        }
+    ENDIF
+    IF_EQ_THEN_PRINTF(VS_FORMAT_MJPEG, subtype)
+        VERBOSE("FormatIndex: %d\n", buf[3]);
+        VERBOSE("NumFrameDescriptors: %d\n", buf[4]);
+        VERBOSE("Flags: %d\n", buf[5]);
+        VERBOSE("DefaultFrameIndex: %d\n", buf[6]);
+        if (_payload == UVC_MJPEG) {
+            FormatIndex = buf[3];
+        }
+    ENDIF
+    IF_EQ_THEN_PRINTF(VS_FRAME_MJPEG, subtype)
+        VERBOSE("FrameIndex: %d\n", buf[3]);
+        VERBOSE("Capabilites: %d\n", buf[4]);
+        VERBOSE("Width: %d\n", LE16(buf+5));
+        VERBOSE("Height: %d\n", LE16(buf+7));
+        VERBOSE("MinBitRate: %d\n", LE32(buf+9));
+        VERBOSE("MaxBitRate: %d\n", LE32(buf+13));
+        VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17));
+        VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21));
+        VERBOSE("FrameIntervalType: %d\n", buf[25]);
+        int it = buf[25];
+        uint32_t max_fi = 333333; // 30.0fps
+        if (it == 0) {
+            VERBOSE("FrameMinInterval: %d\n", buf[26]);
+            VERBOSE("FrameMaxInterval: %d\n", buf[30]);
+            VERBOSE("FrameIntervalStep: %d\n", buf[34]);
+        } else {
+            int pos = 26;
+            for (int n = 1; n <= it; n++) {
+                uint32_t fi = LE32(buf+pos);
+                if (fi >= max_fi) {
+                    max_fi = fi;
+                }
+                float fps = 1e+7 / fi;
+                VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps);
+                pos += 4;
+            }
+        }
+        if (_payload == UVC_MJPEG) {
+            if (_width == LE16(buf+5) && _height == LE16(buf+7)) {
+                FrameIndex = buf[3];
+            }
+            if (dwFrameInterval == 0) {
+                dwFrameInterval = max_fi;
+            }
+        }
+    ENDIF
+    IF_EQ_THEN_PRINTF(VS_COLOR_FORMAT, subtype)
+    ENDIF
+}
+
+void UvcCfg::_parserConfigurationDescriptor(uint8_t* buf, int len) {
+    int pos = 0;
+    _IfClass = 0;
+    _IfSubClass = 0;
+    while (pos < len) {
+        int type = buf[pos+1];
+        //DBG_BYTES(TYPE_Str(type), buf+pos, buf[pos]);
+        IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CONFIGURATION, type)
+            VERBOSE("NumInterfaces: %d\n", buf[pos+4]);
+        ENDIF
+        IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, type)
+            VERBOSE("FirstInterface: %d\n", buf[pos+2]);
+            VERBOSE("InterfaceCount: %d\n", buf[pos+3]);
+            VERBOSE("FunctionClass: %02X\n", buf[pos+4]);
+            VERBOSE("FunctionSubClass: %02X\n", buf[pos+5]);
+            VERBOSE("FunctionProtocol: %02X\n", buf[pos+6]);
+            VERBOSE("Function: %d\n", buf[pos+7]);
+        ENDIF
+        IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE,type)
+            VERBOSE("InterfaceNumber: %d\n", buf[pos+2]);
+            VERBOSE("AlternateSetting: %d\n", buf[pos+3]);
+            VERBOSE("NumEndpoint: %d\n", buf[pos+4]);
+            VERBOSE("InterfaceClass: %02X\n", buf[pos+5]);
+            VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]);
+            VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]);
+            VERBOSE("Interface: %d\n", buf[pos+8]);
+            _If         = buf[pos+2];
+            _Ifalt      = buf[pos+3];
+            _IfClass    = buf[pos+5];
+            _IfSubClass = buf[pos+6];
+        ENDIF
+        IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_ENDPOINT, type)
+            VERBOSE("EndpointAddress: %02X\n", buf[pos+2]);
+            VERBOSE("Attributes: %02X\n", buf[pos+3]);
+            VERBOSE("MaxPacketSize: %d\n", LE16(buf+pos+4));
+            VERBOSE("Interval: %d\n", buf[pos+6]);
+            if (_IfClass == CC_VIDEO && _IfSubClass == SC_VIDEOSTREAMING) {
+                if (bEndpointAddress == buf[pos+2]) {
+                    if (wMaxPacketSize == 0) {
+                        wMaxPacketSize = LE16(buf+pos+4);
+                    }    
+                    if (wMaxPacketSize == LE16(buf+pos+4)) {
+                        bInterface = _If;
+                        bAlternate = _Ifalt;
+                    }
+                }
+            }
+        ENDIF
+        IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CS_INTERFACE, type)
+            IF_EQ_THEN_PRINTF(CC_VIDEO, _IfClass)
+                IF_EQ_THEN_PRINTF(SC_VIDEOCONTROL, _IfSubClass)
+                    _parserVideoControl(buf+pos, buf[pos]);
+                ENDIF
+                IF_EQ_THEN_PRINTF(SC_VIDEOSTREAMING, _IfSubClass)
+                    _parserVideoStream(buf+pos, buf[pos]);
+                ENDIF
+            ENDIF
+            IF_EQ_THEN_PRINTF(CC_AUDIO, _IfClass)
+                IF_EQ_THEN_PRINTF(SC_AUDIOCONTROL, _IfSubClass)
+                    _parserAudioControl(buf+pos, buf[pos]);
+                ENDIF 
+                IF_EQ_THEN_PRINTF(SC_AUDIOSTREAMING, _IfSubClass)
+                    _parserAudioStream(buf+pos, buf[pos]);
+                ENDIF
+            ENDIF
+        ENDIF
+        IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_HUB, type)
+        ENDIF
+        pos += buf[pos];
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UvcCam/UvcCam.h	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,55 @@
+// UvcCam.h 2012/12/9
+#ifndef UVC_CAM_H
+#define UVC_CAM_H
+
+#define UVC_160x120 2
+#define UVC_176x144 3
+#define UVC_320x176 4
+#define UVC_320x240 5
+#define UVC_352x288 6
+#define UVC_432x240 7
+#define UVC_640x480 1
+#define UVC_544x288 8
+#define UVC_640x360 9
+#define UVC_752x416 10
+#define UVC_800x448 11
+#define UVC_800x600 12
+
+#define UVC_MJPEG 2
+#define UVC_YUY2  1
+
+#define VERBOSE(...) do{printf(__VA_ARGS__);} while(0);
+
+class UvcCam : public BaseUvc {
+public:
+    UvcCam(int formatIndex = UVC_MJPEG, int frameIndex = UVC_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL);
+    static bool check(ControlEp* ctlEp);
+};
+
+class UvcCfg {
+public:
+    UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp);
+    uint8_t bEndpointAddress; 
+    uint16_t wMaxPacketSize;
+    uint8_t FormatIndex;
+    uint8_t FrameIndex;
+    uint32_t dwFrameInterval;
+    uint8_t bInterface;
+    uint8_t bAlternate;
+    uint16_t bcdUVC;
+protected:
+    void _parserAudioControl(uint8_t* buf, int len);
+    void _parserAudioStream(uint8_t* buf, int len);
+    void _parserVideoControl(uint8_t* buf, int len);
+    void _parserVideoStream(uint8_t* buf, int len);
+    void _parserConfigurationDescriptor(uint8_t* buf, int len);
+    uint16_t _width;
+    uint16_t _height;
+    uint8_t _payload;
+    int _If;
+    int _Ifalt;
+    int _IfClass;
+    int _IfSubClass;
+};
+
+#endif //UVC_CAM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decodeMJPEG/decodeMJPEG.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,180 @@
+// decodeMJPEG.cpp 2012/12/8
+// decode motion-jpeg to jpeg
+#include "mbed.h"
+#include "decodeMJPEG.h"
+
+#define MARK_SOF0 0xc0
+#define MARK_DHT  0xc4
+#define MARK_RST0 0xd0
+#define MARK_RST7 0xd7
+#define MARK_SOI  0xd8
+#define MARK_EOI  0xd9
+#define MARK_SOS  0xda
+#define MARK_DQT  0xdb
+#define MARK_DRI  0xdd
+#define MARK_APP  0xe0
+ 
+#define SEQ_INIT      0
+#define SEQ_SOI       1
+#define SEQ_FRAME     2
+#define SEQ_MARK      3
+#define SEQ_SEG_LEN   4
+#define SEQ_SEG_LEN2  5
+#define SEQ_SEG_BODY  6
+#define SEQ_SOS       7
+#define SEQ_SOS2      8
+
+static const uint8_t dht[] = {
+0xFF,0xC4,0x01,0xA2,0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,
+0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x10,0x00,
+0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,0x01,
+0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,
+0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
+0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,
+0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,
+0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,
+0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,
+0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,
+0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,
+0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,0xE3,
+0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,
+0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
+0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,
+0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,
+0x52,0xF0,0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,
+0x1A,0x26,0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,
+0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,
+0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,
+0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,
+0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,
+0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
+0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,
+0xF7,0xF8,0xF9,0xFA,
+};
+
+decodeMJPEG::decodeMJPEG()
+{
+    m_seq = SEQ_INIT;
+}
+
+void decodeMJPEG::inputPacket(const uint8_t* buf, int len)
+{
+    for(int i = 12; i < len; i++) {
+        input(buf[i]);
+    }    
+}
+
+void decodeMJPEG::input(uint8_t c)
+{
+    switch(m_seq) {
+        case SEQ_INIT:
+            if (c == 0xff) {
+                m_seq = SEQ_SOI;
+            }
+            break;
+        case SEQ_SOI:
+            if (c == MARK_SOI) {
+                outputJPEG(0xff, JPEG_START); // start
+                outputJPEG(c);
+                m_bDHT = false;
+                m_seq = SEQ_FRAME;
+            } else {
+                m_seq = SEQ_INIT;
+            }
+            break;
+        case SEQ_FRAME:
+            if (c == 0xff) {
+                m_seq = SEQ_MARK;
+            } else {
+                m_seq = SEQ_INIT;
+            }
+            break;
+        case SEQ_MARK:
+            if (c == MARK_SOI || c == MARK_EOI || c == 0x00) {
+                m_seq = SEQ_INIT;
+                break;
+            }
+            m_mark = c;
+            m_seq = SEQ_SEG_LEN;
+            break;
+        case SEQ_SEG_LEN:
+            m_seg_len = c;
+            m_seq = SEQ_SEG_LEN2;
+            break;
+        case SEQ_SEG_LEN2:
+            m_seg_len <<= 8;
+            m_seg_len |= c;
+            m_seg_len -= 2;
+            m_seg_pos = 0;
+            m_seq = SEQ_SEG_BODY;
+            if (m_mark == MARK_SOS) {
+                if (m_bDHT == false) {
+                    for(int i = 0; i < sizeof(dht); i++) {
+                        outputJPEG(dht[i]);
+                    }    
+                }
+                m_output_desable = false;
+            } else if (m_mark == MARK_DHT) {
+                m_bDHT = true;
+                m_output_desable = false;
+            } else {
+                m_output_desable = false;
+            }
+            if (!m_output_desable) {
+                outputJPEG(0xff);
+                outputJPEG(m_mark);
+                outputJPEG((m_seg_len+2) >> 8);
+                outputJPEG((m_seg_len+2) & 0xff);
+            } 
+            break;
+        case SEQ_SEG_BODY:
+            if (!m_output_desable) {
+                outputJPEG(c);
+            }
+            if (++m_seg_pos < m_seg_len) {
+                break;
+            }
+            if (m_mark == MARK_SOS) {
+                m_seq = SEQ_SOS;
+                break;
+            }
+            m_seq = SEQ_FRAME;
+            break;
+        case SEQ_SOS:
+            if (c == 0xff) {
+                m_seq = SEQ_SOS2;
+                break;
+            }
+            outputJPEG(c);
+            break;
+        case SEQ_SOS2:
+            if (c == 0x00) {
+                outputJPEG(0xff);
+                outputJPEG(0x00);
+                m_seq = SEQ_SOS;
+                break;
+            } else if (c >= MARK_RST0 && c <= MARK_RST7) {
+                outputJPEG(0xff);
+                outputJPEG(c);
+                m_seq = SEQ_SOS;
+                break;
+            } else if (c == MARK_EOI) {
+                outputJPEG(0xff);
+                outputJPEG(c, JPEG_END);
+                m_seq = SEQ_INIT;
+                break;
+            } else if (c == MARK_SOI) {
+                outputJPEG(0xff);
+                outputJPEG(c);
+                m_seq = SEQ_INIT;
+                break;
+            }
+            m_seq = SEQ_INIT;
+            break;
+        default:
+            m_seq = SEQ_INIT;
+            break;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decodeMJPEG/decodeMJPEG.h	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,25 @@
+// decodeMJPEG.h 2012/12/9
+#ifndef DECODE_MJPEG_H
+#define DECODE_MJPEG_H
+
+#define JPEG_NONE  0
+#define JPEG_START 1
+#define JPEG_END   2
+#define JPEG_ERROR 3
+
+class decodeMJPEG {
+public:
+    decodeMJPEG();
+    void inputPacket(const uint8_t* buf, int len);
+    virtual void outputJPEG(uint8_t c, int status = JPEG_NONE) = 0;
+protected:
+    void input(uint8_t c);
+    int m_seq;
+    uint8_t m_mark;
+    uint16_t m_seg_pos; 
+    uint16_t m_seg_len;
+    bool m_bDHT;
+    bool m_output_desable;
+};
+
+#endif // DECODE_MJPEG_H
--- a/example1_LogitechC270.cpp	Wed Dec 05 13:25:18 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-#if 1
-//
-// simple color tracking
-//
-#include "mbed.h"
-#include "rtos.h"
-#include "BaseUsbHost.h"
-#define DEBUG
-#include "BaseUsbHostDebug.h"
-#define TEST
-#include "BaseUsbHostTest.h"
-#include "LogitechC270.h"
-#include "BaseJpegDecode.h"
-#include "Terminal.h"
-
-// Logitech C270
-#define WIDTH  160
-#define HEIGHT 120
-
-#define THRESHOLD 200
-
-DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
-Terminal term(USBTX, USBRX);
-
-class CalcCenter : public BaseJpegDecode {
-public:
-    int y_center, x_center;
-    int m_x_sum, m_y_sum, m_sum;
-    uint32_t EOI_count;
-    int16_t m_buf[WIDTH/16*HEIGHT/8];
-    CalcCenter():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 (block == 3) { // 0-1:Y 2:Cb 3:Cr
-            value *= qt[1][0];
-            m_buf[mcu] = value; // debug
-            if (value >= THRESHOLD) { // red
-                m_x_sum += value*(mcu%(WIDTH/16));
-                m_y_sum += value*(mcu/(WIDTH/16));
-                m_sum += value;
-            }
-        }
-    }
-    virtual void outputAC(int mcu, int block, int scan, int value){};
-    virtual void outputMARK(uint8_t c){
-        if (c == 0xd9) { // EOI
-            if(m_sum == 0) {
-                x_center = y_center = -1; // not found
-            } else {
-                x_center = m_x_sum / m_sum;
-                y_center = m_y_sum / m_sum;
-            }
-            m_x_sum = m_y_sum = m_sum = 0; // reset
-            EOI_count++;
-            led3 = !led3;
-        }
-    };
-};
-
-CalcCenter* calc = NULL;
-void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len)
-{
-    if (calc) {
-        calc->input(buf+12, len-12);
-    }
-    if (buf[1]&1) { // FID
-        led1 = !led1;
-    }
-}
-
-BaseUsbHost *UsbHost;
-UsbHub* hub;
-ControlEp* ctlEp = NULL;
-LogitechC270* cam;
-
-void display_thread(void const *args) {
-    Timer t;
-    term.cls();
-    int fg, old_fg = 0xffffff;
-    while(1) {
-        int y;
-        for(y = 0; y < HEIGHT/8; y++) {
-            term.locate(0, y);
-            for(int x = 0; x < WIDTH/16; x++) {
-                int value = calc->m_buf[y*WIDTH/16+x];
-                if (value >= THRESHOLD) {
-                    fg = 0xff0000; // red
-                } else {
-                    fg = 0xffffff; // white
-                }
-                if (fg != old_fg) {
-                    term.foreground(fg);
-                    old_fg = fg;
-                }
-                term.printf("%+4d,", value);
-            }
-        }
-        term.locate(0, y);
-        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]); 
-        }
-        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;
-    }
-}
-
-int main() {
-    term.baud(921600);
-    term.printf("%s\n", __FILE__);
-
-    calc = new CalcCenter;
-    TEST_ASSERT(calc);
-
-    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 (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);
-    cam->setOnResult(callback_motion_jpeg);
-
-    Thread thread(display_thread, NULL, osPriorityBelowNormal);
- 
-    while(1) {
-        cam->poll();
-    }
-}
-#endif
--- a/example1_UsbFlashDrive.cpp	Wed Dec 05 13:25:18 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-#if 0
-#include "mbed.h"
-#include "rtos.h"
-#include "BaseUsbHost.h"
-#define DEBUG
-#include "BaseUsbHostDebug.h"
-#define TEST
-#include "BaseUsbHostTest.h"
-#include "UsbFlashDrive.h"
-
-DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
-Serial pc(USBTX, USBRX);
-
-BaseUsbHost *UsbHost;
-UsbHub* hub;
-ControlEp* ctlEp = NULL;
-UsbFlashDrive* drive;
-int main() {
-    pc.baud(921600);
-    printf("%s\n", __FILE__);
-
-    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 (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 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;
-        t.reset();
-        t.start();
-        if (fp) {
-            for(int i = 0; i < file_size; i++) {
-                int c = i & 0xff;
-                fputc(c, fp);
-                size++;
-            }
-            t.stop();
-            fclose(fp);
-        }
-        printf("write file %d bytes %d ms %s\n", size, t.read_ms(), path);
-        led1 = !led1;
-    }
-    
-    for(int n = 0; n <=9; n++) {
-        sprintf(path, "/usb/test%d.txt", n);
-        FILE* fp = fopen(path, "rb");
-        size = 0;
-        t.reset();
-        t.start();
-        if (fp) {
-            while(1) {
-                int c = fgetc(fp);
-                if (c == EOF) {
-                    break;
-                }
-                size++;
-            } 
-            t.stop();
-            fclose(fp);
-        }
-        printf("read file %d bytes %d ms %s\n", size, t.read_ms(), path);
-        led2 = !led2;
-    }
-
-    exit(1);
-}
-
-#endif
--- a/example1_UsbMouseHost.cpp	Wed Dec 05 13:25:18 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-#if 0
-#include "mbed.h"
-#include "rtos.h"
-#include "BaseUsbHost.h"
-#define DEBUG
-#include "BaseUsbHostDebug.h"
-#define TEST
-#include "BaseUsbHostTest.h"
-#include "UsbMouseHost.h"
-
-Serial pc(USBTX, USBRX);
-DigitalOut led1(LED1);
-
-BaseUsbHost *UsbHost;
-UsbHub* hub;
-ControlEp* ctlEp = NULL;
-UsbMouseHost* mouse;
-int main() {
-    pc.baud(921600);
-    printf("%s\n", __FILE__);
-
-    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 (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;
-        int r = mouse->read(&status);
-        if (r == USB_OK) {
-            printf("%08X\n", status);
-            if (status & 1) { // left 
-                led1 = !led1;
-            } else if (status & 2) { // right 
-                break;
-            }
-        }
-    }
-    exit(1);
-}
-
-#endif
--- a/example2_LifeCamVX700.cpp	Wed Dec 05 13:25:18 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example2_LogitechC270.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,178 @@
+#if 1
+// example2_LogitechC270.cpp
+//
+// simple color tracking
+//
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#include "LogitechC270.h"
+#include "UvcCam.h"
+#include "BaseJpegDecode.h"
+#include "Terminal.h"
+#include "MyThread.h"
+
+// Logitech C270
+#define WIDTH  160
+#define HEIGHT 120
+
+#define THRESHOLD 200
+
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+Terminal term(USBTX, USBRX);
+
+class CalcCenter : public MyThread, public BaseJpegDecode {
+public:
+    int y_center, x_center;
+    int m_x_sum, m_y_sum, m_sum;
+    uint32_t EOI_count;
+    int16_t buf_Cb[WIDTH/16*HEIGHT/8]; // debug
+    int16_t buf_Cr[WIDTH/16*HEIGHT/8]; // debug
+    CalcCenter(BaseUvc* cam) {
+        m_cam = cam;
+        m_cam->setOnResult(this, &CalcCenter::callback_motion_jpeg);
+        EOI_count = 0;
+    }
+protected:
+    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
+        input(buf+12, len-12);
+        if (buf[1]&1) { // FID
+            led1 = !led1;
+        }
+    }
+    
+    virtual void outputDC(int mcu, int block, int value) {
+        if (mcu >= (WIDTH/16*HEIGHT/8)) {
+            return;
+        }
+        if (block == 2) {
+            buf_Cb[mcu] = value * qt[1][0];
+        } else if (block == 3) { // 0-1:Y 2:Cb 3:Cr
+            buf_Cr[mcu] = value * qt[1][0];
+            value *= qt[1][0];
+            if (value >= THRESHOLD) { // red
+                m_x_sum += value*(mcu%(WIDTH/16));
+                m_y_sum += value*(mcu/(WIDTH/16));
+                m_sum += value;
+            }
+        }
+    }
+    virtual void outputAC(int mcu, int block, int scan, int value){};
+    virtual void outputMARK(uint8_t c){
+        if (c == 0xd9) { // EOI
+            if(m_sum == 0) {
+                x_center = y_center = -1; // not found
+            } else {
+                x_center = m_x_sum / m_sum;
+                y_center = m_y_sum / m_sum;
+            }
+            m_x_sum = m_y_sum = m_sum = 0; // reset
+            EOI_count++;
+            led3 = !led3;
+        }
+    }
+
+    virtual void run() {
+        while(true) {
+            if (m_cam) {
+                m_cam->poll();
+            }
+        }
+    }
+    BaseUvc* m_cam;
+};
+
+BaseUvc* cam = NULL;
+CalcCenter* calc = NULL;
+
+#define PI 3.14159265
+
+class display_Thread : public MyThread {
+    virtual void run() {
+        term.cls();
+        int fg, old_fg = 0xffffff;
+        while(1) {
+            int column = 0;
+            for(int y = 0; y < HEIGHT/8; y++) {
+                term.locate(0, column++);
+                for(int x = 0; x < WIDTH/16; x++) {
+                    int value = calc->buf_Cr[y*WIDTH/16+x];
+                    if (value >= THRESHOLD) {
+                        fg = 0xff0000; // red
+                    } else {
+                        fg = 0xffffff; // white
+                    }
+                    if (fg != old_fg) {
+                        term.foreground(fg);
+                        old_fg = fg;
+                    }
+                    term.printf("%+4d,", value);
+                }
+            }
+            term.locate(0, column++);
+            term.printf("Cr:(%d,%d)", calc->x_center, calc->y_center);
+#if 0            
+            for(int y = 0; y < HEIGHT/8; y++) {
+                term.locate(0, column++);
+                for(int x = 0; x < WIDTH/16; x++) {
+                    float Cb = calc->buf_Cb[y*WIDTH/16+x];
+                    float Cr = calc->buf_Cr[y*WIDTH/16+x];
+                    float value;
+                    if (Cb == 0.0) {
+                        value = 0.0;
+                    } else {
+                        value = (atan(Cr / Cb) + PI/2.0)* 360.0 / PI;
+                    }
+                    term.printf("%3.0f,", value);
+                }
+            }
+#endif
+            term.locate(0, column++);
+            term.printf("width=%d height=%d yblock=%d EOI: %u]\n", 
+                         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]); 
+            }
+            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);
+            led2 = !led2;
+        }
+    }
+};
+
+int main() {
+    term.baud(921600);
+    term.printf("%s\n", __FILE__);
+
+    BaseUsbHost* UsbHost = new BaseUsbHost;
+    UsbHub* hub = new UsbHub();
+
+    for(int port = 1; port <= MAX_HUB_PORT; port++) {
+        ControlEp* ctlEp = hub->GetPortEp(port);
+        if (LogitechC270::check(ctlEp)) {
+            cam = new LogitechC270(C270_160x120, _10FPS, ctlEp); 
+            break;
+        }
+        if (UvcCam::check(ctlEp)) {
+            cam = new UvcCam(UVC_MJPEG, UVC_160x120, _10FPS, ctlEp); 
+            break;
+        }
+    }
+    if (cam == NULL) {
+        error("USB camera not found\n");
+    }
+    calc = new CalcCenter(cam);
+    calc->start();
+
+    display_Thread* th = new display_Thread;
+    th->start(osPriorityBelowNormal);
+
+    Thread::wait(osWaitForever);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_captureJPEG.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,140 @@
+#if 0
+// example_captureJPEG.cpp
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#include "LogitechC270.h"
+#include "UvcCam.h"
+#include "UsbFlashDrive.h"
+#include "decodeMJPEG.h"
+#include "MyThread.h"
+
+#define IMAGE_BUF_SIZE (1024*8)
+#define INTERVAL_S 10
+#define SHOT_N 5
+#define BASE_PATH "usb"
+
+Serial pc(USBTX, USBRX);
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+
+class captureJPEG : public MyThread, public decodeMJPEG {
+public:
+    captureJPEG(BaseUvc* cam) {
+        m_cam = cam;
+        m_cam->setOnResult(this, &captureJPEG::callback_motion_jpeg);
+        interval_t.start();
+        shot = 0;
+        for(buf_size = IMAGE_BUF_SIZE; ; buf_size -= 128) {
+            buf = new uint8_t[buf_size];
+            if (buf) {
+                break;
+            }
+        }
+        printf("%p buf size: %d\n", buf, buf_size); 
+    }
+    int shot;    
+    Timer interval_t;
+protected:    
+    virtual void outputJPEG(uint8_t c, int status) {
+        if (status == JPEG_START) {
+            pos = 0;
+            led2 = !led2;
+        }
+        if (pos < buf_size) {
+            buf[pos++] = c;
+        }
+        if (status == JPEG_END) {
+            led3 = !led3;
+            if (interval_t.read_ms() > INTERVAL_S*1000) {
+                interval_t.reset();                               
+                led4 = !led4;
+                if (shot < SHOT_N) {
+                    char path[32];
+                    snprintf(path, sizeof(path), "/%s/image%02d.jpg", BASE_PATH, shot);
+                    printf("%d %s %d bytes\n", shot, path, pos);
+                    FILE* fp = fopen(path, "wb");
+                    if (fp) {
+                        fwrite(buf, pos, 1, fp);
+                        fclose(fp);
+                    }
+                    shot++;
+                }
+            }
+        }
+    }
+
+    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
+        inputPacket(buf, len);
+        if (buf[1]&1) { // FID
+            led1 = !led1;
+        }
+        if (buf[1]&2) { // EOF
+            led2 = !led2;
+        }
+    }
+
+    virtual void run() {
+        while(true) {
+            if (m_cam) {
+                m_cam->poll();
+            }
+        }
+    }
+    uint8_t* buf;
+    int buf_size;
+    int pos;
+    BaseUvc* m_cam;
+};
+
+int main() {
+    pc.baud(921600);
+    printf("%s\n", __FILE__);
+
+    BaseUvc* cam = NULL;
+    UsbFlashDrive* drive = NULL;
+    BaseUsbHost* usbHost = new BaseUsbHost();
+    UsbHub* hub = new UsbHub();
+    
+    for(int i = 1; i <= MAX_HUB_PORT; i++) {
+        ControlEp* ctlEp = hub->GetPortEp(i);
+        if (drive == NULL && UsbFlashDrive::check(ctlEp)) {
+            drive = new UsbFlashDrive("usb", ctlEp);
+        }
+        if (cam == NULL && LogitechC270::check(ctlEp)) {
+            cam = new LogitechC270(C270_160x120, _5FPS, ctlEp); 
+        }
+        if (cam == NULL && UvcCam::check(ctlEp)) {
+            cam = new UvcCam(UVC_MJPEG, UVC_160x120, _5FPS, ctlEp); 
+        }
+    }
+    if (cam == NULL) {
+        error("UVC cam not found\n");
+    }
+    if (drive == NULL) {
+        error("USB flash drive not found\n");
+    }
+    
+    captureJPEG* capture = new captureJPEG(cam);
+    printf("captureJPEG: %p %d\n", capture, sizeof(captureJPEG));
+    capture->set_stack(DEFAULT_STACK_SIZE+256);
+    capture->start();
+
+    for(int n = 0; ; n++) {
+        printf("%d captureJPEG stack used: %d/%d bytes, interval %d/%d %d/%d sec\n", 
+            n, capture->stack_used(), capture->stack_size(), 
+            capture->shot, SHOT_N, capture->interval_t.read_ms()/1000, INTERVAL_S);
+        printf("CC:");
+        for(int i = 0; i < 16; i++) {
+            printf(" %u", cam->report_cc_count[i]);
+        }
+        printf("\n");
+        printf("PS:");
+        for(int i = 0; i < 16; i++) {
+            printf(" %u", cam->report_ps_cc_count[i]);
+        }
+        printf("\n");
+        Thread::wait(3000);
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_captureYUY2.cpp	Tue Dec 11 15:28:00 2012 +0000
@@ -0,0 +1,125 @@
+#if 0
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#include "UvcCam.h"
+#include "MyThread.h"
+#include <bitset>
+
+Serial pc(USBTX, USBRX);
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+
+class decodeYUY2 {
+public:
+    decodeYUY2() {
+        xy = 0;
+    }
+protected:
+    void inputPacket(uint8_t* buf, int len) {
+        for(int i = 12; i < len; i += 4) {
+            outputY(xy, buf[i]);
+            outputCb(xy+1, buf[i+1]);
+            outputY(xy+2, buf[i+2]);
+            outputCr(xy+3, buf[i+3]);
+            xy += 4;
+        }
+        if (buf[1]&2) { //EOF
+            xy = 0;
+        }
+    }
+    virtual void outputY(int xy, uint8_t c)=0;
+    virtual void outputCb(int xy, uint8_t c)=0;
+    virtual void outputCr(int xy, uint8_t c)=0;
+    int xy;
+};
+
+class captureYUY2 : public MyThread, public decodeYUY2 {
+public:
+    captureYUY2(BaseUvc* cam) {
+        m_cam = cam;
+        m_cam->setOnResult(this, &captureYUY2::callback);
+    }
+    bitset<160*120> bitmap;
+    uint8_t buf[160];
+protected:
+    virtual void outputY(int xy, uint8_t c) {
+        if (xy < bitmap.size()) {
+            bitmap.set(xy, c > 0x80);
+        }
+        if (xy < sizeof(buf)) {
+            buf[xy] = c;
+        }
+    }
+    virtual void outputCb(int xy, uint8_t c) {}
+    virtual void outputCr(int xy, uint8_t c) {}
+    void callback(uint16_t frame, uint8_t* buf, int len) {
+        inputPacket(buf, len);
+        if (buf[1]&1) { // FID
+            led1 = !led1;
+        }
+        if (buf[1]&2) { // EOF
+            led2 = !led2;
+        }
+    }
+    virtual void run() {
+        while(true) {
+            if (m_cam) {
+                m_cam->poll();
+            }
+        }
+    }
+    BaseUvc* m_cam;
+};
+
+int main() {
+    pc.baud(921600);
+    printf("%s\n", __FILE__);
+
+    BaseUsbHost* usbHost = new BaseUsbHost();
+    UsbHub* hub = new UsbHub();
+    BaseUvc* cam = NULL;
+    for(int i = 1; i <= MAX_HUB_PORT; i++) {
+        ControlEp* ctlEp = hub->GetPortEp(i);
+        if (cam == NULL && UvcCam::check(ctlEp)) {
+            cam = new UvcCam(UVC_YUY2, UVC_160x120, _5FPS, ctlEp); 
+        }
+    }
+    if (cam == NULL) {
+        error("cam not found\n");
+    }
+    captureYUY2* capture = new captureYUY2(cam);
+    capture->set_stack(DEFAULT_STACK_SIZE-128*12);
+    capture->start();
+
+    for(int n = 0; ; n++) {
+        for(int y = 0; y < 120; y+= 6) {
+            for(int x = 0; x < 160; x+= 3) {
+                printf("%c", capture->bitmap[y*160+x] ? '*':'.');
+            }
+            printf("\n");
+        }
+
+        printf("%d captureYUY2 stack used: %d/%d bytes\n", n, capture->stack_used(),  capture->stack_size());
+        printf("CC:"); // conditon code
+        for(int i = 0; i < 16; i++) {
+            printf(" %u", cam->report_cc_count[i]);
+        }
+        printf("\n");
+        printf("PS:"); // Packet status
+        for(int i = 0; i < 16; i++) {
+            printf(" %u", cam->report_ps_cc_count[i]);
+        }
+        printf("\n");
+       
+        for(int i = 0; i < 64; i++) {
+            printf("%02X ", capture->buf[i]);
+            if (i%16==15) {
+                printf("\n");
+            }
+        }
+        Thread::wait(400);
+        led3 = !led3;
+    }
+}
+
+#endif
--- a/mbed.bld	Wed Dec 05 13:25:18 2012 +0000
+++ b/mbed.bld	Tue Dec 11 15:28:00 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/b60934f96c0c
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/63cdd78b2dc1
\ No newline at end of file