Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
USBHost.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 00018 #include "USBHost.h" 00019 #include "USBHostHub.h" 00020 00021 USBHost * USBHost::instHost = NULL; 00022 00023 #define DEVICE_CONNECTED_EVENT (1 << 0) 00024 #define DEVICE_DISCONNECTED_EVENT (1 << 1) 00025 #define TD_PROCESSED_EVENT (1 << 2) 00026 00027 #define MAX_TRY_ENUMERATE_HUB 3 00028 00029 #define MIN(a, b) ((a > b) ? b : a) 00030 00031 /** 00032 * How interrupts are processed: 00033 * - new device connected: 00034 * - a message is queued in queue_usb_event with the id DEVICE_CONNECTED_EVENT 00035 * - when the usb_thread receives the event, it: 00036 * - resets the device 00037 * - reads the device descriptor 00038 * - sets the address of the device 00039 * - if it is a hub, enumerates it 00040 * - device disconnected: 00041 * - a message is queued in queue_usb_event with the id DEVICE_DISCONNECTED_EVENT 00042 * - when the usb_thread receives the event, it: 00043 * - free the device and all its children (hub) 00044 * - td processed 00045 * - a message is queued in queue_usb_event with the id TD_PROCESSED_EVENT 00046 * - when the usb_thread receives the event, it: 00047 * - call the callback attached to the endpoint where the td is attached 00048 */ 00049 void USBHost::usb_process() 00050 { 00051 00052 bool controlListState; 00053 bool bulkListState; 00054 bool interruptListState; 00055 USBEndpoint * ep; 00056 uint8_t i, j, res, timeout_set_addr = 10; 00057 uint8_t buf[8]; 00058 bool too_many_hub; 00059 int idx; 00060 00061 #if DEBUG_TRANSFER 00062 uint8_t * buf_transfer; 00063 #endif 00064 00065 #if MAX_HUB_NB 00066 uint8_t k; 00067 #endif 00068 00069 while(1) { 00070 osEvent evt = mail_usb_event.get(); 00071 00072 if (evt.status == osEventMail) { 00073 00074 message_t * usb_msg = (message_t*)evt.value.p; 00075 00076 switch (usb_msg->event_id) { 00077 00078 // a new device has been connected 00079 case DEVICE_CONNECTED_EVENT: 00080 too_many_hub = false; 00081 buf[4] = 0; 00082 00083 do { 00084 Lock lock(this); 00085 bool hub_unplugged = true; 00086 00087 int idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent)); 00088 /* check that hub is connected to root port */ 00089 if (usb_msg->hub_parent) { 00090 /* a hub device must be present */ 00091 for (k = 0; k < MAX_HUB_NB; k++) { 00092 if ((&hubs[k] == usb_msg->hub_parent) && (hub_in_use[k])) { 00093 hub_unplugged=false; 00094 } 00095 } 00096 } else { 00097 hub_unplugged = false; 00098 } 00099 00100 if (((idx!=-1) && deviceInUse[idx] ) || ((idx == -1) && hub_unplugged)) { 00101 break; 00102 } 00103 00104 for (i =0 ; i < MAX_DEVICE_CONNECTED; i++) { 00105 if (!deviceInUse[i]) { 00106 USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]); 00107 devices[i].init(usb_msg->hub, usb_msg->port, usb_msg->lowSpeed); 00108 deviceReset[i] = false; 00109 deviceInited[i] = true; 00110 break; 00111 } 00112 } 00113 00114 if (i == MAX_DEVICE_CONNECTED) { 00115 USB_ERR("Too many device connected!!\r\n"); 00116 continue; 00117 } 00118 00119 if (!controlEndpointAllocated) { 00120 control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00); 00121 addEndpoint(NULL, 0, (USBEndpoint*)control); 00122 controlEndpointAllocated = true; 00123 } 00124 00125 #if MAX_HUB_NB 00126 if (usb_msg->hub_parent) { 00127 devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent)); 00128 } 00129 #endif 00130 00131 for (j = 0; j < timeout_set_addr; j++) { 00132 00133 resetDevice(&devices[i]); 00134 00135 // set size of control endpoint 00136 devices[i].setSizeControlEndpoint(8); 00137 00138 devices[i].activeAddress(false); 00139 00140 // get first 8 bit of device descriptor 00141 // and check if we deal with a hub 00142 USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]); 00143 res = getDeviceDescriptor(&devices[i], buf, 8); 00144 00145 if (res != USB_TYPE_OK) { 00146 USB_ERR("usb_thread could not read dev descr"); 00147 continue; 00148 } 00149 00150 // set size of control endpoint 00151 devices[i].setSizeControlEndpoint(buf[7]); 00152 00153 // second step: set an address to the device 00154 res = setAddress(&devices[i], devices[i].getAddress()); 00155 00156 if (res != USB_TYPE_OK) { 00157 USB_ERR("SET ADDR FAILED"); 00158 continue; 00159 } 00160 devices[i].activeAddress(true); 00161 USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress()); 00162 00163 // try to read again the device descriptor to check if the device 00164 // answers to its new address 00165 res = getDeviceDescriptor(&devices[i], buf, 8); 00166 00167 if (res == USB_TYPE_OK) { 00168 break; 00169 } 00170 00171 Thread::wait(100); 00172 } 00173 00174 USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port); 00175 00176 #if MAX_HUB_NB 00177 if (buf[4] == HUB_CLASS) { 00178 for (k = 0; k < MAX_HUB_NB; k++) { 00179 if (hub_in_use[k] == false) { 00180 for (uint8_t j = 0; j < MAX_TRY_ENUMERATE_HUB; j++) { 00181 if (hubs[k].connect(&devices[i])) { 00182 devices[i].hub = &hubs[k]; 00183 hub_in_use[k] = true; 00184 break; 00185 } 00186 } 00187 if (hub_in_use[k] == true) { 00188 break; 00189 } 00190 } 00191 } 00192 00193 if (k == MAX_HUB_NB) { 00194 USB_ERR("Too many hubs connected!!\r\n"); 00195 too_many_hub = true; 00196 } 00197 } 00198 00199 if (usb_msg->hub_parent) { 00200 ((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]); 00201 } 00202 #endif 00203 00204 if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) { 00205 deviceInUse[i] = true; 00206 } 00207 00208 } while(0); 00209 00210 break; 00211 00212 // a device has been disconnected 00213 case DEVICE_DISCONNECTED_EVENT: 00214 00215 do { 00216 Lock lock(this); 00217 00218 controlListState = disableList(CONTROL_ENDPOINT); 00219 bulkListState = disableList(BULK_ENDPOINT); 00220 interruptListState = disableList(INTERRUPT_ENDPOINT); 00221 00222 idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent)); 00223 if (idx != -1) { 00224 freeDevice((USBDeviceConnected*)&devices[idx]); 00225 deviceInited[idx]=false; 00226 } 00227 00228 if (controlListState) { 00229 enableList(CONTROL_ENDPOINT); 00230 } 00231 if (bulkListState) { 00232 enableList(BULK_ENDPOINT); 00233 } 00234 if (interruptListState) { 00235 enableList(INTERRUPT_ENDPOINT); 00236 } 00237 00238 } while(0); 00239 00240 break; 00241 00242 // a td has been processed 00243 // call callback on the ed associated to the td 00244 // we are not in ISR -> users can use printf in their callback method 00245 case TD_PROCESSED_EVENT: 00246 ep = (USBEndpoint *) ((HCTD *)usb_msg->td_addr)->ep; 00247 if (usb_msg->td_state == USB_TYPE_IDLE) { 00248 USB_DBG_EVENT("call callback on td %p [ep: %p state: %s - dev: %p - %s]", usb_msg->td_addr, ep, ep->getStateString(), ep->dev, ep->dev->getName(ep->getIntfNb())); 00249 00250 #if DEBUG_TRANSFER 00251 if (ep->getDir() == IN) { 00252 buf_transfer = ep->getBufStart(); 00253 printf("READ SUCCESS [%d bytes transferred - td: 0x%08X] on ep: [%p - addr: %02X]: ", ep->getLengthTransferred(), usb_msg->td_addr, ep, ep->getAddress()); 00254 for (int i = 0; i < ep->getLengthTransferred(); i++) { 00255 printf("%02X ", buf_transfer[i]); 00256 } 00257 printf("\r\n\r\n"); 00258 } 00259 #endif 00260 ep->call(); 00261 } else { 00262 idx = findDevice(ep->dev); 00263 if (idx != -1) { 00264 if (deviceInUse[idx]) { 00265 USB_WARN("td %p processed but not in idle state: %s [ep: %p - dev: %p - %s]", usb_msg->td_addr, ep->getStateString(), ep, ep->dev, ep->dev->getName(ep->getIntfNb())); 00266 ep->setState(USB_TYPE_IDLE); 00267 /* as error, on interrupt endpoint can be 00268 * reported, call the call back registered , 00269 * if device still in use, this call back 00270 * shall ask again an interrupt request. 00271 */ 00272 ep->call(); 00273 } 00274 } 00275 } 00276 break; 00277 } 00278 00279 mail_usb_event.free(usb_msg); 00280 } 00281 } 00282 } 00283 00284 USBHost::USBHost() : usbThread(osPriorityNormal, USB_THREAD_STACK) 00285 { 00286 #ifndef USBHOST_OTHER 00287 headControlEndpoint = NULL; 00288 headBulkEndpoint = NULL; 00289 headInterruptEndpoint = NULL; 00290 tailControlEndpoint = NULL; 00291 tailBulkEndpoint = NULL; 00292 tailInterruptEndpoint = NULL; 00293 #endif 00294 lenReportDescr = 0; 00295 00296 controlEndpointAllocated = false; 00297 00298 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00299 deviceInUse[i] = false; 00300 devices[i].setAddress(i + 1); 00301 deviceReset[i] = false; 00302 deviceInited[i] = false; 00303 for (uint8_t j = 0; j < MAX_INTF; j++) { 00304 deviceAttachedDriver[i][j] = false; 00305 } 00306 } 00307 00308 #if MAX_HUB_NB 00309 for (uint8_t i = 0; i < MAX_HUB_NB; i++) { 00310 hubs[i].setHost(this); 00311 hub_in_use[i] = false; 00312 } 00313 #endif 00314 00315 usbThread.start(this, &USBHost::usb_process); 00316 } 00317 00318 USBHost::Lock::Lock(USBHost* pHost) : m_pHost(pHost) 00319 { 00320 m_pHost->usb_mutex.lock(); 00321 } 00322 00323 USBHost::Lock::~Lock() 00324 { 00325 m_pHost->usb_mutex.unlock(); 00326 } 00327 00328 void USBHost::transferCompleted(volatile uint32_t addr) 00329 { 00330 uint8_t state; 00331 00332 if(addr == 0) { 00333 return; 00334 } 00335 00336 volatile HCTD* tdList = NULL; 00337 00338 //First we must reverse the list order and dequeue each TD 00339 do { 00340 volatile HCTD* td = (volatile HCTD*)addr; 00341 addr = (uint32_t)td->nextTD; //Dequeue from physical list 00342 td->nextTD = (hcTd*)tdList; //Enqueue into reversed list 00343 tdList = td; 00344 } while(addr); 00345 00346 while(tdList != NULL) { 00347 volatile HCTD* td = tdList; 00348 tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below 00349 if (td->ep != NULL) { 00350 USBEndpoint * ep = (USBEndpoint *)(td->ep); 00351 00352 #ifdef USBHOST_OTHER 00353 state = ((HCTD *)td)->state; 00354 if (state == USB_TYPE_IDLE) { 00355 ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); 00356 } 00357 00358 #else 00359 if (((HCTD *)td)->control >> 28) { 00360 state = ((HCTD *)td)->control >> 28; 00361 } else { 00362 if (td->currBufPtr) { 00363 ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); 00364 } 00365 state = 16 /*USB_TYPE_IDLE*/; 00366 } 00367 #endif 00368 if (state == USB_TYPE_IDLE) { 00369 ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart()); 00370 } 00371 00372 ep->unqueueTransfer(td); 00373 00374 if (ep->getType() != CONTROL_ENDPOINT) { 00375 // callback on the processed td will be called from the usb_thread (not in ISR) 00376 message_t * usb_msg = mail_usb_event.alloc(); 00377 usb_msg->event_id = TD_PROCESSED_EVENT; 00378 usb_msg->td_addr = (void *)td; 00379 usb_msg->td_state = state; 00380 mail_usb_event.put(usb_msg); 00381 } 00382 ep->setState((USB_TYPE)state); 00383 ep->ep_queue.put((uint8_t*)1); 00384 } 00385 } 00386 } 00387 00388 USBHost * USBHost::getHostInst() 00389 { 00390 if (instHost == NULL) { 00391 instHost = new USBHost(); 00392 instHost->init(); 00393 } 00394 return instHost; 00395 } 00396 00397 00398 /* 00399 * Called when a device has been connected 00400 * Called in ISR!!!! (no printf) 00401 */ 00402 /* virtual */ void USBHost::deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent) 00403 { 00404 // be sure that the new device connected is not already connected... 00405 int idx = findDevice(hub, port, hub_parent); 00406 if (idx != -1) { 00407 if (deviceInited[idx]) { 00408 return; 00409 } 00410 } 00411 00412 message_t * usb_msg = mail_usb_event.alloc(); 00413 usb_msg->event_id = DEVICE_CONNECTED_EVENT; 00414 usb_msg->hub = hub; 00415 usb_msg->port = port; 00416 usb_msg->lowSpeed = lowSpeed; 00417 usb_msg->hub_parent = hub_parent; 00418 mail_usb_event.put(usb_msg); 00419 } 00420 00421 /* 00422 * Called when a device has been disconnected 00423 * Called in ISR!!!! (no printf) 00424 */ 00425 /* virtual */ void USBHost::deviceDisconnected(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr) 00426 { 00427 // be sure that the device disconnected is connected... 00428 int idx = findDevice(hub, port, hub_parent); 00429 if (idx != -1) { 00430 if (!deviceInUse[idx]) { 00431 return; 00432 } 00433 } else { 00434 return; 00435 } 00436 00437 message_t * usb_msg = mail_usb_event.alloc(); 00438 usb_msg->event_id = DEVICE_DISCONNECTED_EVENT; 00439 usb_msg->hub = hub; 00440 usb_msg->port = port; 00441 usb_msg->hub_parent = hub_parent; 00442 mail_usb_event.put(usb_msg); 00443 } 00444 00445 void USBHost::freeDevice(USBDeviceConnected * dev) 00446 { 00447 USBEndpoint * ep = NULL; 00448 HCED * ed = NULL; 00449 00450 #if MAX_HUB_NB 00451 if (dev->getClass() == HUB_CLASS) { 00452 if (dev->hub == NULL) { 00453 USB_ERR("HUB NULL!!!!!\r\n"); 00454 } else { 00455 dev->hub->hubDisconnected(); 00456 for (uint8_t i = 0; i < MAX_HUB_NB; i++) { 00457 if (dev->hub == &hubs[i]) { 00458 hub_in_use[i] = false; 00459 break; 00460 } 00461 } 00462 } 00463 } 00464 00465 // notify hub parent that this device has been disconnected 00466 if (dev->getHubParent()) { 00467 dev->getHubParent()->deviceDisconnected(dev); 00468 } 00469 00470 #endif 00471 00472 int idx = findDevice(dev); 00473 if (idx != -1) { 00474 deviceInUse[idx] = false; 00475 deviceReset[idx] = false; 00476 00477 for (uint8_t j = 0; j < MAX_INTF; j++) { 00478 deviceAttachedDriver[idx][j] = false; 00479 if (dev->getInterface(j) != NULL) { 00480 USB_DBG("FREE INTF %d on dev: %p, %p, nb_endpot: %d, %s", j, (void *)dev->getInterface(j), dev, dev->getInterface(j)->nb_endpoint, dev->getName(j)); 00481 for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) { 00482 if ((ep = dev->getEndpoint(j, i)) != NULL) { 00483 #ifndef USBHOST_OTHER 00484 ed = (HCED *)ep->getHCED(); 00485 ed->control |= (1 << 14); //sKip bit 00486 #endif 00487 unqueueEndpoint(ep); 00488 00489 freeTD((volatile uint8_t*)ep->getTDList()[0]); 00490 freeTD((volatile uint8_t*)ep->getTDList()[1]); 00491 00492 freeED((uint8_t *)ep->getHCED()); 00493 } 00494 printList(BULK_ENDPOINT); 00495 printList(INTERRUPT_ENDPOINT); 00496 } 00497 USB_INFO("Device disconnected [%p - %s - hub: %d - port: %d]", dev, dev->getName(j), dev->getHub(), dev->getPort()); 00498 } 00499 } 00500 dev->disconnect(); 00501 } 00502 } 00503 00504 00505 void USBHost::unqueueEndpoint(USBEndpoint * ep) 00506 { 00507 #ifdef USBHOST_OTHER 00508 ep->setState(USB_TYPE_FREE); 00509 #else 00510 USBEndpoint * prec = NULL; 00511 USBEndpoint * current = NULL; 00512 00513 for (int i = 0; i < 2; i++) { 00514 current = (i == 0) ? (USBEndpoint*)headBulkEndpoint : (USBEndpoint*)headInterruptEndpoint; 00515 prec = current; 00516 while (current != NULL) { 00517 if (current == ep) { 00518 if (current->nextEndpoint() != NULL) { 00519 prec->queueEndpoint(current->nextEndpoint()); 00520 if (current == headBulkEndpoint) { 00521 updateBulkHeadED((uint32_t)current->nextEndpoint()->getHCED()); 00522 headBulkEndpoint = current->nextEndpoint(); 00523 } else if (current == headInterruptEndpoint) { 00524 updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED()); 00525 headInterruptEndpoint = current->nextEndpoint(); 00526 } 00527 } 00528 // here we are dequeuing the queue of ed 00529 // we need to update the tail pointer 00530 else { 00531 prec->queueEndpoint(NULL); 00532 if (current == headBulkEndpoint) { 00533 updateBulkHeadED(0); 00534 headBulkEndpoint = current->nextEndpoint(); 00535 } else if (current == headInterruptEndpoint) { 00536 updateInterruptHeadED(0); 00537 headInterruptEndpoint = current->nextEndpoint(); 00538 } 00539 00540 // modify tail 00541 switch (current->getType()) { 00542 case BULK_ENDPOINT: 00543 tailBulkEndpoint = prec; 00544 break; 00545 case INTERRUPT_ENDPOINT: 00546 tailInterruptEndpoint = prec; 00547 break; 00548 default: 00549 break; 00550 } 00551 } 00552 current->setState(USB_TYPE_FREE); 00553 return; 00554 } 00555 prec = current; 00556 current = current->nextEndpoint(); 00557 } 00558 } 00559 #endif 00560 } 00561 00562 00563 USBDeviceConnected * USBHost::getDevice(uint8_t index) 00564 { 00565 if ((index >= MAX_DEVICE_CONNECTED) || (!deviceInUse[index])) { 00566 return NULL; 00567 } 00568 return (USBDeviceConnected*)&devices[index]; 00569 } 00570 00571 // create an USBEndpoint descriptor. the USBEndpoint is not linked 00572 USBEndpoint * USBHost::newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) 00573 { 00574 int i = 0; 00575 HCED * ed = (HCED *)getED(); 00576 HCTD* td_list[2] = { (HCTD*)getTD(), (HCTD*)getTD() }; 00577 00578 memset((void *)td_list[0], 0x00, sizeof(HCTD)); 00579 memset((void *)td_list[1], 0x00, sizeof(HCTD)); 00580 00581 // search a free USBEndpoint 00582 for (i = 0; i < MAX_ENDPOINT; i++) { 00583 if (endpoints[i].getState() == USB_TYPE_FREE) { 00584 endpoints[i].init(ed, type, dir, size, addr, td_list); 00585 USB_DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d, state: %s", &endpoints[i], type, dir, size, addr, endpoints[i].getStateString()); 00586 return &endpoints[i]; 00587 } 00588 } 00589 USB_ERR("could not allocate more endpoints!!!!"); 00590 return NULL; 00591 } 00592 00593 00594 USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev) 00595 { 00596 int index = findDevice(dev); 00597 if (index != -1) { 00598 USB_DBG("Resetting hub %d, port %d\n", dev->getHub(), dev->getPort()); 00599 Thread::wait(100); 00600 if (dev->getHub() == 0) { 00601 resetRootHub(); 00602 } 00603 #if MAX_HUB_NB 00604 else { 00605 dev->getHubParent()->portReset(dev->getPort()); 00606 } 00607 #endif 00608 Thread::wait(100); 00609 deviceReset[index] = true; 00610 return USB_TYPE_OK; 00611 } 00612 00613 return USB_TYPE_ERROR; 00614 } 00615 00616 // link the USBEndpoint to the linked list and attach an USBEndpoint to a device 00617 bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep) 00618 { 00619 00620 if (ep == NULL) { 00621 return false; 00622 } 00623 00624 #ifndef USBHOST_OTHER 00625 HCED * prevEd; 00626 00627 #endif 00628 // set device address in the USBEndpoint descriptor 00629 if (dev == NULL) { 00630 ep->setDeviceAddress(0); 00631 } else { 00632 ep->setDeviceAddress(dev->getAddress()); 00633 } 00634 00635 if ((dev != NULL) && dev->getSpeed()) { 00636 ep->setSpeed(dev->getSpeed()); 00637 } 00638 00639 ep->setIntfNb(intf_nb); 00640 00641 #ifndef USBHOST_OTHER 00642 // queue the new USBEndpoint on the ED list 00643 switch (ep->getType()) { 00644 00645 case CONTROL_ENDPOINT: 00646 prevEd = ( HCED*) controlHeadED(); 00647 if (!prevEd) { 00648 updateControlHeadED((uint32_t) ep->getHCED()); 00649 USB_DBG_TRANSFER("First control USBEndpoint: %08X", (uint32_t) ep->getHCED()); 00650 headControlEndpoint = ep; 00651 tailControlEndpoint = ep; 00652 return true; 00653 } 00654 tailControlEndpoint->queueEndpoint(ep); 00655 tailControlEndpoint = ep; 00656 return true; 00657 00658 case BULK_ENDPOINT: 00659 prevEd = ( HCED*) bulkHeadED(); 00660 if (!prevEd) { 00661 updateBulkHeadED((uint32_t) ep->getHCED()); 00662 USB_DBG_TRANSFER("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED()); 00663 headBulkEndpoint = ep; 00664 tailBulkEndpoint = ep; 00665 break; 00666 } 00667 USB_DBG_TRANSFER("Queue BULK Ed %p after %p\r\n",ep->getHCED(), prevEd); 00668 tailBulkEndpoint->queueEndpoint(ep); 00669 tailBulkEndpoint = ep; 00670 break; 00671 00672 case INTERRUPT_ENDPOINT: 00673 prevEd = ( HCED*) interruptHeadED(); 00674 if (!prevEd) { 00675 updateInterruptHeadED((uint32_t) ep->getHCED()); 00676 USB_DBG_TRANSFER("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED()); 00677 headInterruptEndpoint = ep; 00678 tailInterruptEndpoint = ep; 00679 break; 00680 } 00681 USB_DBG_TRANSFER("Queue INTERRUPT Ed %p after %p\r\n",ep->getHCED(), prevEd); 00682 tailInterruptEndpoint->queueEndpoint(ep); 00683 tailInterruptEndpoint = ep; 00684 break; 00685 default: 00686 return false; 00687 } 00688 00689 #endif 00690 ep->dev = dev; 00691 dev->addEndpoint(intf_nb, ep); 00692 00693 return true; 00694 } 00695 00696 00697 int USBHost::findDevice(USBDeviceConnected * dev) 00698 { 00699 for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00700 if (dev == &devices[i]) { 00701 return i; 00702 } 00703 } 00704 return -1; 00705 } 00706 00707 int USBHost::findDevice(uint8_t hub, uint8_t port, USBHostHub * hub_parent) 00708 { 00709 for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00710 if (devices[i].getHub() == hub && devices[i].getPort() == port) { 00711 if (hub_parent != NULL) { 00712 if (hub_parent == devices[i].getHubParent()) { 00713 return i; 00714 } 00715 } else { 00716 return i; 00717 } 00718 } 00719 } 00720 return -1; 00721 } 00722 00723 void USBHost::printList(ENDPOINT_TYPE type) 00724 { 00725 #if defined(DEBUG_EP_STATE) && !defined(USBHOST_OTHER) 00726 volatile HCED * hced; 00727 switch(type) { 00728 case CONTROL_ENDPOINT: 00729 hced = (HCED *)controlHeadED(); 00730 break; 00731 case BULK_ENDPOINT: 00732 hced = (HCED *)bulkHeadED(); 00733 break; 00734 case INTERRUPT_ENDPOINT: 00735 hced = (HCED *)interruptHeadED(); 00736 break; 00737 } 00738 volatile HCTD * hctd = NULL; 00739 const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : 00740 ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : 00741 ((type == CONTROL_ENDPOINT) ? "CONTROL" : "ISOCHRONOUS")); 00742 printf("State of %s:\r\n", type_str); 00743 while (hced != NULL) { 00744 uint8_t dir = ((hced->control & (3 << 11)) >> 11); 00745 printf("hced: %p [ADDR: %d, DIR: %s, EP_NB: 0x%X]\r\n", hced, 00746 hced->control & 0x7f, 00747 (dir == 1) ? "OUT" : ((dir == 0) ? "FROM_TD":"IN"), 00748 (hced->control & (0xf << 7)) >> 7); 00749 hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0xf)); 00750 while (hctd != hced->tailTD) { 00751 printf("\thctd: %p [DIR: %s]\r\n", hctd, ((hctd->control & (3 << 19)) >> 19) == 1 ? "OUT" : "IN"); 00752 hctd = hctd->nextTD; 00753 } 00754 printf("\thctd: %p\r\n", hctd); 00755 hced = hced->nextED; 00756 } 00757 printf("\r\n\r\n"); 00758 #endif 00759 } 00760 00761 00762 // add a transfer on the TD linked list 00763 USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) 00764 { 00765 USB_TYPE ret=USB_TYPE_PROCESSING; 00766 td_mutex.lock(); 00767 00768 // allocate a TD which will be freed in TDcompletion 00769 volatile HCTD * td = ed->getNextTD(); 00770 if (td == NULL) { 00771 return USB_TYPE_ERROR; 00772 } 00773 00774 #ifndef USBHOST_OTHER 00775 uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT )); 00776 00777 uint32_t td_toggle; 00778 00779 if (ed->getType() == CONTROL_ENDPOINT) { 00780 if (ed->isSetup()) { 00781 td_toggle = TD_TOGGLE_0; 00782 } else { 00783 td_toggle = TD_TOGGLE_1; 00784 } 00785 } else { 00786 td_toggle = 0; 00787 } 00788 00789 td->control = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC); 00790 td->currBufPtr = buf; 00791 td->bufEnd = (buf + (len - 1)); 00792 00793 ENDPOINT_TYPE type = ed->getType(); 00794 00795 disableList(type); 00796 ed->queueTransfer(); 00797 printList(type); 00798 enableList(type); 00799 #else 00800 /* call method specific for endpoint */ 00801 td->currBufPtr = buf; 00802 td->size = len; 00803 ret = ed->queueTransfer(); 00804 #endif 00805 00806 td_mutex.unlock(); 00807 00808 return ret; 00809 } 00810 00811 00812 00813 USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_dev_descr) 00814 { 00815 USB_TYPE t = controlRead( dev, 00816 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00817 GET_DESCRIPTOR, 00818 (DEVICE_DESCRIPTOR << 8) | (0), 00819 0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf)); 00820 if (len_dev_descr) { 00821 *len_dev_descr = MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf); 00822 } 00823 00824 return t; 00825 } 00826 00827 USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_conf_descr) 00828 { 00829 USB_TYPE res; 00830 uint16_t total_conf_descr_length = 0; 00831 00832 // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr 00833 res = controlRead( dev, 00834 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00835 GET_DESCRIPTOR, 00836 (CONFIGURATION_DESCRIPTOR << 8) | (0), 00837 0, buf, CONFIGURATION_DESCRIPTOR_LENGTH); 00838 00839 if (res != USB_TYPE_OK) { 00840 USB_ERR("GET CONF 1 DESCR FAILED"); 00841 return res; 00842 } 00843 total_conf_descr_length = buf[2] | (buf[3] << 8); 00844 total_conf_descr_length = MIN(max_len_buf, total_conf_descr_length); 00845 00846 if (len_conf_descr) { 00847 *len_conf_descr = total_conf_descr_length; 00848 } 00849 00850 USB_DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]); 00851 00852 return controlRead( dev, 00853 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00854 GET_DESCRIPTOR, 00855 (CONFIGURATION_DESCRIPTOR << 8) | (0), 00856 0, buf, total_conf_descr_length); 00857 } 00858 00859 00860 USB_TYPE USBHost::setAddress(USBDeviceConnected * dev, uint8_t address) 00861 { 00862 return controlWrite( dev, 00863 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, 00864 SET_ADDRESS, 00865 address, 00866 0, NULL, 0); 00867 00868 } 00869 00870 USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf) 00871 { 00872 return controlWrite( dev, 00873 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, 00874 SET_CONFIGURATION, 00875 conf, 00876 0, NULL, 0); 00877 } 00878 00879 uint8_t USBHost::numberDriverAttached(USBDeviceConnected * dev) 00880 { 00881 int index = findDevice(dev); 00882 uint8_t cnt = 0; 00883 if (index == -1) { 00884 return 0; 00885 } 00886 for (uint8_t i = 0; i < MAX_INTF; i++) { 00887 if (deviceAttachedDriver[index][i]) { 00888 cnt++; 00889 } 00890 } 00891 return cnt; 00892 } 00893 00894 // enumerate a device with the control USBEndpoint 00895 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) 00896 { 00897 uint16_t total_conf_descr_length = 0; 00898 USB_TYPE res; 00899 00900 do { 00901 Lock lock(this); 00902 00903 // don't enumerate a device which all interfaces are registered to a specific driver 00904 int index = findDevice(dev); 00905 00906 if (index == -1) { 00907 return USB_TYPE_ERROR; 00908 } 00909 00910 uint8_t nb_intf_attached = numberDriverAttached(dev); 00911 USB_DBG("dev: %p nb_intf: %d", dev, dev->getNbIntf()); 00912 USB_DBG("dev: %p nb_intf_attached: %d", dev, nb_intf_attached); 00913 if ((nb_intf_attached != 0) && (dev->getNbIntf() == nb_intf_attached)) { 00914 USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev); 00915 return USB_TYPE_OK; 00916 } 00917 00918 USB_DBG("Enumerate dev: %p", dev); 00919 00920 // third step: get the whole device descriptor to see vid, pid 00921 res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH); 00922 00923 if (res != USB_TYPE_OK) { 00924 USB_DBG("GET DEV DESCR FAILED"); 00925 return res; 00926 } 00927 00928 dev->setClass(data[4]); 00929 dev->setSubClass(data[5]); 00930 dev->setProtocol(data[6]); 00931 dev->setVid(data[8] | (data[9] << 8)); 00932 dev->setPid(data[10] | (data[11] << 8)); 00933 USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); 00934 00935 pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); 00936 00937 res = getConfigurationDescriptor(dev, data, sizeof(data), &total_conf_descr_length); 00938 if (res != USB_TYPE_OK) { 00939 return res; 00940 } 00941 00942 #if (DEBUG > 3) 00943 USB_DBG("CONFIGURATION DESCRIPTOR:\r\n"); 00944 for (int i = 0; i < total_conf_descr_length; i++) { 00945 printf("%02X ", data[i]); 00946 } 00947 printf("\r\n\r\n"); 00948 #endif 00949 00950 // Parse the configuration descriptor 00951 parseConfDescr(dev, data, total_conf_descr_length, pEnumerator); 00952 00953 // only set configuration if not enumerated before 00954 if (!dev->isEnumerated()) { 00955 00956 USB_DBG("Set configuration 1 on dev: %p", dev); 00957 // sixth step: set configuration (only 1 supported) 00958 res = setConfiguration(dev, 1); 00959 00960 if (res != USB_TYPE_OK) { 00961 USB_DBG("SET CONF FAILED"); 00962 return res; 00963 } 00964 } 00965 00966 dev->setEnumerated(); 00967 00968 // Now the device is enumerated! 00969 USB_DBG("dev %p is enumerated\r\n", dev); 00970 00971 } while(0); 00972 00973 // Some devices may require this delay 00974 Thread::wait(100); 00975 00976 return USB_TYPE_OK; 00977 } 00978 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. 00979 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) 00980 { 00981 uint32_t index = 0; 00982 uint32_t len_desc = 0; 00983 uint8_t id = 0; 00984 int nb_endpoints_used = 0; 00985 USBEndpoint * ep = NULL; 00986 uint8_t intf_nb = 0; 00987 bool parsing_intf = false; 00988 uint8_t current_intf = 0; 00989 00990 while (index < len) { 00991 len_desc = conf_descr[index]; 00992 id = conf_descr[index+1]; 00993 switch (id) { 00994 case CONFIGURATION_DESCRIPTOR: 00995 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); 00996 dev->setNbIntf(conf_descr[4]); 00997 break; 00998 case INTERFACE_DESCRIPTOR: 00999 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { 01000 if (intf_nb++ <= MAX_INTF) { 01001 current_intf = conf_descr[index + 2]; 01002 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); 01003 nb_endpoints_used = 0; 01004 USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); 01005 } else { 01006 USB_DBG("Drop intf..."); 01007 } 01008 parsing_intf = true; 01009 } else { 01010 parsing_intf = false; 01011 } 01012 break; 01013 case ENDPOINT_DESCRIPTOR: 01014 if (parsing_intf && (intf_nb <= MAX_INTF) ) { 01015 if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) { 01016 if( pEnumerator->useEndpoint(current_intf, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) ) { 01017 // if the USBEndpoint is isochronous -> skip it (TODO: fix this) 01018 if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) { 01019 ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03), 01020 (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1), 01021 conf_descr[index + 4] | (conf_descr[index + 5] << 8), 01022 conf_descr[index + 2] & 0x0f); 01023 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); 01024 if (ep != NULL && dev != NULL) { 01025 addEndpoint(dev, current_intf, ep); 01026 } else { 01027 USB_DBG("EP NULL"); 01028 } 01029 nb_endpoints_used++; 01030 } else { 01031 USB_DBG("ISO USBEndpoint NOT SUPPORTED"); 01032 } 01033 } 01034 } 01035 } 01036 break; 01037 case HID_DESCRIPTOR: 01038 lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); 01039 break; 01040 default: 01041 break; 01042 } 01043 index += len_desc; 01044 } 01045 } 01046 01047 01048 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) 01049 { 01050 return generalTransfer(dev, ep, buf, len, blocking, BULK_ENDPOINT, true); 01051 } 01052 01053 USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) 01054 { 01055 return generalTransfer(dev, ep, buf, len, blocking, BULK_ENDPOINT, false); 01056 } 01057 01058 USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) 01059 { 01060 return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, true); 01061 } 01062 01063 USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) 01064 { 01065 return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, false); 01066 } 01067 01068 USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write) 01069 { 01070 01071 #if DEBUG_TRANSFER 01072 const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : "ISOCHRONOUS"); 01073 USB_DBG_TRANSFER("----- %s %s [dev: %p - %s - hub: %d - port: %d - addr: %d - ep: %02X]------", type_str, (write) ? "WRITE" : "READ", dev, dev->getName(ep->getIntfNb()), dev->getHub(), dev->getPort(), dev->getAddress(), ep->getAddress()); 01074 #endif 01075 01076 Lock lock(this); 01077 01078 USB_TYPE res; 01079 ENDPOINT_DIRECTION dir = (write) ? OUT : IN; 01080 01081 if (dev == NULL) { 01082 USB_ERR("dev NULL"); 01083 return USB_TYPE_ERROR; 01084 } 01085 01086 if (ep == NULL) { 01087 USB_ERR("ep NULL"); 01088 return USB_TYPE_ERROR; 01089 } 01090 01091 if (ep->getState() != USB_TYPE_IDLE) { 01092 USB_WARN("[ep: %p - dev: %p - %s] NOT IDLE: %s", ep, ep->dev, ep->dev->getName(ep->getIntfNb()), ep->getStateString()); 01093 return ep->getState(); 01094 } 01095 01096 if ((ep->getDir() != dir) || (ep->getType() != type)) { 01097 USB_ERR("[ep: %p - dev: %p] wrong dir or bad USBEndpoint type", ep, ep->dev); 01098 return USB_TYPE_ERROR; 01099 } 01100 01101 if (dev->getAddress() != ep->getDeviceAddress()) { 01102 USB_ERR("[ep: %p - dev: %p] USBEndpoint addr and device addr don't match", ep, ep->dev); 01103 return USB_TYPE_ERROR; 01104 } 01105 01106 #if DEBUG_TRANSFER 01107 if (write) { 01108 USB_DBG_TRANSFER("%s WRITE buffer", type_str); 01109 for (int i = 0; i < ep->getLengthTransferred(); i++) { 01110 printf("%02X ", buf[i]); 01111 } 01112 printf("\r\n\r\n"); 01113 } 01114 #endif 01115 res = addTransfer(ep, buf, len); 01116 01117 if ((blocking)&& (res == USB_TYPE_PROCESSING)) { 01118 #ifdef USBHOST_OTHER 01119 osEvent event = ep->ep_queue.get(TD_TIMEOUT); 01120 if (event.status == osEventTimeout) { 01121 /* control endpoint is confusing for merge on b */ 01122 disableList(CONTROL_ENDPOINT); 01123 ep->setState(USB_TYPE_ERROR); 01124 ep->ep_queue.get(0); 01125 ep->unqueueTransfer(ep->getProcessedTD()); 01126 enableList(CONTROL_ENDPOINT); 01127 } 01128 #else 01129 ep->ep_queue.get(); 01130 #endif 01131 res = ep->getState(); 01132 01133 USB_DBG_TRANSFER("%s TRANSFER res: %s on ep: %p\r\n", type_str, ep->getStateString(), ep); 01134 01135 if (res != USB_TYPE_IDLE) { 01136 return res; 01137 } 01138 01139 return USB_TYPE_OK; 01140 } 01141 01142 return res; 01143 01144 } 01145 01146 01147 USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) 01148 { 01149 return controlTransfer(dev, requestType, request, value, index, buf, len, false); 01150 } 01151 01152 USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) 01153 { 01154 return controlTransfer(dev, requestType, request, value, index, buf, len, true); 01155 } 01156 01157 USB_TYPE USBHost::controlTransfer(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len, bool write) 01158 { 01159 Lock lock(this); 01160 USB_DBG_TRANSFER("----- CONTROL %s [dev: %p - hub: %d - port: %d] ------", (write) ? "WRITE" : "READ", dev, dev->getHub(), dev->getPort()); 01161 01162 int length_transfer = len; 01163 USB_TYPE res; 01164 uint32_t token; 01165 01166 control->setSpeed(dev->getSpeed()); 01167 control->setSize(dev->getSizeControlEndpoint()); 01168 if (dev->isActiveAddress()) { 01169 control->setDeviceAddress(dev->getAddress()); 01170 } else { 01171 control->setDeviceAddress(0); 01172 } 01173 01174 USB_DBG_TRANSFER("Control transfer on device: %d\r\n", control->getDeviceAddress()); 01175 fillControlBuf(requestType, request, value, index, len); 01176 01177 #if DEBUG_TRANSFER 01178 USB_DBG_TRANSFER("SETUP PACKET: "); 01179 for (int i = 0; i < 8; i++) { 01180 printf("%01X ", setupPacket[i]); 01181 } 01182 printf("\r\n"); 01183 #endif 01184 01185 control->setNextToken(TD_SETUP); 01186 res = addTransfer(control, (uint8_t*)setupPacket, 8); 01187 01188 if (res == USB_TYPE_PROCESSING) 01189 #ifdef USBHOST_OTHER 01190 { 01191 osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL); 01192 if (event.status == osEventTimeout) { 01193 disableList(CONTROL_ENDPOINT); 01194 control->setState(USB_TYPE_ERROR); 01195 control->ep_queue.get(0); 01196 control->unqueueTransfer(control->getProcessedTD()); 01197 enableList(CONTROL_ENDPOINT); 01198 } 01199 } 01200 #else 01201 control->ep_queue.get(); 01202 #endif 01203 res = control->getState(); 01204 01205 USB_DBG_TRANSFER("CONTROL setup stage %s", control->getStateString()); 01206 01207 if (res != USB_TYPE_IDLE) { 01208 return res; 01209 } 01210 01211 if (length_transfer) { 01212 token = (write) ? TD_OUT : TD_IN; 01213 control->setNextToken(token); 01214 res = addTransfer(control, (uint8_t *)buf, length_transfer); 01215 01216 if (res == USB_TYPE_PROCESSING) 01217 #ifdef USBHOST_OTHER 01218 { 01219 osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL); 01220 if (event.status == osEventTimeout) { 01221 disableList(CONTROL_ENDPOINT); 01222 control->setState(USB_TYPE_ERROR); 01223 control->ep_queue.get(0); 01224 control->unqueueTransfer(control->getProcessedTD()); 01225 enableList(CONTROL_ENDPOINT); 01226 } 01227 } 01228 #else 01229 control->ep_queue.get(); 01230 #endif 01231 res = control->getState(); 01232 01233 #if DEBUG_TRANSFER 01234 USB_DBG_TRANSFER("CONTROL %s stage %s", (write) ? "WRITE" : "READ", control->getStateString()); 01235 if (write) { 01236 USB_DBG_TRANSFER("CONTROL WRITE buffer"); 01237 for (int i = 0; i < control->getLengthTransferred(); i++) { 01238 printf("%02X ", buf[i]); 01239 } 01240 printf("\r\n\r\n"); 01241 } else { 01242 USB_DBG_TRANSFER("CONTROL READ SUCCESS [%d bytes transferred]", control->getLengthTransferred()); 01243 for (int i = 0; i < control->getLengthTransferred(); i++) { 01244 printf("%02X ", buf[i]); 01245 } 01246 printf("\r\n\r\n"); 01247 } 01248 #endif 01249 01250 if (res != USB_TYPE_IDLE) { 01251 return res; 01252 } 01253 } 01254 01255 token = (write) ? TD_IN : TD_OUT; 01256 control->setNextToken(token); 01257 res = addTransfer(control, NULL, 0); 01258 if (res == USB_TYPE_PROCESSING) 01259 #ifdef USBHOST_OTHER 01260 { 01261 osEvent event = control->ep_queue.get(TD_TIMEOUT_CTRL); 01262 if (event.status == osEventTimeout) { 01263 disableList(CONTROL_ENDPOINT); 01264 control->setState(USB_TYPE_ERROR); 01265 control->ep_queue.get(0); 01266 control->unqueueTransfer(control->getProcessedTD()); 01267 enableList(CONTROL_ENDPOINT); 01268 } 01269 } 01270 #else 01271 control->ep_queue.get(); 01272 #endif 01273 res = control->getState(); 01274 01275 USB_DBG_TRANSFER("CONTROL ack stage %s", control->getStateString()); 01276 01277 if (res != USB_TYPE_IDLE) { 01278 return res; 01279 } 01280 01281 return USB_TYPE_OK; 01282 } 01283 01284 01285 void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint16_t value, uint16_t index, int len) 01286 { 01287 setupPacket[0] = requestType; 01288 setupPacket[1] = request; 01289 setupPacket[2] = (uint8_t) value; 01290 setupPacket[3] = (uint8_t) (value >> 8); 01291 setupPacket[4] = (uint8_t) index; 01292 setupPacket[5] = (uint8_t) (index >> 8); 01293 setupPacket[6] = (uint8_t) len; 01294 setupPacket[7] = (uint8_t) (len >> 8); 01295 }
Generated on Thu Jul 14 2022 14:36:24 by
