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:
Sun Jan 06 11:45:18 2013 +0000
Revision:
3:ae77d63a1eda
Parent:
0:b7d6879637a8
Child:
4:d931d24c2f81
change interface usbhub class

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 3:ae77d63a1eda 1 // BaseUsbHost.cpp 2012/12/25
va009039 0:b7d6879637a8 2 #include "mbed.h"
va009039 0:b7d6879637a8 3 #include "rtos.h"
va009039 0:b7d6879637a8 4 #include "BaseUsbHost.h"
va009039 0:b7d6879637a8 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 0:b7d6879637a8 10 // bits of the USB/OTG clock control register
va009039 0:b7d6879637a8 11 #define HOST_CLK_EN (1<<0)
va009039 0:b7d6879637a8 12 #define DEV_CLK_EN (1<<1)
va009039 0:b7d6879637a8 13 #define PORTSEL_CLK_EN (1<<3)
va009039 0:b7d6879637a8 14 #define AHB_CLK_EN (1<<4)
va009039 0:b7d6879637a8 15
va009039 0:b7d6879637a8 16 // bits of the USB/OTG clock status register
va009039 0:b7d6879637a8 17 #define HOST_CLK_ON (1<<0)
va009039 0:b7d6879637a8 18 #define DEV_CLK_ON (1<<1)
va009039 0:b7d6879637a8 19 #define PORTSEL_CLK_ON (1<<3)
va009039 0:b7d6879637a8 20 #define AHB_CLK_ON (1<<4)
va009039 0:b7d6879637a8 21
va009039 0:b7d6879637a8 22 // we need host clock, OTG/portsel clock and AHB clock
va009039 0:b7d6879637a8 23 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
va009039 0:b7d6879637a8 24
va009039 0:b7d6879637a8 25 #define FI 0x2EDF /* 12000 bits per frame (-1) */
va009039 0:b7d6879637a8 26 #define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
va009039 0:b7d6879637a8 27
va009039 0:b7d6879637a8 28 static BaseUsbHost* pHost = NULL;
va009039 0:b7d6879637a8 29
va009039 0:b7d6879637a8 30 extern "C" void USB_IRQHandler(void) __irq;
va009039 0:b7d6879637a8 31 void USB_IRQHandler(void) __irq
va009039 0:b7d6879637a8 32 {
va009039 0:b7d6879637a8 33 if (pHost) {
va009039 0:b7d6879637a8 34 pHost->irqHandler();
va009039 0:b7d6879637a8 35 }
va009039 0:b7d6879637a8 36 }
va009039 0:b7d6879637a8 37
va009039 0:b7d6879637a8 38 inline static void* malloc_align(size_t size, size_t alignment)
va009039 0:b7d6879637a8 39 {
va009039 0:b7d6879637a8 40 void* p;
va009039 0:b7d6879637a8 41 int r = posix_memalign(&p, alignment, size);
va009039 0:b7d6879637a8 42 if (r == 0) {
va009039 0:b7d6879637a8 43 return p;
va009039 0:b7d6879637a8 44 }
va009039 0:b7d6879637a8 45 return NULL;
va009039 0:b7d6879637a8 46 }
va009039 0:b7d6879637a8 47
va009039 0:b7d6879637a8 48 BaseUsbHost::BaseUsbHost()
va009039 0:b7d6879637a8 49 {
va009039 0:b7d6879637a8 50 if (pHost) {
va009039 0:b7d6879637a8 51 TEST_ASSERT(pHost == NULL);
va009039 0:b7d6879637a8 52 return;
va009039 0:b7d6879637a8 53 }
va009039 0:b7d6879637a8 54 pHost = this;
va009039 0:b7d6879637a8 55 NVIC_DisableIRQ(USB_IRQn);
va009039 0:b7d6879637a8 56 m_pHcca = reinterpret_cast<HCCA*>(malloc_align(sizeof(HCCA), 256));
va009039 0:b7d6879637a8 57 TEST_ASSERT(m_pHcca);
va009039 0:b7d6879637a8 58 init_hw_ohci(m_pHcca);
va009039 0:b7d6879637a8 59 ResetRootHub();
va009039 0:b7d6879637a8 60 NVIC_SetPriority(USB_IRQn, 0);
va009039 0:b7d6879637a8 61 NVIC_EnableIRQ(USB_IRQn);
va009039 0:b7d6879637a8 62 }
va009039 0:b7d6879637a8 63
va009039 0:b7d6879637a8 64 void BaseUsbHost::init_hw_ohci(HCCA* pHcca)
va009039 0:b7d6879637a8 65 {
va009039 0:b7d6879637a8 66 LPC_SC->PCONP &= ~(1UL<<31); //Cut power
va009039 0:b7d6879637a8 67 wait(1);
va009039 0:b7d6879637a8 68 LPC_SC->PCONP |= (1UL<<31); // turn on power for USB
va009039 0:b7d6879637a8 69 LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock
va009039 0:b7d6879637a8 70 // Wait for clocks to become available
va009039 0:b7d6879637a8 71 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
va009039 0:b7d6879637a8 72 ;
va009039 0:b7d6879637a8 73 LPC_USB->OTGStCtrl |= 1;
va009039 0:b7d6879637a8 74 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
va009039 0:b7d6879637a8 75
va009039 0:b7d6879637a8 76 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
va009039 0:b7d6879637a8 77 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
va009039 0:b7d6879637a8 78
va009039 0:b7d6879637a8 79 DBG("initialize OHCI\n");
va009039 0:b7d6879637a8 80 wait_ms(100); /* Wait 50 ms before apply reset */
va009039 0:b7d6879637a8 81 TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision
va009039 0:b7d6879637a8 82 LPC_USB->HcControl = 0; /* HARDWARE RESET */
va009039 0:b7d6879637a8 83 LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
va009039 0:b7d6879637a8 84 LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
va009039 0:b7d6879637a8 85 /* SOFTWARE RESET */
va009039 0:b7d6879637a8 86 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
va009039 0:b7d6879637a8 87 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
va009039 0:b7d6879637a8 88 LPC_USB->HcPeriodicStart = FI*90/100;
va009039 0:b7d6879637a8 89 /* Put HC in operational state */
va009039 0:b7d6879637a8 90 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
va009039 0:b7d6879637a8 91 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
va009039 0:b7d6879637a8 92 TEST_ASSERT(pHcca);
va009039 0:b7d6879637a8 93 for (int i = 0; i < 32; i++) {
va009039 0:b7d6879637a8 94 pHcca->InterruptTable[i] = NULL;
va009039 0:b7d6879637a8 95 }
va009039 0:b7d6879637a8 96 LPC_USB->HcHCCA = (uint32_t)pHcca;
va009039 0:b7d6879637a8 97 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
va009039 0:b7d6879637a8 98 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
va009039 0:b7d6879637a8 99
va009039 0:b7d6879637a8 100 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
va009039 0:b7d6879637a8 101 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
va009039 0:b7d6879637a8 102 }
va009039 0:b7d6879637a8 103
va009039 0:b7d6879637a8 104 void BaseUsbHost::ResetRootHub()
va009039 0:b7d6879637a8 105 {
va009039 0:b7d6879637a8 106 wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
va009039 0:b7d6879637a8 107 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
va009039 0:b7d6879637a8 108 DBG("Before loop\n");
va009039 0:b7d6879637a8 109 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
va009039 0:b7d6879637a8 110 ;
va009039 0:b7d6879637a8 111 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
va009039 0:b7d6879637a8 112 DBG("After loop\n");
va009039 0:b7d6879637a8 113 wait_ms(200); /* Wait for 100 MS after port reset */
va009039 0:b7d6879637a8 114 }
va009039 0:b7d6879637a8 115
va009039 0:b7d6879637a8 116 HCTD* td_reverse(HCTD* td)
va009039 0:b7d6879637a8 117 {
va009039 0:b7d6879637a8 118 HCTD* result = NULL;
va009039 0:b7d6879637a8 119 HCTD* next;
va009039 0:b7d6879637a8 120 while(td) {
va009039 0:b7d6879637a8 121 next = reinterpret_cast<HCTD*>(td->Next);
va009039 0:b7d6879637a8 122 td->Next = reinterpret_cast<uint32_t>(result);
va009039 0:b7d6879637a8 123 result = td;
va009039 0:b7d6879637a8 124 td = next;
va009039 0:b7d6879637a8 125 }
va009039 0:b7d6879637a8 126 return result;
va009039 0:b7d6879637a8 127 }
va009039 0:b7d6879637a8 128
va009039 0:b7d6879637a8 129 void BaseUsbHost::irqHandler()
va009039 0:b7d6879637a8 130 {
va009039 0:b7d6879637a8 131 if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) {
va009039 0:b7d6879637a8 132 return;
va009039 0:b7d6879637a8 133 }
va009039 0:b7d6879637a8 134 m_report_irq++;
va009039 0:b7d6879637a8 135 uint32_t status = LPC_USB->HcInterruptStatus;
va009039 0:b7d6879637a8 136 if (status & OR_INTR_STATUS_FNO) {
va009039 0:b7d6879637a8 137 m_report_FNO++;
va009039 0:b7d6879637a8 138 }
va009039 0:b7d6879637a8 139 if (status & OR_INTR_STATUS_WDH) {
va009039 0:b7d6879637a8 140 uint32_t done_td = m_pHcca->DoneHead;
va009039 0:b7d6879637a8 141 TEST_ASSERT(done_td);
va009039 0:b7d6879637a8 142 m_pHcca->DoneHead = NULL; // reset
va009039 0:b7d6879637a8 143 if (done_td & 1) { // error ?
va009039 0:b7d6879637a8 144 done_td &= ~1;
va009039 0:b7d6879637a8 145 }
va009039 0:b7d6879637a8 146 HCTD* td = td_reverse(reinterpret_cast<HCTD*>(done_td));
va009039 0:b7d6879637a8 147 while(td) {
va009039 0:b7d6879637a8 148 BaseEp* ep = reinterpret_cast<BaseEp*>(td->ep);
va009039 0:b7d6879637a8 149 TEST_ASSERT(ep);
va009039 0:b7d6879637a8 150 ep->irqWdhHandler(td);
va009039 0:b7d6879637a8 151 td = reinterpret_cast<HCTD*>(td->Next);
va009039 0:b7d6879637a8 152 }
va009039 0:b7d6879637a8 153 m_report_WDH++;
va009039 0:b7d6879637a8 154 }
va009039 0:b7d6879637a8 155 LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status
va009039 0:b7d6879637a8 156 }
va009039 0:b7d6879637a8 157
va009039 0:b7d6879637a8 158 BaseEp::BaseEp(int addr, uint8_t ep, uint16_t size, int lowSpeed):m_td_queue_count(0)
va009039 0:b7d6879637a8 159 {
va009039 0:b7d6879637a8 160 DBG("%p FA=%d EN=%02x MPS=%d S=%d\n", this, addr, ep, size, lowSpeed);
va009039 0:b7d6879637a8 161 m_pED = reinterpret_cast<HCED*>(malloc_align(sizeof(HCED), 16));
va009039 0:b7d6879637a8 162 TEST_ASSERT(m_pED);
va009039 0:b7d6879637a8 163 TEST_ASSERT(size >= 8 && size <= 1023);
va009039 0:b7d6879637a8 164 TEST_ASSERT(lowSpeed == 0 || lowSpeed == 1);
va009039 0:b7d6879637a8 165 m_pED->Control = addr | /* USB address */
va009039 0:b7d6879637a8 166 ((ep & 0x7F) << 7) | /* Endpoint address */
va009039 0:b7d6879637a8 167 (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
va009039 0:b7d6879637a8 168 ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */
va009039 0:b7d6879637a8 169 (size << 16); /* MaxPkt Size */
va009039 0:b7d6879637a8 170 m_pED->Next = NULL;
va009039 0:b7d6879637a8 171 }
va009039 0:b7d6879637a8 172
va009039 0:b7d6879637a8 173 int BaseEp::GetAddr()
va009039 0:b7d6879637a8 174 {
va009039 0:b7d6879637a8 175 HCED* ed = m_pED;
va009039 0:b7d6879637a8 176 TEST_ASSERT(ed);
va009039 0:b7d6879637a8 177 if (ed) {
va009039 0:b7d6879637a8 178 return ed->Control & 0x7f;
va009039 0:b7d6879637a8 179 }
va009039 0:b7d6879637a8 180 return 0;
va009039 0:b7d6879637a8 181 }
va009039 0:b7d6879637a8 182
va009039 0:b7d6879637a8 183 int BaseEp::GetLowSpeed()
va009039 0:b7d6879637a8 184 {
va009039 0:b7d6879637a8 185 HCED* ed = m_pED;
va009039 0:b7d6879637a8 186 TEST_ASSERT(ed);
va009039 0:b7d6879637a8 187 if (ed) {
va009039 0:b7d6879637a8 188 if (ed->Control & (1<<13)) {
va009039 0:b7d6879637a8 189 return 1;
va009039 0:b7d6879637a8 190 }
va009039 0:b7d6879637a8 191 }
va009039 0:b7d6879637a8 192 return 0;
va009039 0:b7d6879637a8 193 }
va009039 0:b7d6879637a8 194
va009039 0:b7d6879637a8 195 void BaseEp::update_FunctionAddress(int addr)
va009039 0:b7d6879637a8 196 {
va009039 0:b7d6879637a8 197 TEST_ASSERT(addr >= 0 && addr <= 127);
va009039 0:b7d6879637a8 198 HCED* ed = m_pED;
va009039 0:b7d6879637a8 199 TEST_ASSERT(ed);
va009039 0:b7d6879637a8 200 ed->Control &= ~0x7f;
va009039 0:b7d6879637a8 201 ed->Control |= addr;
va009039 0:b7d6879637a8 202 }
va009039 0:b7d6879637a8 203
va009039 0:b7d6879637a8 204 void BaseEp::update_MaxPacketSize(uint16_t size)
va009039 0:b7d6879637a8 205 {
va009039 0:b7d6879637a8 206 TEST_ASSERT(size >= 8 && size <= 1023);
va009039 0:b7d6879637a8 207 HCED* ed = m_pED;
va009039 0:b7d6879637a8 208 TEST_ASSERT(ed);
va009039 0:b7d6879637a8 209 ed->Control &= ~0xffff0000;
va009039 0:b7d6879637a8 210 ed->Control |= size<<16;
va009039 0:b7d6879637a8 211 }
va009039 0:b7d6879637a8 212
va009039 3:ae77d63a1eda 213 int BaseEp::transfer(uint8_t* buf, int len)
va009039 3:ae77d63a1eda 214 {
va009039 3:ae77d63a1eda 215 HCTD* data_td = m_pED->TailTd;
va009039 3:ae77d63a1eda 216 TEST_ASSERT(data_td);
va009039 3:ae77d63a1eda 217 if (data_td == NULL) {
va009039 3:ae77d63a1eda 218 return USB_ERROR;
va009039 3:ae77d63a1eda 219 }
va009039 3:ae77d63a1eda 220 data_td->CurrBufPtr = buf;
va009039 3:ae77d63a1eda 221 data_td->buf_top = buf;
va009039 3:ae77d63a1eda 222 data_td->buf_size = len;
va009039 3:ae77d63a1eda 223 data_td->BufEnd = const_cast<uint8_t*>(buf)+len-1;
va009039 3:ae77d63a1eda 224 HCTD* blank_td = new_HCTD();
va009039 3:ae77d63a1eda 225 TEST_ASSERT(blank_td);
va009039 3:ae77d63a1eda 226 if (blank_td == NULL) {
va009039 3:ae77d63a1eda 227 return USB_ERROR_MEMORY;
va009039 3:ae77d63a1eda 228 }
va009039 3:ae77d63a1eda 229 data_td->Next = reinterpret_cast<uint32_t>(blank_td);
va009039 3:ae77d63a1eda 230 m_pED->TailTd = blank_td;
va009039 3:ae77d63a1eda 231 enable();
va009039 3:ae77d63a1eda 232 return USB_PROCESSING;
va009039 3:ae77d63a1eda 233 }
va009039 3:ae77d63a1eda 234
va009039 3:ae77d63a1eda 235 int BaseEp::status(uint32_t millisec)
va009039 3:ae77d63a1eda 236 {
va009039 3:ae77d63a1eda 237 HCTD* td = get_queue_HCTD(millisec);
va009039 3:ae77d63a1eda 238 if (td == NULL) {
va009039 3:ae77d63a1eda 239 return USB_PROCESSING;
va009039 3:ae77d63a1eda 240 }
va009039 3:ae77d63a1eda 241 uint8_t cc = td->Control>>28;
va009039 3:ae77d63a1eda 242 int ret;
va009039 3:ae77d63a1eda 243 switch(cc) {
va009039 3:ae77d63a1eda 244 case 0:
va009039 3:ae77d63a1eda 245 case 8:
va009039 3:ae77d63a1eda 246 case 9:
va009039 3:ae77d63a1eda 247 ret = td->buf_size;
va009039 3:ae77d63a1eda 248 if (td->CurrBufPtr) {
va009039 3:ae77d63a1eda 249 ret = td->CurrBufPtr - td->buf_top;
va009039 3:ae77d63a1eda 250 }
va009039 3:ae77d63a1eda 251 break;
va009039 3:ae77d63a1eda 252 case 4:
va009039 3:ae77d63a1eda 253 ret = USB_ERROR_STALL;
va009039 3:ae77d63a1eda 254 break;
va009039 3:ae77d63a1eda 255 case 5:
va009039 3:ae77d63a1eda 256 ret = USB_ERROR_DEVICE_NOT_RESPONDING;
va009039 3:ae77d63a1eda 257 break;
va009039 3:ae77d63a1eda 258 default:
va009039 3:ae77d63a1eda 259 DBG("ConditionCode=%d\n", cc);
va009039 3:ae77d63a1eda 260 ret = USB_ERROR;
va009039 3:ae77d63a1eda 261 break;
va009039 3:ae77d63a1eda 262 }
va009039 3:ae77d63a1eda 263 delete_HCTD(td);
va009039 3:ae77d63a1eda 264 return ret;
va009039 3:ae77d63a1eda 265 }
va009039 3:ae77d63a1eda 266
va009039 3:ae77d63a1eda 267 int BaseEp::send_receive(uint8_t* buf, int len, int millisec)
va009039 3:ae77d63a1eda 268 {
va009039 3:ae77d63a1eda 269 if (m_td_queue_count == 0) {
va009039 3:ae77d63a1eda 270 int rc = transfer(buf, len);
va009039 3:ae77d63a1eda 271 if (rc != USB_PROCESSING) {
va009039 3:ae77d63a1eda 272 return rc;
va009039 3:ae77d63a1eda 273 }
va009039 3:ae77d63a1eda 274 m_td_queue_count++;
va009039 3:ae77d63a1eda 275 }
va009039 3:ae77d63a1eda 276
va009039 3:ae77d63a1eda 277 int ret = status(millisec);
va009039 3:ae77d63a1eda 278 if (ret != USB_PROCESSING) {
va009039 3:ae77d63a1eda 279 m_td_queue_count--;
va009039 3:ae77d63a1eda 280 }
va009039 3:ae77d63a1eda 281 return ret;
va009039 3:ae77d63a1eda 282 }
va009039 3:ae77d63a1eda 283
va009039 0:b7d6879637a8 284 HCTD* BaseEp::new_HCTD(int buf_size)
va009039 0:b7d6879637a8 285 {
va009039 0:b7d6879637a8 286 HCTD* td;
va009039 0:b7d6879637a8 287 int r = posix_memalign(reinterpret_cast<void**>(&td), 16, sizeof(HCTD) + buf_size);
va009039 0:b7d6879637a8 288 if (r == 0) {
va009039 0:b7d6879637a8 289 td->Control = TD_CC|TD_ROUNDING;
va009039 0:b7d6879637a8 290 td->Next = NULL;
va009039 0:b7d6879637a8 291 td->ep = this;
va009039 0:b7d6879637a8 292 td->buf_top = NULL;
va009039 0:b7d6879637a8 293 td->buf_size = buf_size;
va009039 0:b7d6879637a8 294 if (buf_size == 0) {
va009039 0:b7d6879637a8 295 td->CurrBufPtr = NULL;
va009039 0:b7d6879637a8 296 td->BufEnd = NULL;
va009039 0:b7d6879637a8 297 } else {
va009039 0:b7d6879637a8 298 td->CurrBufPtr = td->buf;
va009039 0:b7d6879637a8 299 td->BufEnd = const_cast<uint8_t*>(td->buf)+buf_size-1;
va009039 0:b7d6879637a8 300 }
va009039 0:b7d6879637a8 301 return td;
va009039 0:b7d6879637a8 302 }
va009039 0:b7d6879637a8 303 return NULL;
va009039 0:b7d6879637a8 304 }
va009039 0:b7d6879637a8 305
va009039 0:b7d6879637a8 306 void BaseEp::delete_HCTD(HCTD* p)
va009039 0:b7d6879637a8 307 {
va009039 0:b7d6879637a8 308 free(p);
va009039 0:b7d6879637a8 309 }
va009039 0:b7d6879637a8 310
va009039 0:b7d6879637a8 311 HCTD* BaseEp::get_queue_HCTD(uint32_t millisec)
va009039 0:b7d6879637a8 312 {
va009039 0:b7d6879637a8 313 for(int i = 0; i < 16; i++) {
va009039 0:b7d6879637a8 314 osEvent evt = m_queue.get(millisec);
va009039 0:b7d6879637a8 315 if (evt.status == osEventMessage) {
va009039 0:b7d6879637a8 316 HCTD* td = reinterpret_cast<HCTD*>(evt.value.p);
va009039 0:b7d6879637a8 317 TEST_ASSERT(td);
va009039 0:b7d6879637a8 318 if (td->Control & TD_CC) {
va009039 0:b7d6879637a8 319 m_ConditionCode = td->Control>>28;
va009039 0:b7d6879637a8 320 DBG_TD(td);
va009039 0:b7d6879637a8 321 }
va009039 0:b7d6879637a8 322 return td;
va009039 0:b7d6879637a8 323 } else if (evt.status == osOK) {
va009039 0:b7d6879637a8 324 continue;
va009039 0:b7d6879637a8 325 } else if (evt.status == osEventTimeout) {
va009039 0:b7d6879637a8 326 return NULL;
va009039 0:b7d6879637a8 327 } else {
va009039 0:b7d6879637a8 328 DBG("evt.status: %02x\n", evt.status);
va009039 0:b7d6879637a8 329 TEST_ASSERT(evt.status == osEventMessage);
va009039 0:b7d6879637a8 330 }
va009039 0:b7d6879637a8 331 }
va009039 0:b7d6879637a8 332 return NULL;
va009039 0:b7d6879637a8 333 }
va009039 0:b7d6879637a8 334
va009039 0:b7d6879637a8 335 int BaseEp::wait_queue_HCTD(HCTD* wait_td, uint32_t millisec)
va009039 0:b7d6879637a8 336 {
va009039 0:b7d6879637a8 337 for(int i = 0; i < 16; i++) {
va009039 0:b7d6879637a8 338 HCTD* td = get_queue_HCTD(millisec);
va009039 0:b7d6879637a8 339 if (td) {
va009039 0:b7d6879637a8 340 if (td->Control & TD_CC) {
va009039 3:ae77d63a1eda 341 uint8_t cc = td->Control>>28;
va009039 0:b7d6879637a8 342 DBG_TD(td);
va009039 0:b7d6879637a8 343 delete_HCTD(td);
va009039 3:ae77d63a1eda 344 switch(cc) {
va009039 3:ae77d63a1eda 345 case 4:
va009039 3:ae77d63a1eda 346 return USB_ERROR_STALL;
va009039 3:ae77d63a1eda 347 default:
va009039 3:ae77d63a1eda 348 return USB_ERROR;
va009039 3:ae77d63a1eda 349 }
va009039 0:b7d6879637a8 350 }
va009039 0:b7d6879637a8 351 delete_HCTD(td);
va009039 0:b7d6879637a8 352 if (td == wait_td) {
va009039 0:b7d6879637a8 353 return USB_OK;
va009039 0:b7d6879637a8 354 }
va009039 0:b7d6879637a8 355 }
va009039 0:b7d6879637a8 356 }
va009039 0:b7d6879637a8 357 return USB_ERROR;
va009039 0:b7d6879637a8 358 }