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

Dependents:   BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example

Import programBaseUsbHost_example

BaseUsbHost example program

Revision:
4:d931d24c2f81
Parent:
3:ae77d63a1eda
--- 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;
             }