1 /* mbed USBHost Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "USBHostHub.h"
21 USBHost
* USBHost::instHost
= NULL
;
23 #define DEVICE_CONNECTED_EVENT (1 << 0)
24 #define DEVICE_DISCONNECTED_EVENT (1 << 1)
25 #define TD_PROCESSED_EVENT (1 << 2)
27 #define MAX_TRY_ENUMERATE_HUB 3
29 #define MIN(a, b) ((a > b) ? b : a)
32 * How interrupts are processed:
33 * - new device connected:
34 * - a message is queued in queue_usb_event with the id DEVICE_CONNECTED_EVENT
35 * - when the usb_thread receives the event, it:
37 * - reads the device descriptor
38 * - sets the address of the device
39 * - if it is a hub, enumerates it
40 * - device disconnected:
41 * - a message is queued in queue_usb_event with the id DEVICE_DISCONNECTED_EVENT
42 * - when the usb_thread receives the event, it:
43 * - free the device and all its children (hub)
45 * - a message is queued in queue_usb_event with the id TD_PROCESSED_EVENT
46 * - when the usb_thread receives the event, it:
47 * - call the callback attached to the endpoint where the td is attached
49 void USBHost::usb_process() {
51 bool controlListState
;
53 bool interruptListState
;
55 uint8_t i
, j
, res
, timeout_set_addr
= 10;
61 uint8_t * buf_transfer
;
69 osEvent evt
= mail_usb_event
.get();
71 if (evt
.status
== osEventMail
) {
73 message_t
* usb_msg
= (message_t
*)evt
.value
.p
;
75 switch (usb_msg
->event_id
) {
77 // a new device has been connected
78 case DEVICE_CONNECTED_EVENT
:
86 for (i
= 0; i
< MAX_DEVICE_CONNECTED
; i
++) {
87 if (!deviceInUse
[i
]) {
88 USB_DBG_EVENT("new device connected: %p\r\n", &devices
[i
]);
89 devices
[i
].init(usb_msg
->hub
, usb_msg
->port
, usb_msg
->lowSpeed
);
90 deviceReset
[i
] = false;
91 deviceInited
[i
] = true;
96 if (i
== MAX_DEVICE_CONNECTED
) {
97 USB_ERR("Too many device connected!!\r\n");
101 if (!controlEndpointAllocated
) {
102 control
= newEndpoint(CONTROL_ENDPOINT
, OUT
, 0x08, 0x00);
103 addEndpoint(NULL
, 0, (USBEndpoint
*)control
);
104 controlEndpointAllocated
= true;
108 if (usb_msg
->hub_parent
)
109 devices
[i
].setHubParent((USBHostHub
*)(usb_msg
->hub_parent
));
112 for (j
= 0; j
< timeout_set_addr
; j
++) {
114 resetDevice(&devices
[i
]);
116 // set size of control endpoint
117 devices
[i
].setSizeControlEndpoint(8);
119 devices
[i
].activeAddress(false);
121 // get first 8 bit of device descriptor
122 // and check if we deal with a hub
123 USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices
[i
]);
124 res
= getDeviceDescriptor(&devices
[i
], buf
, 8);
126 if (res
!= USB_TYPE_OK
) {
127 USB_ERR("usb_thread could not read dev descr");
131 // set size of control endpoint
132 devices
[i
].setSizeControlEndpoint(buf
[7]);
134 // second step: set an address to the device
135 res
= setAddress(&devices
[i
], devices
[i
].getAddress());
137 if (res
!= USB_TYPE_OK
) {
138 USB_ERR("SET ADDR FAILED");
141 devices
[i
].activeAddress(true);
142 USB_DBG("Address of %p: %d", &devices
[i
], devices
[i
].getAddress());
144 // try to read again the device descriptor to check if the device
145 // answers to its new address
146 res
= getDeviceDescriptor(&devices
[i
], buf
, 8);
148 if (res
== USB_TYPE_OK
) {
155 USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices
[i
], usb_msg
->hub
, usb_msg
->port
);
158 if (buf
[4] == HUB_CLASS
) {
159 for (k
= 0; k
< MAX_HUB_NB
; k
++) {
160 if (hub_in_use
[k
] == false) {
161 for (uint8_t j
= 0; j
< MAX_TRY_ENUMERATE_HUB
; j
++) {
162 if (hubs
[k
].connect(&devices
[i
])) {
163 devices
[i
].hub
= &hubs
[k
];
164 hub_in_use
[k
] = true;
168 if (hub_in_use
[k
] == true)
173 if (k
== MAX_HUB_NB
) {
174 USB_ERR("Too many hubs connected!!\r\n");
179 if (usb_msg
->hub_parent
)
180 ((USBHostHub
*)(usb_msg
->hub_parent
))->deviceConnected(&devices
[i
]);
183 if ((i
< MAX_DEVICE_CONNECTED
) && !too_many_hub
) {
184 deviceInUse
[i
] = true;
191 // a device has been disconnected
192 case DEVICE_DISCONNECTED_EVENT
:
198 controlListState
= disableList(CONTROL_ENDPOINT
);
199 bulkListState
= disableList(BULK_ENDPOINT
);
200 interruptListState
= disableList(INTERRUPT_ENDPOINT
);
202 idx
= findDevice(usb_msg
->hub
, usb_msg
->port
, (USBHostHub
*)(usb_msg
->hub_parent
));
204 freeDevice((USBDeviceConnected
*)&devices
[idx
]);
207 if (controlListState
) enableList(CONTROL_ENDPOINT
);
208 if (bulkListState
) enableList(BULK_ENDPOINT
);
209 if (interruptListState
) enableList(INTERRUPT_ENDPOINT
);
215 // a td has been processed
216 // call callback on the ed associated to the td
217 // we are not in ISR -> users can use printf in their callback method
218 case TD_PROCESSED_EVENT
:
219 ep
= (USBEndpoint
*) ((HCTD
*)usb_msg
->td_addr
)->ep
;
220 if (usb_msg
->td_state
== USB_TYPE_IDLE
) {
221 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()));
224 if (ep
->getDir() == IN
) {
225 buf_transfer
= ep
->getBufStart();
226 printf("READ SUCCESS [%d bytes transferred - td: 0x%08X] on ep: [%p - addr: %02X]: ", ep
->getLengthTransferred(), usb_msg
->td_addr
, ep
, ep
->getAddress());
227 for (int i
= 0; i
< ep
->getLengthTransferred(); i
++)
228 printf("%02X ", buf_transfer
[i
]);
234 idx
= findDevice(ep
->dev
);
236 if (deviceInUse
[idx
]) {
237 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()));
238 ep
->setState(USB_TYPE_IDLE
);
245 mail_usb_event
.free(usb_msg
);
250 /* static */void USBHost::usb_process_static(void const * arg
) {
251 ((USBHost
*)arg
)->usb_process();
254 USBHost::USBHost() : usbThread(USBHost::usb_process_static
, (void *)this, osPriorityNormal
, USB_THREAD_STACK
)
256 headControlEndpoint
= NULL
;
257 headBulkEndpoint
= NULL
;
258 headInterruptEndpoint
= NULL
;
259 tailControlEndpoint
= NULL
;
260 tailBulkEndpoint
= NULL
;
261 tailInterruptEndpoint
= NULL
;
265 controlEndpointAllocated
= false;
267 for (uint8_t i
= 0; i
< MAX_DEVICE_CONNECTED
; i
++) {
268 deviceInUse
[i
] = false;
269 devices
[i
].setAddress(i
+ 1);
270 deviceReset
[i
] = false;
271 deviceInited
[i
] = false;
272 for (uint8_t j
= 0; j
< MAX_INTF
; j
++)
273 deviceAttachedDriver
[i
][j
] = false;
277 for (uint8_t i
= 0; i
< MAX_HUB_NB
; i
++) {
278 hubs
[i
].setHost(this);
279 hub_in_use
[i
] = false;
284 USBHost::Lock::Lock(USBHost
* pHost
) : m_pHost(pHost
)
286 m_pHost
->usb_mutex
.lock();
289 USBHost::Lock::~Lock()
291 m_pHost
->usb_mutex
.unlock();
294 void USBHost::transferCompleted(volatile uint32_t addr
)
301 volatile HCTD
* tdList
= NULL
;
303 //First we must reverse the list order and dequeue each TD
305 volatile HCTD
* td
= (volatile HCTD
*)addr
;
306 addr
= (uint32_t)td
->nextTD
; //Dequeue from physical list
307 td
->nextTD
= tdList
; //Enqueue into reversed list
311 while(tdList
!= NULL
) {
312 volatile HCTD
* td
= tdList
;
313 tdList
= (volatile HCTD
*)td
->nextTD
; //Dequeue element now as it could be modified below
314 if (td
->ep
!= NULL
) {
315 USBEndpoint
* ep
= (USBEndpoint
*)(td
->ep
);
317 if (((HCTD
*)td
)->control
>> 28) {
318 state
= ((HCTD
*)td
)->control
>> 28;
321 ep
->setLengthTransferred((uint32_t)td
->currBufPtr
- (uint32_t)ep
->getBufStart());
322 state
= 16 /*USB_TYPE_IDLE*/;
325 ep
->unqueueTransfer(td
);
327 if (ep
->getType() != CONTROL_ENDPOINT
) {
328 // callback on the processed td will be called from the usb_thread (not in ISR)
329 message_t
* usb_msg
= mail_usb_event
.alloc();
330 usb_msg
->event_id
= TD_PROCESSED_EVENT
;
331 usb_msg
->td_addr
= (void *)td
;
332 usb_msg
->td_state
= state
;
333 mail_usb_event
.put(usb_msg
);
336 ep
->ep_queue
.put((uint8_t*)1);
341 USBHost
* USBHost::getHostInst()
343 if (instHost
== NULL
) {
344 instHost
= new USBHost();
352 * Called when a device has been connected
353 * Called in ISR!!!! (no printf)
355 /* virtual */ void USBHost::deviceConnected(int hub
, int port
, bool lowSpeed
, USBHostHub
* hub_parent
)
357 // be sure that the new device connected is not already connected...
358 int idx
= findDevice(hub
, port
, hub_parent
);
360 if (deviceInited
[idx
])
364 message_t
* usb_msg
= mail_usb_event
.alloc();
365 usb_msg
->event_id
= DEVICE_CONNECTED_EVENT
;
367 usb_msg
->port
= port
;
368 usb_msg
->lowSpeed
= lowSpeed
;
369 usb_msg
->hub_parent
= hub_parent
;
370 mail_usb_event
.put(usb_msg
);
374 * Called when a device has been disconnected
375 * Called in ISR!!!! (no printf)
377 /* virtual */ void USBHost::deviceDisconnected(int hub
, int port
, USBHostHub
* hub_parent
, volatile uint32_t addr
)
379 // be sure that the device disconnected is connected...
380 int idx
= findDevice(hub
, port
, hub_parent
);
382 if (!deviceInUse
[idx
])
388 message_t
* usb_msg
= mail_usb_event
.alloc();
389 usb_msg
->event_id
= DEVICE_DISCONNECTED_EVENT
;
391 usb_msg
->port
= port
;
392 usb_msg
->hub_parent
= hub_parent
;
393 mail_usb_event
.put(usb_msg
);
396 void USBHost::freeDevice(USBDeviceConnected
* dev
)
398 USBEndpoint
* ep
= NULL
;
402 if (dev
->getClass() == HUB_CLASS
) {
403 if (dev
->hub
== NULL
) {
404 USB_ERR("HUB NULL!!!!!\r\n");
406 dev
->hub
->hubDisconnected();
407 for (uint8_t i
= 0; i
< MAX_HUB_NB
; i
++) {
408 if (dev
->hub
== &hubs
[i
]) {
409 hub_in_use
[i
] = false;
416 // notify hub parent that this device has been disconnected
417 if (dev
->getHubParent())
418 dev
->getHubParent()->deviceDisconnected(dev
);
422 int idx
= findDevice(dev
);
424 deviceInUse
[idx
] = false;
425 deviceReset
[idx
] = false;
427 for (uint8_t j
= 0; j
< MAX_INTF
; j
++) {
428 deviceAttachedDriver
[idx
][j
] = false;
429 if (dev
->getInterface(j
) != NULL
) {
430 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
));
431 for (int i
= 0; i
< dev
->getInterface(j
)->nb_endpoint
; i
++) {
432 if ((ep
= dev
->getEndpoint(j
, i
)) != NULL
) {
433 ed
= (HCED
*)ep
->getHCED();
434 ed
->control
|= (1 << 14); //sKip bit
437 freeTD((volatile uint8_t*)ep
->getTDList()[0]);
438 freeTD((volatile uint8_t*)ep
->getTDList()[1]);
440 freeED((uint8_t *)ep
->getHCED());
442 printList(BULK_ENDPOINT
);
443 printList(INTERRUPT_ENDPOINT
);
445 USB_INFO("Device disconnected [%p - %s - hub: %d - port: %d]", dev
, dev
->getName(j
), dev
->getHub(), dev
->getPort());
453 void USBHost::unqueueEndpoint(USBEndpoint
* ep
)
455 USBEndpoint
* prec
= NULL
;
456 USBEndpoint
* current
= NULL
;
458 for (int i
= 0; i
< 2; i
++) {
459 current
= (i
== 0) ? (USBEndpoint
*)headBulkEndpoint
: (USBEndpoint
*)headInterruptEndpoint
;
461 while (current
!= NULL
) {
463 if (current
->nextEndpoint() != NULL
) {
464 prec
->queueEndpoint(current
->nextEndpoint());
465 if (current
== headBulkEndpoint
) {
466 updateBulkHeadED((uint32_t)current
->nextEndpoint()->getHCED());
467 headBulkEndpoint
= current
->nextEndpoint();
468 } else if (current
== headInterruptEndpoint
) {
469 updateInterruptHeadED((uint32_t)current
->nextEndpoint()->getHCED());
470 headInterruptEndpoint
= current
->nextEndpoint();
473 // here we are dequeuing the queue of ed
474 // we need to update the tail pointer
476 prec
->queueEndpoint(NULL
);
477 if (current
== headBulkEndpoint
) {
479 headBulkEndpoint
= current
->nextEndpoint();
480 } else if (current
== headInterruptEndpoint
) {
481 updateInterruptHeadED(0);
482 headInterruptEndpoint
= current
->nextEndpoint();
486 switch (current
->getType()) {
488 tailBulkEndpoint
= prec
;
490 case INTERRUPT_ENDPOINT
:
491 tailInterruptEndpoint
= prec
;
497 current
->setState(USB_TYPE_FREE
);
501 current
= current
->nextEndpoint();
507 USBDeviceConnected
* USBHost::getDevice(uint8_t index
)
509 if ((index
>= MAX_DEVICE_CONNECTED
) || (!deviceInUse
[index
])) {
512 return (USBDeviceConnected
*)&devices
[index
];
515 // create an USBEndpoint descriptor. the USBEndpoint is not linked
516 USBEndpoint
* USBHost::newEndpoint(ENDPOINT_TYPE type
, ENDPOINT_DIRECTION dir
, uint32_t size
, uint8_t addr
)
519 HCED
* ed
= (HCED
*)getED();
520 HCTD
* td_list
[2] = { (HCTD
*)getTD(), (HCTD
*)getTD() };
522 memset((void *)td_list
[0], 0x00, sizeof(HCTD
));
523 memset((void *)td_list
[1], 0x00, sizeof(HCTD
));
525 // search a free USBEndpoint
526 for (i
= 0; i
< MAX_ENDPOINT
; i
++) {
527 if (endpoints
[i
].getState() == USB_TYPE_FREE
) {
528 endpoints
[i
].init(ed
, type
, dir
, size
, addr
, td_list
);
529 USB_DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d, state: %s", &endpoints
[i
], type
, dir
, size
, addr
, endpoints
[i
].getStateString());
530 return &endpoints
[i
];
533 USB_ERR("could not allocate more endpoints!!!!");
538 USB_TYPE
USBHost::resetDevice(USBDeviceConnected
* dev
)
540 int index
= findDevice(dev
);
542 USB_DBG("Resetting hub %d, port %d\n", dev
->getHub(), dev
->getPort());
544 if (dev
->getHub() == 0) {
549 dev
->getHubParent()->portReset(dev
->getPort());
553 deviceReset
[index
] = true;
557 return USB_TYPE_ERROR
;
560 // link the USBEndpoint to the linked list and attach an USBEndpoint to a device
561 bool USBHost::addEndpoint(USBDeviceConnected
* dev
, uint8_t intf_nb
, USBEndpoint
* ep
)
570 // set device address in the USBEndpoint descriptor
572 ep
->setDeviceAddress(0);
574 ep
->setDeviceAddress(dev
->getAddress());
577 if ((dev
!= NULL
) && dev
->getSpeed()) {
578 ep
->setSpeed(dev
->getSpeed());
581 ep
->setIntfNb(intf_nb
);
583 // queue the new USBEndpoint on the ED list
584 switch (ep
->getType()) {
586 case CONTROL_ENDPOINT
:
587 prevEd
= ( HCED
*) controlHeadED();
589 updateControlHeadED((uint32_t) ep
->getHCED());
590 USB_DBG_TRANSFER("First control USBEndpoint: %08X", (uint32_t) ep
->getHCED());
591 headControlEndpoint
= ep
;
592 tailControlEndpoint
= ep
;
595 tailControlEndpoint
->queueEndpoint(ep
);
596 tailControlEndpoint
= ep
;
600 prevEd
= ( HCED
*) bulkHeadED();
602 updateBulkHeadED((uint32_t) ep
->getHCED());
603 USB_DBG_TRANSFER("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep
->getHCED());
604 headBulkEndpoint
= ep
;
605 tailBulkEndpoint
= ep
;
608 USB_DBG_TRANSFER("Queue BULK Ed %p after %p\r\n",ep
->getHCED(), prevEd
);
609 tailBulkEndpoint
->queueEndpoint(ep
);
610 tailBulkEndpoint
= ep
;
613 case INTERRUPT_ENDPOINT
:
614 prevEd
= ( HCED
*) interruptHeadED();
616 updateInterruptHeadED((uint32_t) ep
->getHCED());
617 USB_DBG_TRANSFER("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep
->getHCED());
618 headInterruptEndpoint
= ep
;
619 tailInterruptEndpoint
= ep
;
622 USB_DBG_TRANSFER("Queue INTERRUPT Ed %p after %p\r\n",ep
->getHCED(), prevEd
);
623 tailInterruptEndpoint
->queueEndpoint(ep
);
624 tailInterruptEndpoint
= ep
;
631 dev
->addEndpoint(intf_nb
, ep
);
637 int USBHost::findDevice(USBDeviceConnected
* dev
)
639 for (int i
= 0; i
< MAX_DEVICE_CONNECTED
; i
++) {
640 if (dev
== &devices
[i
]) {
647 int USBHost::findDevice(uint8_t hub
, uint8_t port
, USBHostHub
* hub_parent
)
649 for (int i
= 0; i
< MAX_DEVICE_CONNECTED
; i
++) {
650 if (devices
[i
].getHub() == hub
&& devices
[i
].getPort() == port
) {
651 if (hub_parent
!= NULL
) {
652 if (hub_parent
== devices
[i
].getHubParent())
662 void USBHost::printList(ENDPOINT_TYPE type
)
665 volatile HCED
* hced
;
667 case CONTROL_ENDPOINT
:
668 hced
= (HCED
*)controlHeadED();
671 hced
= (HCED
*)bulkHeadED();
673 case INTERRUPT_ENDPOINT
:
674 hced
= (HCED
*)interruptHeadED();
677 volatile HCTD
* hctd
= NULL
;
678 const char * type_str
= (type
== BULK_ENDPOINT
) ? "BULK" :
679 ((type
== INTERRUPT_ENDPOINT
) ? "INTERRUPT" :
680 ((type
== CONTROL_ENDPOINT
) ? "CONTROL" : "ISOCHRONOUS"));
681 printf("State of %s:\r\n", type_str
);
682 while (hced
!= NULL
) {
683 uint8_t dir
= ((hced
->control
& (3 << 11)) >> 11);
684 printf("hced: %p [ADDR: %d, DIR: %s, EP_NB: 0x%X]\r\n", hced
,
685 hced
->control
& 0x7f,
686 (dir
== 1) ? "OUT" : ((dir
== 0) ? "FROM_TD":"IN"),
687 (hced
->control
& (0xf << 7)) >> 7);
688 hctd
= (HCTD
*)((uint32_t)(hced
->headTD
) & ~(0xf));
689 while (hctd
!= hced
->tailTD
) {
690 printf("\thctd: %p [DIR: %s]\r\n", hctd
, ((hctd
->control
& (3 << 19)) >> 19) == 1 ? "OUT" : "IN");
693 printf("\thctd: %p\r\n", hctd
);
701 // add a transfer on the TD linked list
702 USB_TYPE
USBHost::addTransfer(USBEndpoint
* ed
, uint8_t * buf
, uint32_t len
)
706 // allocate a TD which will be freed in TDcompletion
707 volatile HCTD
* td
= ed
->getNextTD();
709 return USB_TYPE_ERROR
;
712 uint32_t token
= (ed
->isSetup() ? TD_SETUP
: ( (ed
->getDir() == IN
) ? TD_IN
: TD_OUT
));
716 if (ed
->getType() == CONTROL_ENDPOINT
) {
718 td_toggle
= TD_TOGGLE_0
;
720 td_toggle
= TD_TOGGLE_1
;
726 td
->control
= (TD_ROUNDING
| token
| TD_DELAY_INT(0) | td_toggle
| TD_CC
);
727 td
->currBufPtr
= buf
;
728 td
->bufEnd
= (buf
+ (len
- 1));
730 ENDPOINT_TYPE type
= ed
->getType();
739 return USB_TYPE_PROCESSING
;
744 USB_TYPE
USBHost::getDeviceDescriptor(USBDeviceConnected
* dev
, uint8_t * buf
, uint16_t max_len_buf
, uint16_t * len_dev_descr
)
746 USB_TYPE t
= controlRead( dev
,
747 USB_DEVICE_TO_HOST
| USB_RECIPIENT_DEVICE
,
749 (DEVICE_DESCRIPTOR
<< 8) | (0),
750 0, buf
, MIN(DEVICE_DESCRIPTOR_LENGTH
, max_len_buf
));
752 *len_dev_descr
= MIN(DEVICE_DESCRIPTOR_LENGTH
, max_len_buf
);
757 USB_TYPE
USBHost::getConfigurationDescriptor(USBDeviceConnected
* dev
, uint8_t * buf
, uint16_t max_len_buf
, uint16_t * len_conf_descr
)
760 uint16_t total_conf_descr_length
= 0;
762 // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr
763 res
= controlRead( dev
,
764 USB_DEVICE_TO_HOST
| USB_RECIPIENT_DEVICE
,
766 (CONFIGURATION_DESCRIPTOR
<< 8) | (0),
767 0, buf
, CONFIGURATION_DESCRIPTOR_LENGTH
);
769 if (res
!= USB_TYPE_OK
) {
770 USB_ERR("GET CONF 1 DESCR FAILED");
773 total_conf_descr_length
= buf
[2] | (buf
[3] << 8);
774 total_conf_descr_length
= MIN(max_len_buf
, total_conf_descr_length
);
777 *len_conf_descr
= total_conf_descr_length
;
779 USB_DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length
, buf
[4]);
781 return controlRead( dev
,
782 USB_DEVICE_TO_HOST
| USB_RECIPIENT_DEVICE
,
784 (CONFIGURATION_DESCRIPTOR
<< 8) | (0),
785 0, buf
, total_conf_descr_length
);
789 USB_TYPE
USBHost::setAddress(USBDeviceConnected
* dev
, uint8_t address
) {
790 return controlWrite( dev
,
791 USB_HOST_TO_DEVICE
| USB_RECIPIENT_DEVICE
,
798 USB_TYPE
USBHost::setConfiguration(USBDeviceConnected
* dev
, uint8_t conf
)
800 return controlWrite( dev
,
801 USB_HOST_TO_DEVICE
| USB_RECIPIENT_DEVICE
,
807 uint8_t USBHost::numberDriverAttached(USBDeviceConnected
* dev
) {
808 int index
= findDevice(dev
);
812 for (uint8_t i
= 0; i
< MAX_INTF
; i
++) {
813 if (deviceAttachedDriver
[index
][i
])
819 // enumerate a device with the control USBEndpoint
820 USB_TYPE
USBHost::enumerate(USBDeviceConnected
* dev
, IUSBEnumerator
* pEnumerator
)
822 uint16_t total_conf_descr_length
= 0;
829 // don't enumerate a device which all interfaces are registered to a specific driver
830 int index
= findDevice(dev
);
833 return USB_TYPE_ERROR
;
836 uint8_t nb_intf_attached
= numberDriverAttached(dev
);
837 USB_DBG("dev: %p nb_intf: %d", dev
, dev
->getNbIntf());
838 USB_DBG("dev: %p nb_intf_attached: %d", dev
, nb_intf_attached
);
839 if ((nb_intf_attached
!= 0) && (dev
->getNbIntf() == nb_intf_attached
)) {
840 USB_DBG("Don't enumerate dev: %p because all intf are registered with a driver", dev
);
844 USB_DBG("Enumerate dev: %p", dev
);
846 // third step: get the whole device descriptor to see vid, pid
847 res
= getDeviceDescriptor(dev
, data
, DEVICE_DESCRIPTOR_LENGTH
);
849 if (res
!= USB_TYPE_OK
) {
850 USB_DBG("GET DEV DESCR FAILED");
854 dev
->setClass(data
[4]);
855 dev
->setSubClass(data
[5]);
856 dev
->setProtocol(data
[6]);
857 dev
->setVid(data
[8] | (data
[9] << 8));
858 dev
->setPid(data
[10] | (data
[11] << 8));
859 USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data
[4], data
[8] | (data
[9] << 8), data
[10] | (data
[11] << 8));
861 pEnumerator
->setVidPid( data
[8] | (data
[9] << 8), data
[10] | (data
[11] << 8) );
863 res
= getConfigurationDescriptor(dev
, data
, sizeof(data
), &total_conf_descr_length
);
864 if (res
!= USB_TYPE_OK
) {
869 USB_DBG("CONFIGURATION DESCRIPTOR:\r\n");
870 for (int i
= 0; i
< total_conf_descr_length
; i
++)
871 printf("%02X ", data
[i
]);
875 // Parse the configuration descriptor
876 parseConfDescr(dev
, data
, total_conf_descr_length
, pEnumerator
);
878 // only set configuration if not enumerated before
879 if (!dev
->isEnumerated()) {
881 USB_DBG("Set configuration 1 on dev: %p", dev
);
882 // sixth step: set configuration (only 1 supported)
883 res
= setConfiguration(dev
, 1);
885 if (res
!= USB_TYPE_OK
) {
886 USB_DBG("SET CONF FAILED");
891 dev
->setEnumerated();
893 // Now the device is enumerated!
894 USB_DBG("dev %p is enumerated\r\n", dev
);
898 // Some devices may require this delay
903 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
904 void USBHost::parseConfDescr(USBDeviceConnected
* dev
, uint8_t * conf_descr
, uint32_t len
, IUSBEnumerator
* pEnumerator
)
907 uint32_t len_desc
= 0;
909 int nb_endpoints_used
= 0;
910 USBEndpoint
* ep
= NULL
;
912 bool parsing_intf
= false;
913 uint8_t current_intf
= 0;
915 while (index
< len
) {
916 len_desc
= conf_descr
[index
];
917 id
= conf_descr
[index
+1];
919 case CONFIGURATION_DESCRIPTOR
:
920 USB_DBG("dev: %p has %d intf", dev
, conf_descr
[4]);
921 dev
->setNbIntf(conf_descr
[4]);
923 case INTERFACE_DESCRIPTOR
:
924 if(pEnumerator
->parseInterface(conf_descr
[index
+ 2], conf_descr
[index
+ 5], conf_descr
[index
+ 6], conf_descr
[index
+ 7])) {
925 if (intf_nb
++ <= MAX_INTF
) {
926 current_intf
= conf_descr
[index
+ 2];
927 dev
->addInterface(current_intf
, conf_descr
[index
+ 5], conf_descr
[index
+ 6], conf_descr
[index
+ 7]);
928 nb_endpoints_used
= 0;
929 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]);
931 USB_DBG("Drop intf...");
935 parsing_intf
= false;
938 case ENDPOINT_DESCRIPTOR
:
939 if (parsing_intf
&& (intf_nb
<= MAX_INTF
) ) {
940 if (nb_endpoints_used
< MAX_ENDPOINT_PER_INTERFACE
) {
941 if( pEnumerator
->useEndpoint(current_intf
, (ENDPOINT_TYPE
)(conf_descr
[index
+ 3] & 0x03), (ENDPOINT_DIRECTION
)((conf_descr
[index
+ 2] >> 7) + 1)) ) {
942 // if the USBEndpoint is isochronous -> skip it (TODO: fix this)
943 if ((conf_descr
[index
+ 3] & 0x03) != ISOCHRONOUS_ENDPOINT
) {
944 ep
= newEndpoint((ENDPOINT_TYPE
)(conf_descr
[index
+3] & 0x03),
945 (ENDPOINT_DIRECTION
)((conf_descr
[index
+ 2] >> 7) + 1),
946 conf_descr
[index
+ 4] | (conf_descr
[index
+ 5] << 8),
947 conf_descr
[index
+ 2] & 0x0f);
948 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep
, current_intf
, dev
);
949 if (ep
!= NULL
&& dev
!= NULL
) {
950 addEndpoint(dev
, current_intf
, ep
);
956 USB_DBG("ISO USBEndpoint NOT SUPPORTED");
963 lenReportDescr
= conf_descr
[index
+ 7] | (conf_descr
[index
+ 8] << 8);
973 USB_TYPE
USBHost::bulkWrite(USBDeviceConnected
* dev
, USBEndpoint
* ep
, uint8_t * buf
, uint32_t len
, bool blocking
)
975 return generalTransfer(dev
, ep
, buf
, len
, blocking
, BULK_ENDPOINT
, true);
978 USB_TYPE
USBHost::bulkRead(USBDeviceConnected
* dev
, USBEndpoint
* ep
, uint8_t * buf
, uint32_t len
, bool blocking
)
980 return generalTransfer(dev
, ep
, buf
, len
, blocking
, BULK_ENDPOINT
, false);
983 USB_TYPE
USBHost::interruptWrite(USBDeviceConnected
* dev
, USBEndpoint
* ep
, uint8_t * buf
, uint32_t len
, bool blocking
)
985 return generalTransfer(dev
, ep
, buf
, len
, blocking
, INTERRUPT_ENDPOINT
, true);
988 USB_TYPE
USBHost::interruptRead(USBDeviceConnected
* dev
, USBEndpoint
* ep
, uint8_t * buf
, uint32_t len
, bool blocking
)
990 return generalTransfer(dev
, ep
, buf
, len
, blocking
, INTERRUPT_ENDPOINT
, false);
993 USB_TYPE
USBHost::generalTransfer(USBDeviceConnected
* dev
, USBEndpoint
* ep
, uint8_t * buf
, uint32_t len
, bool blocking
, ENDPOINT_TYPE type
, bool write
) {
996 const char * type_str
= (type
== BULK_ENDPOINT
) ? "BULK" : ((type
== INTERRUPT_ENDPOINT
) ? "INTERRUPT" : "ISOCHRONOUS");
997 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());
1003 ENDPOINT_DIRECTION dir
= (write
) ? OUT
: IN
;
1006 USB_ERR("dev NULL");
1007 return USB_TYPE_ERROR
;
1012 return USB_TYPE_ERROR
;
1015 if (ep
->getState() != USB_TYPE_IDLE
) {
1016 USB_WARN("[ep: %p - dev: %p - %s] NOT IDLE: %s", ep
, ep
->dev
, ep
->dev
->getName(ep
->getIntfNb()), ep
->getStateString());
1017 return ep
->getState();
1020 if ((ep
->getDir() != dir
) || (ep
->getType() != type
)) {
1021 USB_ERR("[ep: %p - dev: %p] wrong dir or bad USBEndpoint type", ep
, ep
->dev
);
1022 return USB_TYPE_ERROR
;
1025 if (dev
->getAddress() != ep
->getDeviceAddress()) {
1026 USB_ERR("[ep: %p - dev: %p] USBEndpoint addr and device addr don't match", ep
, ep
->dev
);
1027 return USB_TYPE_ERROR
;
1032 USB_DBG_TRANSFER("%s WRITE buffer", type_str
);
1033 for (int i
= 0; i
< ep
->getLengthTransferred(); i
++)
1034 printf("%02X ", buf
[i
]);
1038 addTransfer(ep
, buf
, len
);
1043 res
= ep
->getState();
1045 USB_DBG_TRANSFER("%s TRANSFER res: %s on ep: %p\r\n", type_str
, ep
->getStateString(), ep
);
1047 if (res
!= USB_TYPE_IDLE
) {
1054 return USB_TYPE_PROCESSING
;
1059 USB_TYPE
USBHost::controlRead(USBDeviceConnected
* dev
, uint8_t requestType
, uint8_t request
, uint32_t value
, uint32_t index
, uint8_t * buf
, uint32_t len
) {
1060 return controlTransfer(dev
, requestType
, request
, value
, index
, buf
, len
, false);
1063 USB_TYPE
USBHost::controlWrite(USBDeviceConnected
* dev
, uint8_t requestType
, uint8_t request
, uint32_t value
, uint32_t index
, uint8_t * buf
, uint32_t len
) {
1064 return controlTransfer(dev
, requestType
, request
, value
, index
, buf
, len
, true);
1067 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
)
1070 USB_DBG_TRANSFER("----- CONTROL %s [dev: %p - hub: %d - port: %d] ------", (write
) ? "WRITE" : "READ", dev
, dev
->getHub(), dev
->getPort());
1072 int length_transfer
= len
;
1076 control
->setSpeed(dev
->getSpeed());
1077 control
->setSize(dev
->getSizeControlEndpoint());
1078 if (dev
->isActiveAddress()) {
1079 control
->setDeviceAddress(dev
->getAddress());
1081 control
->setDeviceAddress(0);
1084 USB_DBG_TRANSFER("Control transfer on device: %d\r\n", control
->getDeviceAddress());
1085 fillControlBuf(requestType
, request
, value
, index
, len
);
1088 USB_DBG_TRANSFER("SETUP PACKET: ");
1089 for (int i
= 0; i
< 8; i
++)
1090 printf("%01X ", setupPacket
[i
]);
1094 control
->setNextToken(TD_SETUP
);
1095 addTransfer(control
, (uint8_t*)setupPacket
, 8);
1097 control
->ep_queue
.get();
1098 res
= control
->getState();
1100 USB_DBG_TRANSFER("CONTROL setup stage %s", control
->getStateString());
1102 if (res
!= USB_TYPE_IDLE
) {
1106 if (length_transfer
) {
1107 token
= (write
) ? TD_OUT
: TD_IN
;
1108 control
->setNextToken(token
);
1109 addTransfer(control
, (uint8_t *)buf
, length_transfer
);
1111 control
->ep_queue
.get();
1112 res
= control
->getState();
1115 USB_DBG_TRANSFER("CONTROL %s stage %s", (write
) ? "WRITE" : "READ", control
->getStateString());
1117 USB_DBG_TRANSFER("CONTROL WRITE buffer");
1118 for (int i
= 0; i
< control
->getLengthTransferred(); i
++)
1119 printf("%02X ", buf
[i
]);
1122 USB_DBG_TRANSFER("CONTROL READ SUCCESS [%d bytes transferred]", control
->getLengthTransferred());
1123 for (int i
= 0; i
< control
->getLengthTransferred(); i
++)
1124 printf("%02X ", buf
[i
]);
1129 if (res
!= USB_TYPE_IDLE
) {
1134 token
= (write
) ? TD_IN
: TD_OUT
;
1135 control
->setNextToken(token
);
1136 addTransfer(control
, NULL
, 0);
1138 control
->ep_queue
.get();
1139 res
= control
->getState();
1141 USB_DBG_TRANSFER("CONTROL ack stage %s", control
->getStateString());
1143 if (res
!= USB_TYPE_IDLE
)
1150 void USBHost::fillControlBuf(uint8_t requestType
, uint8_t request
, uint16_t value
, uint16_t index
, int len
)
1152 setupPacket
[0] = requestType
;
1153 setupPacket
[1] = request
;
1154 setupPacket
[2] = (uint8_t) value
;
1155 setupPacket
[3] = (uint8_t) (value
>> 8);
1156 setupPacket
[4] = (uint8_t) index
;
1157 setupPacket
[5] = (uint8_t) (index
>> 8);
1158 setupPacket
[6] = (uint8_t) len
;
1159 setupPacket
[7] = (uint8_t) (len
>> 8);