00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "conf_usb_host.h"
00048 #include "USBHDriver.h"
00049 #include "uhi.h"
00050 #include "USBH.h"
00051 #include <stdlib.h>
00052
00053 #ifndef USB_HOST_UHI
00054 # error USB_HOST_UHI must be defined with unless one UHI interface in conf_usb_host.h file.
00055 #endif
00056
00057 #ifdef USB_HOST_HUB_SUPPORT
00058 # error The USB HUB support is not available in this revision.
00059 #endif
00060
00061
00062 #ifndef UHC_CONNECTION_EVENT
00063 # define UHC_CONNECTION_EVENT(dev,b_present)
00064 #endif
00065 #ifndef UHC_DEVICE_CONF
00066 # define UHC_DEVICE_CONF(dev) 1
00067 #endif
00068 #ifndef UHC_ENUM_EVENT
00069 # define UHC_ENUM_EVENT(dev,event)
00070 #endif
00071 #ifndef UHC_WAKEUP_EVENT
00072 # define UHC_WAKEUP_EVENT()
00073 #endif
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 static USBH_device_t USBH_device_root;
00088
00089
00090 static uint8_t USBH_enum_try;
00091
00092
00093 #define UHC_ENUM_NB_TRY 4
00094
00095
00096 #define UHC_USB_ADD_NOT_VALID 0xFF
00097
00098 #ifdef USB_HOST_HUB_SUPPORT
00099
00100 # define UHC_DEVICE_ENUM_ADD USBH_dev_enum->address
00101
00102
00103 static USBH_device_t *USBH_dev_enum;
00104
00105
00106 static uint16_t USBH_power_running;
00107
00108 #else
00109
00110 # define UHC_DEVICE_ENUM_ADD 1 // Static without USB HUB
00111
00112
00113 # define USBH_dev_enum (&USBH_device_root) // Static without USB HUB
00114
00115
00116 # define USBH_power_running 0 // No used without USB HUB
00117 #endif
00118
00119
00120 typedef void (*USBH_sof_timeout_callback_t) (void);
00121
00122
00123 static USBH_sof_timeout_callback_t USBH_sof_timeout_callback;
00124
00125
00126 uint8_t USBH_sof_timeout;
00127
00128
00129 static uhi_api_t USBH_uhis[] = {USB_HOST_UHI};
00130
00131
00132 #define UHC_NB_UHI (sizeof(USBH_uhis)/sizeof(USBH_uhis[0]))
00133
00134
00135 static volatile bool USBH_setup_request_finish;
00136
00137
00138 static volatile bool USBH_setup_request_finish_status;
00139
00140
00141
00142
00143
00144
00145 static void USBH_enable_timeout_callback(
00146 uint8_t timeout,
00147 USBH_sof_timeout_callback_t callback);
00148 static void USBH_enumeration_suspend(void);
00149 static void USBH_enumeration_reset(uhd_callback_reset_t callback);
00150 static void USBH_connection_tree(bool b_plug, USBH_device_t* dev);
00151 static void USBH_enumeration_step1(void);
00152 static void USBH_enumeration_step2(void);
00153 static void USBH_enumeration_step3(void);
00154 static void USBH_enumeration_step4(void);
00155 static void USBH_enumeration_step5(void);
00156 static void USBH_enumeration_step6(
00157 USBHS_Add_t add,
00158 USBH_XfrStatus_t status,
00159 uint16_t payload_trans);
00160 static void USBH_enumeration_step7(void);
00161 static void USBH_enumeration_step8(void);
00162 static void USBH_enumeration_step9(void);
00163 static void USBH_enumeration_step10(
00164 USBHS_Add_t add,
00165 USBH_XfrStatus_t status,
00166 uint16_t payload_trans);
00167 static void USBH_enumeration_step11(void);
00168 static void USBH_enumeration_step12(
00169 USBHS_Add_t add,
00170 USBH_XfrStatus_t status,
00171 uint16_t payload_trans);
00172 static void USBH_enumeration_step13(
00173 USBHS_Add_t add,
00174 USBH_XfrStatus_t status,
00175 uint16_t payload_trans);
00176 static void USBH_enumeration_step14(
00177 USBHS_Add_t add,
00178 USBH_XfrStatus_t status,
00179 uint16_t payload_trans);
00180 static void USBH_enumeration_step15(
00181 USBHS_Add_t add,
00182 USBH_XfrStatus_t status,
00183 uint16_t payload_trans);
00184 #ifdef USB_HOST_LPM_SUPPORT
00185 static void USBH_enumeration_step16_lpm(void);
00186 static void USBH_enumeration_step17_lpm(
00187 USBHS_Add_t add,
00188 USBH_XfrStatus_t status,
00189 uint16_t payload_trans);
00190 #endif // USB_HOST_LPM_SUPPORT
00191 static void USBH_enumeration_error(USBH_enum_status_t status);
00192
00193
00194 static void USBH_remotewakeup(bool b_enable);
00195 static void USBH_setup_request_callback(
00196 USBHS_Add_t add,
00197 USBH_XfrStatus_t status,
00198 uint16_t payload_trans);
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 static void USBH_enable_timeout_callback(uint8_t timeout,
00209 USBH_sof_timeout_callback_t callback)
00210 {
00211 USBH_sof_timeout_callback = callback;
00212 USBH_sof_timeout = timeout;
00213 }
00214
00215
00216
00217
00218
00219 static void USBH_enumeration_suspend(void)
00220 {
00221 #ifdef USB_HOST_HUB_SUPPORT
00222 if (&USBH_device_root != USBH_dev_enum) {
00223
00224 uhi_hub_suspend(USBH_dev_enum);
00225 } else
00226 #endif
00227 {
00228
00229 USBH_HAL_Suspend();
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238 static void USBH_enumeration_reset(uhd_callback_reset_t callback)
00239 {
00240
00241 #ifdef USB_HOST_HUB_SUPPORT
00242 if (&USBH_device_root != USBH_dev_enum) {
00243
00244 uhi_hub_send_reset(USBH_dev_enum, callback);
00245 } else
00246 #endif
00247 {
00248 USBH_HAL_Reset(callback);
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 static void USBH_connection_tree(bool b_plug, USBH_device_t* dev)
00259 {
00260 uint8_t i;
00261 if (b_plug) {
00262 TRACE_INFO_WP("DevAdd ");
00263 USBH_enum_try = 1;
00264 #ifdef USB_HOST_HUB_SUPPORT
00265 USBH_dev_enum = dev;
00266 #endif
00267 USBH_dev_enum->conf_desc = NULL;
00268 USBH_dev_enum->address = 0;
00269 UHC_CONNECTION_EVENT(USBH_dev_enum, true);
00270 USBH_enumeration_step1();
00271 } else {
00272 TRACE_INFO_WP("DevRem");
00273 if (USBH_dev_enum == dev) {
00274
00275 USBH_sof_timeout = 0;
00276 }
00277
00278 USBH_HAL_FreePipe(dev->address, 0xFF);
00279
00280
00281 for (i = 0; i < UHC_NB_UHI; i++) {
00282 USBH_uhis[i].uninstall(dev);
00283 }
00284
00285 UHC_CONNECTION_EVENT(dev, false);
00286 dev->address = UHC_USB_ADD_NOT_VALID;
00287
00288 if (dev->conf_desc != NULL) {
00289 free(dev->conf_desc);
00290 }
00291 #ifdef USB_HOST_HUB_SUPPORT
00292 USBH_power_running -= dev->power;
00293 if (&USBH_device_root != dev) {
00294
00295 dev->prev->next = dev->next;
00296 dev->next->prev = dev->prev;
00297 free(dev);
00298 }
00299 #endif
00300 }
00301 }
00302
00303
00304
00305
00306
00307 static void USBH_enumeration_step1(void)
00308 {
00309 TRACE_INFO_WP("Enum1 ");
00310 USBH_enumeration_reset(USBH_enumeration_step2);
00311 }
00312
00313
00314
00315
00316
00317 static void USBH_enumeration_step2(void)
00318 {
00319 TRACE_INFO_WP("Enum2 ");
00320 USBH_enable_timeout_callback(20, USBH_enumeration_step3);
00321 }
00322
00323
00324
00325
00326
00327 static void USBH_enumeration_step3(void)
00328 {
00329 TRACE_INFO_WP("Enum3 ");
00330 USBH_enumeration_reset(USBH_enumeration_step4);
00331 }
00332
00333
00334
00335
00336
00337 static void USBH_enumeration_step4(void)
00338 {
00339 TRACE_INFO_WP("Enum4 ");
00340 USBH_dev_enum->speed = USBH_HAL_GetSpeed();
00341 USBH_enable_timeout_callback(100, USBH_enumeration_step5);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350 static void USBH_enumeration_step5(void)
00351 {
00352 USBGenericRequest req;
00353 TRACE_INFO_WP("Enum5 ");
00354 req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00355 req.bRequest = USB_REQ_GET_DESCRIPTOR;
00356 req.wValue = (USBGenericDescriptor_DEVICE << 8);
00357 req.wIndex = 0;
00358 req.wLength = offsetof(USBH_device_t, dev_desc.bMaxPacketSize0)
00359 + sizeof(USBH_dev_enum->dev_desc.bMaxPacketSize0);
00360
00361
00362 USBH_HAL_FreePipe(0, 0);
00363 if (!USBH_HAL_ConfigureControlPipe(0, 64)) {
00364 USBH_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
00365 return;
00366 }
00367 if (!USBH_HAL_SetupReq(0,
00368 &req,
00369 (uint8_t*)&USBH_dev_enum->dev_desc,
00370 sizeof(USBDeviceDescriptor),
00371 NULL,
00372 USBH_enumeration_step6)) {
00373 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00374 return;
00375 }
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 static void USBH_enumeration_step6(
00388 USBHS_Add_t add,
00389 USBH_XfrStatus_t status,
00390 uint16_t payload_trans)
00391 {
00392 UNUSED(add);
00393 TRACE_INFO_WP("Enum6 ");
00394 if ((status != UHD_TRANS_NOERROR) || (payload_trans < 8)
00395 || (USBH_dev_enum->dev_desc.bDescriptorType != USBGenericDescriptor_DEVICE)) {
00396 USBH_enumeration_error((status == UHD_TRANS_DISCONNECT)?
00397 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00398 return;
00399 }
00400
00401 USBH_enable_timeout_callback(20, USBH_enumeration_step7);
00402 }
00403
00404
00405
00406
00407
00408 static void USBH_enumeration_step7(void)
00409 {
00410 TRACE_INFO_WP("Enum7 ");
00411 USBH_enumeration_reset(USBH_enumeration_step8);
00412 }
00413
00414
00415
00416
00417
00418 static void USBH_enumeration_step8(void)
00419 {
00420
00421 TRACE_INFO_WP("Enum8 ");
00422 USBH_enable_timeout_callback(100, USBH_enumeration_step9);
00423 }
00424
00425
00426
00427
00428
00429 static void USBH_enumeration_step9(void)
00430 {
00431 USBGenericRequest req;
00432
00433 TRACE_INFO_WP("Enum9 ");
00434 req.bmRequestType = USB_REQ_RECIP_DEVICE
00435 | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
00436 req.bRequest = USB_REQ_SET_ADDRESS;
00437 #ifdef USB_HOST_HUB_SUPPORT
00438 uint8_t usb_addr_free = 0;
00439 USBH_device_t *dev;
00440
00441
00442 dev = &USBH_device_root;
00443 while (usb_addr_free++) {
00444 if (dev->address == usb_addr_free) {
00445 continue;
00446 }
00447 if (dev->next != NULL) {
00448 dev = dev->next;
00449 continue;
00450 }
00451 break;
00452 }
00453 req.wValue = usb_addr_free;
00454 USBH_dev_enum->address = usb_addr_free;
00455 #else
00456 req.wValue = UHC_DEVICE_ENUM_ADD;
00457 USBH_dev_enum->address = UHC_DEVICE_ENUM_ADD;
00458 #endif
00459 req.wIndex = 0;
00460 req.wLength = 0;
00461
00462
00463 USBH_HAL_FreePipe(0, 0);
00464 if (!USBH_HAL_ConfigureControlPipe(0, USBH_dev_enum->dev_desc.bMaxPacketSize0)) {
00465 USBH_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
00466 return;
00467 }
00468
00469 if (!USBH_HAL_SetupReq(0,
00470 &req,
00471 (uint8_t*)&USBH_dev_enum->dev_desc,
00472 sizeof(USBDeviceDescriptor),
00473 NULL,
00474 USBH_enumeration_step10)) {
00475 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00476 return;
00477 }
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 static void USBH_enumeration_step10(
00490 USBHS_Add_t add,
00491 USBH_XfrStatus_t status,
00492 uint16_t payload_trans)
00493 {
00494 UNUSED(add);
00495 UNUSED(payload_trans);
00496 TRACE_INFO_WP("Enum10 ");
00497 if (status != UHD_TRANS_NOERROR) {
00498 USBH_enumeration_error((status == UHD_TRANS_DISCONNECT) ?
00499 UHC_ENUM_DISCONNECT : UHC_ENUM_FAIL);
00500 return;
00501 }
00502
00503 USBH_enable_timeout_callback(20, USBH_enumeration_step11);
00504 }
00505
00506
00507
00508
00509
00510
00511 static void USBH_enumeration_step11(void)
00512 {
00513 USBGenericRequest req;
00514
00515 TRACE_INFO_WP("Enum11 ");
00516
00517 USBH_HAL_FreePipe(0, 0);
00518
00519
00520 if (!USBH_HAL_ConfigureControlPipe(UHC_DEVICE_ENUM_ADD,
00521 USBH_dev_enum->dev_desc.bMaxPacketSize0)) {
00522 USBH_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
00523 return;
00524 }
00525
00526 req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00527 req.bRequest = USB_REQ_GET_DESCRIPTOR;
00528 req.wValue = (USBGenericDescriptor_DEVICE << 8);
00529 req.wIndex = 0;
00530 req.wLength = sizeof(USBDeviceDescriptor);
00531 if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00532 &req,
00533 (uint8_t *) & USBH_dev_enum->dev_desc,
00534 sizeof(USBDeviceDescriptor),
00535 NULL, USBH_enumeration_step12)) {
00536 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00537 return;
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 static void USBH_enumeration_step12(
00550 USBHS_Add_t add,
00551 USBH_XfrStatus_t status,
00552 uint16_t payload_trans)
00553 {
00554 USBGenericRequest req;
00555 uint8_t conf_num;
00556 UNUSED(add);
00557
00558 TRACE_INFO_WP("Enum12 ");
00559 if ((status != UHD_TRANS_NOERROR) || (payload_trans != sizeof(USBDeviceDescriptor))
00560 || (USBH_dev_enum->dev_desc.bDescriptorType != USBGenericDescriptor_DEVICE)) {
00561 USBH_enumeration_error((status==UHD_TRANS_DISCONNECT)?
00562 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00563 return;
00564 }
00565
00566 if (USBH_dev_enum->dev_desc.bNumConfigurations > 1) {
00567 conf_num = UHC_DEVICE_CONF(USBH_dev_enum);
00568 } else {
00569 conf_num = 1;
00570 }
00571
00572 USBH_dev_enum->conf_desc = malloc(sizeof(USBConfigurationDescriptor));
00573 if (USBH_dev_enum->conf_desc == NULL) {
00574 assert(false);
00575 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00576 return;
00577 }
00578
00579 req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00580 req.bRequest = USB_REQ_GET_DESCRIPTOR;
00581 req.wValue = (USBGenericDescriptor_CONFIGURATION << 8) | (conf_num - 1);
00582 req.wIndex = 0;
00583 req.wLength = sizeof(USBConfigurationDescriptor);
00584 if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00585 &req,
00586 (uint8_t *) USBH_dev_enum->conf_desc,
00587 sizeof(USBConfigurationDescriptor),
00588 NULL, USBH_enumeration_step13)) {
00589 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00590 return;
00591 }
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 static void USBH_enumeration_step13(
00603 USBHS_Add_t add,
00604 USBH_XfrStatus_t status,
00605 uint16_t payload_trans)
00606 {
00607 uint8_t conf_num;
00608 uint16_t conf_size;
00609 uint16_t bus_power = 0;
00610 USBGenericRequest req;
00611 UNUSED(add);
00612
00613 TRACE_INFO_WP("Enum13 ");
00614 if ((status != UHD_TRANS_NOERROR) || (payload_trans != sizeof(USBConfigurationDescriptor))
00615 || (USBH_dev_enum->conf_desc->bDescriptorType != USBGenericDescriptor_CONFIGURATION)) {
00616 USBH_enumeration_error((status == UHD_TRANS_DISCONNECT)?
00617 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00618 return;
00619 }
00620 #ifdef USB_HOST_HUB_SUPPORT
00621 USBH_device_t *dev;
00622 dev = USBH_dev_enum;
00623 while (1) {
00624 if (dev->conf_desc->bmAttributes & USB_CONFIG_ATTR_SELF_POWERED) {
00625
00626 break;
00627 }
00628 if (dev == (&USBH_device_root)) {
00629 bus_power = USBH_dev_enum->conf_desc->bMaxPower * 2;
00630 break;
00631 }
00632
00633 dev = dev->hub;
00634 }
00635 #else
00636 if (!(USBH_dev_enum->conf_desc->bmAttributes
00637 &USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP)) {
00638 bus_power = USBH_dev_enum->conf_desc->bMaxPower * 2;
00639 }
00640 #endif
00641 if ((bus_power + USBH_power_running) > USB_HOST_POWER_MAX) {
00642
00643 UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_OVERCURRENT);
00644
00645
00646 USBH_enumeration_suspend();
00647 return;
00648 }
00649 #ifdef USB_HOST_HUB_SUPPORT
00650 USBH_dev_enum->power = bus_power;
00651 USBH_power_running += bus_power;
00652 #endif
00653
00654
00655 conf_size = (USBH_dev_enum->conf_desc->wTotalLength);
00656 conf_num = USBH_dev_enum->conf_desc->bConfigurationValue;
00657 assert(conf_num);
00658
00659 free(USBH_dev_enum->conf_desc);
00660 USBH_dev_enum->conf_desc = malloc(conf_size);
00661 if (USBH_dev_enum->conf_desc == NULL) {
00662 assert(false);
00663 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00664 return;
00665 }
00666
00667 req.bmRequestType =
00668 USB_REQ_RECIP_DEVICE | USB_REQ_TYPE_STANDARD |
00669 USB_REQ_DIR_IN;
00670 req.bRequest = USB_REQ_GET_DESCRIPTOR;
00671 req.wValue = (USBGenericDescriptor_CONFIGURATION << 8) | (conf_num - 1);
00672 req.wIndex = 0;
00673 req.wLength = conf_size;
00674 if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00675 &req,
00676 (uint8_t *) USBH_dev_enum->conf_desc,
00677 conf_size,
00678 NULL, USBH_enumeration_step14)) {
00679 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00680 return;
00681 }
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 static void USBH_enumeration_step14(
00693 USBHS_Add_t add,
00694 USBH_XfrStatus_t status,
00695 uint16_t payload_trans)
00696 {
00697 USBGenericRequest req;
00698 uint8_t i;
00699 bool b_conf_supported = false;
00700 UNUSED(add);
00701
00702 TRACE_INFO_WP("Enum14 ");
00703 if ((status != UHD_TRANS_NOERROR)
00704 || (payload_trans < sizeof(USBConfigurationDescriptor))
00705 || (USBH_dev_enum->conf_desc->bDescriptorType != USBGenericDescriptor_CONFIGURATION)
00706 || (payload_trans != (USBH_dev_enum->conf_desc->wTotalLength))) {
00707 USBH_enumeration_error((status==UHD_TRANS_DISCONNECT)?
00708 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00709 return;
00710 }
00711
00712 for (i = 0; i < UHC_NB_UHI; i++) {
00713 switch (USBH_uhis[i].install(USBH_dev_enum)) {
00714 case UHC_ENUM_SUCCESS:
00715 TRACE_INFO("Device Driver installed");
00716 b_conf_supported = true;
00717 break;
00718
00719 case UHC_ENUM_UNSUPPORTED:
00720 TRACE_INFO(" \n\rUnsupported Device");
00721 TRACE_INFO(" \n\rRestarting enumeration");
00722 break;
00723
00724 default:
00725
00726
00727 USBH_HAL_FreePipe(UHC_DEVICE_ENUM_ADD,0xFF);
00728 UHC_ENUM_EVENT(USBH_dev_enum,UHC_ENUM_HARDWARE_LIMIT);
00729
00730
00731 USBH_enumeration_suspend();
00732 return;
00733 }
00734 }
00735 if (!b_conf_supported) {
00736
00737 UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_UNSUPPORTED);
00738
00739
00740 USBH_enumeration_suspend();
00741 return;
00742 }
00743
00744 req.bmRequestType = USB_REQ_RECIP_DEVICE
00745 | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
00746 req.bRequest = USB_REQ_SET_CONFIGURATION;
00747 req.wValue = USBH_dev_enum->conf_desc->bConfigurationValue;
00748 req.wIndex = 0;
00749 req.wLength = 0;
00750 if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00751 &req,
00752 NULL,
00753 0,
00754 NULL, USBH_enumeration_step15)) {
00755 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00756 return;
00757 }
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static void USBH_enumeration_step15(
00769 USBHS_Add_t add,
00770 USBH_XfrStatus_t status,
00771 uint16_t payload_trans)
00772 {
00773 UNUSED(add);
00774 uint8_t i;
00775 TRACE_INFO_WP("Enum15 ");
00776 if ((status!=UHD_TRANS_NOERROR) || (payload_trans!=0)) {
00777 for( i = 0; i < UHC_NB_UHI; i++) {
00778 USBH_uhis[i].uninstall(USBH_dev_enum);
00779 }
00780 USBH_enumeration_error((status == UHD_TRANS_DISCONNECT)?
00781 UHC_ENUM_DISCONNECT : UHC_ENUM_FAIL);
00782 return;
00783 }
00784
00785
00786 for (i = 0; i < UHC_NB_UHI; i++) {
00787 USBH_uhis[i].enable(USBH_dev_enum);
00788 }
00789
00790 #ifdef USB_HOST_LPM_SUPPORT
00791
00792 if (USBH_device_root.dev_desc.bcdUSB >= (USBDeviceDescriptor_USB2_00)) {
00793
00794
00795 USBH_enumeration_step16_lpm();
00796 return;
00797 }
00798 USBH_dev_enum->lpm_desc = NULL;
00799 #endif
00800
00801 USBH_enum_try = 0;
00802
00803 UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_SUCCESS);
00804 }
00805
00806 #ifdef USB_HOST_LPM_SUPPORT
00807
00808
00809
00810
00811 static void USBH_enumeration_step16_lpm(void)
00812 {
00813 USBGenericRequest req;
00814
00815 TRACE_INFO_WP("Enum16_lpm");
00816 USBH_dev_enum->lpm_desc = malloc(sizeof(USB_DeviceLPMDescriptor));
00817 if (USBH_dev_enum->lpm_desc == NULL) {
00818 assert(false);
00819 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00820 return;
00821 }
00822
00823 req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00824 req.bRequest = USB_REQ_GET_DESCRIPTOR;
00825 req.wValue = USB_DT_BOS << 8;
00826 req.wIndex = 0;
00827 req.wLength = sizeof(USB_DeviceLPMDescriptor);
00828 if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00829 &req,
00830 (uint8_t *) USBH_dev_enum->lpm_desc,
00831 sizeof(USB_DeviceLPMDescriptor),
00832 NULL, USBH_enumeration_step17_lpm)) {
00833 USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00834 return;
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 static void USBH_enumeration_step17_lpm(
00847 USBHS_Add_t add,
00848 USBH_XfrStatus_t status,
00849 uint16_t payload_trans)
00850 {
00851 UNUSED(add);
00852
00853 TRACE_INFO_WP("Enum17_lpm ");
00854
00855 if (status == UHD_TRANS_STALL) {
00856 free(USBH_dev_enum->lpm_desc);
00857 USBH_dev_enum->lpm_desc = NULL;
00858 } else if ((status != UHD_TRANS_NOERROR)
00859 || (payload_trans < sizeof(USB_DeviceLPMDescriptor))
00860 || (USBH_dev_enum->lpm_desc->bos.bDescriptorType != USB_DT_BOS)
00861 || (payload_trans != (USBH_dev_enum->lpm_desc->bos.wTotalLength))) {
00862 USBH_enumeration_error((status==UHD_TRANS_DISCONNECT)?
00863 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00864 return;
00865 } else if (status == UHD_TRANS_NOERROR) {
00866
00867 if ((USBH_dev_enum->lpm_desc->capa_ext.bDescriptorType != USBGenericDescriptor_DEVICE_CAPABILITY)
00868 || (USBH_dev_enum->lpm_desc->capa_ext.bDevCapabilityType != USB_DC_USB20_EXTENSION)
00869 || (!(USBH_dev_enum->lpm_desc->capa_ext.bmAttributes & (USB_DC_EXT_LPM)))) {
00870 free(USBH_dev_enum->lpm_desc);
00871 USBH_dev_enum->lpm_desc = NULL;
00872 }
00873 }
00874
00875 USBH_enum_try = 0;
00876 UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_SUCCESS);
00877 }
00878 #endif // USB_HOST_LPM_SUPPORT
00879
00880
00881
00882
00883
00884
00885 static void USBH_enumeration_error(USBH_enum_status_t status)
00886 {
00887 if (status == UHC_ENUM_DISCONNECT) {
00888 USBH_enum_try = 0;
00889 TRACE_INFO_WP("Enum_Abort ");
00890 return;
00891 }
00892 USBH_HAL_FreePipe(USBH_dev_enum->address, 0xFF);
00893
00894
00895 if (USBH_dev_enum->conf_desc != NULL) {
00896 free(USBH_dev_enum->conf_desc);
00897 USBH_dev_enum->conf_desc = NULL;
00898 }
00899 USBH_dev_enum->address = 0;
00900 if (USBH_enum_try++ < UHC_ENUM_NB_TRY) {
00901
00902 USBH_enumeration_step1();
00903 return;
00904 }
00905
00906 USBH_enumeration_suspend();
00907 UHC_ENUM_EVENT(USBH_dev_enum, status);
00908 USBH_enum_try = 0;
00909 }
00910
00911
00912
00913
00914
00915
00916
00917 static void USBH_remotewakeup(bool b_enable)
00918 {
00919 USBGenericRequest req;
00920 USBH_device_t *dev;
00921
00922 dev = &USBH_device_root;
00923 while(1) {
00924 if (dev->conf_desc->bmAttributes & USBConfigurationDescriptor_REMOTE_WAKEUP) {
00925 if (b_enable) {
00926 req.bRequest = USB_REQ_SET_FEATURE;
00927 } else {
00928 req.bRequest = USB_REQ_CLEAR_FEATURE;
00929 }
00930 req.bmRequestType = USB_REQ_RECIP_DEVICE
00931 |USB_REQ_TYPE_STANDARD|USB_REQ_DIR_OUT;
00932 req.wValue = USB_DEV_FEATURE_REMOTE_WAKEUP;
00933 req.wIndex = 0;
00934 req.wLength = 0;
00935 USBH_HAL_SetupReq(dev->address,&req,NULL,0,NULL,NULL);
00936 }
00937 #ifdef USB_HOST_HUB_SUPPORT
00938 if (dev->next == NULL) {
00939 break;
00940 }
00941 dev = dev->next;
00942 #else
00943 break;
00944 #endif
00945 }
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955 static void USBH_setup_request_callback(
00956 USBHS_Add_t add,
00957 USBH_XfrStatus_t status,
00958 uint16_t payload_trans)
00959 {
00960 UNUSED(add);
00961 UNUSED(payload_trans);
00962 USBH_setup_request_finish_status = (status == UHD_TRANS_NOERROR);
00963 USBH_setup_request_finish = true;
00964 }
00965
00966
00967
00968
00969
00970
00971 void USBH_notify_connection(bool b_plug)
00972 {
00973 if (b_plug) {
00974 assert(USBH_device_root.address == UHC_USB_ADD_NOT_VALID);
00975
00976 #ifdef USB_HOST_HUB_SUPPORT
00977 USBH_power_running = 0;
00978 #endif
00979 } else {
00980 if (USBH_device_root.address == UHC_USB_ADD_NOT_VALID) {
00981
00982
00983 return;
00984 }
00985 }
00986
00987 USBH_connection_tree(b_plug, &USBH_device_root);
00988 }
00989
00990 void USBH_notify_sof(bool b_micro)
00991 {
00992
00993 uint8_t i;
00994 for ( i = 0; i < UHC_NB_UHI; i++) {
00995 if (USBH_uhis[i].sof_notify != NULL) {
00996 USBH_uhis[i].sof_notify(b_micro);
00997 }
00998 }
00999
01000 if (!b_micro) {
01001
01002 if (USBH_sof_timeout) {
01003 if (--USBH_sof_timeout == 0) {
01004 USBH_sof_timeout_callback();
01005 }
01006 }
01007 }
01008 }
01009
01010 void USBH_notify_resume(void)
01011 {
01012 USBH_remotewakeup(false);
01013 UHC_WAKEUP_EVENT();
01014 }
01015
01016 #ifdef USB_HOST_LPM_SUPPORT
01017 void USBH_notify_resume_lpm(void)
01018 {
01019 UHC_WAKEUP_EVENT();
01020 }
01021 #endif
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 void USBH_start(void)
01032 {
01033 USBH_device_root.address = UHC_USB_ADD_NOT_VALID;
01034 USBH_sof_timeout = 0;
01035 USBH_HAL_EnableUsbHost();
01036 }
01037
01038 void USBH_stop(bool b_id_stop)
01039 {
01040
01041 USBH_HAL_DisableUsb(b_id_stop);
01042 }
01043
01044 void USBH_suspend(bool b_remotewakeup)
01045 {
01046 if (USBH_enum_try) {
01047
01048 return;
01049 }
01050
01051 if (b_remotewakeup) {
01052 USBH_remotewakeup(true);
01053 }
01054
01055 USBH_HAL_Suspend();
01056 }
01057
01058 bool USBH_is_suspend(void)
01059 {
01060 if (USBH_device_root.address == UHC_USB_ADD_NOT_VALID) {
01061 return true;
01062 }
01063 return USBH_HAL_IsSuspended();
01064 }
01065
01066 void USBH_resume(void)
01067 {
01068 if (!USBH_is_suspend()) {
01069 return;
01070 }
01071
01072 USBH_HAL_Resume();
01073 }
01074
01075 #ifdef USB_HOST_LPM_SUPPORT
01076 bool USBH_suspend_lpm(bool b_remotewakeup, uint8_t besl)
01077 {
01078 if (USBH_enum_try) {
01079
01080 return false;
01081 }
01082
01083
01084 if (USBH_dev_enum->lpm_desc == NULL) {
01085
01086 return false;
01087 }
01088
01089
01090 return uhd_suspend_lpm(b_remotewakeup, besl);
01091 }
01092 #endif // USB_HOST_LPM_SUPPORT
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 uint8_t USBH_get_device_number(void)
01103 {
01104 #ifdef USB_HOST_HUB_SUPPORT
01105 uint8_t nb_dev = 0;
01106 USBH_device_t *dev;
01107
01108 if (USBH_device_root.address != UHC_USB_ADD_NOT_VALID) {
01109 dev = &USBH_device_root;
01110 while (nb_dev++) {
01111 if (dev->next == NULL) {
01112 break;
01113 }
01114 dev = dev->next;
01115 }
01116 }
01117 return nb_dev;
01118 #else
01119 return (USBH_device_root.address != UHC_USB_ADD_NOT_VALID) ? 1 : 0;
01120 #endif
01121 }
01122
01123 char *USBH_dev_get_string_manufacturer(USBH_device_t * dev)
01124 {
01125 if (!dev->dev_desc.iManufacturer) {
01126 return NULL;
01127 }
01128 return USBH_dev_get_string(dev, dev->dev_desc.iManufacturer);
01129 }
01130
01131 char *USBH_dev_get_string_product(USBH_device_t * dev)
01132 {
01133 if (!dev->dev_desc.iProduct) {
01134 return NULL;
01135 }
01136 return USBH_dev_get_string(dev, dev->dev_desc.iProduct);
01137 }
01138
01139 char *USBH_dev_get_string_serial(USBH_device_t * dev)
01140 {
01141 if (!dev->dev_desc.iSerialNumber) {
01142 return NULL;
01143 }
01144 return USBH_dev_get_string(dev, dev->dev_desc.iSerialNumber);
01145 }
01146
01147 char *USBH_dev_get_string(USBH_device_t * dev, uint8_t str_id)
01148 {
01149 USBGenericRequest req;
01150 USBStringDescriptor str_header;
01151 USBStringLangIdDescriptor *str_desc;
01152 char *string;
01153 uint8_t i;
01154 UNUSED(dev);
01155
01156 req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
01157 req.bRequest = USB_REQ_GET_DESCRIPTOR;
01158 req.wValue = (USBGenericDescriptor_STRING << 8) | str_id;
01159 req.wIndex = 0;
01160 req.wLength = sizeof(USBStringDescriptor);
01161
01162
01163 USBH_setup_request_finish = false;
01164 if (!USBH_HAL_SetupReq(0,
01165 &req,
01166 (uint8_t*)&str_header,
01167 sizeof(USBStringDescriptor),
01168 NULL,
01169 USBH_setup_request_callback)) {
01170 return NULL;
01171 }
01172 while (!USBH_setup_request_finish);
01173 if (!USBH_setup_request_finish_status) {
01174 return NULL;
01175 }
01176
01177 str_desc = malloc(str_header.bLength);
01178 if (str_desc == NULL) {
01179 return NULL;
01180 }
01181 req.wLength = str_header.bLength;
01182 USBH_setup_request_finish = false;
01183 if (!USBH_HAL_SetupReq(0,
01184 &req,
01185 (uint8_t*)str_desc,
01186 str_header.bLength,
01187 NULL,
01188 USBH_setup_request_callback)) {
01189 return NULL;
01190 }
01191 while (!USBH_setup_request_finish);
01192 if (!USBH_setup_request_finish_status) {
01193 free(str_desc);
01194 return NULL;
01195 }
01196
01197 str_header.bLength = (str_header.bLength - 2) / 2;
01198 string = malloc(str_header.bLength + 1);
01199 if (string == NULL) {
01200 free(str_desc);
01201 return NULL;
01202 }
01203 for (i = 0; i < str_header.bLength; i++) {
01204 string[i] = (str_desc->string[i]) & 0xFF;
01205 }
01206 string[i] = 0;
01207 free(str_desc);
01208
01209 return string;
01210 }
01211
01212 uint16_t USBH_dev_get_power(USBH_device_t* dev)
01213 {
01214 return dev->conf_desc->bMaxPower * 2;
01215 }
01216
01217 USBH_Speed_t USBH_dev_get_speed(USBH_device_t * dev)
01218 {
01219 return dev->speed;
01220 }
01221
01222 bool USBH_dev_is_high_speed_support(USBH_device_t* dev)
01223 {
01224 USBGenericRequest req;
01225 USBDeviceQualifierDescriptor qualifier;
01226
01227 if (dev->speed == UHD_SPEED_HIGH) {
01228 return true;
01229 }
01230 if (dev->speed == UHD_SPEED_FULL) {
01231 req.bmRequestType = USB_REQ_RECIP_DEVICE
01232 | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_IN;
01233 req.bRequest = USB_REQ_GET_DESCRIPTOR;
01234 req.wValue = (USBGenericDescriptor_DEVICEQUALIFIER << 8);
01235 req.wIndex = 0;
01236 req.wLength = sizeof(qualifier);
01237
01238
01239 USBH_setup_request_finish = false;
01240 if (!USBH_HAL_SetupReq(0,
01241 &req,
01242 (uint8_t*)&qualifier,
01243 sizeof(qualifier),
01244 NULL,
01245 USBH_setup_request_callback)) {
01246 return NULL;
01247 }
01248 while (!USBH_setup_request_finish);
01249 return USBH_setup_request_finish_status;
01250 }
01251 return false;
01252 }
01253
01254
01255
01256