BaseUsbHost example program

Dependencies:   BaseUsbHost FATFileSystem mbed mbed-rtos

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Sun Jan 06 11:47:51 2013 +0000
Parent:
2:c10029b87439
Child:
4:41ff237a64ec
Commit message:
update library

Changed in this revision

BaseJpegDecode.lib Show diff for this revision Revisions of this file
BaseUsbHost.lib Show annotated file Show diff for this revision Revisions of this file
EthernetInterface.lib Show diff for this revision Revisions of this file
FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
LifeCamVX700/LifeCamVX700.cpp Show diff for this revision Revisions of this file
LifeCamVX700/LifeCamVX700.h 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
Terminal.lib 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 diff for this revision Revisions of this file
UsbMouseHost/UsbMouseHost.h Show diff for this revision Revisions of this file
UvcCam/UvcCam.cpp Show diff for this revision Revisions of this file
UvcCam/UvcCam.h Show diff for this revision Revisions of this file
example2_LogitechC270.cpp Show diff for this revision Revisions of this file
example_captureJPEG.cpp Show diff for this revision Revisions of this file
example_captureYUY2.cpp Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BaseJpegDecode.lib	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/va009039/code/BaseJpegDecode/#e243fa781e5c
--- a/BaseUsbHost.lib	Tue Dec 11 15:28:00 2012 +0000
+++ b/BaseUsbHost.lib	Sun Jan 06 11:47:51 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/va009039/code/BaseUsbHost/#fe1e62051d88
+http://mbed.org/users/va009039/code/BaseUsbHost/#ae77d63a1eda
--- a/EthernetInterface.lib	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/EthernetInterface/#a0ee3ae75cfa
--- a/FATFileSystem.lib	Tue Dec 11 15:28:00 2012 +0000
+++ b/FATFileSystem.lib	Sun Jan 06 11:47:51 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
+http://mbed.org/users/va009039/code/FATFileSystem/#86638c0f65b0
--- a/LifeCamVX700/LifeCamVX700.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-// 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;
-}
-
--- a/LifeCamVX700/LifeCamVX700.h	Tue Dec 11 15:28:00 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
--- a/LogitechC270/LogitechC270.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ b/LogitechC270/LogitechC270.cpp	Sun Jan 06 11:47:51 2013 +0000
@@ -1,4 +1,4 @@
-// LogitechC270.cpp 2012/12/11
+// LogitechC270.cpp 2013/1/3
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -8,7 +8,7 @@
 #include "BaseUsbHostTest.h"
 #include "LogitechC270.h"
 
-LogitechC270::LogitechC270(int frameIndex, uint32_t interval, ControlEp* ctlEp)
+LogitechC270::LogitechC270(int formatIndex, int frameIndex, uint32_t interval, ControlEp* ctlEp)
 {
     uint8_t buf[26];
     
@@ -47,7 +47,7 @@
     DBG_BYTES("GET_CUR Probe", buf, 26);
 
     memset(buf, 0, 26);
-    buf[2] = C270_MJPEG;
+    buf[2] = formatIndex;
     buf[3] = frameIndex;
     *reinterpret_cast<uint32_t*>(buf+4) = interval;
     
@@ -57,7 +57,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[2], formatIndex);
     TEST_ASSERT_EQUAL(buf[3], frameIndex);
     TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
     DBG_BYTES("GET_CUR Commit", buf, 26);
--- a/LogitechC270/LogitechC270.h	Tue Dec 11 15:28:00 2012 +0000
+++ b/LogitechC270/LogitechC270.h	Sun Jan 06 11:47:51 2013 +0000
@@ -1,6 +1,5 @@
-// LogitechC270.h 2012/12/5
-#ifndef LOGITECH_C270_H
-#define LOGITECH_C270_H
+// LogitechC270.h 2013/1/6
+#pragma once
 
 #define C270_VID 0x046d
 #define C270_PID 0x0825
@@ -27,7 +26,6 @@
 
 class LogitechC270 : public BaseUvc {
 public:
-    LogitechC270(int frameIndex = C270_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL);
+    LogitechC270(int formatIndex = C270_MJPEG, int frameIndex = C270_160x120, uint32_t interval = _5FPS, ControlEp* ctlEp = NULL);
     static bool check(ControlEp* ctlEp);
 };
-#endif //LOGITECH_C270_H
--- a/Terminal.lib	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/cbayley/code/Terminal/#543e8e498e09
--- a/UsbFlashDrive/UsbFlashDrive.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.cpp	Sun Jan 06 11:47:51 2013 +0000
@@ -1,4 +1,4 @@
-// UsbFlashDrive.cpp 2012/12/5
+// UsbFlashDrive.cpp 2013/1/5
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -6,15 +6,10 @@
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
-
 #include "UsbFlashDrive.h"
 
 //#define WRITE_PROTECT
 
-int LE16(const uint8_t* d)
-{
-    return d[0] | (d[1] << 8);
-}
 
 uint32_t BE32(uint8_t* d)
 {
@@ -46,6 +41,8 @@
         TEST_ASSERT_TRUE(ctlEp);
     }
 
+    CTASSERT(sizeof(CBW) == 31);
+    CTASSERT(sizeof(CSW) == 13);
     TEST_ASSERT(sizeof(CBW) == 31);
     TEST_ASSERT(sizeof(CSW) == 13);
 
@@ -68,18 +65,48 @@
     if (ctlEp == NULL) {
         return false;
     }
-    uint8_t buf[8];
-    int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, sizeof(buf));
+    CTASSERT(sizeof(StandardDeviceDescriptor) == 18);
+    CTASSERT(sizeof(StandardConfigurationDescriptor) == 9);
+    CTASSERT(sizeof(StandardInterfaceDescriptor) == 9);
+    TEST_ASSERT(sizeof(StandardDeviceDescriptor) == 18);
+    TEST_ASSERT(sizeof(StandardConfigurationDescriptor) == 9);
+    TEST_ASSERT(sizeof(StandardInterfaceDescriptor) == 9);
+
+    StandardDeviceDescriptor desc;
+    int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, reinterpret_cast<uint8_t*>(&desc), sizeof(StandardDeviceDescriptor));
     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) {
+    if (desc.bDeviceClass == 8) {
+        return true;
+    } else if (desc.bDeviceClass != 0x00) {
+        return false;
+    }
+    uint8_t temp[4];
+    rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp));
+    if (rc != USB_OK) {
         return false;
-    }    
-    return true;
+    }
+    StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp);
+    uint8_t* buf = new uint8_t[cfg->wTotalLength];
+    
+    rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength);
+    if (rc != USB_OK) {
+        return false;
+    }
+    DBG_HEX(buf, cfg->wTotalLength);
+    bool ret = false;
+    for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) {
+        StandardInterfaceDescriptor* desc = reinterpret_cast<StandardInterfaceDescriptor*>(buf+pos);
+        if (desc->bDescriptorType == 4) { // interface ?
+            if (desc->bInterfaceClass == 8 && desc->bInterfaceSubClass == 6 && desc->bInterfaceProtocol == 0x50) {
+                ret = true;
+            }
+            break;
+        }
+    }
+    delete[] buf;
+    return ret;
 }
 
 int UsbFlashDrive::disk_initialize()
@@ -165,64 +192,38 @@
 
 int UsbFlashDrive::ParseConfiguration(ControlEp* ctlEp)
 {
-  TEST_ASSERT(ctlEp);
-  int rc;
-  uint8_t ConfigDesc[9];
-  int index = 0;
-  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);
-  TEST_ASSERT(ConfigDesc[1] == 0x02);
-  int wTotalLength = *((uint16_t*)&ConfigDesc[2]);
-  DBG("TotalLength: %d\n", wTotalLength);
-  int bConfigValue = ConfigDesc[5];
-  TEST_ASSERT(bConfigValue == 1);
-  DBG("ConfigValue: %d\n", bConfigValue);
-  DBG("MaxPower: %d mA\n", ConfigDesc[8]*2);   
-
-  uint8_t* buf = new uint8_t[wTotalLength];
-  TEST_ASSERT(buf);
-  rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
-  TEST_ASSERT(rc == USB_OK);
-  TEST_ASSERT(ConfigDesc[1] == 0x02);
-  for (int pos = 0; pos < wTotalLength; pos += buf[pos]) {
-      DBG_BYTES("CFG", buf+pos, buf[pos]);
-      int type = buf[pos+1];
-      if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04
-        DBG("InterfaceNumber: %d\n", buf[pos+2]);
-        DBG("AlternateSetting: %d\n", buf[pos+3]);
-        DBG("NumEndpoint: %d\n", buf[pos+4]);
-        DBG("InterfaceClass: %02X\n", buf[pos+5]);
-        DBG("InterfaceSubClass: %02X\n", buf[pos+6]);
-        DBG("InterfaceProtocol: %02X\n", buf[pos+7]);
-        TEST_ASSERT(buf[pos+6] == 0x06); // SCSI
-        TEST_ASSERT(buf[pos+7] == 0x50); // bulk only
-      } 
-      if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) {
-          TEST_ASSERT(buf[pos] == 7);
-          uint8_t att = buf[pos+3];
-          if (att == 2) { // bulk
-              uint8_t ep = buf[pos+2];
-              bool dir = ep & 0x80; // true=IN
-              uint16_t size = LE16(buf+pos+4);
-              DBG("EndpointAddress: %02X\n", ep);
-              DBG("Attribute: %02X\n", att);
-              DBG("MaxPacketSize: %d\n", size); 
-              BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), ep, size);
-              TEST_ASSERT(pEp);
-              if (dir) {
-                  m_pEpBulkIn = pEp;
-              } else {
-                  m_pEpBulkOut = pEp;
-              } 
-          }
-      }
-  }
-  delete[] buf;
-  TEST_ASSERT(m_pEpBulkIn);
-  TEST_ASSERT(m_pEpBulkOut);
-  return 0;   
+    TEST_ASSERT(ctlEp);
+    TEST_ASSERT(sizeof(StandardEndpointDescriptor) == 7);
+    uint8_t temp[4];
+    int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, temp, sizeof(temp));
+    if (rc != USB_OK) {
+        return rc;
+    }
+    StandardConfigurationDescriptor* cfg = reinterpret_cast<StandardConfigurationDescriptor*>(temp);
+    uint8_t* buf = new uint8_t[cfg->wTotalLength];
+    rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, buf, cfg->wTotalLength);
+    if (rc != USB_OK) {
+        return rc;
+    }
+    DBG_HEX(buf, cfg->wTotalLength);
+    for(int pos = 0; pos < cfg->wTotalLength; pos += buf[pos]) {
+        StandardEndpointDescriptor* desc = reinterpret_cast<StandardEndpointDescriptor*>(buf+pos);
+        if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) {
+            if (desc->bmAttributes == 2) { // bulk
+                BulkEp* pEp = new BulkEp(ctlEp->GetAddr(), desc->bEndpointAddress, desc->wMaxPacketSize);
+                if (desc->bEndpointAddress & 0x80) {
+                    m_pEpBulkIn = pEp;
+                } else {
+                    m_pEpBulkOut = pEp;
+                }
+            }
+        }
+    }
+    delete[] buf;
+    if (m_pEpBulkIn && m_pEpBulkOut) {
+        return USB_OK;
+    }
+    return USB_ERROR;    
 }
 
 int UsbFlashDrive::BulkOnlyMassStorageReset(ControlEp* ctlEp)
--- a/UsbFlashDrive/UsbFlashDrive.h	Tue Dec 11 15:28:00 2012 +0000
+++ b/UsbFlashDrive/UsbFlashDrive.h	Sun Jan 06 11:47:51 2013 +0000
@@ -1,6 +1,5 @@
-// usbFlashDrive.h 2012/12/5
-#ifndef USB_FLASH_DRIVE_H
-#define USB_FLASH_DRIVE_H
+// usbFlashDrive.h 2013/1/5
+#pragma once
 
 #include "FATFileSystem.h"
 
@@ -74,5 +73,3 @@
     uint32_t m_report_disk_status;
     uint32_t m_report_disk_sync;
 };
-
-#endif // USB_FLASH_DRIVE_H
\ No newline at end of file
--- a/UsbMouseHost/UsbMouseHost.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-// UsbMouseHost.cpp 2012/12/5
-#include "mbed.h"
-#include "rtos.h"
-#include "BaseUsbHost.h"
-#define DEBUG
-#include "BaseUsbHostDebug.h"
-#define TEST
-#include "BaseUsbHostTest.h"
-#include "UsbMouseHost.h"
-
-UsbMouseHost::UsbMouseHost(ControlEp* ctlEp)
-{
-    if (ctlEp == NULL) { // root hub
-        DBG_OHCI(LPC_USB->HcRhPortStatus1);
-        int lowSpeed = 0;
-        if (LPC_USB->HcRhPortStatus1 & 0x200) {
-            lowSpeed = 1;
-        }
-        ctlEp = new ControlEp(lowSpeed);
-        TEST_ASSERT_TRUE(ctlEp);
-    }
-    bool r = check(ctlEp);
-    TEST_ASSERT(r);
- 
-    int rc = ctlEp->SetConfiguration(1);
-    TEST_ASSERT_EQUAL(rc, USB_OK);
-
-    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->interruptReceive(reinterpret_cast<uint8_t*>(status), 4, millisec);
-    if (rc < 0) { // error?
-        *status = 0x00000000;
-        return rc;
-    }
-    return USB_OK;
-}
--- a/UsbMouseHost/UsbMouseHost.h	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-// 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;
-    InterruptEp* m_intEp;
-};
-
-#endif //USB_MOUSE_HOST_H
\ No newline at end of file
--- a/UvcCam/UvcCam.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,566 +0,0 @@
-// 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];
-    }
-}
-
--- a/UvcCam/UvcCam.h	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-// 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
--- a/example2_LogitechC270.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-#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
--- a/example_captureJPEG.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-#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
--- a/example_captureYUY2.cpp	Tue Dec 11 15:28:00 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Jan 06 11:47:51 2013 +0000
@@ -0,0 +1,122 @@
+// BaseUsbHost_example/main.cpp 2013/1/6
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#include "LogitechC270.h"
+#include "LifeCamVX700.h"
+#include "UvcCam.h"
+#include "UsbFlashDrive.h"
+#include "decodeMJPEG.h"
+#include "MyThread.h"
+#include <string>
+
+#define IMAGE_BUF_SIZE (1024*6)
+#define INTERVAL_S 20
+
+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();
+        buf_size = IMAGE_BUF_SIZE;
+        buf = new uint8_t[buf_size];
+        pos = 0;
+    }
+    Timer interval_t;
+private:    
+    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();                               
+                time_t timestamp = time(NULL);
+                struct tm* tminfo = localtime(&timestamp);
+                char tmbuf[64];
+                strftime(tmbuf, sizeof(tmbuf), "/usb/img%M%S.jpg", tminfo);
+                string path = tmbuf;
+                printf("%s %d bytes\n", path.c_str(), pos);
+                FILE* fp = fopen(path.c_str(), "wb");
+                if (fp) {
+                    fwrite(buf, pos, 1, fp);
+                    fclose(fp);
+                }
+                led4 = !led4;
+            }
+        }
+    }
+
+    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
+        inputPacket(buf, len);
+        led1 = buf[1]&1;    // FID
+        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;
+};
+
+void no_memory () {
+  error("Failed to allocate memory!\n");
+}
+
+int main() {
+    pc.baud(921600);
+    printf("%s\n", __FILE__);
+    set_new_handler(no_memory);
+
+    BaseUvc* cam = NULL;
+    UsbFlashDrive* drive = NULL;
+    BaseUsbHost* usbHost = new BaseUsbHost();
+    ControlEp* ctlEp = new ControlEp; // root hub
+    if (!UsbHub::check(ctlEp)) {
+        error("USB Hub is not connected.\n");
+    }
+    UsbHub* hub = new UsbHub(ctlEp);
+    for(vector<ControlEp*>::iterator it = hub->PortEp.begin(); it != hub->PortEp.end(); ++it) {
+        if (drive == NULL && UsbFlashDrive::check(*it)) {
+            drive = new UsbFlashDrive("usb", *it);
+        } else if (cam == NULL && LogitechC270::check(*it)) {
+            cam = new LogitechC270(C270_MJPEG, C270_160x120, _5FPS, *it); 
+        } else if (cam == NULL && LifeCamVX700::check(*it)) {
+            cam = new LifeCamVX700(VX700_160x120, _5FPS, *it); 
+        } else if (cam == NULL && UvcCam::check(*it)) {
+            cam = new UvcCam(UVC_MJPEG, UVC_160x120, _5FPS, *it); 
+        }
+    }
+    if (cam == NULL) {
+        error("UVC Camera is not connected.\n");
+    }
+    if (drive == NULL) {
+        error("USB flash drive is not connected.\n");
+    }
+    
+    captureJPEG* capture = new captureJPEG(cam);
+    capture->set_stack(DEFAULT_STACK_SIZE+128*4);
+    capture->start();
+
+    for(int n = 0; ; n++) {
+        printf("%d captureJPEG stack used: %d/%d bytes\n", n, capture->stack_used(), capture->stack_size());
+        Thread::wait(5*1000);
+    }
+}