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