USB host library, support isochronous,bulk,interrupt and control.
Dependents: BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example
Import programBaseUsbHost_example
BaseUsbHost example program
Diff: BaseUsbHostCtlEp.cpp
- 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; +} +