summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-04-24 12:04:56 +0700
committerhathach <[email protected]>2026-04-26 11:51:49 +0700
commitd3107be360b45c4b8dbc223dcc5e5f57b582c5ff (patch)
tree5fe81a43ee805c78546a2d6c590a6edd42187365 /src
parent8a63f9c57ee29bd34367c347663e86fe432a0a37 (diff)
usbd_control: consolidate status stage ep selection
Extract the "which endpoint is the Status stage on" rule into a single TU_ATTR_ALWAYS_INLINE helper, and use it from both status_stage_xact() and the completion callback. Replaces the two-operand wLength/direction check with a direct endpoint-match comparison, matching the first operand's pattern. Per USB 2.0 §9.3.1, when wLength == 0 the bmRequestType Direction bit is ignored and the Status stage is always IN; otherwise the Status stage is opposite to the Data stage direction. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/device/usbd_control.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c
index 1ec9b4649..b5dae7d59 100644
--- a/src/device/usbd_control.c
+++ b/src/device/usbd_control.c
@@ -71,15 +71,17 @@ uint8_t* usbd_get_ctrl_buf(void) {
// Application API
//--------------------------------------------------------------------+
+// Endpoint used for the Status stage of a control transfer.
+// Per USB 2.0 §9.3.1, when wLength == 0 the Direction bit is ignored and the Status stage
+// is always IN. Otherwise the Status stage is opposite to the Data stage direction.
+TU_ATTR_ALWAYS_INLINE static inline uint8_t status_stage_ep(const tusb_control_request_t* request) {
+ if (request->wLength == 0) return EDPT_CTRL_IN;
+ return request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
+}
+
// Queue ZLP status transaction
-static inline bool status_stage_xact(uint8_t rhport, const tusb_control_request_t* request) {
- // Always use EDPT_CTRL_IN when control request wLength is zero
- if (request->wLength==0) {
- return usbd_edpt_xfer(rhport, EDPT_CTRL_IN, NULL, 0, false);
- }
- // Opposite to endpoint in Data Phase
- const uint8_t ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
- return usbd_edpt_xfer(rhport, ep_addr, NULL, 0, false);
+TU_ATTR_ALWAYS_INLINE static inline bool status_stage_xact(uint8_t rhport, const tusb_control_request_t* request) {
+ return usbd_edpt_xfer(rhport, status_stage_ep(request), NULL, 0, false);
}
// Status phase
@@ -160,10 +162,8 @@ void usbd_control_set_request(const tusb_control_request_t* request) {
bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) result;
- // Endpoint Address is opposite to direction bit, this is Status Stage complete event
- // Control request with zero wLength and IN direction also is Status Stage complete event
- if ((tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction)||
- (_ctrl_xfer.request.wLength==0&&_ctrl_xfer.request.bmRequestType_bit.direction==TUSB_DIR_IN)) {
+ // Status Stage complete: callback endpoint matches the Status stage endpoint
+ if (ep_addr == status_stage_ep(&_ctrl_xfer.request)) {
TU_ASSERT(0 == xferred_bytes);
// invoke optional dcd hook if available