USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

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