Skip to content

Commit b7664f2

Browse files
tmon-nordicfabiobaltieri
authored andcommitted
usb: device_next: Make stack High-Bandwidth aware
Add macros for converting between Max Packet Size and total payload length. Allow drivers specify whether endpoint supports high-bandwidth interrupt and high-bandwidth isochronous transfers. Signed-off-by: Tomasz Moń <[email protected]>
1 parent e333739 commit b7664f2

File tree

6 files changed

+44
-7
lines changed

6 files changed

+44
-7
lines changed

drivers/usb/udc/udc_common.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ static bool ep_check_config(const struct device *dev,
262262
return false;
263263
}
264264

265-
if (mps > cfg->caps.mps) {
265+
if (USB_MPS_EP_SIZE(mps) > USB_MPS_EP_SIZE(cfg->caps.mps)) {
266266
return false;
267267
}
268268

@@ -273,12 +273,16 @@ static bool ep_check_config(const struct device *dev,
273273
}
274274
break;
275275
case USB_EP_TYPE_INTERRUPT:
276-
if (!cfg->caps.interrupt) {
276+
if (!cfg->caps.interrupt ||
277+
(USB_MPS_ADDITIONAL_TRANSACTIONS(mps) &&
278+
!cfg->caps.high_bandwidth)) {
277279
return false;
278280
}
279281
break;
280282
case USB_EP_TYPE_ISO:
281-
if (!cfg->caps.iso) {
283+
if (!cfg->caps.iso ||
284+
(USB_MPS_ADDITIONAL_TRANSACTIONS(mps) &&
285+
!cfg->caps.high_bandwidth)) {
282286
return false;
283287
}
284288
break;

include/zephyr/drivers/usb/udc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ struct udc_ep_caps {
7676
uint32_t bulk : 1;
7777
/** ISO transfer capable endpoint */
7878
uint32_t iso : 1;
79+
/** High-Bandwidth (interrupt or iso) capable endpoint */
80+
uint32_t high_bandwidth : 1;
7981
/** IN transfer capable endpoint */
8082
uint32_t in : 1;
8183
/** OUT transfer capable endpoint */

include/zephyr/usb/usb_ch9.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,29 @@ struct usb_association_descriptor {
348348
/** Calculate high speed isochronous endpoint bInterval from a value in microseconds */
349349
#define USB_HS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)
350350

351+
/** Get endpoint size field from Max Packet Size value */
352+
#define USB_MPS_EP_SIZE(mps) ((mps) & BIT_MASK(11))
353+
354+
/** Get number of additional transactions per microframe from Max Packet Size value */
355+
#define USB_MPS_ADDITIONAL_TRANSACTIONS(mps) (((mps) & 0x1800) >> 11)
356+
357+
/** Calculate total payload length from Max Packet Size value */
358+
#define USB_MPS_TO_TPL(mps) \
359+
((1 + USB_MPS_ADDITIONAL_TRANSACTIONS(mps)) * USB_MPS_EP_SIZE(mps))
360+
361+
/** Calculate Max Packet Size value from total payload length */
362+
#define USB_TPL_TO_MPS(tpl) \
363+
(((tpl) > 2048) ? ((2 << 11) | ((tpl) / 3)) : \
364+
((tpl) > 1024) ? ((1 << 11) | ((tpl) / 2)) : \
365+
(tpl))
366+
367+
/** Determine whether total payload length value is valid according to USB 2.0 */
368+
#define USB_TPL_IS_VALID(tpl) \
369+
(((tpl) > 3072) ? false : \
370+
((tpl) > 2048) ? ((tpl) % 3 == 0) : \
371+
((tpl) > 1024) ? ((tpl) % 2 == 0) : \
372+
((tpl) >= 0))
373+
351374
#ifdef __cplusplus
352375
}
353376
#endif

subsys/usb/device_next/class/usbd_hid.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@ static const struct hid_device_driver_api hid_device_api = {
742742
(USBD_HID_INTERFACE_ALTERNATE_DEFINE(n)))
743743

744744
#define USBD_HID_INSTANCE_DEFINE(n) \
745+
HID_VERIFY_REPORT_SIZES(n); \
746+
\
745747
NET_BUF_POOL_DEFINE(hid_buf_pool_in_##n, \
746748
CONFIG_USBD_HID_IN_BUF_COUNT, 0, \
747749
sizeof(struct udc_buf_info), NULL); \

subsys/usb/device_next/class/usbd_hid_macros.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@
153153
*/
154154
#define HID_OUT_EP_MPS(n, alt) \
155155
COND_CODE_1(alt, \
156-
(sys_cpu_to_le16(DT_INST_PROP(n, out_report_size))), \
156+
(sys_cpu_to_le16(USB_TPL_TO_MPS(DT_INST_PROP(n, out_report_size)))), \
157157
(sys_cpu_to_le16(MIN(DT_INST_PROP(n, out_report_size), 64U))))
158158

159159
/*
@@ -162,7 +162,7 @@
162162
*/
163163
#define HID_IN_EP_MPS(n, alt) \
164164
COND_CODE_1(alt, \
165-
(sys_cpu_to_le16(DT_INST_PROP(n, in_report_size))), \
165+
(sys_cpu_to_le16(USB_TPL_TO_MPS(DT_INST_PROP(n, in_report_size)))), \
166166
(sys_cpu_to_le16(MIN(DT_INST_PROP(n, in_report_size), 64U))))
167167

168168
#define HID_OUT_EP_DEFINE(n, hs, alt) \
@@ -206,4 +206,10 @@
206206
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \
207207
(&hid_buf_pool_out_##n), (NULL))
208208

209+
#define HID_VERIFY_REPORT_SIZES(n) \
210+
BUILD_ASSERT(USB_TPL_IS_VALID(DT_INST_PROP_OR(n, out_report_size, 0)), \
211+
"out-report-size must be valid Total Packet Length"); \
212+
BUILD_ASSERT(USB_TPL_IS_VALID(DT_INST_PROP_OR(n, in_report_size, 0)), \
213+
"in-report-size must be valid Total Packet Length");
214+
209215
#endif /* ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ */

tests/drivers/udc/src/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ static struct net_buf *test_udc_ep_buf_alloc(const struct device *dev,
197197
struct net_buf *buf;
198198

199199
buf = udc_ep_buf_alloc(dev, ed->bEndpointAddress,
200-
sys_le16_to_cpu(ed->wMaxPacketSize));
200+
USB_MPS_TO_TPL(sys_le16_to_cpu(ed->wMaxPacketSize)));
201201

202202
zassert_not_null(buf, "Failed to allocate request");
203203

@@ -338,7 +338,7 @@ static void test_udc_ep_api(const struct device *dev,
338338
/* It needs a little reserve for memory management overhead. */
339339
for (int n = 0; n < (CONFIG_UDC_BUF_COUNT - 4); n++) {
340340
buf = udc_ep_buf_alloc(dev, ed->bEndpointAddress,
341-
sys_le16_to_cpu(ed->wMaxPacketSize));
341+
USB_MPS_TO_TPL(sys_le16_to_cpu(ed->wMaxPacketSize)));
342342
zassert_not_null(buf,
343343
"Failed to allocate request (%d) for 0x%02x",
344344
n, ed->bEndpointAddress);

0 commit comments

Comments
 (0)