Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: DISCO-F469NI_USB_Disk STM32F4xx_USB_Memory
Fork of USBHOST by
USBHost.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 00018 #include "USBHost.h" 00019 #include "USBHostHub.h" 00020 00021 USBHost * USBHost::instHost = NULL; 00022 00023 #define DEVICE_CONNECTED_EVENT (1 << 0) 00024 #define DEVICE_DISCONNECTED_EVENT (1 << 1) 00025 #define TD_PROCESSED_EVENT (1 << 2) 00026 00027 #define MAX_TRY_ENUMERATE_HUB 3 00028 00029 #define MIN(a, b) ((a > b) ? b : a) 00030 00031 /** 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 }
Generated on Wed Jul 13 2022 01:49:38 by
1.7.2
