USB Host WAN Dongle library
Fork of USBHostWANDongle_bleedingedge 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 Tue Jul 12 2022 20:45:23 by 1.7.2