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