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