USB host library, support isochronous,bulk,interrupt and control.
Dependents: BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example
Import programBaseUsbHost_example
BaseUsbHost example program
BaseUsbHostCtlEp.cpp
- Committer:
- va009039
- Date:
- 2013-01-25
- Revision:
- 4:d931d24c2f81
- Parent:
- 3:ae77d63a1eda
- Child:
- 5:8a2d056e9b38
File content as of revision 4:d931d24c2f81:
// BaseUsbHostCtlEp.cpp 2013/1/25 #include "mbed.h" #include "rtos.h" #include "BaseUsbHost.h" //#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(this); TEST_ASSERT(td); m_pED->TailTd = td; m_pED->HeadTd = td; m_pED->Next = reinterpret_cast<HCED*>(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); if (r != USB_OK) { return r; } TEST_ASSERT(buf[0] == 0x12); TEST_ASSERT(buf[1] == 0x01); TEST_ASSERT(buf[7] >= 8); 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(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(this); TEST_ASSERT(data_td); data_td->transfer(data, length); data_td->Control |= TD_TOGGLE_1|TD_IN|TD_DI; setup_td->Next = data_td; HCTD* status_td = new HCTD(this); TEST_ASSERT(status_td); status_td->Control |= TD_TOGGLE_1|TD_OUT; // OUT(DATA1) data_td->Next = status_td; HCTD* blank_td = new HCTD(this); TEST_ASSERT(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 if (r != USB_OK) { return r; } HCTD* td = get_queue_HCTD(100); if (td == data_td) { delete 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; HCTD* status_td = new HCTD(this); TEST_ASSERT(status_td); HCTD* blank_td = new HCTD(this); TEST_ASSERT(blank_td); 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 = status_td; status_td->Next = blank_td; if (length != 0) { HCTD* data_td = new HCTD(this); TEST_ASSERT(data_td); data_td->Control |= TD_TOGGLE_1|TD_OUT|TD_DI; 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); 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; } 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; }