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

Dependents:   BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example

Import programBaseUsbHost_example

BaseUsbHost example program

Committer:
va009039
Date:
Mon Feb 11 12:00:47 2013 +0000
Revision:
5:8a2d056e9b38
Parent:
4:d931d24c2f81
add GetStringDescriptor()

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 5:8a2d056e9b38 1 // BaseUsbHostCtlEp.cpp 2013/2/11
va009039 0:b7d6879637a8 2 #include "mbed.h"
va009039 0:b7d6879637a8 3 #include "rtos.h"
va009039 0:b7d6879637a8 4 #include "BaseUsbHost.h"
va009039 4:d931d24c2f81 5 //#define DEBUG
va009039 0:b7d6879637a8 6 #include "BaseUsbHostDebug.h"
va009039 0:b7d6879637a8 7 #define TEST
va009039 0:b7d6879637a8 8 #include "BaseUsbHostTest.h"
va009039 0:b7d6879637a8 9
va009039 4:d931d24c2f81 10 #pragma pack(push,1)
va009039 4:d931d24c2f81 11 struct SETUP {
va009039 4:d931d24c2f81 12 uint8_t bmRequestType;// +0
va009039 4:d931d24c2f81 13 uint8_t bRequest; // +1
va009039 4:d931d24c2f81 14 uint16_t wValue; // +2
va009039 4:d931d24c2f81 15 uint16_t wIndex; // +4
va009039 4:d931d24c2f81 16 uint16_t wLength; // +6
va009039 4:d931d24c2f81 17 // +8
va009039 4:d931d24c2f81 18 SETUP(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) {
va009039 4:d931d24c2f81 19 CTASSERT(sizeof(SETUP) == 8);
va009039 4:d931d24c2f81 20 TEST_ASSERT(sizeof(SETUP) == 8);
va009039 4:d931d24c2f81 21 bmRequestType = RequestType;
va009039 4:d931d24c2f81 22 bRequest = Request;
va009039 4:d931d24c2f81 23 wValue = Value;
va009039 4:d931d24c2f81 24 wIndex = Index;
va009039 4:d931d24c2f81 25 wLength = Length;
va009039 4:d931d24c2f81 26 };
va009039 4:d931d24c2f81 27 };
va009039 4:d931d24c2f81 28 #pragma pack(pop)
va009039 4:d931d24c2f81 29
va009039 0:b7d6879637a8 30 static uint8_t device_addr = 1;
va009039 0:b7d6879637a8 31 ControlEp::ControlEp(int lowSpeed):BaseEp(0, 0, 8, lowSpeed)
va009039 0:b7d6879637a8 32 {
va009039 4:d931d24c2f81 33 CTASSERT(HCTD_QUEUE_SIZE >= 3);
va009039 0:b7d6879637a8 34 TEST_ASSERT(HCTD_QUEUE_SIZE >= 3);
va009039 4:d931d24c2f81 35 HCTD* td = new HCTD(this);
va009039 0:b7d6879637a8 36 TEST_ASSERT(td);
va009039 0:b7d6879637a8 37 m_pED->TailTd = td;
va009039 0:b7d6879637a8 38 m_pED->HeadTd = td;
va009039 0:b7d6879637a8 39
va009039 4:d931d24c2f81 40 m_pED->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
va009039 0:b7d6879637a8 41 LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(m_pED);
va009039 0:b7d6879637a8 42
va009039 0:b7d6879637a8 43 DBG_OHCI(LPC_USB->HcControlHeadED);
va009039 0:b7d6879637a8 44 DBG_ED(m_pED);
va009039 0:b7d6879637a8 45
va009039 0:b7d6879637a8 46 int r = open(device_addr);
va009039 0:b7d6879637a8 47 if (r == USB_OK) {
va009039 0:b7d6879637a8 48 device_addr++;
va009039 0:b7d6879637a8 49 }
va009039 0:b7d6879637a8 50 }
va009039 0:b7d6879637a8 51
va009039 0:b7d6879637a8 52 int ControlEp::SetAddress(int addr)
va009039 0:b7d6879637a8 53 {
va009039 0:b7d6879637a8 54 return controlSend(0x00, 5, addr);
va009039 0:b7d6879637a8 55 }
va009039 0:b7d6879637a8 56
va009039 0:b7d6879637a8 57 int ControlEp::GetDescriptor(int descType, int descIndex, uint8_t* data, int length)
va009039 0:b7d6879637a8 58 {
va009039 0:b7d6879637a8 59 return controlReceive(0x80, 6, (descType<<8)|descIndex, 0, data, length);
va009039 0:b7d6879637a8 60 }
va009039 0:b7d6879637a8 61
va009039 0:b7d6879637a8 62 int ControlEp::SetConfiguration(int config)
va009039 0:b7d6879637a8 63 {
va009039 0:b7d6879637a8 64 return controlSend(0x00, 9, config);
va009039 0:b7d6879637a8 65 }
va009039 0:b7d6879637a8 66
va009039 0:b7d6879637a8 67 int ControlEp::GetConfiguration(int *config)
va009039 0:b7d6879637a8 68 {
va009039 0:b7d6879637a8 69 uint8_t buf[1];
va009039 0:b7d6879637a8 70 int rc = controlReceive(0x80, 8, 0, 0, buf, 1);
va009039 0:b7d6879637a8 71 *config = buf[0];
va009039 0:b7d6879637a8 72 return rc;
va009039 0:b7d6879637a8 73 }
va009039 0:b7d6879637a8 74
va009039 0:b7d6879637a8 75 int ControlEp::SetInterfaceAlternate(int interface, int alternate)
va009039 0:b7d6879637a8 76 {
va009039 0:b7d6879637a8 77 int rc = controlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE,
va009039 0:b7d6879637a8 78 SET_INTERFACE, alternate, interface, NULL, 0);
va009039 0:b7d6879637a8 79 return rc;
va009039 0:b7d6879637a8 80 }
va009039 0:b7d6879637a8 81
va009039 0:b7d6879637a8 82 int ControlEp::GetInterface(int interface, int *alternate)
va009039 0:b7d6879637a8 83 {
va009039 0:b7d6879637a8 84 uint8_t buf[1];
va009039 0:b7d6879637a8 85 int rc = controlReceive(0x81, 10, 0, interface, buf, 1);
va009039 0:b7d6879637a8 86 *alternate = buf[0];
va009039 0:b7d6879637a8 87 return rc;
va009039 0:b7d6879637a8 88 }
va009039 0:b7d6879637a8 89
va009039 5:8a2d056e9b38 90 string ControlEp::GetStringDescriptor(int index)
va009039 5:8a2d056e9b38 91 {
va009039 5:8a2d056e9b38 92 string s = "";
va009039 5:8a2d056e9b38 93 uint8_t buf[128];
va009039 5:8a2d056e9b38 94 int r = GetDescriptor(USB_DESCRIPTOR_TYPE_STRING, index, buf, sizeof(buf));
va009039 5:8a2d056e9b38 95 if (r != USB_OK) {
va009039 5:8a2d056e9b38 96 return s;
va009039 5:8a2d056e9b38 97 }
va009039 5:8a2d056e9b38 98 DBG_HEX(buf, sizeof(buf));
va009039 5:8a2d056e9b38 99 StandardStringDescriptor* desc = reinterpret_cast<StandardStringDescriptor*>(buf);
va009039 5:8a2d056e9b38 100 if (desc->bLength <= 2 || desc->bDescriptorType != 3) {
va009039 5:8a2d056e9b38 101 return s;
va009039 5:8a2d056e9b38 102 }
va009039 5:8a2d056e9b38 103 for(int i = 0; i < desc->bLength-2; i += 2) {
va009039 5:8a2d056e9b38 104 s += desc->bString[i];
va009039 5:8a2d056e9b38 105 }
va009039 5:8a2d056e9b38 106 return s;
va009039 5:8a2d056e9b38 107 }
va009039 5:8a2d056e9b38 108
va009039 0:b7d6879637a8 109 int ControlEp::open(int addr)
va009039 0:b7d6879637a8 110 {
va009039 0:b7d6879637a8 111 TEST_ASSERT(addr >= 1 && addr <= 127);
va009039 0:b7d6879637a8 112 uint8_t buf[8];
va009039 0:b7d6879637a8 113 int r = GetDescriptor(1, 0, buf, 8);
va009039 0:b7d6879637a8 114 if (r != USB_OK) {
va009039 0:b7d6879637a8 115 return r;
va009039 0:b7d6879637a8 116 }
va009039 0:b7d6879637a8 117 TEST_ASSERT(buf[0] == 0x12);
va009039 0:b7d6879637a8 118 TEST_ASSERT(buf[1] == 0x01);
va009039 0:b7d6879637a8 119 TEST_ASSERT(buf[7] >= 8);
va009039 0:b7d6879637a8 120 update_MaxPacketSize(buf[7]);
va009039 0:b7d6879637a8 121 r = SetAddress(addr);
va009039 0:b7d6879637a8 122 TEST_ASSERT(r == USB_OK);
va009039 0:b7d6879637a8 123 if (r != USB_OK) {
va009039 0:b7d6879637a8 124 return r;
va009039 0:b7d6879637a8 125 }
va009039 0:b7d6879637a8 126 wait_ms(2);
va009039 0:b7d6879637a8 127 update_FunctionAddress(addr);
va009039 0:b7d6879637a8 128 return USB_OK;
va009039 0:b7d6879637a8 129 }
va009039 0:b7d6879637a8 130
va009039 0:b7d6879637a8 131 int ControlEp::controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
va009039 0:b7d6879637a8 132 uint8_t* data, int length) {
va009039 0:b7d6879637a8 133 DBG("Type: %02X Request: %02X Value: %04X Index: %04X %p %d\n", bmRequestType, bRequest, wValue, wIndex, data, length);
va009039 0:b7d6879637a8 134 HCTD* setup_td = m_pED->TailTd;
va009039 4:d931d24c2f81 135 SETUP setup(bmRequestType, bRequest, wValue, wIndex, length);
va009039 4:d931d24c2f81 136 setup_td->transfer(reinterpret_cast<uint8_t*>(&setup), sizeof(SETUP));
va009039 4:d931d24c2f81 137 setup_td->Control |= TD_TOGGLE_0|TD_SETUP|TD_DI;
va009039 0:b7d6879637a8 138
va009039 4:d931d24c2f81 139 HCTD* data_td = new HCTD(this);
va009039 0:b7d6879637a8 140 TEST_ASSERT(data_td);
va009039 4:d931d24c2f81 141 data_td->transfer(data, length);
va009039 0:b7d6879637a8 142 data_td->Control |= TD_TOGGLE_1|TD_IN|TD_DI;
va009039 4:d931d24c2f81 143 setup_td->Next = data_td;
va009039 0:b7d6879637a8 144
va009039 4:d931d24c2f81 145 HCTD* status_td = new HCTD(this);
va009039 0:b7d6879637a8 146 TEST_ASSERT(status_td);
va009039 0:b7d6879637a8 147 status_td->Control |= TD_TOGGLE_1|TD_OUT; // OUT(DATA1)
va009039 4:d931d24c2f81 148 data_td->Next = status_td;
va009039 0:b7d6879637a8 149
va009039 4:d931d24c2f81 150 HCTD* blank_td = new HCTD(this);
va009039 0:b7d6879637a8 151 TEST_ASSERT(blank_td);
va009039 4:d931d24c2f81 152 status_td->Next = blank_td;
va009039 0:b7d6879637a8 153 m_pED->TailTd = blank_td;
va009039 0:b7d6879637a8 154
va009039 0:b7d6879637a8 155 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
va009039 0:b7d6879637a8 156 LPC_USB->HcControl |= OR_CONTROL_CLE;
va009039 0:b7d6879637a8 157
va009039 0:b7d6879637a8 158 int r = wait_queue_HCTD(setup_td, 100); // wait setup stage
va009039 3:ae77d63a1eda 159 if (r != USB_OK) {
va009039 3:ae77d63a1eda 160 return r;
va009039 3:ae77d63a1eda 161 }
va009039 0:b7d6879637a8 162 HCTD* td = get_queue_HCTD(100);
va009039 0:b7d6879637a8 163 if (td == data_td) {
va009039 4:d931d24c2f81 164 delete td;
va009039 0:b7d6879637a8 165 } else {
va009039 0:b7d6879637a8 166 DBG_TD(td);
va009039 0:b7d6879637a8 167 TEST_ASSERT(td == data_td);
va009039 0:b7d6879637a8 168 return USB_ERROR;
va009039 0:b7d6879637a8 169 }
va009039 0:b7d6879637a8 170 r = wait_queue_HCTD(status_td, 100); // wait status stage
va009039 0:b7d6879637a8 171 return r;
va009039 0:b7d6879637a8 172 }
va009039 0:b7d6879637a8 173
va009039 0:b7d6879637a8 174 int ControlEp::controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
va009039 0:b7d6879637a8 175 const uint8_t* data, int length) {
va009039 0:b7d6879637a8 176 DBG("Type: %02X Request: %02X Value: %04X Index: %04X %p %d\n", bmRequestType, bRequest, wValue, wIndex, data, length);
va009039 0:b7d6879637a8 177 HCTD* setup_td = m_pED->TailTd;
va009039 0:b7d6879637a8 178
va009039 4:d931d24c2f81 179 HCTD* status_td = new HCTD(this);
va009039 0:b7d6879637a8 180 TEST_ASSERT(status_td);
va009039 4:d931d24c2f81 181 HCTD* blank_td = new HCTD(this);
va009039 0:b7d6879637a8 182 TEST_ASSERT(blank_td);
va009039 4:d931d24c2f81 183
va009039 4:d931d24c2f81 184 SETUP setup(bmRequestType, bRequest, wValue, wIndex, length);
va009039 4:d931d24c2f81 185 setup_td->transfer(reinterpret_cast<uint8_t*>(&setup), sizeof(SETUP));
va009039 4:d931d24c2f81 186 setup_td->Control |= TD_TOGGLE_0|TD_SETUP|TD_DI;
va009039 0:b7d6879637a8 187 status_td->Control |= TD_TOGGLE_1|TD_IN; // IN(DATA1)
va009039 4:d931d24c2f81 188 setup_td->Next = status_td;
va009039 4:d931d24c2f81 189 status_td->Next = blank_td;
va009039 0:b7d6879637a8 190
va009039 0:b7d6879637a8 191 if (length != 0) {
va009039 4:d931d24c2f81 192 HCTD* data_td = new HCTD(this);
va009039 0:b7d6879637a8 193 TEST_ASSERT(data_td);
va009039 0:b7d6879637a8 194 data_td->Control |= TD_TOGGLE_1|TD_OUT|TD_DI;
va009039 4:d931d24c2f81 195 data_td->transfer(const_cast<uint8_t*>(data), length);
va009039 4:d931d24c2f81 196 setup_td->Next = data_td;
va009039 4:d931d24c2f81 197 data_td->Next = status_td;
va009039 0:b7d6879637a8 198 }
va009039 0:b7d6879637a8 199 m_pED->TailTd = blank_td;
va009039 0:b7d6879637a8 200 DBG_ED(m_pED);
va009039 0:b7d6879637a8 201
va009039 0:b7d6879637a8 202 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
va009039 0:b7d6879637a8 203 LPC_USB->HcControl |= OR_CONTROL_CLE;
va009039 0:b7d6879637a8 204
va009039 0:b7d6879637a8 205 int r = wait_queue_HCTD(status_td, 200); // wait status stage
va009039 0:b7d6879637a8 206 return r;
va009039 0:b7d6879637a8 207 }
va009039 0:b7d6879637a8 208
va009039 4:d931d24c2f81 209 HCTD::HCTD(BaseEp* obj) {
va009039 4:d931d24c2f81 210 CTASSERT(sizeof(HCTD) == 36);
va009039 4:d931d24c2f81 211 TEST_ASSERT(sizeof(HCTD) == 36);
va009039 4:d931d24c2f81 212 TEST_ASSERT(obj);
va009039 4:d931d24c2f81 213 Control = TD_CC|TD_ROUNDING;
va009039 4:d931d24c2f81 214 CurrBufPtr = NULL;
va009039 4:d931d24c2f81 215 Next = NULL;
va009039 4:d931d24c2f81 216 BufEnd = NULL;
va009039 4:d931d24c2f81 217 buf_top = NULL;
va009039 4:d931d24c2f81 218 buf_size = 0;
va009039 4:d931d24c2f81 219 ep = obj;
va009039 0:b7d6879637a8 220 }