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:
Fri Jan 25 14:51:33 2013 +0000
Parent:
3:ae77d63a1eda
Child:
5:8a2d056e9b38
Commit message:
add UsbHub::search()

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.cpp 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
BaseUsbHostUvc.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BaseUsbHost.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHost.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,8 +1,8 @@
-// BaseUsbHost.cpp 2012/12/25
+// BaseUsbHost.cpp 2013/1/25
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-#define DEBUG
+//#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
@@ -35,16 +35,6 @@
     }
 }
 
-inline static void* malloc_align(size_t size, size_t alignment)
-{
-    void* p;
-    int r = posix_memalign(&p, alignment, size);
-    if (r == 0) {
-        return p;
-    }
-    return NULL;
-}
-
 BaseUsbHost::BaseUsbHost()
 {
     if (pHost) {
@@ -53,7 +43,7 @@
     }
     pHost = this;
     NVIC_DisableIRQ(USB_IRQn);
-    m_pHcca = reinterpret_cast<HCCA*>(malloc_align(sizeof(HCCA), 256));
+    m_pHcca = new HCCA();
     TEST_ASSERT(m_pHcca);
     init_hw_ohci(m_pHcca);
     ResetRootHub();
@@ -93,7 +83,7 @@
     for (int i = 0; i < 32; i++) {
         pHcca->InterruptTable[i] = NULL;
     }
-    LPC_USB->HcHCCA = (uint32_t)pHcca;
+    LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca);
     LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
     LPC_USB->HcInterruptEnable  = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
 
@@ -118,8 +108,8 @@
     HCTD* result = NULL;
     HCTD* next;
     while(td) {
-        next = reinterpret_cast<HCTD*>(td->Next);
-        td->Next = reinterpret_cast<uint32_t>(result);
+        next = const_cast<HCTD*>(td->Next);
+        td->Next = result;
         result = td;
         td = next;
     }
@@ -137,18 +127,24 @@
         m_report_FNO++;
     }
     if (status & OR_INTR_STATUS_WDH) {
-        uint32_t done_td = m_pHcca->DoneHead;
+        union {
+            HCTD* done_td;
+            uint32_t lsb;
+        };
+        done_td = const_cast<HCTD*>(m_pHcca->DoneHead);
         TEST_ASSERT(done_td);
         m_pHcca->DoneHead = NULL; // reset
-        if (done_td & 1) { // error ?
-            done_td &= ~1;
+        if (lsb & 1) { // error ?
+            lsb &= ~1;
         }
-        HCTD* td = td_reverse(reinterpret_cast<HCTD*>(done_td));
+        HCTD* td = td_reverse(done_td);
         while(td) {
-            BaseEp* ep = reinterpret_cast<BaseEp*>(td->ep);
+            BaseEp* ep = td->ep;
             TEST_ASSERT(ep);
-            ep->irqWdhHandler(td);
-            td = reinterpret_cast<HCTD*>(td->Next);
+            if (ep) {
+                ep->irqWdhHandler(td);
+            }
+            td = td->Next;
         }
         m_report_WDH++;
     }
@@ -158,36 +154,26 @@
 BaseEp::BaseEp(int addr, uint8_t ep, uint16_t size, int lowSpeed):m_td_queue_count(0)
 {
     DBG("%p FA=%d EN=%02x MPS=%d S=%d\n", this, addr, ep, size, lowSpeed);
-    m_pED  = reinterpret_cast<HCED*>(malloc_align(sizeof(HCED), 16));
-    TEST_ASSERT(m_pED);
     TEST_ASSERT(size >= 8 && size <= 1023);    
     TEST_ASSERT(lowSpeed == 0 || lowSpeed == 1);
-    m_pED->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 */
-    m_pED->Next = NULL;
+    m_pED  = new HCED(addr, ep, size, lowSpeed);
+    TEST_ASSERT(m_pED);
 }
 
 int BaseEp::GetAddr()
 {
-    HCED* ed = m_pED;
-    TEST_ASSERT(ed);
-    if (ed) {
-        return ed->Control & 0x7f;
+    TEST_ASSERT(m_pED);
+    if (m_pED) {
+        return m_pED->FunctionAddress();
     }
     return 0;
 }
 
 int BaseEp::GetLowSpeed()
 {
-    HCED* ed = m_pED;
-    TEST_ASSERT(ed);
-    if (ed) {
-        if (ed->Control & (1<<13)) {
-            return 1;
-        }
+    TEST_ASSERT(m_pED);
+    if (m_pED) {
+        return m_pED->Speed();
     }
     return 0;
 }
@@ -195,19 +181,19 @@
 void BaseEp::update_FunctionAddress(int addr)
 {
     TEST_ASSERT(addr >= 0 && addr <= 127);
-    HCED* ed = m_pED;
-    TEST_ASSERT(ed);
-    ed->Control &= ~0x7f;
-    ed->Control |= addr;
+    TEST_ASSERT(m_pED);
+    if (m_pED) {
+        m_pED->setFunctionAddress(addr);
+    }
 }
 
 void BaseEp::update_MaxPacketSize(uint16_t size)
 {
     TEST_ASSERT(size >= 8 && size <= 1023);
-    HCED* ed = m_pED;
-    TEST_ASSERT(ed);
-    ed->Control &= ~0xffff0000;
-    ed->Control |= size<<16;
+    TEST_ASSERT(m_pED);
+    if (m_pED) {
+        m_pED->setMaxPacketSize(size);
+    }
 }
 
 int BaseEp::transfer(uint8_t* buf, int len)
@@ -217,16 +203,13 @@
     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();
+    data_td->transfer(buf, len);
+    HCTD* blank_td = new HCTD(this);
     TEST_ASSERT(blank_td);
     if (blank_td == NULL) {
         return USB_ERROR_MEMORY;
     }
-    data_td->Next = reinterpret_cast<uint32_t>(blank_td);
+    data_td->Next = blank_td;
     m_pED->TailTd = blank_td;
     enable();
     return USB_PROCESSING;
@@ -238,16 +221,13 @@
     if (td == NULL) {
         return USB_PROCESSING;
     }
-    uint8_t cc = td->Control>>28;
+    uint8_t cc = td->ConditionCode();
     int ret;
     switch(cc) {
         case 0:
         case 8:
         case 9:
-            ret = td->buf_size;
-            if (td->CurrBufPtr) {
-                ret = td->CurrBufPtr - td->buf_top;
-            }
+            ret = td->status();
             break;
         case 4:
             ret = USB_ERROR_STALL;
@@ -260,7 +240,7 @@
             ret = USB_ERROR;
             break;
     }
-    delete_HCTD(td); 
+    delete td; 
     return ret;
 }
 
@@ -281,33 +261,6 @@
     return ret;
 }
 
-HCTD* BaseEp::new_HCTD(int buf_size)
-{
-    HCTD* td;
-    int r = posix_memalign(reinterpret_cast<void**>(&td), 16, sizeof(HCTD) + buf_size);
-    if (r == 0) {
-        td->Control = TD_CC|TD_ROUNDING;
-        td->Next = NULL;
-        td->ep = this;
-        td->buf_top = NULL;
-        td->buf_size = buf_size;
-        if (buf_size == 0) {
-            td->CurrBufPtr = NULL;
-            td->BufEnd = NULL;
-        } else {
-            td->CurrBufPtr = td->buf;
-            td->BufEnd = const_cast<uint8_t*>(td->buf)+buf_size-1;
-        }
-        return td;
-    }
-    return NULL;
-}
-
-void BaseEp::delete_HCTD(HCTD* p)
-{
-    free(p);
-}
-
 HCTD* BaseEp::get_queue_HCTD(uint32_t millisec)
 {
     for(int i = 0; i < 16; i++) {
@@ -315,8 +268,9 @@
         if (evt.status == osEventMessage) {
             HCTD* td = reinterpret_cast<HCTD*>(evt.value.p);
             TEST_ASSERT(td);
-            if (td->Control & TD_CC) {
-                m_ConditionCode = td->Control>>28;
+            uint8_t cc = td->ConditionCode();
+            if (cc != 0) {
+                m_ConditionCode = cc;
                 DBG_TD(td);
             }
             return td;
@@ -337,10 +291,10 @@
     for(int i = 0; i < 16; i++) {
         HCTD* td = get_queue_HCTD(millisec);
         if (td) {
-            if (td->Control & TD_CC) {
-                uint8_t cc = td->Control>>28;
+            uint8_t cc = td->ConditionCode();
+            if (cc != 0) {
                 DBG_TD(td);
-                delete_HCTD(td);
+                delete td;
                 switch(cc) {
                     case 4:
                         return USB_ERROR_STALL; 
@@ -348,7 +302,7 @@
                         return USB_ERROR;
                 }
             }
-            delete_HCTD(td);
+            delete td;
             if (td == wait_td) {
                 return USB_OK;
             }
--- a/BaseUsbHost.h	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHost.h	Fri Jan 25 14:51:33 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHost.h 2013/1/5
+// BaseUsbHost.h 2013/1/24
 #pragma once
 #include <vector>
 
@@ -33,7 +33,7 @@
 #define  SET_INTERFACE           11
 
 #pragma pack(push,1)
-typedef struct {                // offset 
+struct StandardDeviceDescriptor {// offset 
     uint8_t bLength;            // +0
     uint8_t bDescriptorType;    // +1
     uint16_t bcdUSB;            // +2
@@ -48,9 +48,9 @@
     uint8_t iProduct;           // +15
     uint8_t iSerialNumber;      // +16
     uint8_t bNumConfigurations; // +17
-} StandardDeviceDescriptor;     // +18
+};                              // +18
 
-typedef struct {                   // offset
+struct StandardConfigurationDescriptor {// offset
     uint8_t bLength;               // +0
     uint8_t bDescriptorType;       // +1
     uint16_t wTotalLength;         // +2
@@ -59,9 +59,9 @@
     uint8_t iConfiguration;        // +6
     uint8_t bmAttributes;          // +7
     uint8_t bMaxPower;             // +8
-} StandardConfigurationDescriptor; // +9
+};                                 // +9
 
-typedef struct {               // offset
+struct StandardInterfaceDescriptor {// offset
     uint8_t bLength;           // +0      
     uint8_t bDescriptorType;   // +1
     uint8_t bInterfaceNumber;  // +2
@@ -71,18 +71,18 @@
     uint8_t bInterfaceSubClass;// +6
     uint8_t bInterfaceProtocol;// +7
     uint8_t iInterface;        // +8
-} StandardInterfaceDescriptor; // +9
+};                             // +9
 
-typedef struct {              // offset
+struct StandardEndpointDescriptor {// 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
+};                            // +7
 
-typedef struct {              // offset
+struct HubDescriptor {        // offset
     uint8_t bDescLength;      // +0
     uint8_t bDescriptorType;  // +1
     uint8_t bNbrPorts;        // +2
@@ -91,7 +91,7 @@
     uint8_t bHubContrCurrent; // +6
     uint8_t DeviceRemovable;  // +7
     uint8_t PortPweCtrlMak;   // +8
-} HubDescriptor;              // +9
+};                            // +9
 #pragma pack(pop)
 
 // ------------------ HcControl Register ---------------------
@@ -135,44 +135,150 @@
 #define  TD_TOGGLE_1     (uint32_t)(0x03000000) /* Toggle 1 */
 #define  TD_CC           (uint32_t)(0xF0000000) /* Completion Code */
 
-typedef struct {    // Host Controller Communication Area
-    uint32_t InterruptTable[32]; // Interrupt Table
-    __IO uint16_t FrameNumber;   // Frame Number
-    __IO uint16_t Pad1;
-    __IO uint32_t DoneHead;      // Done Head
-    uint8_t Reserved[116];       // Reserved for future use
-    uint8_t Unknown[4];          // Unused
-} HCCA;
+class BaseEp;
+struct HCTD {    // HostController Transfer Descriptor
+    __IO uint32_t Control;    // +0 Transfer descriptor control
+    __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer
+    HCTD* Next;               // +8 Physical pointer to next Transfer Descriptor
+    uint8_t*  BufEnd;         // +12 Physical address of end of buffer
+    uint8_t* buf_top;         // +16 Buffer start address
+    uint16_t buf_size;        // +20 buffer size size
+    uint8_t _dummy[10];       // +22 dummy
+    BaseEp* ep;               // +32 endpoint object
+                              // +36
+    HCTD(BaseEp* obj);
+    inline void* operator new(size_t size) {
+        void* p;
+        if (posix_memalign(&p, 16, size) == 0) {
+            return p;
+        }
+        return NULL;
+    }
 
-typedef struct {    // HostController Transfer Descriptor
-    __IO uint32_t  Control;    // +0 Transfer descriptor control
-    __IO uint8_t*  CurrBufPtr; // +4 Physical address of current buffer pointer
-    __IO uint32_t  Next;       // +8 Physical pointer to next Transfer Descriptor
-    uint8_t*  BufEnd;          // +12 Physical address of end of buffer
-    uint8_t* buf_top;          // +16 Buffer start address
-    uint16_t buf_size;         // +20 buffer size size
-    uint8_t setup[8];          // +22 setup cmd area
-    uint8_t _dummy[2];         // +30 dummy
-    void *ep;                  // +32 endpoint object
-    __IO uint8_t buf[0];       // +36 buffer
-} HCTD;                        // +36 
+    inline void operator delete(void* p) {
+        free(p);
+    }
+
+    inline void transfer(uint8_t* data, int len) {
+        CurrBufPtr = data;
+        buf_top = data;
+        buf_size = len;
+        BufEnd = const_cast<uint8_t*>(data)+len-1;
+    }
 
-typedef struct {    // HostController Isochronous Transfer Descriptor
+    inline int status() {
+        if (CurrBufPtr) {
+            return CurrBufPtr - buf_top;
+        }
+        return buf_size;
+    }
+    
+    inline uint8_t ConditionCode() {
+        return Control>>28;
+    }    
+}; 
+
+struct HCITD {    // HostController Isochronous Transfer Descriptor
     __IO uint32_t Control;      // +0 Transfer descriptor control
     uint8_t*  BufferPage0;      // +4 Buffer Page 0
-    __IO uint32_t  Next;        // +8 Physical pointer to next Transfer Descriptor
+    HCITD* Next;                // +8 Physical pointer to next Isochronous Transfer Descriptor
     uint8_t*  BufferEnd;        // +12 buffer End
     __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
-    void *ep;                   // +32 endpoint object
+    BaseEp* ep;                 // +32 endpoint object
     __IO uint8_t buf[0];        // +36 buffer
-} HCITD;                        // +36
+                                // +36
+    HCITD(BaseEp* 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);
+    }
 
-typedef struct {    // HostController EndPoint Descriptor
+    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
-    uint32_t Next;         // +12 Physical address of next Endpoint descriptor
-} HCED;
+    HCED* Next;            // +12 Physical address of next Endpoint descriptor
+                           // +16
+    HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed) {
+        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;
+    }
+};
+
+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);
+    }
+};
 
 class BaseUsbHost {
 public:
@@ -203,8 +309,6 @@
     int status(uint32_t millisec=osWaitForever);
     //
     virtual void enable() = 0;
-    HCTD* new_HCTD(int buf_size=0);
-    void delete_HCTD(HCTD* p);
     virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} // WDH
     int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever);
     // report
@@ -231,7 +335,6 @@
     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(){};
 };
 
@@ -259,9 +362,9 @@
     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
+    uint16_t m_PacketSize;
 private:
-    HCITD* new_HCITD();
+    HCITD* new_HCITD(BaseEp* obj);
     int m_itd_queue_count;
     uint16_t m_FrameNumber;
     int m_FrameCount; // 1-8
@@ -276,6 +379,22 @@
     int SetPortPower(int port);
     int ClearPortPower(int port);
     vector<ControlEp*> PortEp;
+    template<class T> ControlEp* search(int skip = 0) {
+        for(vector<ControlEp*>::iterator it = PortEp.begin(); it != PortEp.end(); ++it) {
+            if (T::check(*it)) {
+                if (skip-- <= 0) {
+                    return *it;
+                }
+            }
+        }
+        return NULL;   
+    }
+    template<class T> ControlEp* assign(int port) {
+        if (port >= 0 && port < PortEp.size()) {
+            return PortEp[port];
+        }
+        return NULL;
+    }
 private:
     int PortReset(int port);
     int SetPortFeature(int feature, int index);
--- a/BaseUsbHostBlkEp.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostBlkEp.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,22 +1,22 @@
-// BaseUsbHostBlkEp.cpp 2012/12/24
+// BaseUsbHostBlkEp.cpp 2013/1/25
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-#define DEBUG
+//#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
 
 BulkEp::BulkEp(int addr, uint8_t ep, uint16_t size): BaseEp(addr, ep, size)
 {
-    HCTD* td = new_HCTD();
+    HCTD* td = new HCTD(this);
     m_pED->TailTd = td;
     m_pED->HeadTd = td; 
     TEST_ASSERT(td);
     if (td == NULL) {
         return;
     }
-    m_pED->Next = LPC_USB->HcBulkHeadED;
+    m_pED->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED);
     LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(m_pED);
   
     DBG_OHCI(LPC_USB->HcBulkHeadED);
--- a/BaseUsbHostCtlEp.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostCtlEp.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,22 +1,43 @@
-// BaseUsbHostCtlEp.cpp 2013/1/2
+// BaseUsbHostCtlEp.cpp 2013/1/25
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-#define DEBUG
+//#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
 
+#pragma pack(push,1)
+struct SETUP {
+    uint8_t bmRequestType;// +0
+    uint8_t bRequest;     // +1
+    uint16_t wValue;      // +2
+    uint16_t wIndex;      // +4
+    uint16_t wLength;     // +6
+                          // +8
+    SETUP(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) {
+        CTASSERT(sizeof(SETUP) == 8);
+        TEST_ASSERT(sizeof(SETUP) == 8);
+        bmRequestType = RequestType;
+        bRequest = Request;
+        wValue = Value;
+        wIndex = Index;
+        wLength = Length;
+    };
+};
+#pragma pack(pop)
+
 static uint8_t device_addr = 1;
 ControlEp::ControlEp(int lowSpeed):BaseEp(0, 0, 8, lowSpeed)
 {
+    CTASSERT(HCTD_QUEUE_SIZE >= 3);
     TEST_ASSERT(HCTD_QUEUE_SIZE >= 3);
-    HCTD* td = new_HCTD();
+    HCTD* td = new HCTD(this);
     TEST_ASSERT(td);
     m_pED->TailTd = td;
     m_pED->HeadTd = td; 
     
-    m_pED->Next = LPC_USB->HcControlHeadED;
+    m_pED->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
     LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(m_pED);
 
     DBG_OHCI(LPC_USB->HcControlHeadED);
@@ -71,7 +92,6 @@
     TEST_ASSERT(addr >= 1 && addr <= 127);
     uint8_t buf[8];
     int r = GetDescriptor(1, 0, buf, 8);
-    TEST_ASSERT(r == USB_OK);
     if (r != USB_OK) {
         return r;
     }
@@ -93,36 +113,36 @@
                      uint8_t* data, int length) {
     DBG("Type: %02X Request: %02X Value: %04X Index: %04X %p %d\n", bmRequestType, bRequest, wValue, wIndex, data, length);
     HCTD* setup_td = m_pED->TailTd;
-    setup(setup_td, bmRequestType, bRequest, wValue, wIndex, length);
-    setup_td->Control |= TD_DI;
+    SETUP setup(bmRequestType, bRequest, wValue, wIndex, length);
+    setup_td->transfer(reinterpret_cast<uint8_t*>(&setup), sizeof(SETUP));
+    setup_td->Control |= TD_TOGGLE_0|TD_SETUP|TD_DI; 
 
-    HCTD* data_td = new_HCTD(length);
+    HCTD* data_td = new HCTD(this);
     TEST_ASSERT(data_td);
+    data_td->transfer(data, length);
     data_td->Control |= TD_TOGGLE_1|TD_IN|TD_DI; 
-    setup_td->Next = reinterpret_cast<uint32_t>(data_td);
+    setup_td->Next = data_td;
 
-    HCTD* status_td = new_HCTD();
+    HCTD* status_td = new HCTD(this);
     TEST_ASSERT(status_td);
     status_td->Control |= TD_TOGGLE_1|TD_OUT; // OUT(DATA1)
-    data_td->Next = reinterpret_cast<uint32_t>(status_td);
+    data_td->Next = status_td;
 
-    HCTD* blank_td = new_HCTD();
+    HCTD* blank_td = new HCTD(this);
     TEST_ASSERT(blank_td);
-    status_td->Next = reinterpret_cast<uint32_t>(blank_td);
+    status_td->Next = blank_td;
     m_pED->TailTd = blank_td;
 
     LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
     LPC_USB->HcControl |= OR_CONTROL_CLE;
 
     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);
-        delete_HCTD(td);
+        delete td;
     } else {
         DBG_TD(td);
         TEST_ASSERT(td == data_td);
@@ -137,24 +157,26 @@
                      const uint8_t* data, int length) {
     DBG("Type: %02X Request: %02X Value: %04X Index: %04X %p %d\n", bmRequestType, bRequest, wValue, wIndex, data, length);
     HCTD* setup_td = m_pED->TailTd;
-    setup(setup_td, bmRequestType, bRequest, wValue, wIndex, length);
 
-    HCTD* status_td = new_HCTD();
+    HCTD* status_td = new HCTD(this);
     TEST_ASSERT(status_td);
-    HCTD* blank_td = new_HCTD();
+    HCTD* blank_td = new HCTD(this);
     TEST_ASSERT(blank_td);
-    setup_td->Control |= TD_DI;
+    
+    SETUP setup(bmRequestType, bRequest, wValue, wIndex, length);
+    setup_td->transfer(reinterpret_cast<uint8_t*>(&setup), sizeof(SETUP));
+    setup_td->Control |= TD_TOGGLE_0|TD_SETUP|TD_DI; 
     status_td->Control |= TD_TOGGLE_1|TD_IN; // IN(DATA1)
-    setup_td->Next = reinterpret_cast<uint32_t>(status_td);
-    status_td->Next = reinterpret_cast<uint32_t>(blank_td);
+    setup_td->Next = status_td;
+    status_td->Next = blank_td;
 
     if (length != 0) {
-        HCTD* data_td = new_HCTD(length);
+        HCTD* data_td = new HCTD(this);
         TEST_ASSERT(data_td);
         data_td->Control |= TD_TOGGLE_1|TD_OUT|TD_DI; 
-        memcpy(const_cast<uint8_t*>(data_td->buf), data, length);
-        setup_td->Next = reinterpret_cast<uint32_t>(data_td);
-        data_td->Next = reinterpret_cast<uint32_t>(status_td);
+        data_td->transfer(const_cast<uint8_t*>(data), length);
+        setup_td->Next = data_td;
+        data_td->Next = status_td;
     }
     m_pED->TailTd = blank_td;
     DBG_ED(m_pED);
@@ -167,18 +189,15 @@
     return r;
 }
 
-void ControlEp::setup(HCTD* td, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, 
-                      uint16_t wIndex, uint16_t wLength)
-{
-    td->setup[0] = bmRequestType;
-    td->setup[1] = bRequest;
-    td->setup[2] = wValue;
-    td->setup[3] = wValue>>8;
-    td->setup[4] = wIndex;
-    td->setup[5] = wIndex>>8;
-    td->setup[6] = wLength;
-    td->setup[7] = wLength>>8;
-    td->Control |= TD_TOGGLE_0|TD_SETUP; 
-    td->CurrBufPtr = td->setup;
-    td->BufEnd = td->setup+8-1;
+HCTD::HCTD(BaseEp* obj) {
+    CTASSERT(sizeof(HCTD) == 36);
+    TEST_ASSERT(sizeof(HCTD) == 36);
+    TEST_ASSERT(obj);
+    Control = TD_CC|TD_ROUNDING;
+    CurrBufPtr = NULL;
+    Next = NULL;
+    BufEnd = NULL;
+    buf_top = NULL;
+    buf_size = 0;
+    ep = obj;
 }
--- a/BaseUsbHostDebug.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostDebug.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,14 +1,9 @@
-// BaseUseHostDebug.cpp 2012/12/4
+// BaseUseHostDebug.cpp 2013/1/11
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
 #include "BaseUsbHostDebug.h"
 
-#define OHCI_REG_READ(REG)     (LPC_USB->##REG)
-#define OHCI_REG_WRITE(REG,B) LPC_USB->##REG = (B)
-#define OHCI_REG_OR(REG,B)    LPC_USB->##REG |= (B)
-#define OHCI_REG_AND(REG,B)   LPC_USB->##REG &= (B)
-
 void print_td(FILE* stream, HCTD* td)
 {
     if (td == NULL) {
@@ -17,11 +12,7 @@
     }
     uint32_t* p = reinterpret_cast<uint32_t*>(td);
     fprintf(stream, "TD %p: %08X %08X %08X %08X", p, p[0], p[1], p[2], p[3]);
-    fprintf(stream, " ep=%p", td->ep);
-    for(int i = 0; i < 8; i++) {
-        fprintf(stream, " %02X", td->buf[i]);
-    }
-    fprintf(stream, "\n");
+    fprintf(stream, " ep=%p\n", td->ep);
     uint8_t* bp = reinterpret_cast<uint8_t*>(p[1]);
     uint8_t* be = reinterpret_cast<uint8_t*>(p[3]);
     if (bp) {
@@ -43,7 +34,7 @@
         HCTD* tdtail = reinterpret_cast<HCTD*>(p[1]);
         while(td != NULL && td != tdtail) {
             print_td(stream, td);
-            td = reinterpret_cast<HCTD*>(td->Next);
+            td = td->Next;
         }
         p = reinterpret_cast<uint32_t*>(p[3]);
     }
@@ -72,7 +63,7 @@
         HCITD* itdtail = reinterpret_cast<HCITD*>(p[1]);
         while(itd != NULL && itd != itdtail) {
             print_itd(stream, itd);
-            itd = reinterpret_cast<HCITD*>(itd->Next);
+            itd = itd->Next;
         }
         p = reinterpret_cast<uint32_t*>(p[3]);
     }
--- a/BaseUsbHostHub.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostHub.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,8 +1,8 @@
-// BaseUsbHostHub.cpp 2013/1/6
+// BaseUsbHostHub.cpp 2013/1/25
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-#define DEBUG
+//#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
@@ -34,17 +34,17 @@
     } else {
         m_ctlEp = ctlEp;
     }
-    uint8_t desc[9];
-    int rc = m_ctlEp->GetDescriptor(1, 0, desc, sizeof(desc));
+    CTASSERT(sizeof(StandardDeviceDescriptor) == 18);
+    StandardDeviceDescriptor devdesc;
+    int rc = m_ctlEp->GetDescriptor(1, 0, reinterpret_cast<uint8_t*>(&devdesc), sizeof(StandardDeviceDescriptor));
     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);
-    TEST_ASSERT_TRUE(desc[4] == 0x09); // hub
-    if (desc[4] != 0x09) { // hub ?
+    TEST_ASSERT_TRUE(devdesc.bLength == 0x12);
+    TEST_ASSERT_TRUE(devdesc.bDescriptorType == 0x01);
+    TEST_ASSERT_TRUE(devdesc.bDeviceClass == 0x09); // hub
+    if (devdesc.bDeviceClass != 0x09) { // hub ?
         return;
     }
     CTASSERT(sizeof(HubDescriptor) == 9);
@@ -58,7 +58,7 @@
     TEST_ASSERT(hubdesc.bDescLength == 9); // length
     TEST_ASSERT(hubdesc.bDescriptorType == 0x29); // hub
     TEST_ASSERT(hubdesc.bNbrPorts >= 1);
-    TEST_ASSERT(hubdesc.bNbrPorts <= 7);
+    TEST_ASSERT(hubdesc.bNbrPorts <= 16);
 
     m_ctlEp->SetConfiguration(1);
 
--- a/BaseUsbHostIntEp.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostIntEp.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -10,7 +10,7 @@
 InterruptEp::InterruptEp(int addr, uint8_t ep, uint16_t size, int lowSpeed)
     :BaseEp(addr, ep, size, lowSpeed)
 {
-    HCTD* td = new_HCTD();
+    HCTD* td = new HCTD(this);
     m_pED->HeadTd = td; 
     m_pED->TailTd = td;
     TEST_ASSERT(td);
@@ -24,7 +24,7 @@
     }
     int n = 0;
     m_pED->Next = pHcca->InterruptTable[n];
-    pHcca->InterruptTable[n] = reinterpret_cast<uint32_t>(m_pED);
+    pHcca->InterruptTable[n] = m_pED;
 
     DBG_ED(m_pED);
 }
--- a/BaseUsbHostIsoEp.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostIsoEp.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,12 +1,32 @@
-// BaseUsbHostIsoEp.cpp 2012/12/31
+// BaseUsbHostIsoEp.cpp 2013/1/25
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
-#define DEBUG
+//#define DEBUG
 #include "BaseUsbHostDebug.h"
 #define TEST
 #include "BaseUsbHostTest.h"
 
+HCITD::HCITD(BaseEp* 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;
+    }
+}
+
 IsochronousEp::IsochronousEp(int addr, uint8_t ep, uint16_t size):BaseEp(addr, ep, size)
 {
     DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size);
@@ -20,7 +40,7 @@
     TEST_ASSERT(m_FrameCount >= 1 && m_FrameCount <= 8);
     m_itd_queue_count = 0;
     reset();
-    HCITD* itd = new_HCITD();
+    HCITD* itd = new_HCITD(this);
     m_pED->TailTd = reinterpret_cast<HCTD*>(itd);
     m_pED->HeadTd = reinterpret_cast<HCTD*>(itd); 
     TEST_ASSERT(itd);
@@ -33,14 +53,14 @@
         return;
     }
     for(int i = 0; i < 32; i++) {
-        if (hcca->InterruptTable[i] == 0) {
-            hcca->InterruptTable[i] = reinterpret_cast<uint32_t>(m_pED);
+        if (hcca->InterruptTable[i] == NULL) {
+            hcca->InterruptTable[i] = m_pED;
         } else {
-            HCED* nextEd = reinterpret_cast<HCED*>(hcca->InterruptTable[i]);
-            while(nextEd->Next && nextEd->Next != reinterpret_cast<uint32_t>(m_pED)) {
-                nextEd = reinterpret_cast<HCED*>(nextEd->Next);
+            HCED* nextEd = hcca->InterruptTable[i];
+            while(nextEd->Next && nextEd->Next != m_pED) {
+                nextEd = nextEd->Next;
             }
-            nextEd->Next = reinterpret_cast<uint32_t>(m_pED);
+            nextEd->Next = m_pED;
         }
     }
     DBG_ED(m_pED);
@@ -51,31 +71,12 @@
     m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
 }
 
-HCITD* IsochronousEp::new_HCITD()
+HCITD* IsochronousEp::new_HCITD(BaseEp* obj)
 {
-    HCITD* itd;
-    int r = posix_memalign(reinterpret_cast<void**>(&itd), 32, sizeof(HCITD)+m_PacketSize*m_FrameCount);
-    if (r != 0) {
+    HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize);
+    if (itd == NULL) {
         return NULL;
     } 
-    int di = 0; //DelayInterrupt
-    itd->Control = 0xe0000000            | // CC ConditionCode NOT ACCESSED
-                 ((m_FrameCount-1) << 24)| // FC FrameCount
-                       TD_DELAY_INT(di)  | // DI DelayInterrupt
-                     m_FrameNumber;        // SF StartingFrame
-    itd->BufferPage0 = const_cast<uint8_t*>(itd->buf);
-    itd->BufferEnd = const_cast<uint8_t*>(itd->buf) + m_PacketSize * m_FrameCount - 1;
-    itd->Next = NULL; 
-    itd->ep = this;
-    uint32_t addr = reinterpret_cast<uint32_t>(itd->buf);
-    for(int i = 0; i < m_FrameCount; i++) {
-        uint16_t offset = addr & 0x0fff;
-        if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(itd->BufferEnd)&0xfffff000)) {
-            offset |= 0x1000;
-        }
-        itd->OffsetPSW[i] = 0xe000|offset;
-        addr += m_PacketSize;
-    }
     m_FrameNumber += m_FrameCount;
     return itd;
 }
@@ -89,12 +90,12 @@
         if (itd == NULL) {
             return NULL;
         }
-        HCITD* blank_itd = new_HCITD();
+        HCITD* blank_itd = new_HCITD(this);
         TEST_ASSERT(blank_itd);
         if (blank_itd == NULL) {
             return NULL;
         }
-        itd->Next = reinterpret_cast<uint32_t>(blank_itd);
+        itd->Next = blank_itd;
         m_pED->TailTd = reinterpret_cast<HCTD*>(blank_itd);
         m_itd_queue_count++;
         //DBG_IED(m_pED);
@@ -115,13 +116,6 @@
         if (evt.status == osEventMessage) {
             HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
             TEST_ASSERT(itd);
-            if (itd == NULL) {
-                return NULL;
-            }
-            uint8_t cc = itd->Control>>28;
-            if (cc != 0) {
-                m_ConditionCode = cc;
-            }
             return itd;
         } else if (evt.status == osOK) {
             continue;
--- a/BaseUsbHostUvc.cpp	Sun Jan 06 11:45:18 2013 +0000
+++ b/BaseUsbHostUvc.cpp	Fri Jan 25 14:51:33 2013 +0000
@@ -1,4 +1,4 @@
-// BaseUsbHostUvc.cpp 2012/12/11
+// BaseUsbHostUvc.cpp 2013/1/11
 #include "mbed.h"
 #include "rtos.h"
 #include "BaseUsbHost.h"
@@ -11,19 +11,18 @@
 {
     HCITD* itd = m_isoEp->isochronousReveive(millisec);
     if (itd) {
-        uint8_t cc = itd->Control>>28;
+        uint8_t cc = itd->ConditionCode();
         report_cc_count[cc]++;
-        if (cc == 0) { // ConditionCode
-            //DBG_ITD(itd);
-            uint16_t frame = itd->Control & 0xffff;
-            int fc = ((itd->Control>>24)&7)+1;
+        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 pswn = itd->OffsetPSW[i];
-                cc = pswn>>12;
+                uint16_t psw = itd->OffsetPSW[i];
+                cc = psw>>12;
                 if (cc == 0 || cc == 9) {
-                    int len = pswn & 0x7ff;
+                    int len = psw & 0x7ff;
                     onResult(frame, buf, len);
                }
                report_ps_cc_count[cc]++;
@@ -31,13 +30,16 @@
                frame++;
             }
         }
-        m_isoEp->delete_HCTD(reinterpret_cast<HCTD*>(itd));
+        delete itd;
     }
 }
 
 int BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size)
 {
     TEST_ASSERT(m_ctlEp);
+    if (m_ctlEp == NULL) {
+        return USB_ERROR;
+    }
     int rc;
     if (req == SET_CUR) {    
         rc = m_ctlEp->controlSend(
@@ -72,4 +74,3 @@
     m_pCbItem = NULL;
     m_pCbMeth = NULL;
 }
-