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 USBHostWANDongle by
USBHost.cpp
00001 /* Copyright (c) 2010-2012 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #define __DEBUG__ 0 //WARN: ENABLING DEBUGGING HERE WILL PRINTF IN IRQS!! UNEXPECTED BEHAVIOUR MAY RESULT... 00020 #ifndef __MODULE__ 00021 #define __MODULE__ "USBHost.cpp" 00022 #endif 00023 00024 #include "core/dbg.h" 00025 #include <cstdint> 00026 00027 #include "USBHost.h" 00028 #include "rtos.h" 00029 00030 00031 #define NB_MAX_INTF 2 00032 00033 USBHost * USBHost::instHost = NULL; 00034 00035 USBHost::USBHost() 00036 #if 0 //try not to use this 00037 : m_usbQueue(), m_usbThread(3, this, &USBHost::usbProcess) 00038 #endif 00039 { 00040 headControlEndpoint = NULL; 00041 headBulkEndpoint = NULL; 00042 headInterruptEndpoint = NULL; 00043 tailControlEndpoint = NULL; 00044 tailBulkEndpoint = NULL; 00045 tailInterruptEndpoint = NULL; 00046 00047 nb_devices = 0; 00048 lenReportDescr = 0; 00049 00050 controlEndpointAllocated = false; 00051 00052 for (int i = 0; i < MAX_DEVICE_NB; i++) { 00053 deviceInUse[i] = false; 00054 devices[i].setAddress(i + 1); 00055 deviceReset[i] = false; 00056 } 00057 } 00058 00059 00060 void USBHost::transferCompleted(volatile uint32_t addr) { 00061 #if 0 //try not to use this 00062 Interrupt::enter(); 00063 m_usbQueue.post(addr); 00064 Interrupt::leave(); 00065 #else 00066 00067 if(addr == NULL) //Nothing to process? 00068 { 00069 return; 00070 } 00071 00072 volatile HCTD* tdList = NULL; 00073 00074 //First we must reverse the list order and dequeue each TD 00075 do 00076 { 00077 volatile HCTD* td = (volatile HCTD*)addr; 00078 00079 if(td->control & 0xF0000000 != 0) 00080 { 00081 WARN("Condition code %02x", td->control >> 28); 00082 } 00083 00084 addr = td->nextTD; //Dequeue from physical list 00085 td->nextTD = (uint32_t)tdList; //Enqueue into reversed list 00086 tdList = td; 00087 } while(addr); 00088 00089 //Now we can process the list 00090 USBEndpoint * volatile iter = NULL; 00091 00092 while(tdList != NULL) 00093 { 00094 bool found = false; 00095 volatile HCTD* td = tdList; 00096 tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below 00097 for (int i = 0; i < 3; i++) { 00098 if (found) { 00099 break; 00100 } 00101 iter = (i == 0) ? headControlEndpoint : ( (i == 1) ? headBulkEndpoint : headInterruptEndpoint); 00102 while (iter != NULL) { 00103 if (iter->getProcessedTD() == td) { 00104 DBG("td=%p FOUND ed: %08X", td, (void *)iter->getHCED()); 00105 if (((HCTD *)td)->control >> 28) { 00106 DBG("TD Error: %d", td->control >> 28); 00107 iter->setState(USB_TYPE_TDFAIL); 00108 } else if ((uint32_t)iter->getHCED() & 0x1) { 00109 DBG("HALTED"); 00110 iter->setState(USB_TYPE_HALTED); 00111 } else if (!td->currBufPtr) { 00112 DBG("!%p", iter); 00113 iter->setState(USB_TYPE_IDLE); 00114 found=true; 00115 } else { 00116 DBG("!%p", iter); 00117 iter->setState(USB_TYPE_IDLE); 00118 iter->setLengthTransferred(td->currBufPtr - iter->getBufStart()); 00119 found=true; 00120 } 00121 break; 00122 } 00123 iter = iter->nextEndpoint(); 00124 } 00125 } 00126 00127 00128 if (found) { 00129 iter->unqueueTransfer(td); 00130 00131 if (iter->getType() != CONTROL_ENDPOINT) { 00132 iter->call(); 00133 } 00134 } 00135 else 00136 { 00137 WARN("TD not found!!!"); 00138 freeTD((uint8_t *)td); //Device must have been disconnected meanwhile 00139 } 00140 00141 } 00142 #endif 00143 } 00144 00145 USBHost * USBHost::getHostInst() { 00146 if (instHost == NULL) { 00147 instHost = new USBHost(); 00148 instHost->init(); 00149 } 00150 return instHost; 00151 } 00152 00153 00154 /* 00155 * Call in ISR when a device has been connected 00156 */ 00157 void USBHost::deviceConnected(int hub, int port, bool lowSpeed) { 00158 00159 for (int i = 0; i < MAX_DEVICE_NB; i++) { 00160 if (!deviceInUse[i]) { 00161 deviceInUse[i] = true; 00162 WARN("will call init on device %p: speed: %d", (void *)&devices[i], lowSpeed); 00163 devices[i].init(hub, port, lowSpeed); 00164 deviceReset[i] = false; 00165 break; 00166 } 00167 } 00168 00169 if (!controlEndpointAllocated) { 00170 control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00); 00171 addEndpoint(NULL, 0, (USBEndpoint*)control); 00172 controlEndpointAllocated = true; 00173 } 00174 } 00175 00176 /* 00177 * Call in ISR when a device has been disconnected 00178 */ 00179 void USBHost::deviceDisconnected(int hub, int port, volatile uint32_t addr) { 00180 00181 bool controlListState = disableControlList(); 00182 bool bulkListState = disableBulkList(); 00183 bool interruptListState = disableInterruptList(); 00184 00185 transferCompleted(addr); //Finish processing any pending completed TD 00186 00187 for (int i = 0; i < MAX_DEVICE_NB; i++) { 00188 if ((devices[i].getHub() == hub) && (devices[i].getPort() == port)) { 00189 WARN("device disconnected: %p", (void *)&devices[i]); 00190 deviceInUse[i] = false; 00191 deviceReset[i] = false; 00192 freeDevice((USBDeviceConnected*)&devices[i]); 00193 break; 00194 } 00195 } 00196 nb_devices--; 00197 00198 if (controlListState) enableControlList(); 00199 if (bulkListState) enableBulkList(); 00200 if (interruptListState) enableInterruptList(); 00201 } 00202 00203 void USBHost::freeDevice(USBDeviceConnected * dev) { 00204 USBEndpoint * ep = NULL; 00205 // HCTD * td = NULL; 00206 HCED * ed = NULL; 00207 00208 for (int j = 0; j < dev->getNbInterface(); j++) { 00209 DBG("FREE INTF %d, %p, nb_endpot: %d", j, (void *)dev->getInterface(j), dev->getInterface(j)->nb_endpoint); 00210 for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) { 00211 if ((ep = dev->getEndpoint(j, i)) != NULL) { 00212 DBG("Freeing USBEndpoint"); 00213 ed = (HCED *)ep->getHCED(); 00214 ed->control |= (1 << 13); //sKip bit 00215 DBG("Dequeueing USBEndpoint"); 00216 unqueueEndpoint(ep); 00217 00218 DBG("Freeing first transfer descriptor"); 00219 freeTD((volatile uint8_t*)ep->getTDList()[0]); 00220 DBG("Freeing second transfer descriptor"); 00221 freeTD((volatile uint8_t*)ep->getTDList()[1]); 00222 00223 DBG("Freeing USBEndpoint descriptor"); 00224 freeED((uint8_t *)ep->getHCED()); 00225 } 00226 //printBulk(); 00227 //printInt(); 00228 } 00229 } 00230 DBG("Disconnecting device"); 00231 dev->disconnect(); 00232 DBG("Device disconnected"); 00233 } 00234 00235 00236 void USBHost::unqueueEndpoint(USBEndpoint * ep) { 00237 USBEndpoint * prec = NULL; 00238 USBEndpoint * current = NULL; 00239 bool found = false; 00240 00241 DBG("want to unqueue ep: %p", (void *)ep->getHCED()); 00242 00243 for (int i = 0; i < 2; i++) { 00244 if (found) { 00245 DBG("USBEndpoint unqueued: %p", (void *)ep->getHCED()); 00246 break; 00247 } 00248 current = (i == 0) ? (USBEndpoint*)headBulkEndpoint : (USBEndpoint*)headInterruptEndpoint; 00249 prec = current; 00250 while (current != NULL) { 00251 if (current == ep) { 00252 if (current->nextEndpoint() != NULL) { 00253 prec->queueEndpoint(current->nextEndpoint()); 00254 if (current == headBulkEndpoint) { 00255 updateBulkHeadED((uint32_t)current->nextEndpoint()->getHCED()); 00256 headBulkEndpoint = current->nextEndpoint(); 00257 } 00258 if (current == headInterruptEndpoint) { 00259 updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED()); 00260 headInterruptEndpoint = current->nextEndpoint(); 00261 } 00262 } else { 00263 prec->queueEndpoint(NULL); 00264 if (current == headBulkEndpoint) { 00265 updateBulkHeadED(0); 00266 headBulkEndpoint = current->nextEndpoint(); 00267 } 00268 if (current == headInterruptEndpoint) { 00269 updateInterruptHeadED(0); 00270 headInterruptEndpoint = current->nextEndpoint(); 00271 } 00272 } 00273 found = true; 00274 current->setState(USB_TYPE_FREE); 00275 break; 00276 } 00277 prec = current; 00278 current = current->nextEndpoint(); 00279 } 00280 } 00281 //printBulk(); 00282 //printInt(); 00283 } 00284 00285 00286 USBDeviceConnected * USBHost::getDevice(uint8_t index) { 00287 if ((index >= MAX_DEVICE_NB) || (!deviceInUse[index])) { 00288 DBG("getDevice failed. Index is: %d, and deviceInUse[%d] is %s", index, index, deviceInUse[index]); 00289 return NULL; 00290 } 00291 return (USBDeviceConnected*)&devices[index]; 00292 } 00293 00294 00295 00296 // create an USBEndpoint descriptor. the USBEndpoint is not linked 00297 USBEndpoint * USBHost::newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) { 00298 int i = 0; 00299 HCED * ed = (HCED *)getED(); 00300 HCTD* td_list[2] = { (HCTD*)getTD(), (HCTD*)getTD() }; 00301 00302 memset((void *)td_list[0], 0x00, sizeof(HCTD)); 00303 memset((void *)td_list[1], 0x00, sizeof(HCTD)); 00304 00305 // search a free USBEndpoint 00306 for (i = 0; i < MAX_ENDPOINT; i++) { 00307 if (endpoints[i].getState() == USB_TYPE_FREE) { 00308 DBG("Trying to create ep"); 00309 endpoints[i].init(ed, type, dir, size, addr, td_list); 00310 //endpoints[i].queueTransfer(nullTd); 00311 DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d", &endpoints[i], type, dir, size, addr); 00312 return &endpoints[i]; 00313 } 00314 } 00315 DBG("could not allocate more endpoints!!!!"); 00316 return NULL; 00317 } 00318 00319 00320 USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev) { 00321 int index = findDevice(dev); 00322 if ((index != -1) && (!deviceReset[index])) { 00323 resetPort(dev->getHub(), dev->getPort()); 00324 deviceReset[index] = true; 00325 return USB_TYPE_OK; 00326 } 00327 return USB_TYPE_NOTFOUND; 00328 } 00329 00330 // link the USBEndpoint to the linked list and attach an USBEndpoint to a device 00331 bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep) { 00332 00333 if (ep == NULL) { 00334 return false; 00335 } 00336 00337 DBG("New ep %p", ep); 00338 00339 HCED * prevEd; 00340 00341 // set device address in the USBEndpoint descriptor 00342 if (dev == NULL) { 00343 ep->setDeviceAddress(0); 00344 } else { 00345 ep->setDeviceAddress(dev->getAddress()); 00346 } 00347 00348 if (dev != NULL && dev->getSpeed()) { 00349 DBG("add USBEndpoint: set speed"); 00350 ep->setSpeed(dev->getSpeed()); 00351 } 00352 00353 // queue the new USBEndpoint on the ED list 00354 switch (ep->getType()) { 00355 00356 case CONTROL_ENDPOINT: 00357 prevEd = ( HCED*) controlHeadED(); 00358 if (!prevEd) { 00359 updateControlHeadED((uint32_t) ep->getHCED()); 00360 DBG("First control USBEndpoint: %08X", (uint32_t) ep->getHCED()); 00361 headControlEndpoint = ep; 00362 tailControlEndpoint = ep; 00363 return true; 00364 } 00365 tailControlEndpoint->queueEndpoint(ep); 00366 tailControlEndpoint = ep; 00367 return true; 00368 00369 case BULK_ENDPOINT: 00370 prevEd = ( HCED*) bulkHeadED(); 00371 if (!prevEd) { 00372 updateBulkHeadED((uint32_t) ep->getHCED()); 00373 //DBG("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED()); 00374 headBulkEndpoint = ep; 00375 tailBulkEndpoint = ep; 00376 break; 00377 } 00378 tailBulkEndpoint->queueEndpoint(ep); 00379 tailBulkEndpoint = ep; 00380 break; 00381 00382 case INTERRUPT_ENDPOINT: 00383 prevEd = ( HCED*) interruptHeadED(); 00384 if (!prevEd) { 00385 updateInterruptHeadED((uint32_t) ep->getHCED()); 00386 //DBG("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED()); 00387 headInterruptEndpoint = ep; 00388 tailInterruptEndpoint = ep; 00389 break; 00390 } 00391 tailInterruptEndpoint->queueEndpoint(ep); 00392 tailInterruptEndpoint = ep; 00393 break; 00394 default: 00395 return false; 00396 } 00397 00398 dev->addEndpoint(intf_nb, ep); 00399 //printBulk(); 00400 //printInt(); 00401 00402 return true; 00403 } 00404 00405 00406 int USBHost::findDevice(USBDeviceConnected * dev) { 00407 for (int i = 0; i < MAX_DEVICE_NB; i++) { 00408 if (dev == &devices[i]) { 00409 return i; 00410 } 00411 } 00412 return -1; 00413 } 00414 00415 void USBHost::printBulk() { 00416 HCED * hced = (HCED *)bulkHeadED(); 00417 HCTD * hctd = NULL; 00418 printf("---------State of Bulk:--------\r\n"); 00419 while (hced != NULL) { 00420 printf("hced: %p\r\n", hced); 00421 hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f)); 00422 while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) { 00423 printf("\thctd: %p\r\n", hctd); 00424 hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f)); 00425 } 00426 printf("\thctd: %p\r\n", hctd); 00427 hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f)); 00428 } 00429 printf("--------------------\r\n"); 00430 } 00431 00432 void USBHost::printInt() { 00433 HCED * hced = (HCED *)interruptHeadED(); 00434 HCTD * hctd = NULL; 00435 printf("---------State of Int:--------\r\n"); 00436 while (hced != NULL) { 00437 printf("hced: %p\r\n", hced); 00438 hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f)); 00439 while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) { 00440 printf("\thctd: %p\r\n", hctd); 00441 hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f)); 00442 } 00443 printf("\thctd: %p\r\n", hctd); 00444 hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f)); 00445 } 00446 printf("--------------------\r\n"); 00447 } 00448 00449 00450 // add a transfer on the TD linked list 00451 USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) { 00452 00453 // allocate a TD which will be freed in TDcompletion 00454 volatile HCTD * td = ed->getNextTD(); 00455 if (td == NULL) { 00456 return USB_TYPE_ERROR; 00457 } 00458 00459 DBG("Next td = %p",td); 00460 00461 uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT )); 00462 00463 uint32_t td_toggle; 00464 00465 if (ed->getType() == CONTROL_ENDPOINT) { 00466 if (ed->isSetup()) { 00467 td_toggle = TD_TOGGLE_0; 00468 } else { 00469 td_toggle = TD_TOGGLE_1; 00470 } 00471 } else { 00472 td_toggle = 0; 00473 } 00474 00475 DBG("Buf=%d, len=%d", buf, len); 00476 td->control = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC); 00477 td->currBufPtr = (uint32_t) buf; 00478 td->bufEnd = (uint32_t)(buf + (len - 1)); 00479 00480 DBG("Now do queue transfer on ep %p", ed); 00481 00482 ed->queueTransfer(); 00483 00484 DBG("Enable list if needed"); 00485 00486 switch (ed->getType()) { 00487 case CONTROL_ENDPOINT: 00488 enableControlList(); 00489 break; 00490 case BULK_ENDPOINT: 00491 enableBulkList(); 00492 break; 00493 case INTERRUPT_ENDPOINT: 00494 //printInt(); 00495 enableInterruptList(); 00496 break; 00497 } 00498 00499 DBG("Wait for HC to process TD"); 00500 00501 00502 return USB_TYPE_PROCESSING; 00503 } 00504 00505 00506 00507 USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf) { 00508 return controlRead( dev, 00509 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00510 GET_DESCRIPTOR, 00511 (DEVICE_DESCRIPTOR << 8) | (0), 00512 0, 00513 buf, 00514 DEVICE_DESCRIPTOR_LENGTH); 00515 } 00516 00517 USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t * len_conf_descr) { 00518 USB_TYPE res; 00519 uint16_t total_conf_descr_length = 0; 00520 00521 // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr 00522 res = controlRead( dev, 00523 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00524 GET_DESCRIPTOR, 00525 (CONFIGURATION_DESCRIPTOR << 8) | (0), 00526 0, 00527 buf, 00528 CONFIGURATION_DESCRIPTOR_LENGTH); 00529 00530 if (res != USB_TYPE_OK) { 00531 ERR("GET CONF 1 DESCR FAILED"); 00532 return res; 00533 } 00534 total_conf_descr_length = buf[2] | (buf[3] << 8); 00535 if (len_conf_descr != NULL) { 00536 *len_conf_descr = total_conf_descr_length; 00537 } 00538 DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]); 00539 00540 return controlRead( dev, 00541 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00542 GET_DESCRIPTOR, 00543 (CONFIGURATION_DESCRIPTOR << 8) | (0), 00544 0, 00545 buf, 00546 total_conf_descr_length); 00547 00548 } 00549 00550 USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf) { 00551 return controlWrite( dev, 00552 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, 00553 SET_CONFIGURATION, 00554 conf, 00555 0, 00556 NULL, 00557 0); 00558 00559 } 00560 00561 00562 // enumerate a device with the control USBEndpoint 00563 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) { 00564 uint8_t data[415]; 00565 uint16_t total_conf_descr_length = 0; 00566 USB_TYPE res; 00567 00568 DBG("data = %p", data); 00569 00570 if (dev->isEnumerated()) { 00571 return USB_TYPE_OK; 00572 } 00573 00574 // first step: get the size of USBEndpoint 0 00575 DBG("Get size of EP 0"); 00576 res = controlRead( dev, 00577 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, 00578 GET_DESCRIPTOR, 00579 (DEVICE_DESCRIPTOR << 8) | (0), 00580 0, 00581 data, 00582 8); 00583 00584 if (res != USB_TYPE_OK) { 00585 ERR("Control read failed!!"); 00586 return res; 00587 } 00588 dev->setSizeControlEndpoint(data[7]); 00589 DBG("size control USBEndpoint: %d", dev->getSizeControlEndpoint()); 00590 00591 DBG("Now set addr"); 00592 // second step: set an address to the device 00593 res = controlWrite( dev, 00594 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, 00595 SET_ADDRESS, 00596 dev->getAddress(), 00597 0, 00598 NULL, 00599 0); 00600 00601 if (res != USB_TYPE_OK) { 00602 DBG("SET ADDR FAILED"); 00603 freeDevice(dev); 00604 return res; 00605 } 00606 dev->activeAddress(); 00607 00608 00609 // third step: get the whole device descriptor to see vid, pid 00610 res = getDeviceDescriptor(dev, data); 00611 00612 if (res != USB_TYPE_OK) { 00613 DBG("GET DEV DESCR FAILED"); 00614 return res; 00615 } 00616 dev->setClass(data[4]); 00617 dev->setSubClass(data[5]); 00618 dev->setProtocol(data[6]); 00619 dev->setVid(data[8] | (data[9] << 8)); 00620 dev->setPid(data[10] | (data[11] << 8)); 00621 DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); 00622 00623 pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); 00624 00625 res = getConfigurationDescriptor(dev, data, &total_conf_descr_length); 00626 if (res != USB_TYPE_OK) { 00627 return res; 00628 } 00629 00630 // Parse the configuration descriptor 00631 parseConfDescr(dev, data, total_conf_descr_length, pEnumerator); 00632 00633 00634 // sixth step: set configuration (only 1 supported) 00635 res = setConfiguration(dev, 1); 00636 00637 if (res != USB_TYPE_OK) { 00638 DBG("SET CONF FAILED"); 00639 freeDevice(dev); 00640 return res; 00641 } 00642 00643 // Now the device is enumerated! 00644 dev->setEnumerated(); 00645 DBG("device enumerated!!!!"); 00646 00647 // Some devices may require this delay 00648 Thread::wait(100); 00649 00650 return USB_TYPE_OK; 00651 } 00652 00653 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. 00654 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) { 00655 uint32_t index = 0; 00656 uint32_t len_desc = 0; 00657 uint8_t id = 0; 00658 int nb_endpoints_used = 0; 00659 USBEndpoint * ep = NULL; 00660 uint8_t intf_nb = 0; 00661 bool parsing_intf = false; 00662 00663 while (index < len) { 00664 len_desc = conf_descr[index]; 00665 id = conf_descr[index+1]; 00666 switch (id) { 00667 case CONFIGURATION_DESCRIPTOR: 00668 break; 00669 case INTERFACE_DESCRIPTOR: 00670 if(pEnumerator->parseInterface(intf_nb, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) 00671 { 00672 if (intf_nb++ <= NB_MAX_INTF) { 00673 dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); 00674 nb_endpoints_used = 0; 00675 DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", intf_nb - 1, (void *)dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); 00676 } else { 00677 DBG("Drop intf..."); 00678 } 00679 parsing_intf = true; 00680 } 00681 else 00682 { 00683 parsing_intf = false; 00684 } 00685 break; 00686 case ENDPOINT_DESCRIPTOR: 00687 DBG("Ep DESC"); 00688 if (parsing_intf && (intf_nb <= NB_MAX_INTF) ) { 00689 if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) { 00690 if( pEnumerator->useEndpoint(intf_nb - 1, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) ) 00691 { 00692 // if the USBEndpoint is isochronous -> skip it (TODO: fix this) 00693 if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) { 00694 ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03), 00695 (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1), 00696 conf_descr[index + 4] | (conf_descr[index + 5] << 8), 00697 conf_descr[index + 2] & 0x0f); 00698 DBG("ADD USBEndpoint %p, on interf %d on device %p", (void *)ep, intf_nb - 1, (void *)dev); 00699 if (ep != NULL && dev != NULL) { 00700 addEndpoint(dev, intf_nb - 1, ep); 00701 } else { 00702 DBG("EP NULL"); 00703 } 00704 nb_endpoints_used++; 00705 } else { 00706 DBG("ISO USBEndpoint NOT SUPPORTED"); 00707 } 00708 } 00709 } 00710 } 00711 //DBG("USBEndpoint DESCR"); 00712 break; 00713 case HID_DESCRIPTOR: 00714 lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); 00715 break; 00716 default: 00717 break; 00718 } 00719 index += len_desc; 00720 } 00721 } 00722 00723 00724 USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { 00725 USB_TYPE res; 00726 00727 if (dev == NULL || ep == NULL) { 00728 return USB_TYPE_ERROR; 00729 } 00730 00731 if ((ep->getDir() != IN) || (ep->getType() != BULK_ENDPOINT)) { 00732 DBG("wrong dir or bad USBEndpoint type"); 00733 return USB_TYPE_ERROR; 00734 } 00735 if (dev->getAddress() != ep->getDeviceAddress()) { 00736 DBG("USBEndpoint addr and device addr don't match"); 00737 return USB_TYPE_ERROR; 00738 } 00739 addTransfer(ep, buf, len); 00740 if (blocking) { 00741 unlock(); 00742 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00743 lock(); 00744 if (res != USB_TYPE_IDLE) { 00745 return res; 00746 } 00747 return USB_TYPE_OK; 00748 } 00749 return USB_TYPE_PROCESSING; 00750 } 00751 00752 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { 00753 USB_TYPE res; 00754 00755 if (dev == NULL || ep == NULL) { 00756 return USB_TYPE_ERROR; 00757 } 00758 00759 if ((ep->getDir() != OUT) || (ep->getType() != BULK_ENDPOINT)) { 00760 DBG("wrong dir or bad USBEndpoint type"); 00761 return USB_TYPE_ERROR; 00762 } 00763 if (dev->getAddress() != ep->getDeviceAddress()) { 00764 DBG("USBEndpoint addr and device addr don't match"); 00765 return USB_TYPE_ERROR; 00766 } 00767 addTransfer(ep, buf, len); 00768 if (blocking) { 00769 unlock(); 00770 while ((res = control->getState()) == USB_TYPE_PROCESSING) 00771 { 00772 DBG("!!!!!!!!!!!!!wait bulkwrite"); 00773 Thread::wait(100); 00774 } 00775 lock(); 00776 DBG("!!!!!!!!!!!!! bulkwrite finished"); 00777 if (res != USB_TYPE_IDLE) { 00778 return res; 00779 } 00780 return USB_TYPE_OK; 00781 } 00782 return USB_TYPE_PROCESSING; 00783 } 00784 00785 USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { 00786 USB_TYPE res; 00787 00788 if (dev == NULL || ep == NULL) { 00789 return USB_TYPE_ERROR; 00790 } 00791 00792 if (ep->getState() != USB_TYPE_IDLE) { 00793 return ep->getState(); 00794 } 00795 00796 if ((ep->getDir() != OUT) || (ep->getType() != INTERRUPT_ENDPOINT)) { 00797 ERR("wrong dir or bad USBEndpoint type: %d, %d", ep->getDir(), ep->getType()); 00798 return USB_TYPE_ERROR; 00799 } 00800 if (dev->getAddress() != ep->getDeviceAddress()) { 00801 ERR("USBEndpoint addr and device addr don't match"); 00802 return USB_TYPE_ERROR; 00803 } 00804 addTransfer(ep, buf, len); 00805 if (blocking) { 00806 while ((res = ep->getState()) == USB_TYPE_PROCESSING); 00807 if (res != USB_TYPE_IDLE) { 00808 return res; 00809 } 00810 return USB_TYPE_OK; 00811 } 00812 return USB_TYPE_PROCESSING; 00813 } 00814 00815 USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { 00816 USB_TYPE res; 00817 00818 if (dev == NULL || ep == NULL) { 00819 return USB_TYPE_ERROR; 00820 } 00821 00822 if (ep->getState() != USB_TYPE_IDLE) { 00823 return ep->getState(); 00824 } 00825 00826 if ((ep->getDir() != IN) || (ep->getType() != INTERRUPT_ENDPOINT)) { 00827 ERR("wrong dir or bad USBEndpoint type"); 00828 return USB_TYPE_ERROR; 00829 } 00830 00831 if (dev->getAddress() != ep->getDeviceAddress()) { 00832 ERR("USBEndpoint addr and device addr don't match"); 00833 return USB_TYPE_ERROR; 00834 } 00835 addTransfer(ep, buf, len); 00836 if (blocking) { 00837 while ((res = ep->getState()) == USB_TYPE_PROCESSING); 00838 if (res != USB_TYPE_IDLE) { 00839 return res; 00840 } 00841 return USB_TYPE_OK; 00842 } 00843 return USB_TYPE_PROCESSING; 00844 } 00845 00846 00847 USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00848 int length_transfer = len; 00849 //DBG("want to transfer: %d bytes\r\n", length_transfer); 00850 USB_TYPE res; 00851 control->setSpeed(dev->getSpeed()); 00852 control->setSize(dev->getSizeControlEndpoint()); 00853 if (dev->isActiveAddress()) { 00854 control->setDeviceAddress(dev->getAddress()); 00855 } else { 00856 control->setDeviceAddress(0); 00857 } 00858 fillControlBuf(requestType, request, value, index, len); 00859 /* DBG("will call transfer: "); 00860 for (int i = 0; i < 8; i++) { 00861 DBG("%02X ", setupPacket[i]); 00862 }*/ 00863 control->setNextToken(TD_SETUP); 00864 addTransfer(control, (uint8_t*)setupPacket, 8); 00865 DBG("Now wait for TD to be processed"); 00866 unlock(); 00867 DBG("Unlocked"); 00868 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00869 lock(); 00870 DBG("TD processed with result %d", res); 00871 if (res != USB_TYPE_IDLE) { 00872 return res; 00873 } 00874 00875 if (length_transfer) { 00876 DBG("In data to be transfered..."); 00877 control->setNextToken(TD_IN); 00878 addTransfer(control, (uint8_t *)buf, length_transfer); 00879 unlock(); 00880 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00881 lock(); 00882 if (res != USB_TYPE_IDLE) { 00883 return res; 00884 } 00885 } 00886 00887 DBG("Transfer NULL packet (OUT)"); 00888 control->setNextToken(TD_OUT); 00889 addTransfer(control, NULL, 0); 00890 unlock(); 00891 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00892 lock(); 00893 if (res != USB_TYPE_IDLE) { 00894 return res; 00895 } 00896 return USB_TYPE_OK; 00897 } 00898 00899 00900 USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00901 control->setSpeed(dev->getSpeed()); 00902 00903 int length_transfer = len; 00904 USB_TYPE res; 00905 00906 control->setSize(dev->getSizeControlEndpoint()); 00907 if (dev->isActiveAddress()) { 00908 control->setDeviceAddress(dev->getAddress()); 00909 } else { 00910 control->setDeviceAddress(0); 00911 } 00912 fillControlBuf(requestType, request, value, index, len); 00913 /*DBG("will call transfer: "); 00914 for (int i = 0; i < 8; i++) { 00915 printf("%01X ", setupPacket[i]); 00916 } 00917 printf("\r\n");*/ 00918 control->setNextToken(TD_SETUP); 00919 addTransfer(control, (uint8_t*)setupPacket, 8); 00920 unlock(); 00921 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00922 lock(); 00923 if (res != USB_TYPE_IDLE) { 00924 return res; 00925 } 00926 00927 if (length_transfer) { 00928 control->setNextToken(TD_OUT); 00929 addTransfer(control, (uint8_t *)buf, length_transfer); 00930 unlock(); 00931 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00932 lock(); 00933 if (res != USB_TYPE_IDLE) { 00934 return res; 00935 } 00936 } 00937 00938 control->setNextToken(TD_IN); 00939 addTransfer(control, NULL, 0); 00940 unlock(); 00941 while ((res = control->getState()) == USB_TYPE_PROCESSING); 00942 lock(); 00943 if (res != USB_TYPE_IDLE) { 00944 return res; 00945 } 00946 return USB_TYPE_OK; 00947 } 00948 00949 00950 void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, int len) { 00951 #ifdef __BIG_ENDIAN 00952 #error "Must implement BE to LE conv here" 00953 #endif 00954 setupPacket[0] = requestType; 00955 setupPacket[1] = request; 00956 //We are in LE so it's fine 00957 *((uint32_t*)&setupPacket[2]) = value; 00958 *((uint32_t*)&setupPacket[4]) = index; 00959 *((uint32_t*)&setupPacket[6]) = (uint32_t) len; 00960 } 00961
Generated on Thu Jul 14 2022 09:11:27 by
1.7.2
