USB host library, support isochronous,bulk,interrupt and control.

Dependents:   BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example

Import programBaseUsbHost_example

BaseUsbHost example program

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Sun Jan 06 11:45:18 2013 +0000
Parent:
2:fe1e62051d88
Child:
4:d931d24c2f81
Commit message:
change interface usbhub class

Changed in this revision

BaseUsbHost.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbHost.h Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostBlkEp.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostCtlEp.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostDebug.h Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostHub.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostIntEp.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostIsoEp.cpp Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostTest.h Show annotated file Show diff for this revision Revisions of this file
BaseUsbHostUvc.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BaseUsbHost.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHost.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHost.cpp 2012/12/4
+// BaseUsbHost.cpp 2012/12/25
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -95,8 +95,6 @@
     }
     LPC_USB->HcHCCA = (uint32_t)pHcca;
     LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
-
-    //LPC_USB->HcInterruptEnable  = MIE|WDH|RHSC|FNO;
     LPC_USB->HcInterruptEnable  = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
 
     LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
@@ -212,6 +210,77 @@
     ed->Control |= size<<16;
 }
 
+int BaseEp::transfer(uint8_t* buf, int len)
+{
+    HCTD* data_td = m_pED->TailTd;
+    TEST_ASSERT(data_td);
+    if (data_td == NULL) {
+        return USB_ERROR;
+    }
+    data_td->CurrBufPtr = buf;
+    data_td->buf_top = buf;
+    data_td->buf_size = len;
+    data_td->BufEnd = const_cast<uint8_t*>(buf)+len-1;
+    HCTD* blank_td = new_HCTD();
+    TEST_ASSERT(blank_td);
+    if (blank_td == NULL) {
+        return USB_ERROR_MEMORY;
+    }
+    data_td->Next = reinterpret_cast<uint32_t>(blank_td);
+    m_pED->TailTd = blank_td;
+    enable();
+    return USB_PROCESSING;
+}
+
+int BaseEp::status(uint32_t millisec)
+{
+    HCTD* td = get_queue_HCTD(millisec);
+    if (td == NULL) {
+        return USB_PROCESSING;
+    }
+    uint8_t cc = td->Control>>28;
+    int ret;
+    switch(cc) {
+        case 0:
+        case 8:
+        case 9:
+            ret = td->buf_size;
+            if (td->CurrBufPtr) {
+                ret = td->CurrBufPtr - td->buf_top;
+            }
+            break;
+        case 4:
+            ret = USB_ERROR_STALL;
+            break;
+        case 5:
+            ret = USB_ERROR_DEVICE_NOT_RESPONDING;
+            break;
+        default:
+            DBG("ConditionCode=%d\n", cc);
+            ret = USB_ERROR;
+            break;
+    }
+    delete_HCTD(td); 
+    return ret;
+}
+
+int BaseEp::send_receive(uint8_t* buf, int len, int millisec)
+{
+    if (m_td_queue_count == 0) {
+        int rc = transfer(buf, len);
+        if (rc != USB_PROCESSING) {
+            return rc;
+        }
+        m_td_queue_count++;
+    }
+    
+    int ret = status(millisec);
+    if (ret != USB_PROCESSING) {
+        m_td_queue_count--;
+    }
+    return ret;
+}
+
 HCTD* BaseEp::new_HCTD(int buf_size)
 {
     HCTD* td;
@@ -269,9 +338,15 @@
         HCTD* td = get_queue_HCTD(millisec);
         if (td) {
             if (td->Control & TD_CC) {
+                uint8_t cc = td->Control>>28;
                 DBG_TD(td);
                 delete_HCTD(td);
-                return USB_ERROR;
+                switch(cc) {
+                    case 4:
+                        return USB_ERROR_STALL; 
+                    default:
+                        return USB_ERROR;
+                }
             }
             delete_HCTD(td);
             if (td == wait_td) {
--- a/BaseUsbHost.h	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHost.h	Sun Jan 06 11:45:18 2013 +0000
@@ -1,11 +1,13 @@
-// BaseUsbHost.h 2012/12/11
-#ifndef BASE_USB_HOST_H
-#define BASE_USB_HOST_H
+// BaseUsbHost.h 2013/1/5
+#pragma once
+#include <vector>
 
 #define USB_OK            0
 #define USB_PROCESSING   -1
 #define USB_ERROR        -2
 #define USB_ERROR_MEMORY -3
+#define USB_ERROR_STALL  -4
+#define USB_ERROR_DEVICE_NOT_RESPONDING -5
 
 // USB STANDARD REQUEST DEFINITIONS
 #define  USB_DESCRIPTOR_TYPE_DEVICE         1
@@ -29,6 +31,69 @@
 #define  GET_DESCRIPTOR          6
 #define  SET_CONFIGURATION       9
 #define  SET_INTERFACE           11
+
+#pragma pack(push,1)
+typedef struct {                // offset 
+    uint8_t bLength;            // +0
+    uint8_t bDescriptorType;    // +1
+    uint16_t bcdUSB;            // +2
+    uint8_t bDeviceClass;       // +4
+    uint8_t bDeviceSubClass;    // +5
+    uint8_t bDeviceProtocol;    // +6
+    uint8_t bMaxPacketSize;     // +7
+    uint16_t idVendor;          // +8
+    uint16_t idProduct;         // +10
+    uint16_t bcdDevice;         // +12
+    uint8_t iManufacturer;      // +14
+    uint8_t iProduct;           // +15
+    uint8_t iSerialNumber;      // +16
+    uint8_t bNumConfigurations; // +17
+} StandardDeviceDescriptor;     // +18
+
+typedef struct {                   // offset
+    uint8_t bLength;               // +0
+    uint8_t bDescriptorType;       // +1
+    uint16_t wTotalLength;         // +2
+    uint8_t bNumInterfaces;        // +4
+    uint8_t bConfigurationValue;   // +5
+    uint8_t iConfiguration;        // +6
+    uint8_t bmAttributes;          // +7
+    uint8_t bMaxPower;             // +8
+} StandardConfigurationDescriptor; // +9
+
+typedef struct {               // offset
+    uint8_t bLength;           // +0      
+    uint8_t bDescriptorType;   // +1
+    uint8_t bInterfaceNumber;  // +2
+    uint8_t bAlternateSetting; // +3
+    uint8_t bNumEndpoints;     // +4
+    uint8_t bInterfaceClass;   // +5
+    uint8_t bInterfaceSubClass;// +6
+    uint8_t bInterfaceProtocol;// +7
+    uint8_t iInterface;        // +8
+} StandardInterfaceDescriptor; // +9
+
+typedef struct {              // offset
+    uint8_t bLength;          // +0
+    uint8_t bDescriptorType;  // +1
+    uint8_t bEndpointAddress; // +2
+    uint8_t bmAttributes;     // +3
+    uint16_t wMaxPacketSize;  // +4
+    uint8_t bInterval;        // +6
+} StandardEndpointDescriptor; // +7
+
+typedef struct {              // offset
+    uint8_t bDescLength;      // +0
+    uint8_t bDescriptorType;  // +1
+    uint8_t bNbrPorts;        // +2
+    uint16_t wHubCharacteristics;// +3
+    uint8_t bPwrOn2PwrGood;   // +5
+    uint8_t bHubContrCurrent; // +6
+    uint8_t DeviceRemovable;  // +7
+    uint8_t PortPweCtrlMak;   // +8
+} HubDescriptor;              // +9
+#pragma pack(pop)
+
 // ------------------ HcControl Register ---------------------
 #define  OR_CONTROL_PLE                 0x00000004
 #define  OR_CONTROL_IE                  0x00000008
@@ -109,22 +174,20 @@
     uint32_t Next;         // +12 Physical address of next Endpoint descriptor
 } HCED;
 
-#define DELETE_TD(A) free(A)
-#define DELETE_ITD(A) free(A)
-
 class BaseUsbHost {
 public:
     BaseUsbHost();
-    void init_hw_ohci(HCCA* pHcca);
-    void ResetRootHub();
     void irqHandler();
-    HCCA* m_pHcca;
     // report
     uint32_t m_report_irq; 
     uint32_t m_report_RHSC;
     uint32_t m_report_FNO; 
     uint32_t m_report_WDH;  
     uint32_t m_report_sp;
+private:
+    void init_hw_ohci(HCCA* pHcca);
+    void ResetRootHub();
+    HCCA* m_pHcca;
 };
 
 #define HCTD_QUEUE_SIZE 3
@@ -136,25 +199,28 @@
     int GetLowSpeed();
     void update_FunctionAddress(int addr);
     void update_MaxPacketSize(uint16_t size);
+    int transfer(uint8_t* buf, int len);
+    int status(uint32_t millisec=osWaitForever);
     //
+    virtual void enable() = 0;
     HCTD* new_HCTD(int buf_size=0);
     void delete_HCTD(HCTD* p);
-    HCED* m_pED;
-    // TD done queue
-    virtual void irqWdhHandler(HCTD* td) = 0; // WDH
-    HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever);
+    virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} // WDH
     int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever);
-    Queue<HCTD, HCTD_QUEUE_SIZE> m_queue;
-    int m_td_queue_count;
     // report
     uint8_t m_ConditionCode;
     int m_report_queue_error;
+protected:
+    int send_receive(uint8_t* buf, int len, int millisec);
+    HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever);
+    HCED* m_pED;
+    Queue<HCTD, HCTD_QUEUE_SIZE> m_queue; // TD done queue
+    int m_td_queue_count;
 };
 
 class ControlEp : public BaseEp {
 public:
     ControlEp(int lowSpeed = 0);
-    virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);}
     int GetDescriptor(int descType, int descIndex, uint8_t* data, int length);
     int SetAddress(int addr); // device address 
     int SetConfiguration(int config);
@@ -163,59 +229,60 @@
     int GetInterface(int interface, int *alternate);
     int controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex=0, const uint8_t* data=NULL, int length=0);
     int controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t* data, int length);
-    //
+private:
     int open(int addr);
     void setup(HCTD* td, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex=0, uint16_t wLength=0);
+    virtual void enable(){};
 };
 
 class BulkEp : public BaseEp {
 public:
     BulkEp(int addr, uint8_t ep, uint16_t size);
-    virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);}
     int bulkSend(const uint8_t* buf, int len, int millisec=osWaitForever);
     int bulkReceive(uint8_t* buf, int len, int millisec=osWaitForever);
+private:
+    virtual void enable();
 };
 
 class InterruptEp : public BaseEp {
 public:
     InterruptEp(int addr, uint8_t ep, uint16_t size, int lowSpeed=0);
     int interruptReceive(uint8_t* buf, int len, int millisec=osWaitForever);
-    virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);}
+private:
+    virtual void enable();
 };
 
 class IsochronousEp : public BaseEp {
 public:
     IsochronousEp(int addr, uint8_t ep, uint16_t size);
-    virtual void irqWdhHandler(HCTD* td);
-    void reset();
+    void reset(int delay_ms = 100);
     HCITD* isochronousReveive(int millisec=osWaitForever);
     int isochronousSend(uint8_t* buf, int len, int millisec=osWaitForever);
+    HCITD* get_queue_HCITD(int millisec);
+    int m_PacketSize; // 128,192
+private:
     HCITD* new_HCITD();
-    HCITD* get_queue_HCITD(int millisec);
     int m_itd_queue_count;
     uint16_t m_FrameNumber;
-    int m_PacketSize; // 128,192
     int m_FrameCount; // 1-8
+    virtual void enable();
 };
 
 // --- HUB --------------------------------------------------
-#define MAX_HUB_PORT 4
-
 class UsbHub {
 public:
     UsbHub(ControlEp* ctlEp = NULL);
-    ControlEp* GetPortEp(int port); // port: 1-4
+    static bool check(ControlEp* ctlEp);
     int SetPortPower(int port);
     int ClearPortPower(int port);
-protected:
-    void DeviceConnected(int port, int low_speed);
+    vector<ControlEp*> PortEp;
+private:
     int PortReset(int port);
     int SetPortFeature(int feature, int index);
     int ClearPortFeature(int feature, int index);
     int SetPortReset(int port);
     int GetPortStatus(int port, uint32_t* status);
     ControlEp* m_ctlEp;
-    ControlEp* PortEp[MAX_HUB_PORT]; // port endpoint(control) 
 };
 
 // --- UVC --------------------------------------------------
@@ -263,5 +330,3 @@
     void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int);
     void (*m_pCb)(uint16_t, uint8_t*, int);
 };
-
-#endif //BASE_USB_HOST_H
--- a/BaseUsbHostBlkEp.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostBlkEp.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -1,8 +1,8 @@
-// BaseUsbHostBlkEp.cpp 2012/12/11
+// BaseUsbHostBlkEp.cpp 2012/12/24
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-//#define DEBUG
+#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
@@ -18,85 +18,23 @@
     }
     m_pED->Next = LPC_USB->HcBulkHeadED;
     LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(m_pED);
-    
+  
     DBG_OHCI(LPC_USB->HcBulkHeadED);
     DBG_ED(m_pED);
+}
 
+void BulkEp::enable()
+{
     LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
     LPC_USB->HcControl |= OR_CONTROL_BLE;
 }
 
 int BulkEp::bulkReceive(uint8_t* buf, int len, int millisec)
 {
-    if (m_td_queue_count == 0) {
-        HCTD* data_td = m_pED->TailTd;
-        TEST_ASSERT(data_td);
-        if (data_td == NULL) {
-            return USB_ERROR;
-        }
-        data_td->Control |= TD_IN;
-        data_td->CurrBufPtr = buf;
-        data_td->BufEnd = const_cast<uint8_t*>(buf)+len-1;
-        HCTD* blank_td = new_HCTD();
-        TEST_ASSERT(blank_td);
-        if (blank_td == NULL) {
-            return USB_ERROR_MEMORY;
-        }
-        data_td->Next = reinterpret_cast<uint32_t>(blank_td);
-        m_pED->TailTd = blank_td;
-        m_td_queue_count++;
-        DBG_ED(m_pED);
-        LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
-        LPC_USB->HcControl |= OR_CONTROL_BLE;
-    }
-    
-    HCTD* td = get_queue_HCTD(millisec);
-    if (td == NULL) {
-        return USB_PROCESSING;
-    }
-    DBG_TD(td);
-    int ret = len;
-    if (td->CurrBufPtr) {
-        ret = td->CurrBufPtr - buf;
-    }
-    delete_HCTD(td); 
-    m_td_queue_count--;
-    return ret;
+    return send_receive(buf, len, millisec);
 }
 
 int BulkEp::bulkSend(const uint8_t* buf, int len, int millisec)
 {
-    HCTD* data_td = m_pED->TailTd;
-    TEST_ASSERT(data_td);
-    if (data_td == NULL) {
-        return USB_ERROR;
-    }
-    data_td->Control |= TD_OUT;
-    data_td->CurrBufPtr = const_cast<uint8_t*>(buf);
-    data_td->BufEnd = const_cast<uint8_t*>(buf)+len-1;
-    HCTD* blank_td = new_HCTD();
-    TEST_ASSERT(blank_td);
-    if (blank_td == NULL) {
-        return USB_ERROR_MEMORY;
-    }
-    data_td->Next = reinterpret_cast<uint32_t>(blank_td);
-    m_pED->TailTd = blank_td;
-    m_td_queue_count++;
-    DBG_ED(m_pED);
-    
-    LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
-    LPC_USB->HcControl |= OR_CONTROL_BLE;
- 
-    HCTD* td = get_queue_HCTD(millisec);
-    if (td) {
-        DBG_TD(td);
-        int ret = len;
-        if (td->CurrBufPtr) {
-            ret = td->CurrBufPtr - buf;
-        }
-        delete_HCTD(td); 
-        m_td_queue_count--;
-        return ret;
-    }
-    return USB_ERROR;
+    return send_receive(const_cast<uint8_t*>(buf), len, millisec);
 }
--- a/BaseUsbHostCtlEp.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostCtlEp.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHostCtlEp.cpp 2012/12/5
+// BaseUsbHostCtlEp.cpp 2013/1/2
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -99,7 +99,6 @@
     HCTD* data_td = new_HCTD(length);
     TEST_ASSERT(data_td);
     data_td->Control |= TD_TOGGLE_1|TD_IN|TD_DI; 
-    //data_td->Control |= TD_IN|TD_DI; 
     setup_td->Next = reinterpret_cast<uint32_t>(data_td);
 
     HCTD* status_td = new_HCTD();
@@ -117,6 +116,9 @@
 
     int r = wait_queue_HCTD(setup_td, 100); // wait setup stage
     TEST_ASSERT(r == USB_OK);
+    if (r != USB_OK) {
+        return r;
+    }
     HCTD* td = get_queue_HCTD(100);
     if (td == data_td) {
         memcpy(data, const_cast<uint8_t*>(td->buf), length);
@@ -180,4 +182,3 @@
     td->CurrBufPtr = td->setup;
     td->BufEnd = td->setup+8-1;
 }
-
--- a/BaseUsbHostDebug.h	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostDebug.h	Sun Jan 06 11:45:18 2013 +0000
@@ -1,6 +1,6 @@
-// BaseUsbHostDebug.h 2012/12/2
-#ifndef BASE_USB_HOST_DEBUG_H
-#define BASE_USB_HOST_DEBUG_H
+// BaseUsbHostDebug.h 2013/1/2
+#pragma once
+
 #ifdef DEBUG
 #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
 #define DBG_PRINTF(...) do{fprintf(stderr,__VA_ARGS__);}while(0);
@@ -29,5 +29,3 @@
 void print_ied(FILE* stream, HCED* ed);
 void print_bytes(FILE* stream, char* s, uint8_t* buf, int len);
 void print_hex(FILE* stream, uint8_t* p, int len);
-
-#endif //BASE_USB_HOST_DEBUG_H
--- a/BaseUsbHostHub.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostHub.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHostHub.cpp 2012/12/11
+// BaseUsbHostHub.cpp 2013/1/6
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -7,26 +7,22 @@
 #define TEST
 #include "BaseUsbHostTest.h"
 
-#define PORT_CONNECTION 0
-#define PORT_ENABLE  1
-#define PORT_SUSPEND  2
+#define PORT_CONNECTION   0
+#define PORT_ENABLE       1
+#define PORT_SUSPEND      2
 #define PORT_OVER_CURRENT 3
-#define PORT_RESET 4
-#define PORT_POWER 8
-#define PORT_LOW_SPEED 9
+#define PORT_RESET        4
+#define PORT_POWER        8
+#define PORT_LOW_SPEED    9
 
-#define C_PORT_CONNECTION 16
-#define C_PORT_ENABLE 17
-#define C_PORT_SUSPEND 18
+#define C_PORT_CONNECTION   16
+#define C_PORT_ENABLE       17
+#define C_PORT_SUSPEND      18
 #define C_PORT_OVER_CURRENT 19
-#define C_PORT_RESET 20
+#define C_PORT_RESET        20
 
 UsbHub::UsbHub(ControlEp* ctlEp)
 {
-    for(int i = 0; i < MAX_HUB_PORT; i++) {
-        PortEp[i] = NULL;
-    }
-    
     if (ctlEp == NULL) {
         DBG_OHCI(LPC_USB->HcRhPortStatus1);
         int lowSpeed = 0;
@@ -39,7 +35,11 @@
         m_ctlEp = ctlEp;
     }
     uint8_t desc[9];
-    m_ctlEp->GetDescriptor(1, 0, desc, sizeof(desc));
+    int rc = m_ctlEp->GetDescriptor(1, 0, desc, sizeof(desc));
+    TEST_ASSERT(rc == USB_OK);
+    if (rc != USB_OK) {
+        return;
+    }
     DBG_HEX(desc, sizeof(desc));
     TEST_ASSERT_TRUE(desc[0] == 0x12);
     TEST_ASSERT_TRUE(desc[1] == 0x01);
@@ -47,44 +47,65 @@
     if (desc[4] != 0x09) { // hub ?
         return;
     }
+    CTASSERT(sizeof(HubDescriptor) == 9);
+    TEST_ASSERT(sizeof(HubDescriptor) == 9);
+    HubDescriptor hubdesc;
+    rc = m_ctlEp->controlReceive(0xa0, 6, 0x29<<8, 0, reinterpret_cast<uint8_t*>(&hubdesc), sizeof(HubDescriptor));
+    TEST_ASSERT(rc == USB_OK);
+    if (rc != USB_OK) {
+        return;
+    }
+    TEST_ASSERT(hubdesc.bDescLength == 9); // length
+    TEST_ASSERT(hubdesc.bDescriptorType == 0x29); // hub
+    TEST_ASSERT(hubdesc.bNbrPorts >= 1);
+    TEST_ASSERT(hubdesc.bNbrPorts <= 7);
 
-    m_ctlEp->controlReceive(0xa0, 6, 0x29<<8, 0, desc, sizeof(desc));
-    DBG_HEX(desc, sizeof(desc));
-    TEST_ASSERT_TRUE(desc[0] == 9); // length
-    TEST_ASSERT_TRUE(desc[1] == 0x29); // hub
-    int bNbrPorts = desc[2];
-    TEST_ASSERT_TRUE(bNbrPorts <= MAX_HUB_PORT);
     m_ctlEp->SetConfiguration(1);
 
     uint32_t status;
-    m_ctlEp->controlReceive(0xa0, 0, 0, 0, (uint8_t*)&status, 4);
+    rc = m_ctlEp->controlReceive(0xa0, 0, 0, 0, reinterpret_cast<uint8_t*>(&status), 4);
+    TEST_ASSERT(rc == USB_OK);
+    if (rc != USB_OK) {
+        return;
+    }
     DBG("HUB STATUS: %08X\n", status);
 
-    for(int i = 1; i <= bNbrPorts; i++) {
+    for(int i = 1; i <= hubdesc.bNbrPorts; i++) {
         SetPortPower(i); // power on
+        wait_ms(hubdesc.bPwrOn2PwrGood*2);
         uint32_t status;
         GetPortStatus(i, &status);
         DBG("port: %d status: %08X\n", i, status);
         if (status & 0x010000) { // Connect Status Change, has changed
             TEST_ASSERT(status & 0x000001);
             ClearPortFeature(C_PORT_CONNECTION, i);
-            bool low_speed = false;
+            int lowSpeed = 0;
             if (status & 0x0200) {
-                low_speed = true;
+                lowSpeed = 1;
             }
-            DeviceConnected(i, low_speed);
+            PortReset(i);
+            ControlEp* ctlEp = new ControlEp(lowSpeed);
+            PortEp.push_back(ctlEp);
         } else {
-            ClearPortPower(i); // power on
+            ClearPortPower(i); // power off
         }
     }
 }
 
-ControlEp* UsbHub::GetPortEp(int port)
+bool UsbHub::check(ControlEp* ctlEp)
 {
-    if (port >= 1 && port <= MAX_HUB_PORT) {
-        return PortEp[port-1];
+    if (ctlEp == NULL) {
+        return false;
     }
-    return NULL;
+    StandardDeviceDescriptor desc;
+    int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, reinterpret_cast<uint8_t*>(&desc), sizeof(StandardDeviceDescriptor));
+    if (rc != USB_OK) {
+        return false;
+    }
+    if (desc.bDeviceClass == 9) { // hub?
+        return true;
+    }
+    return false;
 }
 
 int UsbHub::SetPortPower(int port)
@@ -117,17 +138,6 @@
     return m_ctlEp->controlReceive(0xa3, GET_STATUS, 0, port, (uint8_t*)status, 4);
 }
 
-void UsbHub::DeviceConnected(int port, int low_speed)
-{
-    DBG("port=%d low_speed=%d\n", port, low_speed);
-    PortReset(port);
-    ControlEp* ctlEp = new ControlEp(low_speed);
-    TEST_ASSERT_TRUE(ctlEp);
- 
-    PortEp[port-1] = ctlEp;
-    DBG("PortEp[%d]: %p\n", port-1, PortEp[port-1]);
-}
-
 int UsbHub::PortReset(int port)
 {
     DBG("%p port=%d\n", this, port);
--- a/BaseUsbHostIntEp.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostIntEp.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHostIntEp.cpp 2012/12/11
+// BaseUsbHostIntEp.cpp 2012/12/24
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -11,8 +11,8 @@
     :BaseEp(addr, ep, size, lowSpeed)
 {
     HCTD* td = new_HCTD();
+    m_pED->HeadTd = td; 
     m_pED->TailTd = td;
-    m_pED->HeadTd = td; 
     TEST_ASSERT(td);
     if (td == NULL) {
         return;
@@ -25,42 +25,16 @@
     int n = 0;
     m_pED->Next = pHcca->InterruptTable[n];
     pHcca->InterruptTable[n] = reinterpret_cast<uint32_t>(m_pED);
+
+    DBG_ED(m_pED);
+}
+
+void InterruptEp::enable()
+{
     LPC_USB->HcControl |= OR_CONTROL_PLE;
 }
     
 int InterruptEp::interruptReceive(uint8_t* buf, int len, int millisec)
 {
-    if (m_td_queue_count == 0) {
-        HCTD* data_td = m_pED->TailTd;
-        TEST_ASSERT(data_td);
-        if (data_td == NULL) {
-            return USB_ERROR;
-        }
-        data_td->Control |= TD_IN;
-        data_td->CurrBufPtr = buf;
-        data_td->BufEnd = const_cast<uint8_t*>(buf)+len-1;
-        HCTD* blank_td = new_HCTD();
-        TEST_ASSERT(blank_td);
-        if (blank_td == NULL) {
-            return USB_ERROR_MEMORY;
-        }
-        data_td->Next = reinterpret_cast<uint32_t>(blank_td);
-        m_pED->TailTd = blank_td;
-        m_td_queue_count++;
-        DBG_ED(m_pED);
-        LPC_USB->HcControl |= OR_CONTROL_PLE; // Enable Periodic
-    }
-        
-    HCTD* td = get_queue_HCTD(millisec);
-    if (td == NULL) {
-        return USB_PROCESSING;
-    }
-    DBG_TD(td);
-    int ret = len;
-    if (td->CurrBufPtr) {
-        ret = td->CurrBufPtr - buf;
-    }
-    delete_HCTD(td); 
-    m_td_queue_count--;
-    return ret;
+    return send_receive(buf, len, millisec);
 }
--- a/BaseUsbHostIsoEp.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostIsoEp.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHostIsoEp.cpp 2012/12/11
+// BaseUsbHostIsoEp.cpp 2012/12/31
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -46,18 +46,9 @@
     DBG_ED(m_pED);
 }
 
-void IsochronousEp::reset()
+void IsochronousEp::reset(int delay_ms)
 {
-    m_FrameNumber = LPC_USB->HcFmNumber + 100; // 100msec
-}
-
-void IsochronousEp::irqWdhHandler(HCTD* td)
-{
-    osStatus st = m_queue.put(td);
-    if (st != osOK) {
-        //led4_error = 1;
-    }
-    //led2 = !led2;
+    m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
 }
 
 HCITD* IsochronousEp::new_HCITD()
@@ -89,7 +80,6 @@
     return itd;
 }
 
-
 HCITD* IsochronousEp::isochronousReveive(int millisec)
 {
     TEST_ASSERT(m_itd_queue_count >= 0);
@@ -108,7 +98,7 @@
         m_pED->TailTd = reinterpret_cast<HCTD*>(blank_itd);
         m_itd_queue_count++;
         //DBG_IED(m_pED);
-        LPC_USB->HcControl |= OR_CONTROL_PLE; // Enable Periodic
+        enable(); // Enable Periodic
     }
     
     HCITD* itd = get_queue_HCITD(millisec);
@@ -145,3 +135,8 @@
     }
     return NULL;
 }
+
+void IsochronousEp::enable()
+{
+    LPC_USB->HcControl |= OR_CONTROL_PLE;
+}
--- a/BaseUsbHostTest.h	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostTest.h	Sun Jan 06 11:45:18 2013 +0000
@@ -1,6 +1,12 @@
-// BaseUsbHostTest.h 2012/12/2
-#ifndef BASE_USB_HOST_TEST_H
-#define BASE_USB_HOST_TEST_H
+// BaseUsbHostTest.h 2013/1/5
+#pragma once
+
+#ifndef CTASSERT
+template <bool>struct CtAssert;
+template <>struct CtAssert<true> {};
+#define CTASSERT(A) CtAssert<A>();
+#endif //CTASSERT
+
 #ifdef TEST
 #define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
 #define TEST_ASSERT_TRUE(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
@@ -12,4 +18,3 @@
 #define TEST_ASSERT_FALSE(A) while(0);
 #define TEST_ASSERT_EQUAL(A,B) while(0);
 #endif
-#endif // BASE_USB_HOST_TEST_H
--- a/BaseUsbHostUvc.cpp	Tue Dec 11 15:26:54 2012 +0000
+++ b/BaseUsbHostUvc.cpp	Sun Jan 06 11:45:18 2013 +0000
@@ -17,7 +17,6 @@
             //DBG_ITD(itd);
             uint16_t frame = itd->Control & 0xffff;
             int fc = ((itd->Control>>24)&7)+1;
-            TEST_ASSERT(fc == m_isoEp->m_FrameCount);
             uint8_t* buf = const_cast<uint8_t*>(itd->buf); 
             int mps = m_isoEp->m_PacketSize;
             for(int i = 0; i < fc; i++) {