Skip to content

Refactor USB control transfer handling into usbd.c#3627

Merged
hathach merged 10 commits into
masterfrom
merge-usbd-control
May 5, 2026
Merged

Refactor USB control transfer handling into usbd.c#3627
hathach merged 10 commits into
masterfrom
merge-usbd-control

Conversation

@hathach

@hathach hathach commented Apr 29, 2026

Copy link
Copy Markdown
Owner

Summary of Changes

  • Centralized control transfer state management into the _usbd_dev structure for improved organization and maintainability.
  • Removed the unused usbd_control_reset function.
  • Deprecated usbd_control.c, merging its functionality into usbd.c to reduce redundancy and streamline codebase structure.
  • Removed tu_edpt_state_t struct (busy/stalled/claimed bitfield) → plain volatile uint8_t arrays plus TU_EDPT_STATE_BUSY/STALLED/CLAIMED masks (now #defines). All bitfield assignments converted to mask ops (|=, &= ~mask, & for tests).
  • Extracted process_std_device_request from process_setup_received for readability

Copilot AI review requested due to automatic review settings April 29, 2026 15:28
Comment thread src/device/usbd.c Dismissed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors TinyUSB device control transfer handling by moving EP0 control transfer state and logic into src/device/usbd.c, deprecating the legacy usbd_control.c translation unit, and updating build/test wiring accordingly.

Changes:

  • Moved EP0 control-transfer state into _usbd_dev and inlined former usbd_control.c logic into usbd.c.
  • Dropped usbd_control.c from in-tree build source lists; left a deprecated stub file for downstream builds.
  • Updated unit-test/fuzz/make/cmake build definitions to stop compiling usbd_control.c.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/unit-test/CMakeLists.txt Stops linking usbd_control.c into Ceedling-backed unit test executables.
test/fuzz/rules.mk Removes usbd_control.c from fuzz build sources.
src/tinyusb.mk Removes usbd_control.c from the TinyUSB makefile source list.
src/device/usbd_control.c Replaced with a deprecated stub TU that warns downstream builders.
src/device/usbd.c Adds control-transfer state to _usbd_dev and hosts the EP0 control transfer implementation.
src/CMakeLists.txt Removes usbd_control.c from TinyUSB CMake source enumeration.
hw/bsp/rp2040/family.cmake Removes usbd_control.c from rp2040 BSP target sources.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/device/usbd.c
Comment on lines +857 to +865
(void) request;
return status_stage_xact(rhport, status_stage_ep(&_usbd_dev.ctrl_xfer.request));
}

// Transmit data to/from the control endpoint. If wLength is zero, a status packet is sent instead.
bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t* request, void* buffer, uint16_t len) {
// _usbd_dev.ctrl_xfer.request and reset fields are pre-initialized at process_setup_received entry
(void) request;
usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tud_control_xfer() ignores its request argument and instead uses _usbd_dev.ctrl_xfer.request. This breaks call sites that intentionally pass a modified request (e.g. process_get_descriptor() creates mod_request with a shorter wLength to avoid sending a ZLP on the very first GET_DEVICE_DESCRIPTOR when EP0 size < 18). Consider copying *request into _usbd_dev.ctrl_xfer.request (or at least using request->wLength for data_len/status-stage direction) so these existing semantics keep working.

Suggested change
(void) request;
return status_stage_xact(rhport, status_stage_ep(&_usbd_dev.ctrl_xfer.request));
}
// Transmit data to/from the control endpoint. If wLength is zero, a status packet is sent instead.
bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t* request, void* buffer, uint16_t len) {
// _usbd_dev.ctrl_xfer.request and reset fields are pre-initialized at process_setup_received entry
(void) request;
usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;
usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;
TU_ASSERT(request);
ctrl_xfer->request = *request;
return status_stage_xact(rhport, status_stage_ep(&ctrl_xfer->request));
}
// Transmit data to/from the control endpoint. If wLength is zero, a status packet is sent instead.
bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t* request, void* buffer, uint16_t len) {
// _usbd_dev.ctrl_xfer.request and reset fields are pre-initialized at process_setup_received entry
usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;
TU_ASSERT(request);
ctrl_xfer->request = *request;

Copilot uses AI. Check for mistakes.
Comment thread src/device/usbd.c
@@ -459,17 +473,6 @@ static char const *const _usbd_event_str[DCD_EVENT_COUNT] = {
"Func Call"
};

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usbd_driver_print_control_complete_name() was removed from this file, but it’s still declared in src/device/usbd_pvt.h behind #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL. If any in-tree or out-of-tree code links against that symbol when debug logging is enabled, this will become an undefined reference. Either keep a (possibly static-less) implementation in usbd.c under the same #if, or remove/adjust the declaration in the header.

Suggested change
void usbd_driver_print_control_complete_name(void) {
// Keep the debug symbol declared in usbd_pvt.h available for any
// in-tree or out-of-tree code that links against it when debug logging
// is enabled.
}

Copilot uses AI. Check for mistakes.
Comment thread src/device/usbd_control.c Outdated
Comment on lines +30 to +31
// keep resolving. Drop usbd_control.c from your build to silence the warning.
#warning "src/device/usbd_control.c is deprecated and now empty; remove it from your build (its content lives in src/device/usbd.c)."

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is now a stub with an unconditional #warning. #warning is non-standard and, combined with common -Werror settings (or compilers that don’t support it), can break downstream/vendor builds that still compile this translation unit. Consider guarding the warning by compiler support and/or a config macro (or replacing it with a portable deprecation mechanism) so including the legacy path doesn’t hard-fail builds.

Suggested change
// keep resolving. Drop usbd_control.c from your build to silence the warning.
#warning "src/device/usbd_control.c is deprecated and now empty; remove it from your build (its content lives in src/device/usbd.c)."
// keep resolving. Drop usbd_control.c from your build to silence the message.
#if !defined(TINYUSB_SILENCE_DEPRECATED_USBD_CONTROL_WARNING)
#if defined(_MSC_VER) || defined(__clang__) || defined(__GNUC__)
#pragma message("src/device/usbd_control.c is deprecated and now empty; remove it from your build (its content lives in src/device/usbd.c).")
#endif
#endif

Copilot uses AI. Check for mistakes.
@github-actions

github-actions Bot commented Apr 29, 2026

Copy link
Copy Markdown

Size Difference Report

Because TinyUSB code size varies by port and configuration, the metrics below represent the averaged totals across all example builds.

Note: If there is no change, only one value is shown.

Changes >1% in size

file .text .rodata .data .bss size % diff
tusb.c 469 ➙ 451 (-18) 0 397 ➙ 383 (-14) 3 470 ➙ 453 (-17) -3.6%
usbd.c 3231 ➙ 3522 (+291) 58 88 ➙ 91 (+3) 275 ➙ 355 (+80) 3571 ➙ 3941 (+370) +10.4%
usbd_control.c 567 ➙ 0 (-567) 0 508 ➙ 0 (-508) 79 ➙ 0 (-79) 645 ➙ 0 (-645) -100.0%
TOTAL 4267 ➙ 3973 (-294) 58 993 ➙ 474 (-519) 357 ➙ 358 (+1) 4686 ➙ 4394 (-292) -6.2%

Changes <1% in size

file .text .rodata .data .bss size % diff
usbh.c 4652 ➙ 4637 (-15) 55 99 1034 5807 ➙ 5791 (-16) -0.3%
TOTAL 4652 ➙ 4637 (-15) 55 99 1034 5807 ➙ 5791 (-16) -0.3%
No changes
file .text .rodata .data .bss size % diff
audio_device.c 2896 0 1259 1625 4515 +0.0%
cdc_device.c 1239 16 1092 735 1972 +0.0%
cdc_host.c 6381 487 15 985 7579 +0.0%
dcd_ch32_usbfs.c 1475 0 0 2444 3919 +0.0%
dcd_ch32_usbhs.c 1468 0 0 448 1916 +0.0%
dcd_ci_fs.c 1924 0 0 1290 3214 +0.0%
dcd_ci_hs.c 1758 0 0 1344 2535 +0.0%
dcd_da146xx.c 3067 0 0 144 3211 +0.0%
dcd_dwc2.c 4245 19 0 265 4529 +0.0%
dcd_eptri.c 2272 0 0 259 2531 +0.0%
dcd_ft9xx.c 3280 0 0 172 3452 +0.0%
dcd_khci.c 1952 0 0 1290 3242 +0.0%
dcd_lpc17_40.c 1478 0 0 648 1802 +0.0%
dcd_lpc_ip3511.c 1463 0 0 264 1683 +0.0%
dcd_mm32f327x_otg.c 1477 0 0 1290 2767 +0.0%
dcd_msp430x5xx.c 1799 0 0 176 1975 +0.0%
dcd_musb.c 2226 0 0 171 2396 +0.0%
dcd_nrf5x.c 2916 0 0 292 3208 +0.0%
dcd_nuc120.c 1095 0 0 78 1173 +0.0%
dcd_nuc121.c 1168 0 0 101 1270 +0.0%
dcd_nuc505.c 0 0 1532 157 1689 +0.0%
dcd_rp2040.c 841 0 764 653 2258 +0.0%
dcd_rusb2.c 2917 0 0 156 3073 +0.0%
dcd_samd.c 1036 0 0 266 1302 +0.0%
dcd_samg.c 1321 0 0 72 1393 +0.0%
dcd_stm32_fsdev.c 2558 0 0 291 2849 +0.0%
dfu_device.c 776 ➙ 777 (+1) 28 712 138 914 +0.0%
dfu_rt_device.c 157 0 134 0 157 +0.0%
dwc2_common.c 603 22 0 0 615 +0.0%
ecm_rndis_device.c 1047 0 1 2759 3807 +0.0%
ehci.c 2763 0 0 6043 7597 +0.0%
fsdev_common.c 180 0 0 0 180 +0.0%
hcd_ch32_usbfs.c 2485 0 0 498 2983 +0.0%
hcd_ci_hs.c 184 0 0 0 184 +0.0%
hcd_dwc2.c 5007 25 1 513 5545 +0.0%
hcd_khci.c 2442 0 0 449 2891 +0.0%
hcd_musb.c 3073 0 0 157 3230 +0.0%
hcd_pio_usb.c 262 0 240 0 502 +0.0%
hcd_rp2040.c 2000 17 4 321 2342 +0.0%
hcd_rusb2.c 2923 0 0 245 3168 +0.0%
hcd_samd.c 2220 0 0 324 2544 +0.0%
hcd_stm32_fsdev.c 3259 0 1 420 3680 +0.0%
hid_device.c 1125 44 997 119 1244 +0.0%
hid_host.c 1240 0 0 1251 2491 +0.0%
hub.c 1384 8 8 30 1418 +0.0%
midi_device.c 1151 0 1007 624 1773 +0.0%
midi_host.c 1341 7 7 3635 4979 +0.0%
msc_device.c 2517 108 2281 806 3323 +0.0%
msc_host.c 1587 0 0 394 1982 +0.0%
mtp_device.c 1696 22 735 588 2292 +0.0%
ncm_device.c 1544 28 720 4452 6010 +0.0%
ohci.c 1940 0 0 2414 4353 +0.0%
printer_device.c 830 0 706 566 1394 +0.0%
rp2040_usb.c 366 35 647 11 1060 +0.0%
rusb2_common.c 160 0 16 0 176 +0.0%
tusb_fifo.c 850 0 483 0 845 +0.0%
typec_stm32.c 820 8 2 12 842 +0.0%
usbc.c 420 2 20 166 608 +0.0%
usbtmc_device.c 2196 24 68 316 2544 +0.0%
vendor_device.c 641 0 534 565 1204 +0.0%
video_device.c 4443 5 1235 479 4914 +0.0%
TOTAL 109884 ➙ 109885 (+1) 905 15221 43911 155244 +0.0%

@github-actions

github-actions Bot commented Apr 29, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

Top 10 targets by memory change (%) (out of 2233 targets) View Project Dashboard →

target .text .rodata .data .bss total % diff
raspberrypi_cm4/cdc_msc 57,372 → 57,116 (-256) 4,584 → 744 (-3,840) 61,956 → 57,860 (-4,096) -6.6%
fomu/dfu_runtime 10,580 → 10,012 (-568) 10,607 → 10,039 (-568) -5.4%
fomu/hid_generic_inout 12,232 → 11,636 (-596) 12,259 → 11,663 (-596) -4.9%
fomu/hid_multiple_interface 13,412 → 12,816 (-596) 13,439 → 12,843 (-596) -4.4%
fomu/hid_boot_interface 13,468 → 12,872 (-596) 13,495 → 12,899 (-596) -4.4%
fomu/midi_test 13,868 → 13,260 (-608) 13,895 → 13,287 (-608) -4.4%
fomu/hid_composite 13,740 → 13,144 (-596) 13,767 → 13,171 (-596) -4.3%
lpcxpresso1347/audio_test_multi_rate 9,956 → 9,656 (-300) 3,332 → 3,076 (-256) 13,764 → 13,208 (-556) -4.0%
fomu/cdc_dual_ports 15,260 → 14,652 (-608) 15,287 → 14,679 (-608) -4.0%
fomu/printer_to_cdc 15,628 → 15,020 (-608) 15,651 → 15,043 (-608) -3.9%

…`_usbd_dev` structure and remove `usbd_control_reset`
@hathach hathach force-pushed the merge-usbd-control branch from b301f79 to eb66712 Compare May 4, 2026 01:55
Comment thread src/device/usbd.c Dismissed
Comment thread src/device/usbd.c
Comment on lines +1007 to +1031
switch (p_request->wValue) { //-V2520
case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
TU_LOG_USBD(" Enable Remote Wakeup\r\n");
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = 1;
tud_control_status(rhport, p_request);
return true;

#if CFG_TUD_TEST_MODE
case TUSB_REQ_FEATURE_TEST_MODE: {
// Only handle the test mode if supported and valid
TU_VERIFY(0 == tu_u16_low(p_request->wIndex));

uint8_t const selector = tu_u16_high(p_request->wIndex);
TU_VERIFY(TUSB_FEATURE_TEST_J <= selector && selector <= TUSB_FEATURE_TEST_FORCE_ENABLE);

_usbd_dev.ctrl_xfer.complete_cb = process_test_mode_cb;
tud_control_status(rhport, p_request);
return true;
}
#endif

// Stall unsupported feature selector
default: return false;
}
Comment thread src/device/usbd.c Dismissed
@hathach hathach merged commit 9b1b781 into master May 5, 2026
315 of 316 checks passed
@hathach hathach deleted the merge-usbd-control branch May 5, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants