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