Implement USB CLEAR_FEATURE request for ENDPOINT_HALT.

From USB 2.0, section 9.4.5:

"For endpoints using data toggle, regardless of whether an endpoint has
the Halt feature set, a ClearFeature(ENDPOINT_HALT) request always
results in the data toggle being reinitialized to DATA0."
This commit is contained in:
Martin Ling
2022-03-29 13:47:41 +01:00
parent d3e4e9b6de
commit 84898a0bcb
4 changed files with 51 additions and 1 deletions

View File

@ -302,6 +302,17 @@ void usb_endpoint_stall(
// TODO: Also need to reset data toggle in both directions?
}
void usb_endpoint_reset_data_toggle(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_TXR;
} else {
USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_RXR;
}
}
static void usb_controller_run() {
USB0_USBCMD_D |= USB0_USBCMD_D_RS;
}

View File

@ -70,6 +70,10 @@ void usb_endpoint_disable(
const usb_endpoint_t* const endpoint
);
void usb_endpoint_reset_data_toggle(
const usb_endpoint_t* const endpoint
);
void usb_endpoint_flush(
const usb_endpoint_t* const endpoint
);

View File

@ -333,7 +333,6 @@ static usb_request_status_t usb_standard_request_get_configuration(
}
}
static usb_request_status_t usb_standard_request_get_status_setup(
usb_endpoint_t* const endpoint
) {
@ -367,6 +366,35 @@ static usb_request_status_t usb_standard_request_get_status(
}
}
static usb_request_status_t usb_standard_request_clear_feature_setup(
usb_endpoint_t* const endpoint)
{
switch (endpoint->setup.value) {
case USB_FEATURE_SELECTOR_ENDPOINT_HALT:
usb_endpoint_reset_data_toggle(endpoint);
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
static usb_request_status_t usb_standard_request_clear_feature(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
switch (stage) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_clear_feature_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
/*********************************************************************/
usb_request_status_t usb_standard_request(
@ -389,6 +417,9 @@ usb_request_status_t usb_standard_request(
case USB_STANDARD_REQUEST_GET_CONFIGURATION:
return usb_standard_request_get_configuration(endpoint, stage);
case USB_STANDARD_REQUEST_CLEAR_FEATURE:
return usb_standard_request_clear_feature(endpoint, stage);
default:
return USB_REQUEST_STATUS_STALL;
}

View File

@ -70,6 +70,10 @@ typedef enum {
USB_STANDARD_REQUEST_SYNCH_FRAME = 12,
} usb_standard_request_t;
typedef enum {
USB_FEATURE_SELECTOR_ENDPOINT_HALT = 0,
} usb_feature_selector_t;
typedef enum {
USB_SETUP_REQUEST_TYPE_shift = 5,
USB_SETUP_REQUEST_TYPE_mask = 3 << USB_SETUP_REQUEST_TYPE_shift,