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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mps > cfg->caps.mps) {
|
if (USB_MPS_EP_SIZE(mps) > USB_MPS_EP_SIZE(cfg->caps.mps)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,12 +273,16 @@ static bool ep_check_config(const struct device *dev,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_EP_TYPE_INTERRUPT:
|
case USB_EP_TYPE_INTERRUPT:
|
||||||
if (!cfg->caps.interrupt) {
|
if (!cfg->caps.interrupt ||
|
||||||
|
(USB_MPS_ADDITIONAL_TRANSACTIONS(mps) &&
|
||||||
|
!cfg->caps.high_bandwidth)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_EP_TYPE_ISO:
|
case USB_EP_TYPE_ISO:
|
||||||
if (!cfg->caps.iso) {
|
if (!cfg->caps.iso ||
|
||||||
|
(USB_MPS_ADDITIONAL_TRANSACTIONS(mps) &&
|
||||||
|
!cfg->caps.high_bandwidth)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -76,6 +76,8 @@ struct udc_ep_caps {
|
||||||
uint32_t bulk : 1;
|
uint32_t bulk : 1;
|
||||||
/** ISO transfer capable endpoint */
|
/** ISO transfer capable endpoint */
|
||||||
uint32_t iso : 1;
|
uint32_t iso : 1;
|
||||||
|
/** High-Bandwidth (interrupt or iso) capable endpoint */
|
||||||
|
uint32_t high_bandwidth : 1;
|
||||||
/** IN transfer capable endpoint */
|
/** IN transfer capable endpoint */
|
||||||
uint32_t in : 1;
|
uint32_t in : 1;
|
||||||
/** OUT transfer capable endpoint */
|
/** OUT transfer capable endpoint */
|
||||||
|
|
|
@ -348,6 +348,29 @@ struct usb_association_descriptor {
|
||||||
/** Calculate high speed isochronous endpoint bInterval from a value in microseconds */
|
/** 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)
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -742,6 +742,8 @@ static const struct hid_device_driver_api hid_device_api = {
|
||||||
(USBD_HID_INTERFACE_ALTERNATE_DEFINE(n)))
|
(USBD_HID_INTERFACE_ALTERNATE_DEFINE(n)))
|
||||||
|
|
||||||
#define USBD_HID_INSTANCE_DEFINE(n) \
|
#define USBD_HID_INSTANCE_DEFINE(n) \
|
||||||
|
HID_VERIFY_REPORT_SIZES(n); \
|
||||||
|
\
|
||||||
NET_BUF_POOL_DEFINE(hid_buf_pool_in_##n, \
|
NET_BUF_POOL_DEFINE(hid_buf_pool_in_##n, \
|
||||||
CONFIG_USBD_HID_IN_BUF_COUNT, 0, \
|
CONFIG_USBD_HID_IN_BUF_COUNT, 0, \
|
||||||
sizeof(struct udc_buf_info), NULL); \
|
sizeof(struct udc_buf_info), NULL); \
|
||||||
|
|
|
@ -153,7 +153,7 @@
|
||||||
*/
|
*/
|
||||||
#define HID_OUT_EP_MPS(n, alt) \
|
#define HID_OUT_EP_MPS(n, alt) \
|
||||||
COND_CODE_1(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))))
|
(sys_cpu_to_le16(MIN(DT_INST_PROP(n, out_report_size), 64U))))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -162,7 +162,7 @@
|
||||||
*/
|
*/
|
||||||
#define HID_IN_EP_MPS(n, alt) \
|
#define HID_IN_EP_MPS(n, alt) \
|
||||||
COND_CODE_1(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))))
|
(sys_cpu_to_le16(MIN(DT_INST_PROP(n, in_report_size), 64U))))
|
||||||
|
|
||||||
#define HID_OUT_EP_DEFINE(n, hs, alt) \
|
#define HID_OUT_EP_DEFINE(n, hs, alt) \
|
||||||
|
@ -206,4 +206,10 @@
|
||||||
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \
|
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, out_report_size), \
|
||||||
(&hid_buf_pool_out_##n), (NULL))
|
(&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_ */
|
#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;
|
struct net_buf *buf;
|
||||||
|
|
||||||
buf = udc_ep_buf_alloc(dev, ed->bEndpointAddress,
|
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");
|
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. */
|
/* It needs a little reserve for memory management overhead. */
|
||||||
for (int n = 0; n < (CONFIG_UDC_BUF_COUNT - 4); n++) {
|
for (int n = 0; n < (CONFIG_UDC_BUF_COUNT - 4); n++) {
|
||||||
buf = udc_ep_buf_alloc(dev, ed->bEndpointAddress,
|
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,
|
zassert_not_null(buf,
|
||||||
"Failed to allocate request (%d) for 0x%02x",
|
"Failed to allocate request (%d) for 0x%02x",
|
||||||
n, ed->bEndpointAddress);
|
n, ed->bEndpointAddress);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue