diff --git a/components/usb/Kconfig b/components/usb/Kconfig index 939a2b1d14..993d9ccb5f 100644 --- a/components/usb/Kconfig +++ b/components/usb/Kconfig @@ -53,4 +53,58 @@ menu "USB-OTG" bool "Periodic OUT" endchoice + menu "Root Hub configuration" + + config USB_HOST_DEBOUNCE_DELAY_MS + depends on USB_OTG_SUPPORTED + int "Debounce delay in ms" + default 250 + help + On connection of a USB device, the USB 2.0 specification requires a "debounce interval with a minimum + duration of 100ms" to allow the connection to stabilize (see USB 2.0 chapter 7.1.7.3 for more details). + During the debounce interval, no new connection/disconnection events are registered. + + The default value is set to 250 ms to be safe. + + config USB_HOST_RESET_HOLD_MS + depends on USB_OTG_SUPPORTED + int "Reset hold in ms" + default 30 + help + The reset signaling can be generated on any Hub or Host Controller port by request from the USB System + Software. The USB 2.0 specification requires that "the reset signaling must be driven for a minimum of + 10ms" (see USB 2.0 chapter 7.1.7.5 for more details). After the reset, the hub port will transition to + the Enabled state (refer to Section 11.5). + + The default value is set to 30 ms to be safe. + + config USB_HOST_RESET_RECOVERY_MS + depends on USB_OTG_SUPPORTED + int "Reset recovery delay in ms" + default 30 + help + After a port stops driving the reset signal, the USB 2.0 specification requires that the "USB System + Software guarantees a minimum of 10 ms for reset recovery" before the attached device is expected to + respond to data transfers (see USB 2.0 chapter 7.1.7.3 for more details). The device may ignore any + data transfers during the recovery interval. + + The default value is set to 30 ms to be safe. + + + config USB_HOST_SET_ADDR_RECOVERY_MS + depends on USB_OTG_SUPPORTED + int "SetAddress() recovery time in ms" + default 10 + help + "After successful completion of the Status stage, the device is allowed a SetAddress() recovery + interval of 2 ms. At the end of this interval, the device must be able to accept Setup packets + addressed to the new address. Also, at the end of the recovery interval, the device must not respond to + tokens sent to the old address (unless, of course, the old and new address is the same)." See USB 2.0 + chapter 9.2.6.3 for more details. + + The default value is set to 10 ms to be safe. + + + endmenu #Root Hub configuration + endmenu #USB-OTG diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index 4af0e84fcd..bc062c82d3 100644 --- a/components/usb/hcd_dwc.c +++ b/components/usb/hcd_dwc.c @@ -28,9 +28,9 @@ // --------------------- Constants ------------------------- #define INIT_DELAY_MS 30 //A delay of at least 25ms to enter Host mode. Make it 30ms to be safe -#define DEBOUNCE_DELAY_MS 250 //A debounce delay of 250ms -#define RESET_HOLD_MS 30 //Spec requires at least 10ms. Make it 30ms to be safe -#define RESET_RECOVERY_MS 30 //Reset recovery delay of 10ms (make it 30 ms to be safe) to allow for connected device to recover (and for port enabled interrupt to occur) +#define DEBOUNCE_DELAY_MS CONFIG_USB_HOST_DEBOUNCE_DELAY_MS +#define RESET_HOLD_MS CONFIG_USB_HOST_RESET_HOLD_MS +#define RESET_RECOVERY_MS CONFIG_USB_HOST_RESET_RECOVERY_MS #define RESUME_HOLD_MS 30 //Spec requires at least 20ms, Make it 30ms to be safe #define RESUME_RECOVERY_MS 20 //Resume recovery of at least 10ms. Make it 20 ms to be safe. This will include the 3 LS bit times of the EOP diff --git a/components/usb/hub.c b/components/usb/hub.c index be09ffdf95..da53cae2b6 100644 --- a/components/usb/hub.c +++ b/components/usb/hub.c @@ -32,6 +32,8 @@ implement the bare minimum to control the root HCD port. #define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED #endif +#define SET_ADDR_RECOVERY_INTERVAL_MS CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS + #define ENUM_CTRL_TRANSFER_MAX_DATA_LEN CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE #define ENUM_DEV_ADDR 1 //Device address used in enumeration #define ENUM_CONFIG_INDEX 0 //Index of the first configuration of the device @@ -79,6 +81,7 @@ typedef enum { ENUM_STAGE_SECOND_RESET, /**< Reset the device again (Workaround for old USB devices that get confused by the previous short dev desc request). */ ENUM_STAGE_SET_ADDR, /**< Send SET_ADDRESS request */ ENUM_STAGE_CHECK_ADDR, /**< Update the enum pipe's target address */ + ENUM_STAGE_SET_ADDR_RECOVERY, /**< Wait SET ADDRESS recovery interval at least for 2ms due to usb_20, chapter 9.2.6.3 */ ENUM_STAGE_GET_FULL_DEV_DESC, /**< Get the full dev desc */ ENUM_STAGE_CHECK_FULL_DEV_DESC, /**< Check the full dev desc, fill it into the device object in USBH. Save the string descriptor indexes*/ ENUM_STAGE_GET_SHORT_CONFIG_DESC, /**< Getting a short config desc (wLength is ENUM_SHORT_DESC_REQ_LEN) */ @@ -117,6 +120,7 @@ const char *const enum_stage_strings[] = { "SECOND_RESET", "SET_ADDR", "CHECK_ADDR", + "SET_ADDR_RECOVERY", "GET_FULL_DEV_DESC", "CHECK_FULL_DEV_DESC", "GET_SHORT_CONFIG_DESC", @@ -411,6 +415,22 @@ static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl) return true; } +static bool enum_stage_wait(enum_ctrl_t *enum_ctrl) +{ + switch (enum_ctrl->stage) { + case ENUM_STAGE_SET_ADDR_RECOVERY: { + vTaskDelay(pdMS_TO_TICKS(SET_ADDR_RECOVERY_INTERVAL_MS)); // Need a short delay before device is ready. Todo: IDF-7007 + return true; + } + + default: //Should never occur + abort(); + break; + } + + return false; +} + static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl) { //Dequeue the URB @@ -696,6 +716,7 @@ static void enum_set_next_stage(enum_ctrl_t *enum_ctrl, bool last_stage_pass) case ENUM_STAGE_GET_SHORT_DEV_DESC: case ENUM_STAGE_SECOND_RESET: case ENUM_STAGE_SET_ADDR: + case ENUM_STAGE_SET_ADDR_RECOVERY: case ENUM_STAGE_GET_FULL_DEV_DESC: case ENUM_STAGE_GET_SHORT_CONFIG_DESC: case ENUM_STAGE_GET_FULL_CONFIG_DESC: @@ -857,6 +878,10 @@ static void enum_handle_events(void) case ENUM_STAGE_GET_FULL_SER_STR_DESC: stage_pass = enum_stage_transfer(enum_ctrl); break; + //Recovery interval + case ENUM_STAGE_SET_ADDR_RECOVERY: + stage_pass = enum_stage_wait(enum_ctrl); + break; //Transfer check stages case ENUM_STAGE_CHECK_SHORT_DEV_DESC: case ENUM_STAGE_CHECK_ADDR: