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

Dependents:   BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example

Import programBaseUsbHost_example

BaseUsbHost example program

Revision:
0:b7d6879637a8
Child:
1:3b7bc4f87a61
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseUsbHostCtlEp.cpp	Tue Dec 04 13:29:41 2012 +0000
@@ -0,0 +1,189 @@
+// BaseUsbHostCtlEp.cpp 2012/12/4
+#include "mbed.h"
+#include "rtos.h"
+#include "BaseUsbHost.h"
+#define DEBUG
+#include "BaseUsbHostDebug.h"
+#define TEST
+#include "BaseUsbHostTest.h"
+
+static uint8_t device_addr = 1;
+ControlEp::ControlEp(int lowSpeed):BaseEp(0, 0, 8, lowSpeed)
+{
+    TEST_ASSERT(HCTD_QUEUE_SIZE >= 3);
+    HCTD* td = new_HCTD();
+    TEST_ASSERT(td);
+    m_pED->TailTd = td;
+    m_pED->HeadTd = td; 
+    
+    m_pED->Next = LPC_USB->HcControlHeadED;
+    LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(m_pED);
+
+    DBG_OHCI(LPC_USB->HcControlHeadED);
+    DBG_ED(m_pED);
+
+    int r = open(device_addr);
+    if (r == USB_OK) {
+        device_addr++;
+    }
+}
+
+int ControlEp::SetAddress(int addr)
+{
+    return controlSend(0x00, 5, addr);
+}
+
+int ControlEp::GetDescriptor(int descType, int descIndex, uint8_t* data, int length)
+{
+    return controlReceive(0x80, 6, (descType<<8)|descIndex, 0, data, length);
+}
+
+int ControlEp::SetConfiguration(int config)
+{
+    return controlSend(0x00, 9, config);
+}
+
+int ControlEp::GetConfiguration(int *config)
+{
+    uint8_t buf[1];
+    int rc = controlReceive(0x80, 8, 0, 0, buf, 1);
+    *config = buf[0];
+    return rc;
+}
+
+int ControlEp::SetInterfaceAlternate(int interface, int alternate)
+{
+    int rc = controlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE, 
+                     SET_INTERFACE, alternate, interface, NULL, 0);
+    return rc;
+}
+
+int ControlEp::GetInterface(int interface, int *alternate)
+{
+    uint8_t buf[1];
+    int rc = controlReceive(0x81, 10, 0, interface, buf, 1);
+    *alternate = buf[0];
+    return rc;
+}
+
+int ControlEp::open(int addr)
+{
+    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;
+    }
+    TEST_ASSERT(buf[0] == 0x12);
+    TEST_ASSERT(buf[1] == 0x01);
+    TEST_ASSERT(buf[7] >= 8);
+    DeviceClass = buf[3];
+    DeviceSubClass = buf[4];
+    DeviceProtocol = buf[5];
+    DBG("DeviceClass: %02X\n", DeviceClass);
+    DBG("DeviceSubClass: %02X\n", DeviceSubClass);
+    DBG("DeviceProtocol: %02X\n", DeviceProtocol);
+    update_MaxPacketSize(buf[7]);
+    r = SetAddress(addr);    
+    TEST_ASSERT(r == USB_OK);
+    if (r != USB_OK) {
+        return r;
+    }
+    wait_ms(2);
+    update_FunctionAddress(addr);
+    return USB_OK;
+}
+
+int ControlEp::controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+                     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;
+
+    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();
+    TEST_ASSERT(status_td);
+    status_td->Control |= TD_TOGGLE_1|TD_OUT; // OUT(DATA1)
+    data_td->Next = reinterpret_cast<uint32_t>(status_td);
+
+    HCTD* blank_td = new_HCTD();
+    TEST_ASSERT(blank_td);
+    status_td->Next = reinterpret_cast<uint32_t>(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);
+    HCTD* td = get_queue_HCTD(100);
+    if (td == data_td) {
+        memcpy(data, const_cast<uint8_t*>(td->buf), length);
+        delete_HCTD(td);
+    } else {
+        DBG_TD(td);
+        TEST_ASSERT(td == data_td);
+        return USB_ERROR;
+    }
+    r = wait_queue_HCTD(status_td, 100); // wait status stage
+    TEST_ASSERT(r == USB_OK);
+    return r;
+}
+
+int ControlEp::controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
+                     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();
+    TEST_ASSERT(status_td);
+    HCTD* blank_td = new_HCTD();
+    TEST_ASSERT(blank_td);
+    setup_td->Control |= 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);
+
+    if (length != 0) {
+        HCTD* data_td = new_HCTD(length);
+        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);
+    }
+    m_pED->TailTd = blank_td;
+    DBG_ED(m_pED);
+
+    LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
+    LPC_USB->HcControl |= OR_CONTROL_CLE;
+    
+    int r = wait_queue_HCTD(status_td, 200); // wait status stage
+    TEST_ASSERT(r == USB_OK);
+    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;
+}
+