mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/usb_host_dwc_hal_chan_halt_race_condition' into 'master'
USB Host: Fix USB DWC HAL host channel halt race condition + Incorrect bmRequestType direction flag Closes IDF-6348 See merge request espressif/esp-idf!21452
This commit is contained in:
commit
9cce5849e8
@ -279,16 +279,21 @@ void usb_dwc_hal_chan_activate(usb_dwc_hal_chan_t *chan_obj, void *xfer_desc_lis
|
||||
|
||||
bool usb_dwc_hal_chan_request_halt(usb_dwc_hal_chan_t *chan_obj)
|
||||
{
|
||||
//Cannot request halt on a channel that is pending error handling
|
||||
if (usb_dwc_ll_hcchar_chan_is_enabled(chan_obj->regs)) {
|
||||
//If the register indicates that the channel is still active, the active flag must have been previously set
|
||||
HAL_ASSERT(chan_obj->flags.active);
|
||||
if (chan_obj->flags.active) {
|
||||
/*
|
||||
Request a halt so long as the channel's active flag is set.
|
||||
- If the underlying hardware channel is already halted but the channel is pending interrupt handling,
|
||||
disabling the channel will have no effect (i.e., no channel interrupt is generated).
|
||||
- If the underlying channel is currently active, disabling the channel will trigger a channel interrupt.
|
||||
|
||||
Regardless, setting the "halt_requested" should cause "usb_dwc_hal_chan_decode_intr()" to report the
|
||||
USB_DWC_HAL_CHAN_EVENT_HALT_REQ event when channel interrupt is handled (pending or triggered).
|
||||
*/
|
||||
usb_dwc_ll_hcchar_disable_chan(chan_obj->regs);
|
||||
chan_obj->flags.halt_requested = 1;
|
||||
return false;
|
||||
} else {
|
||||
//We just clear the active flag here as it could still be set (if we have a pending channel interrupt)
|
||||
chan_obj->flags.active = 0;
|
||||
//Channel was never active to begin with, simply return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -359,6 +364,10 @@ usb_dwc_hal_chan_event_t usb_dwc_hal_chan_decode_intr(usb_dwc_hal_chan_t *chan_o
|
||||
usb_dwc_hal_chan_event_t chan_event;
|
||||
//Note: We don't assert on (chan_obj->flags.active) here as it could have been already cleared by usb_dwc_hal_chan_request_halt()
|
||||
|
||||
/*
|
||||
Note: Do not change order of checks as some events take precedence over others.
|
||||
Errors > Channel Halt Request > Transfer completed
|
||||
*/
|
||||
if (chan_intrs & CHAN_INTRS_ERROR_MSK) { //Note: Errors are uncommon, so we check against the entire interrupt mask to reduce frequency of entering this call path
|
||||
HAL_ASSERT(chan_intrs & USB_DWC_LL_INTR_CHAN_CHHLTD); //An error should have halted the channel
|
||||
//Store the error in hal context
|
||||
|
@ -1336,7 +1336,7 @@ esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl,
|
||||
//Check that control transfer is valid
|
||||
HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set
|
||||
usb_device_handle_t dev_hdl = transfer->device_handle;
|
||||
bool xfer_is_in = ((usb_setup_packet_t *)transfer->data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_OUT;
|
||||
bool xfer_is_in = ((usb_setup_packet_t *)transfer->data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_IN;
|
||||
usb_device_info_t dev_info;
|
||||
ESP_ERROR_CHECK(usbh_dev_get_info(dev_hdl, &dev_info));
|
||||
HOST_CHECK(transfer_check(transfer, USB_TRANSFER_TYPE_CTRL, dev_info.bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG);
|
||||
|
Loading…
x
Reference in New Issue
Block a user