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:
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user