Kenji Arai / USBHOST

Dependents:   DISCO-F469NI_USB_Disk STM32F4xx_USB_Memory

Fork of USBHOST by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

USBHost.cpp

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