From 8b783cad103e3d206a810d81cd37523359d723e1 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 25 Aug 2026 00:19:22 +0100 Subject: [PATCH] Align USB endpoint buffers to fix RP2040 Plover HID issues (#26417) --- tmk_core/protocol/chibios/usb_driver.h | 158 +++++++++++++------------ 1 file changed, 80 insertions(+), 78 deletions(-) diff --git a/tmk_core/protocol/chibios/usb_driver.h b/tmk_core/protocol/chibios/usb_driver.h index 3ddc4d9dba6..b3a3e5f8906 100644 --- a/tmk_core/protocol/chibios/usb_driver.h +++ b/tmk_core/protocol/chibios/usb_driver.h @@ -24,6 +24,8 @@ NULL, /* SETUP buffer (not a SETUP endpoint) */ #endif +#define EPSIZE_ALIGN(n) (((n) + 3) & ~3) + /* * Implementation notes: * @@ -33,96 +35,96 @@ * Given `USBv1/hal_usb_lld.h` marks the field as "not currently used" this code file * makes the assumption this is safe to avoid littering with preprocessor directives. */ -#define QMK_USB_ENDPOINT_IN(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \ - { \ - .usb_requests_cb = _usb_requests_cb, .report_storage = _report_storage, \ - .ep_config = \ - { \ - mode, /* EP Mode */ \ - NULL, /* SETUP packet notification callback */ \ - usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \ - NULL, /* OUT notification callback */ \ - ep_size, /* IN maximum packet size */ \ - 0, /* OUT maximum packet size */ \ - NULL, /* IN Endpoint state */ \ - NULL, /* OUT endpoint state */ \ - usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \ - }, \ - .config = { \ - .usbp = &USB_DRIVER, \ - .ep = ep_num, \ - .buffer_capacity = _buffer_capacity, \ - .buffer_size = ep_size, \ - .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0}, \ - } \ +#define QMK_USB_ENDPOINT_IN(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \ + { \ + .usb_requests_cb = _usb_requests_cb, .report_storage = _report_storage, \ + .ep_config = \ + { \ + mode, /* EP Mode */ \ + NULL, /* SETUP packet notification callback */ \ + usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \ + NULL, /* OUT notification callback */ \ + ep_size, /* IN maximum packet size */ \ + 0, /* OUT maximum packet size */ \ + NULL, /* IN Endpoint state */ \ + NULL, /* OUT endpoint state */ \ + usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \ + }, \ + .config = { \ + .usbp = &USB_DRIVER, \ + .ep = ep_num, \ + .buffer_capacity = _buffer_capacity, \ + .buffer_size = EPSIZE_ALIGN(ep_size), \ + .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0}, \ + } \ } #if !defined(USB_ENDPOINTS_ARE_REORDERABLE) -# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \ - { \ - .ep_config = \ - { \ - mode, /* EP Mode */ \ - NULL, /* SETUP packet notification callback */ \ - NULL, /* IN notification callback */ \ - usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \ - 0, /* IN maximum packet size */ \ - ep_size, /* OUT maximum packet size */ \ - NULL, /* IN Endpoint state */ \ - NULL, /* OUT endpoint state */ \ - usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \ - }, \ - .config = { \ - .usbp = &USB_DRIVER, \ - .ep = ep_num, \ - .buffer_capacity = _buffer_capacity, \ - .buffer_size = ep_size, \ - .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0} \ - } \ +# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \ + { \ + .ep_config = \ + { \ + mode, /* EP Mode */ \ + NULL, /* SETUP packet notification callback */ \ + NULL, /* IN notification callback */ \ + usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \ + 0, /* IN maximum packet size */ \ + ep_size, /* OUT maximum packet size */ \ + NULL, /* IN Endpoint state */ \ + NULL, /* OUT endpoint state */ \ + usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \ + }, \ + .config = { \ + .usbp = &USB_DRIVER, \ + .ep = ep_num, \ + .buffer_capacity = _buffer_capacity, \ + .buffer_size = EPSIZE_ALIGN(ep_size), \ + .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0} \ + } \ } #else -# define QMK_USB_ENDPOINT_IN_SHARED(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \ - { \ - .usb_requests_cb = _usb_requests_cb, .is_shared = true, .report_storage = _report_storage, \ - .ep_config = \ - { \ - mode, /* EP Mode */ \ - NULL, /* SETUP packet notification callback */ \ - usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \ - usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \ - ep_size, /* IN maximum packet size */ \ - ep_size, /* OUT maximum packet size */ \ - NULL, /* IN Endpoint state */ \ - NULL, /* OUT endpoint state */ \ - usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \ - }, \ - .config = { \ - .usbp = &USB_DRIVER, \ - .ep = ep_num, \ - .buffer_capacity = _buffer_capacity, \ - .buffer_size = ep_size, \ - .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0}, \ - } \ +# define QMK_USB_ENDPOINT_IN_SHARED(mode, ep_size, ep_num, _buffer_capacity, _usb_requests_cb, _report_storage) \ + { \ + .usb_requests_cb = _usb_requests_cb, .is_shared = true, .report_storage = _report_storage, \ + .ep_config = \ + { \ + mode, /* EP Mode */ \ + NULL, /* SETUP packet notification callback */ \ + usb_endpoint_in_tx_complete_cb, /* IN notification callback */ \ + usb_endpoint_out_rx_complete_cb, /* OUT notification callback */ \ + ep_size, /* IN maximum packet size */ \ + ep_size, /* OUT maximum packet size */ \ + NULL, /* IN Endpoint state */ \ + NULL, /* OUT endpoint state */ \ + usb_lld_endpoint_fields /* USB driver specific endpoint fields */ \ + }, \ + .config = { \ + .usbp = &USB_DRIVER, \ + .ep = ep_num, \ + .buffer_capacity = _buffer_capacity, \ + .buffer_size = EPSIZE_ALIGN(ep_size), \ + .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0}, \ + } \ } /* The current assumption is that there are no standalone OUT endpoints, so the * OUT endpoint is always initialized by the IN endpoint. */ -# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \ - { \ - .ep_config = \ - { \ - 0 /* Already defined in the IN endpoint */ \ - }, \ - .config = { \ - .usbp = &USB_DRIVER, \ - .ep = ep_num, \ - .buffer_capacity = _buffer_capacity, \ - .buffer_size = ep_size, \ - .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, ep_size)]){0} \ - } \ +# define QMK_USB_ENDPOINT_OUT(mode, ep_size, ep_num, _buffer_capacity) \ + { \ + .ep_config = \ + { \ + 0 /* Already defined in the IN endpoint */ \ + }, \ + .config = { \ + .usbp = &USB_DRIVER, \ + .ep = ep_num, \ + .buffer_capacity = _buffer_capacity, \ + .buffer_size = EPSIZE_ALIGN(ep_size), \ + .buffer = (_Alignas(4) uint8_t[BQ_BUFFER_SIZE(_buffer_capacity, EPSIZE_ALIGN(ep_size))]){0} \ + } \ } #endif