Skip to content

Commit 53c01b9

Browse files
feat(usb_host): Remote wakeup WIP
- HCD and USB Host tests
1 parent af7de6d commit 53c01b9

File tree

11 files changed

+772
-14
lines changed

11 files changed

+772
-14
lines changed

host/usb/include/usb/usb_host.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,50 @@ esp_err_t usb_host_get_config_desc(usb_host_client_handle_t client_hdl, usb_devi
548548
*/
549549
esp_err_t usb_host_free_config_desc(const usb_config_desc_t *config_desc);
550550

551+
/**
552+
* @brief Set remote wakeup feature on a device
553+
*
554+
* This function enables, or disables remote wakeup feature on a connected device. Device must support remote wakeup
555+
* at fist place
556+
*
557+
* @note A control transfer is sent to a device, to enable/disable the feature
558+
* @note A client must open the device first
559+
*
560+
* @param[in] client_hdl Handle of a client, that opened the device
561+
* @param[in] dev_hdl Handle of a device, on which the remote wakeup is about to be enabled/disabled
562+
* @param[in] enable Remote wakeup enable/disable
563+
*
564+
* @return
565+
* - ESP_OK: Remote wakeup set successfully
566+
* - ESP_ERR_INVALID_ARG: Invalid argument
567+
* - ESP_ERR_INVALID_STATE: Client did not open the device
568+
* - ESP_ERR_NOT_ALLOWED: Device does not support remote wakeup
569+
* - ESP_ERR_NO_MEM: Not enough memory
570+
*/
571+
esp_err_t usb_host_device_remote_wakeup_enable(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, bool enable);
572+
573+
/**
574+
* @brief Check if a remote wakeup is currently set
575+
*
576+
* This function checks if a remote wakeup feature is currently enabled or disabled on a connected device. Device must
577+
* support remote wakeup at fist place
578+
*
579+
* @note A control transfer is sent to a device, get a device status descriptor
580+
* @note A client must open the device first
581+
*
582+
* @param[in] client_hdl Handle of a client, that opened the device
583+
* @param[in] dev_hdl Handle of a device, on which the remote wakeup is about to be checked
584+
* @param[out] enabled Remote wakeup is currently enabled/disabled
585+
*
586+
* @return
587+
* - ESP_OK: Remote wakeup status checked successfully
588+
* - ESP_ERR_INVALID_ARG: Invalid argument
589+
* - ESP_ERR_INVALID_STATE: Client did not open the device
590+
* - ESP_ERR_NOT_ALLOWED: Device does not support remote wakeup
591+
* - ESP_ERR_NO_MEM: Not enough memory
592+
*/
593+
esp_err_t usb_host_device_remote_wakeup_check(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, bool *enabled);
594+
551595
// ----------------------------------------------- Interface Functions -------------------------------------------------
552596

553597
/**

host/usb/include/usb/usb_types_ch9.h

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,19 @@ ESP_STATIC_ASSERT(sizeof(usb_device_status_t) == sizeof(uint16_t), "Size of usb_
153153
#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07
154154
#define USB_W_VALUE_DT_INTERFACE_POWER 0x08
155155

156+
/**
157+
* @brief Feature selector bit masks belonging to the wValue field of a setup packet
158+
*
159+
* See Table 9-6 of USB2.0 specification for more details
160+
*/
161+
#define ENDPOINT_HALT 0x00
162+
#define DEVICE_REMOTE_WAKEUP 0x01
163+
#define TEST_MODE 0x02
164+
156165
/**
157166
* @brief Initializer for a GET_STATUS request
158167
*
159-
* Sets the address of a connected device
168+
* Gets the status of a connected device
160169
*/
161170
#define USB_SETUP_PACKET_INIT_GET_STATUS(setup_pkt_ptr) ({ \
162171
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
@@ -166,6 +175,36 @@ ESP_STATIC_ASSERT(sizeof(usb_device_status_t) == sizeof(uint16_t), "Size of usb_
166175
(setup_pkt_ptr)->wLength = 2; \
167176
})
168177

178+
/**
179+
* @brief Initializer for a CLEAR_FEATURE request
180+
*
181+
* Clears the feature of a connected device
182+
*
183+
* See Chapter 9.4.1 of USB2.0 specification for more details
184+
*/
185+
#define USB_SETUP_PACKET_INIT_CLEAR_FEATURE(setup_pkt_ptr, feature_to_clear) ({ \
186+
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
187+
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_CLEAR_FEATURE; \
188+
(setup_pkt_ptr)->wValue = feature_to_clear; \
189+
(setup_pkt_ptr)->wIndex = 0; \
190+
(setup_pkt_ptr)->wLength = 0; \
191+
})
192+
193+
/**
194+
* @brief Initializer for a SET_FEATURE request
195+
*
196+
* Sets the feature of a connected device
197+
*
198+
* See Chapter 9.4.9 of USB2.0 specification for more details
199+
*/
200+
#define USB_SETUP_PACKET_INIT_SET_FEATURE(setup_pkt_ptr, feature_to_set) ({ \
201+
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
202+
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_FEATURE; \
203+
(setup_pkt_ptr)->wValue = feature_to_set; \
204+
(setup_pkt_ptr)->wIndex = 0; \
205+
(setup_pkt_ptr)->wLength = 0; \
206+
})
207+
169208
/**
170209
* @brief Initializer for a SET_ADDRESS request
171210
*

host/usb/private_include/hcd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ typedef enum {
6969
HCD_PORT_EVENT_DISCONNECTION, /**< A device disconnection has been detected */
7070
HCD_PORT_EVENT_ERROR, /**< A port error has been detected. Port is now HCD_PORT_STATE_RECOVERY */
7171
HCD_PORT_EVENT_OVERCURRENT, /**< Overcurrent detected on the port. Port is now HCD_PORT_STATE_RECOVERY */
72+
HCD_PORT_EVENT_REMOTE_WAKEUP,
7273
} hcd_port_event_t;
7374

7475
/**

host/usb/src/hcd_dwc.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,12 @@ static hcd_port_event_t _intr_hdlr_hprt(port_t *port, usb_dwc_hal_port_event_t h
831831
port->flags.conn_dev_ena = 0;
832832
break;
833833
}
834+
case USB_DWC_HAL_PORT_EVENT_REMOTE_WAKEUP: {
835+
//ESP_EARLY_LOGI(HCD_DWC_TAG, "WAKE");
836+
//port->state = HCD_PORT_STATE_ENABLED;
837+
port_event = HCD_PORT_EVENT_REMOTE_WAKEUP;
838+
break;
839+
}
834840
default: {
835841
abort();
836842
break;
@@ -1231,6 +1237,8 @@ static esp_err_t _port_cmd_power_on(port_t *port)
12311237
} else {
12321238
ret = ESP_ERR_INVALID_STATE;
12331239
}
1240+
//esp_rom_printf("power on: HPRT = %lx\n", usb_dwc_hal_port_get_hprt_val(port->hal));
1241+
//esp_rom_printf("power on: GINTSTS = %lx\n", usb_dwc_hal_port_get_gintsts_val(port->hal));
12341242
return ret;
12351243
}
12361244

@@ -1326,19 +1334,21 @@ static esp_err_t _port_cmd_bus_suspend(port_t *port)
13261334
// Port must have been previously enabled, and all pipes must already be halted
13271335
if (!(port->state == HCD_PORT_STATE_ENABLED && _port_check_all_pipes_halted(port))) {
13281336
ret = ESP_ERR_INVALID_STATE;
1337+
esp_rom_printf("ERR1\n");
13291338
goto exit;
13301339
}
13311340

13321341
usb_dwc_hal_port_suspend(port->hal);
13331342
port->state = HCD_PORT_STATE_SUSPENDING;
13341343

13351344
HCD_EXIT_CRITICAL();
1336-
vTaskDelay(pdMS_TO_TICKS(SUSPEND_ENTRY_MS));
1345+
vTaskDelay(pdMS_TO_TICKS(100));
13371346
HCD_ENTER_CRITICAL();
13381347

13391348
if (port->state != HCD_PORT_STATE_SUSPENDING) {
13401349
// Port state unexpectedly changed
13411350
ret = ESP_ERR_INVALID_RESPONSE;
1351+
esp_rom_printf("ERR2\n");
13421352
goto exit;
13431353
}
13441354

@@ -1350,6 +1360,7 @@ static esp_err_t _port_cmd_bus_suspend(port_t *port)
13501360
// Sanity check, the root port should have entered the suspended state after the SUSPEND_ENTRY_MS delay
13511361
if (!usb_dwc_ll_hprt_get_port_suspend(port->hal->dev)) {
13521362
ret = ESP_ERR_NOT_FINISHED;
1363+
esp_rom_printf("ERR3\n");
13531364
goto exit;
13541365
}
13551366

@@ -1362,17 +1373,36 @@ static esp_err_t _port_cmd_bus_suspend(port_t *port)
13621373

13631374
static esp_err_t _port_cmd_bus_resume(port_t *port)
13641375
{
1376+
uint32_t hprt, gintsts, state;
13651377
esp_err_t ret;
13661378
// Port can only be resumed if it was previously suspended
13671379
if (port->state != HCD_PORT_STATE_SUSPENDED) {
13681380
ret = ESP_ERR_INVALID_STATE;
13691381
goto exit;
13701382
}
1383+
hprt = usb_dwc_hal_port_get_hprt_val(port->hal);
1384+
gintsts = usb_dwc_hal_port_get_gintsts_val(port->hal);
1385+
state = usb_dwc_hal_hprt_get_pwr_line_status(port->hal);
1386+
1387+
// Res1 (Wkp1)
1388+
esp_rom_printf("HPRT: %lx\n", hprt);
1389+
esp_rom_printf("GINTSTS: %lx\n", gintsts);
1390+
esp_rom_printf("State %lx\n", state);
1391+
13711392
// Put and hold the bus in the K state.
13721393
usb_dwc_hal_port_toggle_resume(port->hal, true);
13731394
port->state = HCD_PORT_STATE_RESUMING;
13741395
HCD_EXIT_CRITICAL();
1375-
vTaskDelay(pdMS_TO_TICKS(RESUME_HOLD_MS));
1396+
vTaskDelay(pdMS_TO_TICKS(50));
1397+
1398+
// Res2 (Wkp2)
1399+
hprt = usb_dwc_hal_port_get_hprt_val(port->hal);
1400+
gintsts = usb_dwc_hal_port_get_gintsts_val(port->hal);
1401+
state = usb_dwc_hal_hprt_get_pwr_line_status(port->hal);
1402+
esp_rom_printf("HPRT: %lx\n", hprt);
1403+
esp_rom_printf("GINTSTS: %lx\n", gintsts);
1404+
esp_rom_printf("State %lx\n", state);
1405+
13761406
HCD_ENTER_CRITICAL();
13771407
// Return and hold the bus to the J state (as port of the LS EOP)
13781408
usb_dwc_hal_port_toggle_resume(port->hal, false);
@@ -1382,7 +1412,15 @@ static esp_err_t _port_cmd_bus_resume(port_t *port)
13821412
goto exit;
13831413
}
13841414
HCD_EXIT_CRITICAL();
1385-
vTaskDelay(pdMS_TO_TICKS(RESUME_RECOVERY_MS));
1415+
vTaskDelay(pdMS_TO_TICKS(100));
1416+
1417+
// Res3 (Wkp3)
1418+
hprt = usb_dwc_hal_port_get_hprt_val(port->hal);
1419+
gintsts = usb_dwc_hal_port_get_gintsts_val(port->hal);
1420+
state = usb_dwc_hal_hprt_get_pwr_line_status(port->hal);
1421+
esp_rom_printf("HPRT: %lx\n", hprt);
1422+
esp_rom_printf("GINTSTS: %lx\n", gintsts);
1423+
esp_rom_printf("State %lx\n", state);
13861424
HCD_ENTER_CRITICAL();
13871425
if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) {
13881426
// Port state unexpectedly changed
@@ -1485,8 +1523,11 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl)
14851523
return ESP_OK;
14861524
}
14871525

1526+
static port_t *s_port;
1527+
14881528
esp_err_t hcd_port_command(hcd_port_handle_t port_hdl, hcd_port_cmd_t command)
14891529
{
1530+
s_port = (port_t *)port_hdl;
14901531
esp_err_t ret = ESP_ERR_INVALID_STATE;
14911532
port_t *port = (port_t *)port_hdl;
14921533
xSemaphoreTake(port->port_mux, portMAX_DELAY);
@@ -2688,6 +2729,8 @@ static inline bool _check_port_pipe_state(pipe_t *pipe, bool *submit_urb)
26882729

26892730
esp_err_t hcd_urb_enqueue(hcd_pipe_handle_t pipe_hdl, urb_t *urb)
26902731
{
2732+
//esp_rom_printf("HPRT: %lx\n", usb_dwc_hal_port_get_hprt_val(s_port->hal));
2733+
//esp_rom_printf("power on: GINTSTS = %lx\n", usb_dwc_hal_port_get_gintsts_val(s_port->hal));
26912734
// Check that URB has not already been enqueued
26922735
HCD_CHECK(urb->hcd_ptr == NULL && urb->hcd_var == URB_HCD_STATE_IDLE, ESP_ERR_INVALID_STATE);
26932736
pipe_t *pipe = (pipe_t *)pipe_hdl;

host/usb/src/hub.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,18 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
441441

442442
break;
443443
}
444+
case HCD_PORT_EVENT_REMOTE_WAKEUP:
445+
// Root port, including all the connected devices were resumed (global resume)
446+
// Clear all EPs and propagate the resumed event to clients
447+
//usbh_devs_set_pm_actions_all(USBH_DEV_RESUME | USBH_DEV_RESUME_EVT);
448+
//esp_rom_printf("p_hub_driver_obj->dynamic.root_port_state = %d\n", p_hub_driver_obj->dynamic.root_port_state);
449+
450+
// Change Port state
451+
//HUB_DRIVER_ENTER_CRITICAL();
452+
//p_hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_ENABLED;
453+
//HUB_DRIVER_EXIT_CRITICAL();
454+
hub_root_mark_resume();
455+
break;
444456
default:
445457
abort(); // Should never occur
446458
break;

0 commit comments

Comments
 (0)