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ń <tomasz.mon@nordicsemi.no>
This commit is contained in:
parent
e333739f3a
commit
b7664f27c8
6 changed files with 44 additions and 7 deletions
|
@ -262,7 +262,7 @@ static bool ep_check_config(const struct device *dev,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mps > cfg->caps.mps) {
|
||||
if (USB_MPS_EP_SIZE(mps) > USB_MPS_EP_SIZE(cfg->caps.mps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -273,12 +273,16 @@ static bool ep_check_config(const struct device *dev,
|
|||
}
|
||||
break;
|
||||
case USB_EP_TYPE_INTERRUPT:
|
||||
if (!cfg->caps.interrupt) {
|
||||
if (!cfg->caps.interrupt ||
|
||||
(USB_MPS_ADDITIONAL_TRANSACTIONS(mps) &&
|
||||
!cfg->caps.high_bandwidth)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case USB_EP_TYPE_ISO:
|
||||
if (!cfg->caps.iso) {
|
||||
if (!cfg->caps.iso ||
|
||||
(USB_MPS_ADDITIONAL_TRANSACTIONS(mps) &&
|
||||
!cfg->caps.high_bandwidth)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -76,6 +76,8 @@ struct udc_ep_caps {
|
|||
uint32_t bulk : 1;
|
||||
/** ISO transfer capable endpoint */
|
||||
uint32_t iso : 1;
|
||||
/** High-Bandwidth (interrupt or iso) capable endpoint */
|
||||
uint32_t high_bandwidth : 1;
|
||||
/** IN transfer capable endpoint */
|
||||
uint32_t in : 1;
|
||||
/** OUT transfer capable endpoint */
|
||||
|
|
|
@ -348,6 +348,29 @@ struct usb_association_descriptor {
|
|||
/** Calculate high speed isochronous endpoint bInterval from a value in microseconds */
|
||||
#define USB_HS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U)
|
||||
|
||||
/** Get endpoint size field from Max Packet Size value */
|
||||
#define USB_MPS_EP_SIZE(mps) ((mps) & BIT_MASK(11))
|
||||
|
||||
/** Get number of additional transactions per microframe from Max Packet Size value */
|
||||
#define USB_MPS_ADDITIONAL_TRANSACTIONS(mps) (((mps) & 0x1800) >> 11)
|
||||
|
||||
/** Calculate total payload length from Max Packet Size value */
|
||||
#define USB_MPS_TO_TPL(mps) \
|
||||
((1 + USB_MPS_ADDITIONAL_TRANSACTIONS(mps)) * USB_MPS_EP_SIZE(mps))
|
||||
|
||||
/** Calculate Max Packet Size value from total payload length */
|
||||
#define USB_TPL_TO_MPS(tpl) \
|
||||
(((tpl) > 2048) ? ((2 << 11) | ((tpl) / 3)) : \
|
||||
((tpl) > 1024) ? ((1 << 11) | ((tpl) / 2)) : \
|
||||
(tpl))
|
||||
|
||||
/** Determine whether total payload length value is valid according to USB 2.0 */
|
||||
#define USB_TPL_IS_VALID(tpl) \
|
||||
(((tpl) > 3072) ? false : \
|
||||
((tpl) > 2048) ? ((tpl) % 3 == 0) : \
|
||||
((tpl) > 1024) ? ((tpl) % 2 == 0) : \
|
||||
((tpl) >= 0))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -742,6 +742,8 @@ static const struct hid_device_driver_api hid_device_api = {
|
|||
(USBD_HID_INTERFACE_ALTERNATE_DEFINE(n)))
|
||||
|
||||
#define USBD_HID_INSTANCE_DEFINE(n) \
|
||||
HID_VERIFY_REPORT_SIZES(n); \
|
||||
\
|
||||
NET_BUF_POOL_DEFINE(hid_buf_pool_in_##n, \
|
||||
CONFIG_USBD_HID_IN_BUF_COUNT, 0, \
|
||||
sizeof(struct udc_buf_info), NULL); \
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
*/
|
||||
#define HID_OUT_EP_MPS(n, alt) \
|
||||
COND_CODE_1(alt, \
|
||||
(sys_cpu_to_le16(DT_INST_PROP(n, out_report_size))), \
|
||||
(sys_cpu_to_le16(USB_TPL_TO_MPS(DT_INST_PROP(n, out_report_size)))), \
|
||||
(sys_cpu_to_le16(MIN(DT_INST_PROP(n, out_report_size), 64U))))
|
||||
|
||||
/*
|
||||
|
@ -162,7 +162,7 @@
|
|||
*/
|
||||
#define HID_IN_EP_MPS(n, alt) \
|
||||
COND_CODE_1(alt, \
|
||||
(sys_cpu_to_le16(DT_INST_PROP(n, in_report_size))), \
|
||||
(sys_cpu_to_le16(USB_TPL_TO_MPS(DT_INST_PROP(n, in_report_size)))), \
|
||||
(sys_cpu_to_le16(MIN(DT_INST_PROP(n, in_report_size), 64U))))
|
||||
|
||||
#define HID_OUT_EP_DEFINE(n, hs, alt) \
|
||||
|
@ -206,4 +206,10 @@
|
|||
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \
|
||||
(&hid_buf_pool_out_##n), (NULL))
|
||||
|
||||
#define HID_VERIFY_REPORT_SIZES(n) \
|
||||
BUILD_ASSERT(USB_TPL_IS_VALID(DT_INST_PROP_OR(n, out_report_size, 0)), \
|
||||
"out-report-size must be valid Total Packet Length"); \
|
||||
BUILD_ASSERT(USB_TPL_IS_VALID(DT_INST_PROP_OR(n, in_report_size, 0)), \
|
||||
"in-report-size must be valid Total Packet Length");
|
||||
|
||||
#endif /* ZEPHYR_USB_DEVICE_CLASS_HID_MACROS_H_ */
|
||||
|
|
|
@ -197,7 +197,7 @@ static struct net_buf *test_udc_ep_buf_alloc(const struct device *dev,
|
|||
struct net_buf *buf;
|
||||
|
||||
buf = udc_ep_buf_alloc(dev, ed->bEndpointAddress,
|
||||
sys_le16_to_cpu(ed->wMaxPacketSize));
|
||||
USB_MPS_TO_TPL(sys_le16_to_cpu(ed->wMaxPacketSize)));
|
||||
|
||||
zassert_not_null(buf, "Failed to allocate request");
|
||||
|
||||
|
@ -338,7 +338,7 @@ static void test_udc_ep_api(const struct device *dev,
|
|||
/* It needs a little reserve for memory management overhead. */
|
||||
for (int n = 0; n < (CONFIG_UDC_BUF_COUNT - 4); n++) {
|
||||
buf = udc_ep_buf_alloc(dev, ed->bEndpointAddress,
|
||||
sys_le16_to_cpu(ed->wMaxPacketSize));
|
||||
USB_MPS_TO_TPL(sys_le16_to_cpu(ed->wMaxPacketSize)));
|
||||
zassert_not_null(buf,
|
||||
"Failed to allocate request (%d) for 0x%02x",
|
||||
n, ed->bEndpointAddress);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue