see: http://mbed.org/users/okini3939/notebook/wifi_webcam/

Dependencies:   GSwifiInterface_ap_webcam USBHost mbed

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Fri Jun 06 00:44:06 2014 +0000
Commit message:
1st build

Changed in this revision

GSwifiInterface.lib Show annotated file Show diff for this revision Revisions of this file
USBHost.lib Show annotated file Show diff for this revision Revisions of this file
USBHostC270/BaseUvc.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostC270/BaseUvc.h Show annotated file Show diff for this revision Revisions of this file
USBHostC270/USBHostC270.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostC270/USBHostC270.h Show annotated file Show diff for this revision Revisions of this file
USBHostC270/USBisochronous/USBIsochronous.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostC270/USBisochronous/USBIsochronous.h Show annotated file Show diff for this revision Revisions of this file
USBHostC270/decodeMJPEG/decodeMJPEG.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostC270/decodeMJPEG/decodeMJPEG.h Show annotated file Show diff for this revision Revisions of this file
USBHostCam/CamInfo.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostCam/USBHostCam.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostCam/USBHostCam.h Show annotated file Show diff for this revision Revisions of this file
main.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifiInterface.lib	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/okini3939/code/GSwifiInterface_ap_webcam/#2085f090fe31
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost.lib	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/va009039/code/USBHost/#a338d6a681fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/BaseUvc.cpp	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,74 @@
+// BaseUvc.cpp
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "USBIsochronous.h"
+#include "BaseUvc.h"
+
+void BaseUvc::poll(int millisec)
+{
+    HCITD* itd = m_isoEp->isochronousReceive(millisec);
+    if (itd) {
+        uint8_t cc = itd->ConditionCode();
+        report_cc_count[cc]++;
+        if (cc == 0) {
+            uint16_t frame = itd->StartingFrame();
+            int fc = itd->FrameCount();
+            uint8_t* buf = const_cast<uint8_t*>(itd->buf); 
+            int mps = m_isoEp->m_PacketSize;
+            for(int i = 0; i < fc; i++) {
+                uint16_t psw = itd->OffsetPSW[i];
+                cc = psw>>12;
+                if (cc == 0 || cc == 9) {
+                    int len = psw & 0x7ff;
+                    onResult(frame, buf, len);
+               }
+               report_ps_cc_count[cc]++;
+               buf += mps;
+               frame++;
+            }
+        }
+        delete itd;
+    }
+}
+
+USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size)
+{
+    if (req == SET_CUR) {    
+        return host->controlWrite(dev,
+                    USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 
+                    req, cs<<8, index, buf, size);
+    }
+    return host->controlRead(dev,
+                USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 
+                req, cs<<8, index, buf, size);
+}
+
+USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt)
+{
+    return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE,
+                                   SET_INTERFACE, alt, intf, NULL, 0);
+}
+
+void BaseUvc::onResult(uint16_t frame, uint8_t* buf, int len)
+{
+  if(m_pCbItem && m_pCbMeth)
+    (m_pCbItem->*m_pCbMeth)(frame, buf, len);
+  else if(m_pCb)
+    m_pCb(frame, buf, len);
+}
+
+void BaseUvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
+{
+    m_pCb = pMethod;
+    m_pCbItem = NULL;
+    m_pCbMeth = NULL;
+}
+    
+void BaseUvc::clearOnResult()
+{
+    m_pCb = NULL;
+    m_pCbItem = NULL;
+    m_pCbMeth = NULL;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/BaseUvc.h	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,52 @@
+// BaseUvc.h
+#include "USBIsochronous.h"
+#pragma once
+
+// --- UVC --------------------------------------------------
+#define _30FPS  333333
+#define _25FPS  400000
+#define _20FPS  500000
+#define _15FPS  666666
+#define _10FPS 1000000
+#define _5FPS  2000000
+#define _1FPS 10000000
+
+#define SET_CUR  0x01
+#define GET_CUR  0x81
+#define GET_MIN  0x82
+#define GET_MAX  0x83
+#define GET_RES  0x84
+#define GET_LEN  0x85
+#define GET_INFO 0x86
+#define GET_DEF  0x87
+
+#define VS_PROBE_CONTROL  0x01
+#define VS_COMMIT_CONTROL 0x02
+
+class BaseUvc {
+public:
+    void poll(int millisec = 0);
+    USB_TYPE Control(int req, int cs, int index, uint8_t* buf, int size);
+    USB_TYPE setInterfaceAlternate(uint8_t intf, uint8_t alt);
+    IsochronousEp* m_isoEp;
+    uint32_t report_cc_count[16];  // ConditionCode
+    uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode
+    // callback
+    void onResult(uint16_t frame, uint8_t* buf, int len);
+    void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) );
+    class CDummy;
+    template<class T> 
+    void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) )
+    {
+        m_pCb = NULL;
+        m_pCbItem = (CDummy*) pItem;
+        m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod;
+    }
+    void clearOnResult();
+    CDummy* m_pCbItem;
+    void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int);
+    void (*m_pCb)(uint16_t, uint8_t*, int);
+protected:
+    USBHost * host;
+    USBDeviceConnected * dev;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/USBHostC270.cpp	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,165 @@
+#include "USBHostC270.h"
+#include "dbg.h"
+
+//#define C270_DEBUG 1
+#ifdef C270_DEBUG
+#define C270_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
+#else
+#define C270_DBG(...)  while(0);
+#endif
+
+// ------------------ HcControl Register ---------------------
+#define  OR_CONTROL_IE                  0x00000008
+
+USBHostC270::USBHostC270(int formatIndex, int frameIndex, uint32_t interval)
+{
+    C270_DBG("formatIndex: %d, frameIndex: %d, interval: %d", formatIndex, frameIndex, interval);
+    _formatIndex = formatIndex;
+    _frameIndex = frameIndex;
+    _interval = interval;
+    clearOnResult();
+    host = USBHost::getHostInst();
+    m_isoEp = new IsochronousEp;
+    init();
+}
+
+void USBHostC270::init()
+{
+    C270_DBG("");
+    dev_connected = false;
+    dev = NULL;
+    c270_intf = -1;
+    c270_device_found = false;
+    c270_vid_pid_found = false;
+}
+
+bool USBHostC270::connected()
+{
+    return dev_connected;
+}
+
+bool USBHostC270::connect()
+{
+    if (dev_connected) {
+        return true;
+    }
+
+    for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+            
+            C270_DBG("Trying to connect C270 device\r\n");
+            
+            if(host->enumerate(dev, this)) {
+                break;
+            }
+            if (c270_device_found) {
+                USB_INFO("New C270 device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, c270_intf);
+                dev->setName("C270", c270_intf);
+                host->registerDriver(dev, c270_intf, this, &USBHostC270::onDisconnect);
+                int addr = dev->getAddress();
+                m_isoEp->init(addr, C270_EN, C270_MPS);
+                uint8_t buf[26];
+                memset(buf, 0, sizeof(buf));
+                buf[2] = _formatIndex;
+                buf[3] = _frameIndex;
+                *reinterpret_cast<uint32_t*>(buf+4) = _interval;
+                USB_TYPE res = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, sizeof(buf));
+                if (res != USB_TYPE_OK) {
+                    C270_DBG("SET_CUR VS_COMMIT_CONTROL FAILED");
+                }
+                res = setInterfaceAlternate(1, C270_IF_ALT); // alt=1 packet size = 192
+                if (res != USB_TYPE_OK) {
+                    C270_DBG("SET_INTERFACE FAILED");
+                }
+                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
+
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+void USBHostC270::onDisconnect()
+{
+    C270_DBG("dev_connected: %d", dev_connected);
+    if (dev_connected) {
+        m_isoEp->disconnect();
+        init();
+    }
+}
+
+/*virtual*/ void USBHostC270::setVidPid(uint16_t vid, uint16_t pid)
+{
+    C270_DBG("vid:%04x,pid:%04x", vid, pid);
+    if (vid == C270_VID && pid == C270_PID) { 
+        c270_vid_pid_found = true;
+    } else {
+        c270_vid_pid_found = false;
+    }
+}
+
+/*virtual*/ bool USBHostC270::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    C270_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol);
+    if ((c270_intf == -1) && c270_vid_pid_found) {
+        c270_intf = intf_nb;
+        c270_vid_pid_found = false;
+        c270_device_found = true;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostC270::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    C270_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir);
+    return false;
+}
+
+#define SEQ_READ_IDOL 0
+#define SEQ_READ_EXEC 1
+#define SEQ_READ_DONE 2
+
+int USBHostC270::readJPEG(uint8_t* buf, int size, int timeout_ms) {
+    _buf = buf;
+    _pos = 0;
+    _size = size;
+    _seq = SEQ_READ_IDOL;
+    setOnResult(this, &USBHostC270::callback_motion_jpeg);
+    Timer timeout_t;
+    timeout_t.reset();
+    timeout_t.start();
+    while(timeout_t.read_ms() < timeout_ms && _seq != SEQ_READ_DONE) {
+        poll(timeout_ms);
+    } 
+    return _pos;
+}
+
+/* virtual */ void USBHostC270::outputJPEG(uint8_t c, int status) { // from decodeMJPEG
+    if (_seq == SEQ_READ_IDOL) {
+        if (status == JPEG_START) {
+            _pos = 0;
+            _seq = SEQ_READ_EXEC;
+        }
+    }
+    if (_seq == SEQ_READ_EXEC) {
+        if (_pos < _size) {
+            _buf[_pos++] = c;  
+        }  
+        if (status == JPEG_END) {
+            _seq = SEQ_READ_DONE;
+        }
+    }
+}
+
+void USBHostC270::callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
+        inputPacket(buf, len);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/USBHostC270.h	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,92 @@
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "BaseUvc.h"
+#include "decodeMJPEG.h"
+
+// Logitech C270
+#define C270_VID 0x046d
+#define C270_PID 0x0825
+#define C270_160x120 2
+#define C270_176x144 3
+#define C270_320x176 4
+#define C270_320x240 5
+#define C270_352x288 6
+#define C270_432x240 7
+#define C270_640x480 1
+#define C270_544x288 8
+#define C270_640x360 9
+#define C270_752x416 10
+#define C270_800x448 11
+#define C270_800x600 12
+
+#define C270_MJPEG 2
+#define C270_YUV2  1
+
+#define C270_EN  0x81
+#define C270_MPS  192
+#define C270_IF_ALT 1
+
+#define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+
+class IsochronousEp;
+class BaseUvc;
+/** 
+ * A class to communicate a C270
+ */
+class USBHostC270 : public IUSBEnumerator, public BaseUvc, public decodeMJPEG {
+public:
+    /**
+    * Constructor
+    *
+    */
+    USBHostC270(int formatIndex = C270_MJPEG, int frameIndex = C270_160x120, uint32_t interval = _5FPS);
+
+    /**
+    * Check if a C270 device is connected
+    *
+    * @return true if a MSD device is connected
+    */
+    bool connected();
+
+    /**
+     * Try to connect to a C270 device
+     *
+     * @return true if connection was successful
+     */
+    bool connect();
+
+    /**
+     * read jpeg image
+     *
+     * @param buf read buffer 
+     * @param size buffer size 
+     * @param timeout_ms timeout default 15sec
+     * @return jpeg size if read success else -1
+     */
+    int readJPEG(uint8_t* buf, int size, int timeout_ms = 15*1000);
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+    bool dev_connected;
+
+    int c270_intf;
+    bool c270_device_found;
+    bool c270_vid_pid_found;
+    int _formatIndex;
+    int _frameIndex;
+    uint32_t _interval;
+    uint8_t _seq;
+    uint8_t* _buf;
+    int _pos;
+    int _size;
+
+    virtual void outputJPEG(uint8_t c, int status); // from decodeMJPEG
+    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len);
+    void init();
+    void onDisconnect();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/USBisochronous/USBIsochronous.cpp	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,212 @@
+// USBIsochronous.cpp
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "USBIsochronous.h"
+
+//#define ISO_DEBUG 1
+#ifdef ISO_DEBUG
+#define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
+#else
+#define ISO_DBG(...)  while(0);
+#endif
+
+#define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+
+HCITD::HCITD(IsochronousEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
+    Control = 0xe0000000           | // CC ConditionCode NOT ACCESSED
+             ((FrameCount-1) << 24)| // FC FrameCount
+                  TD_DELAY_INT(0)  | // DI DelayInterrupt
+                 FrameNumber;        // SF StartingFrame
+    BufferPage0 = const_cast<uint8_t*>(buf);
+    BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
+    Next = NULL; 
+    ep = obj;
+    uint32_t addr = reinterpret_cast<uint32_t>(buf);
+    for(int i = 0; i < FrameCount; i++) {
+        uint16_t offset = addr & 0x0fff;
+        if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
+            offset |= 0x1000;
+        }
+        OffsetPSW[i] = 0xe000|offset;
+        addr += PacketSize;
+    }
+}
+
+void IsochronousEp::init(int addr, uint8_t ep, uint16_t size, uint8_t frameCount, uint8_t queueLimit)
+{
+    //ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size);
+    TEST_ASSERT(addr >= 1);    
+    TEST_ASSERT(size >= 8 && size <= 1023);    
+    m_pED  = new _HCED(addr, ep, size);
+    TEST_ASSERT(m_pED);
+    
+    m_pED->setFormat(); // F Format ITD
+
+    TEST_ASSERT(size >= 128 && size <= 1023);
+    m_PacketSize = size;
+    TEST_ASSERT(frameCount >= 1 && frameCount <= 8);
+    m_FrameCount = frameCount;
+    TEST_ASSERT(queueLimit >= 1 && queueLimit <= HCITD_QUEUE_SIZE);
+    m_itd_queue_limit = queueLimit;
+    
+    m_itd_queue_count = 0;
+    reset();
+    HCITD* itd = new_HCITD(this);
+    m_pED->init_queue<HCITD>(itd); 
+    TEST_ASSERT(itd);
+    if (itd == NULL) {
+        return;
+    }
+    _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
+    TEST_ASSERT(hcca);
+    if (hcca == NULL) {
+        return;
+    }
+    hcca->enqueue(m_pED);
+}
+
+void IsochronousEp::reset(int delay_ms)
+{
+    m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
+}
+
+HCITD* IsochronousEp::new_HCITD(IsochronousEp* obj)
+{
+    HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize);
+    if (itd == NULL) {
+        return NULL;
+    } 
+    m_FrameNumber += m_FrameCount;
+    return itd;
+}
+
+HCITD* IsochronousEp::isochronousReceive(int timeout_ms)
+{
+    TEST_ASSERT(m_itd_queue_count >= 0);
+    while(m_itd_queue_count < m_itd_queue_limit) {
+        if (m_pED == NULL) {
+            ISO_DBG("m_pED is NULL");
+            break;
+        }
+        if (m_pED->Skip()) {
+            break;
+        }
+        HCITD* blank_itd = new_HCITD(this);
+        TEST_ASSERT(blank_itd);
+        if (m_pED->enqueue<HCITD>(blank_itd)) {
+            m_itd_queue_count++;
+        }
+        enable(); // Enable Periodic
+    }
+    
+    HCITD* itd = get_queue_HCITD(timeout_ms);
+    if (itd) {
+        m_itd_queue_count--;
+    }
+    return itd;
+}
+
+int IsochronousEp::isochronousSend(uint8_t* buf, int len, int timeout_ms)
+{
+    //ISO_DBG("buf: %p, len: %d", buf, len);
+    HCITD* itd = get_queue_HCITD(timeout_ms);
+    if (itd) {
+        delete itd;
+        m_itd_queue_count--;
+        TEST_ASSERT(m_itd_queue_count >= 0);
+    }
+    TEST_ASSERT(m_itd_queue_count >= 0);
+    if(m_itd_queue_count < m_itd_queue_limit) {
+        if (m_pED == NULL) {
+            ISO_DBG("m_pED is NULL");
+            return 0;
+        }
+        if (m_pED->Skip()) {
+            return 0;
+        }
+        itd = new_HCITD(this);
+        TEST_ASSERT(itd);
+        //ISO_DBG("m_pED: %p itd: %p", m_pED, itd);
+        memcpy(const_cast<uint8_t*>(itd->buf), buf, len);
+        if (m_pED->enqueue<HCITD>(itd)) {
+            m_itd_queue_count++;
+        }
+        enable(); // Enable Periodic
+        //ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count);
+        return len;
+    }
+    return 0;
+}
+
+HCITD* IsochronousEp::get_queue_HCITD(int timeout_ms)
+{
+    Timer t;
+    t.reset();
+    t.start();
+    do {
+        osEvent evt = m_queue.get(0);
+        if (evt.status == osEventMessage) {
+            HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
+            TEST_ASSERT(itd);
+            return itd;
+        } else if (evt.status == osOK) {
+            ;
+        } else if (evt.status == osEventTimeout) {
+            break;
+        } else {
+            ISO_DBG("evt.status: %02x\n", evt.status);
+            TEST_ASSERT(evt.status == osEventMessage);
+            break;
+        }
+    } while(t.read_ms() < timeout_ms);
+    return NULL;
+}
+
+void IsochronousEp::enable()
+{
+    LPC_USB->HcControl |= OR_CONTROL_PLE;
+}
+
+void IsochronousEp::disconnect()
+{
+    m_pED->setSkip(); // skip bit on
+    ISO_DBG("rtos-queue: %d", m_itd_queue_count);
+    int queue_count = m_itd_queue_count;
+    Timer t;
+    t.reset();
+    t.start();
+    do {
+        HCITD* itd = get_queue_HCITD(10);
+        if (itd) {
+            ISO_DBG("delete ITD:%p from rtos-queue %d ms", itd, t.read_ms());
+            delete itd;
+            queue_count--;
+            t.reset();
+        }
+    } while(t.read_ms() < 50);
+    ISO_DBG("rtos-queue: %d, %d ms", queue_count, t.read_ms());
+    TEST_ASSERT(queue_count >= 0);
+    while(1) {
+        HCITD* itd = m_pED->dequeue<HCITD>();
+        if (itd == NULL) {
+            break;
+        }
+        ISO_DBG("delete ITD:%p from ED(%p)-queue", itd, m_pED);        
+        delete itd;
+        TEST_ASSERT(queue_count > 0);
+        queue_count--;
+    }            
+    TEST_ASSERT(queue_count == 0);
+    HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd);
+    ISO_DBG("delete ITD:%p from ED(%p)-tail", tail, m_pED);
+    TEST_ASSERT(tail);
+    delete tail;
+    m_pED->init_queue<HCITD>(NULL);
+    
+    _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
+    TEST_ASSERT(hcca);
+    hcca->dequeue(m_pED);
+    ISO_DBG("delete ED:%p", m_pED);
+    delete m_pED;
+    m_pED = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/USBisochronous/USBIsochronous.h	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,200 @@
+// USBIsochronous.h
+#pragma once
+
+class IsochronousEp;
+struct HCITD {    // HostController Isochronous Transfer Descriptor
+    __IO uint32_t Control;      // +0 Transfer descriptor control
+    uint8_t*  BufferPage0;      // +4 Buffer Page 0
+    HCITD* Next;                // +8 Physical pointer to next Isochronous Transfer Descriptor
+    uint8_t*  BufferEnd;        // +12 buffer End
+    __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
+    IsochronousEp* ep;          // +32 endpoint object
+    __IO uint8_t buf[0];        // +36 buffer
+                                // +36
+    HCITD(IsochronousEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize);
+    inline void* operator new(size_t size, int buf_size) {
+        void* p;
+        if (posix_memalign(&p, 32, size+buf_size) == 0) {
+            return p;
+        }
+        return NULL;
+    }
+
+    inline void operator delete(void* p) {
+        free(p);
+    }
+
+    inline uint16_t StartingFrame() {
+        return Control & 0xffff;
+    }
+
+    inline uint8_t FrameCount() {
+        return ((Control>>24)&7)+1;
+    }    
+
+    inline uint8_t ConditionCode() {
+        return Control>>28;
+    }
+};
+
+struct _HCED {    // HostController EndPoint Descriptor
+    __IO uint32_t Control; // +0 Endpoint descriptor control
+    HCTD* TailTd;          // +4 Physical address of tail in Transfer descriptor list
+    __IO HCTD* HeadTd;     // +8 Physcial address of head in Transfer descriptor list
+    _HCED* Next;           // +12 Physical address of next Endpoint descriptor
+                           // +16
+    _HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed = 0) {
+        Control =  addr            | /* USB address */
+        ((ep & 0x7F) << 7)         | /* Endpoint address */
+        (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
+        ((lowSpeed?1:0) << 13)     | /* speed full=0 low=1 */
+        (size << 16);                /* MaxPkt Size */
+        Next = NULL;
+    }
+
+    inline void* operator new(size_t size) {
+        void* p;
+        if (posix_memalign(&p, 16, size) == 0) {
+            return p;
+        }
+        return NULL;
+    }
+
+    inline void operator delete(void* p) {
+        free(p);
+    }
+
+    inline uint8_t FunctionAddress() {
+        return Control & 0x7f;
+    }
+
+    inline int Speed() {
+        return (Control>>13)&1;
+    }
+
+    inline void setFunctionAddress(int addr) {
+        Control &= ~0x7f;
+        Control |= addr;
+    }
+
+    inline void setMaxPacketSize(uint16_t size) {
+        Control &= ~0xffff0000;
+        Control |= size<<16;
+    }
+
+    int Skip() {
+        return (Control>>14) & 1;
+    }
+
+    void setSkip() {
+        Control |= (1<<14);
+    }
+
+    void setFormat() {
+        Control |= (1<<15);
+    }
+
+    template<typename T>
+    inline bool enqueue(T* td) {
+        if (td) {
+            T* tail = reinterpret_cast<T*>(TailTd);
+            if (tail) {
+                tail->Next = td;
+                TailTd = reinterpret_cast<HCTD*>(td);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    template<typename T>
+    inline T* dequeue() {
+        T* head = reinterpret_cast<T*>(reinterpret_cast<uint32_t>(HeadTd)&~3); // delete Halted and Toggle Carry bit
+        T* tail = reinterpret_cast<T*>(TailTd);
+        if (head == NULL || tail == NULL || head == tail) {
+            return NULL;
+        }
+        HeadTd = reinterpret_cast<HCTD*>(head->Next);
+        return head;
+    }
+    template<typename T>
+    void init_queue(T* td) {
+        TailTd = reinterpret_cast<HCTD*>(td);
+        HeadTd = reinterpret_cast<HCTD*>(td); 
+    }
+};
+
+struct _HCCA {    // Host Controller Communication Area
+    _HCED* InterruptTable[32]; // +0 Interrupt Table
+    __IO uint16_t FrameNumber;// +128 Frame Number
+    __IO uint16_t Pad1;       // +130
+    __IO HCTD* DoneHead;      // +132 Done Head
+    uint8_t Reserved[116];    // +136 Reserved for future use
+    uint8_t Unknown[4];       // +252 Unused
+                              // +256
+    inline void* operator new(size_t size) {
+        void* p;
+        if (posix_memalign(&p, 256, size) == 0) {
+            return p;
+        }
+        return NULL;
+    }
+
+    inline void operator delete(void* p) {
+        free(p);
+    }
+    
+    inline void enqueue(_HCED* ed) {
+        for(int i = 0; i < 32; i++) {
+            if (InterruptTable[i] == NULL) {
+                InterruptTable[i] = ed;
+            } else {
+                _HCED* nextEd = InterruptTable[i];
+                while(nextEd->Next && nextEd->Next != ed) {
+                    nextEd = nextEd->Next;
+                }
+                nextEd->Next = ed;
+            }
+        }
+    }
+    
+    inline void dequeue(_HCED* ed) {
+         for(int i = 0; i < 32; i++) {
+            if (InterruptTable[i] == ed) {
+                InterruptTable[i] = ed->Next;
+            } else if (InterruptTable[i]) {
+                _HCED* nextEd = InterruptTable[i];
+                while(nextEd) {
+                    if (nextEd->Next == ed) {
+                        nextEd->Next = ed->Next;
+                        break;
+                    }
+                    nextEd = nextEd->Next;
+                }
+            }
+         }
+    }
+};
+
+#define HCITD_QUEUE_SIZE 3
+
+class IsochronousEp {
+public:
+    void init(int addr, uint8_t ep, uint16_t size, uint8_t frameCount = 4, uint8_t queueLimit = HCITD_QUEUE_SIZE);
+    void reset(int delay_ms = 100);
+    HCITD* isochronousReceive(int timeout_ms);
+    int isochronousSend(uint8_t* buf, int len, int timeout_ms);
+    HCITD* get_queue_HCITD(int timeout_ms);
+    uint16_t m_PacketSize;
+    void disconnect();
+    void irqWdhHandler(HCITD* itd) {m_queue.put(itd);} // WDH
+private:
+    HCITD* new_HCITD(IsochronousEp* obj);
+    Queue<HCITD, HCITD_QUEUE_SIZE> m_queue; // ITD done queue
+    int m_itd_queue_count;
+    int m_itd_queue_limit;
+    uint16_t m_FrameNumber;
+    int m_FrameCount; // 1-8
+    void enable();
+    _HCED* m_pED;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/decodeMJPEG/decodeMJPEG.cpp	Fri Jun 06 00:44:06 2014 +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/USBHostC270/decodeMJPEG/decodeMJPEG.h	Fri Jun 06 00:44:06 2014 +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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostCam/CamInfo.cpp	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,193 @@
+// CamInfo.cpp
+#include "USBHostCam.h"
+
+// Logitech C270
+#define C270_VID 0x046d
+#define C270_PID 0x0825
+#define C270_160x120 2
+#define C270_176x144 3
+#define C270_320x176 4
+#define C270_320x240 5
+#define C270_352x288 6
+#define C270_432x240 7
+#define C270_640x480 1
+#define C270_544x288 8
+#define C270_640x360 9
+#define C270_752x416 10
+#define C270_800x448 11
+#define C270_800x600 12
+
+#define C270_MJPEG 2
+#define C270_YUV2  1
+
+#define C270_EN  0x81
+#define C270_MPS  192
+#define C270_IF_ALT_192 1
+#define C270_IF_ALT(A) C270_IF_ALT_##A
+
+#define C270_INFO(SIZE) {C270_VID, C270_PID, _##SIZE, 0, \
+    "C270", \
+    C270_MJPEG, \
+    C270_##SIZE, \
+    _5FPS, \
+    C270_EN, \
+    192, \
+    C270_IF_ALT(192), \
+    4, \
+    3}
+
+#define C210_PID 0x819
+#define C210_INFO(SIZE) {C270_VID, C210_PID, _##SIZE, 0, \
+    "C270", \
+    C270_MJPEG, \
+    C270_##SIZE, \
+    _5FPS, \
+    C270_EN, \
+    192, \
+    C270_IF_ALT(192), \
+    4, \
+    3}
+
+// Logitech Qcam Orbit AF QCAM-200R
+#define Q200R_VID 0x046d
+#define Q200R_PID 0x0994
+#define Q200R_160x120 1
+#define Q200R_176x144 2
+#define Q200R_320x240 3
+#define Q200R_352x288 4
+#define Q200R_640x480 5
+#define Q200R_800x600 6
+
+#define Q200R_MJPEG 1
+#define Q200R_YUV2  2
+
+#define Q200R_EN  0x81
+#define Q200R_MPS  192
+#define Q200R_IF_ALT_192 1
+#define Q200R_IF_ALT_384 2
+#define Q200R_IF_ALT_512 3
+#define Q200R_IF_ALT_640 4
+#define Q200R_IF_ALT_800 5
+#define Q200R_IF_ALT_944 6
+#define Q200R_IF_ALT(A) Q200R_IF_ALT_##A
+#define Q200R_INFO(SIZE) {Q200R_VID, Q200R_PID, _##SIZE, 0, \
+    "Q200R", \
+    Q200R_MJPEG, \
+    Q200R_##SIZE, \
+    _5FPS, \
+    Q200R_EN, \
+    192, \
+    Q200R_IF_ALT(192), \
+    4, \
+    3}
+
+//LifeCam VX700 / VX500
+#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_128 1 
+#define VX700_IF_ALT(A) VX700_IF_ALT_##A
+#define VX700_INFO(SIZE) {VX700_VID, VX700_PID, _##SIZE, 0, \
+    "VX700", \
+    VX700_MJPEG, \
+    VX700_##SIZE, \
+    _5FPS, \
+    VX700_EN, \
+    128, \
+    VX700_IF_ALT(128), \
+    4, \
+    3}
+
+//Sonix USB 2.0 Camera
+#define SONIX_160x120 5
+#define SONIX_176x144 4
+#define SONIX_320x240 3
+#define SONIX_352x288 2
+#define SONIX_640x480 1
+
+#define SONIX_IF_ALT_128 1
+#define SONIX_IF_ALT_256 2
+#define SONIX_IF_ALT_512 3
+#define SONIX_IF_ALT_600 4
+#define SONIX_IF_ALT_800 5
+#define SONIX_IF_ALT_956 6
+#define SONIX_IF_ALT(A) SONIX_IF_ALT_##A
+#define SONIX_INFO(SIZE) {0x0c45, 0x62c0, _##SIZE, 0, \
+    "SONIX", \
+    1, \
+    SONIX_##SIZE, \
+    _5FPS, \
+    0x81, \
+    128, \
+    SONIX_IF_ALT(128), \
+    4, \
+    3}
+
+static const CamInfo CamInfoList[] = {
+// Logitech C270
+C270_INFO(160x120),
+C270_INFO(176x144),
+C270_INFO(320x176),
+C270_INFO(320x240),
+C270_INFO(352x288),
+C270_INFO(432x240),
+C270_INFO(640x480),
+C270_INFO(544x288),
+C270_INFO(640x360),
+C270_INFO(752x416),
+C270_INFO(800x448),
+C270_INFO(800x600),
+
+// Logitech C210
+C210_INFO(160x120),
+C210_INFO(176x144),
+C210_INFO(320x176),
+C210_INFO(320x240),
+C210_INFO(352x288),
+C210_INFO(432x240),
+C210_INFO(640x480),
+C210_INFO(544x288),
+C210_INFO(640x360),
+C210_INFO(752x416),
+C210_INFO(800x448),
+C210_INFO(800x600),
+
+// Logitech Qcam Orbit AF QCAM-200R
+Q200R_INFO(160x120),
+Q200R_INFO(176x144),
+Q200R_INFO(320x240),
+Q200R_INFO(352x288),
+Q200R_INFO(640x480),
+Q200R_INFO(800x600),
+
+// LifeCam VX700
+VX700_INFO(160x120),
+VX700_INFO(176x144),
+VX700_INFO(320x240),
+VX700_INFO(352x288),
+VX700_INFO(640x480),
+
+// Sonix USB 2.0 Camera
+SONIX_INFO(160x120),
+SONIX_INFO(176x144),
+SONIX_INFO(320x240),
+SONIX_INFO(352x288),
+SONIX_INFO(640x480),
+
+// Not found
+{0,0,0,0},
+};
+
+CamInfo* getCamInfoList() {
+    return const_cast<CamInfo*>(CamInfoList);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostCam/USBHostCam.cpp	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,176 @@
+// USBHostCam.cpp
+#include "USBHostCam.h"
+#include "dbg.h"
+
+//#define CAM_DEBUG 1
+#ifdef CAM_DEBUG
+#define CAM_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
+#else
+#define CAM_DBG(...)  while(0);
+#endif
+
+// ------------------ HcControl Register ---------------------
+#define  OR_CONTROL_IE                  0x00000008
+
+CamInfo* getCamInfoList(); // CamInfo.cpp
+
+USBHostCam::USBHostCam(uint8_t size, uint8_t option, CamInfo* user_caminfo)
+{
+    CAM_DBG("size: %d, option: %d", size, option);
+    _caminfo_size = size;
+    _caminfo_option = option;
+    if (user_caminfo) {
+        CamInfoList = user_caminfo;
+    } else {
+        CamInfoList = getCamInfoList();
+    }
+    clearOnResult();
+    host = USBHost::getHostInst();
+    m_isoEp = new IsochronousEp;
+    init();
+}
+
+void USBHostCam::init()
+{
+    CAM_DBG("");
+    dev_connected = false;
+    dev = NULL;
+    cam_intf = -1;
+    device_found = false;
+    caminfo_found = false;
+}
+
+bool USBHostCam::connected()
+{
+    return dev_connected;
+}
+
+bool USBHostCam::connect()
+{
+    if (dev_connected) {
+        return true;
+    }
+
+    for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+            
+            CAM_DBG("Trying to connect Cam device\r\n");
+            
+            if(host->enumerate(dev, this)) {
+                break;
+            }
+            if (device_found) {
+                USB_INFO("New Cam: %s device: VID:%04x PID:%04x [dev: %p - intf: %d]", caminfo->name, dev->getVid(), dev->getPid(), dev, cam_intf);
+                dev->setName(caminfo->name, cam_intf);
+                host->registerDriver(dev, cam_intf, this, &USBHostCam::onDisconnect);
+                int addr = dev->getAddress();
+                m_isoEp->init(addr, caminfo->en, caminfo->mps, caminfo->frameCount, caminfo->queueLimit);
+                uint8_t buf[26];
+                memset(buf, 0, sizeof(buf));
+                buf[2] = caminfo->formatIndex;
+                buf[3] = caminfo->frameIndex;
+                *reinterpret_cast<uint32_t*>(buf+4) = caminfo->interval;
+                USB_TYPE res = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, sizeof(buf));
+                if (res != USB_TYPE_OK) {
+                    CAM_DBG("SET_CUR VS_COMMIT_CONTROL FAILED");
+                }
+                res = setInterfaceAlternate(1, caminfo->if_alt);
+                if (res != USB_TYPE_OK) {
+                    CAM_DBG("SET_INTERFACE FAILED");
+                }
+                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
+
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+void USBHostCam::onDisconnect()
+{
+    CAM_DBG("dev_connected: %d", dev_connected);
+    if (dev_connected) {
+        m_isoEp->disconnect();
+        init();
+    }
+}
+
+/*virtual*/ void USBHostCam::setVidPid(uint16_t vid, uint16_t pid)
+{
+    CAM_DBG("vid:%04x,pid:%04x", vid, pid);
+    caminfo = CamInfoList;
+    while(caminfo->vid != 0) {
+        if (caminfo->vid == vid && caminfo->pid == pid && 
+            caminfo->size == _caminfo_size && caminfo->option == _caminfo_option) {
+            caminfo_found = true;
+            break;
+        }
+        caminfo++;
+    }
+}
+
+/*virtual*/ bool USBHostCam::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    CAM_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol);
+    if ((cam_intf == -1) && caminfo_found) {
+        cam_intf = intf_nb;
+        device_found = true;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostCam::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    CAM_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir);
+    return false;
+}
+
+#define SEQ_READ_IDOL 0
+#define SEQ_READ_EXEC 1
+#define SEQ_READ_DONE 2
+
+int USBHostCam::readJPEG(uint8_t* buf, int size, int timeout_ms) {
+    _buf = buf;
+    _pos = 0;
+    _size = size;
+    _seq = SEQ_READ_IDOL;
+    setOnResult(this, &USBHostCam::callback_motion_jpeg);
+    Timer timeout_t;
+    timeout_t.reset();
+    timeout_t.start();
+    while(timeout_t.read_ms() < timeout_ms && _seq != SEQ_READ_DONE && connected()) {
+        poll();
+        Thread::wait(1);
+    } 
+    return _pos;
+}
+
+/* virtual */ void USBHostCam::outputJPEG(uint8_t c, int status) { // from decodeMJPEG
+    if (_seq == SEQ_READ_IDOL) {
+        if (status == JPEG_START) {
+            _pos = 0;
+            _seq = SEQ_READ_EXEC;
+        }
+    }
+    if (_seq == SEQ_READ_EXEC) {
+        if (_pos < _size) {
+            _buf[_pos++] = c;  
+        }  
+        if (status == JPEG_END) {
+            _seq = SEQ_READ_DONE;
+        }
+    }
+}
+
+void USBHostCam::callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
+        inputPacket(buf, len);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostCam/USBHostCam.h	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,101 @@
+// USBHostCam.h
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "USBIsochronous.h"
+#include "BaseUvc.h"
+#include "decodeMJPEG.h"
+#pragma once
+
+#define _160x120 2
+#define _176x144 3
+#define _320x176 4
+#define _320x240 5
+#define _352x288 6
+#define _432x240 7
+#define _640x480 1
+#define _544x288 8
+#define _640x360 9
+#define _752x416 10
+#define _800x448 11
+#define _800x600 12
+
+#define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+
+struct CamInfo {
+    uint16_t vid;
+    uint16_t pid;
+    uint8_t size;
+    uint8_t option;
+//
+    const char* name;
+    uint8_t formatIndex;
+    uint8_t frameIndex;
+    uint32_t interval;
+    uint8_t en;
+    uint8_t mps;
+    uint8_t if_alt;
+    uint8_t frameCount; // ITD frame count 1-8
+    uint8_t queueLimit; // ITD queue limit 1-3
+};
+
+/** 
+ * A class to communicate a Cam
+ */
+class USBHostCam : public IUSBEnumerator, public BaseUvc, public decodeMJPEG {
+public:
+    /**
+    * Constructor
+    *
+    */
+    USBHostCam(uint8_t size = _160x120, uint8_t option = 0, CamInfo* user_caminfo = NULL);
+
+    /**
+    * Check if a Cam device is connected
+    *
+    * @return true if a Cam device is connected
+    */
+    bool connected();
+
+    /**
+     * Try to connect to a Cam device
+     *
+     * @return true if connection was successful
+     */
+    bool connect();
+
+    /**
+     * read jpeg image
+     *
+     * @param buf read buffer 
+     * @param size buffer size 
+     * @param timeout_ms timeout default 15sec
+     * @return jpeg size if read success else -1
+     */
+    int readJPEG(uint8_t* buf, int size, int timeout_ms = 15*1000);
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+    bool dev_connected;
+
+    int cam_intf;
+    bool device_found;
+    bool caminfo_found;
+    uint8_t _seq;
+    uint8_t* _buf;
+    int _pos;
+    int _size;
+    CamInfo* CamInfoList;
+    CamInfo* caminfo;
+    uint8_t _caminfo_size;
+    uint8_t _caminfo_option;
+
+    virtual void outputJPEG(uint8_t c, int status); // from decodeMJPEG
+    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len);
+    void init();
+    void onDisconnect();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,74 @@
+/*
+ * see: http://mbed.org/users/okini3939/notebook/wifi_webcam/
+ *
+ * using: http://mbed.org/users/va009039/code/USBHostC270_example/
+ * using: http://mbed.org/users/gsfan/code/GSwifiInterface/
+ */
+
+#include "mbed.h"
+#include "GSwifiInterface.h"
+#include "USBHostC270.h"
+
+#define SEC  GSwifi::SEC_OPEN
+#define SSID "MBED"
+#define PASS "1234567890"
+#define MODE GSwifi::WM_LIMITEDAP
+
+DigitalOut led1(LED1), led2(LED2), led3(LED3);
+Serial pc(USBTX, USBRX);
+LocalFileSystem local("local");
+GSwifiInterface *gs;
+
+int main() {
+    Timer t;
+
+    pc.baud(115200);
+    pc.printf("GSwifi_ap_webcam\r\n");
+
+    gs = new GSwifiInterface(p13, p14, p12, P0_22, p20, NC, 115200);
+    wait_ms(300);
+//    gs->init(); //Use DHCP
+    gs->init("192.168.1.1", "255.255.255.0", "192.168.1.1", "192.168.1.1", "www.mbed");
+    if (gs->connect(SEC, SSID, PASS, MODE)) return -1; // join the network
+    NVIC_SetPriority(UART1_IRQn, 1);
+    printf("IP Address is %s\r\n", gs->getIPAddress());
+
+    gs->httpd();
+    gs->httpdAttach("/", "/local/");
+
+    USBHostC270* cam = new USBHostC270(C270_MJPEG, C270_160x120, _10FPS); // Logitech C270
+//    USBHostC270* cam = new USBHostC270(C270_MJPEG, C270_320x240, _5FPS); // Logitech C270
+
+    t.start();
+    led1 = 1;
+    for (;;) {
+        gs->poll();
+
+        if (!cam->connected()) {
+            led2 = 1;
+            if (t.read() > 0.5) {
+                cam->connect();
+                if (cam->connected()) printf("webcam has detected\r\n");
+                t.reset();
+            }
+        } else {
+            led2 = 0;
+            cam->poll();
+            if (t.read() > 10) {
+                led3 = 1;
+                uint8_t buf[1024*8];
+                int r = cam->readJPEG(buf, sizeof(buf));
+                if (r) {
+                    FILE* fp = fopen("/local/photo.jpg", "wb");
+                    if (fp) {
+                        fwrite(buf, r, 1, fp);
+                        fclose(fp);
+                    }
+                    printf("took a picture\r\n");
+                }
+                t.reset();
+                led3 = 0;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Jun 06 00:44:06 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/0b3ab51c8877
\ No newline at end of file