Skip to content

usb: fixes for USB device support #2971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions dts/bindings/usb/zephyr,hid-device.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ compatible: "zephyr,hid-device"
include: base.yaml

properties:
interface-name:
type: string
label:
description: |
HID device name. When this property is present, a USB device will use it
as the string descriptor of the interface.
The string defined by the label property is also used for the USB device
interface string descriptor.

protocol-code:
type: string
Expand Down
2 changes: 1 addition & 1 deletion samples/subsys/usb/hid-keyboard/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/ {
hid_dev_0: hid_dev_0 {
compatible = "zephyr,hid-device";
interface-name = "HID0";
label = "HID0";
protocol-code = "keyboard";
in-report-size = <64>;
in-polling-period-us = <1000>;
Expand Down
2 changes: 1 addition & 1 deletion samples/subsys/usb/hid-keyboard/large_in_report.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/ {
hid_dev_0: hid_dev_0 {
compatible = "zephyr,hid-device";
interface-name = "HID0";
label = "HID0";
in-report-size = <256>;
in-polling-period-us = <1000>;
};
Expand Down
2 changes: 1 addition & 1 deletion samples/subsys/usb/hid-mouse/usbd_next.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/ {
hid_dev_0: hid_dev_0 {
compatible = "zephyr,hid-device";
interface-name = "HID0";
label = "HID0";
protocol-code = "none";
in-polling-period-us = <1000>;
in-report-size = <64>;
Expand Down
12 changes: 6 additions & 6 deletions subsys/usb/device/class/bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,20 @@ static void hci_tx_thread(void *p1, void *p2, void *p3)

type = net_buf_pull_u8(buf);
switch (type) {
case BT_BUF_EVT:
case BT_HCI_H4_EVT:
usb_transfer_sync(
bluetooth_ep_data[HCI_INT_EP_IDX].ep_addr,
buf->data, buf->len,
USB_TRANS_WRITE | USB_TRANS_NO_ZLP);
break;
case BT_BUF_ACL_IN:
case BT_HCI_H4_ACL:
usb_transfer_sync(
bluetooth_ep_data[HCI_IN_EP_IDX].ep_addr,
buf->data, buf->len,
USB_TRANS_WRITE);
break;
default:
LOG_ERR("Unknown type %u", type);
LOG_ERR("Unsupported type %u", type);
break;
}

Expand Down Expand Up @@ -200,11 +200,11 @@ static uint16_t hci_acl_pkt_len(const uint8_t *data, size_t data_len)
struct bt_hci_acl_hdr *acl_hdr;
size_t hdr_len = sizeof(*acl_hdr);

if (data_len - 1 < hdr_len) {
if (data_len < hdr_len) {
return 0;
}

acl_hdr = (struct bt_hci_acl_hdr *)(data + 1);
acl_hdr = (struct bt_hci_acl_hdr *)data;

return sys_le16_to_cpu(acl_hdr->len) + hdr_len;
}
Expand Down Expand Up @@ -250,7 +250,7 @@ static void acl_read_cb(uint8_t ep, int size, void *priv)
LOG_DBG("len %u, chunk %u", buf->len, size);
}

if (buf != NULL && pkt_len == buf->len) {
if (buf != NULL && pkt_len == buf->len - 1) {
k_fifo_put(&rx_queue, buf);
LOG_DBG("put");
buf = NULL;
Expand Down
64 changes: 49 additions & 15 deletions subsys/usb/device_next/class/bt_hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,12 @@
}

net_buf_add_mem(buf, bt_buf->data, bt_buf->len);
usbd_ep_enqueue(c_data, buf);
k_sem_take(&hci_data->sync_sem, K_FOREVER);
if (usbd_ep_enqueue(c_data, buf)) {
LOG_ERR("Failed to enqueue transfer");
} else {
k_sem_take(&hci_data->sync_sem, K_FOREVER);
}

net_buf_unref(buf);
}

Expand All @@ -210,14 +214,14 @@
type = net_buf_pull_u8(bt_buf);

switch (type) {
case BT_BUF_EVT:
case BT_HCI_H4_EVT:
ep = bt_hci_get_int_in(c_data);
break;
case BT_BUF_ACL_IN:
case BT_HCI_H4_ACL:
ep = bt_hci_get_bulk_in(c_data);
break;
default:
LOG_ERR("Unknown type %u", type);
LOG_ERR("Unsupported type %u", type);
continue;
}

Expand Down Expand Up @@ -273,19 +277,43 @@
return ret;
}

static uint16_t hci_acl_pkt_len(struct net_buf *const buf)
static uint16_t hci_pkt_get_len(const uint8_t h4_type,
const uint8_t *data, const size_t size)
{

Check notice on line 282 in subsys/usb/device_next/class/bt_hci.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/bt_hci.c:282 -static uint16_t hci_pkt_get_len(const uint8_t h4_type, - const uint8_t *data, const size_t size) +static uint16_t hci_pkt_get_len(const uint8_t h4_type, const uint8_t *data, const size_t size)
struct bt_hci_acl_hdr *acl_hdr;
size_t hdr_len;
size_t hdr_len = 0;
uint16_t len = 0;

hdr_len = sizeof(*acl_hdr);
if (buf->len - 1 < hdr_len) {
return 0;
switch (h4_type) {
case BT_HCI_H4_CMD: {
struct bt_hci_cmd_hdr *cmd_hdr;

hdr_len = sizeof(*cmd_hdr);
cmd_hdr = (struct bt_hci_cmd_hdr *)data;
len = cmd_hdr->param_len + hdr_len;
break;
}
case BT_HCI_H4_ACL: {
struct bt_hci_acl_hdr *acl_hdr;

acl_hdr = (struct bt_hci_acl_hdr *)(buf->data + 1);
hdr_len = sizeof(*acl_hdr);
acl_hdr = (struct bt_hci_acl_hdr *)data;
len = sys_le16_to_cpu(acl_hdr->len) + hdr_len;
break;
}
case BT_HCI_H4_ISO: {
struct bt_hci_iso_hdr *iso_hdr;

hdr_len = sizeof(*iso_hdr);
iso_hdr = (struct bt_hci_iso_hdr *)data;
len = bt_iso_hdr_len(sys_le16_to_cpu(iso_hdr->len)) + hdr_len;
break;
}
default:
LOG_ERR("Unknown H4 buffer type");
return 0;
}

return sys_le16_to_cpu(acl_hdr->len) + hdr_len;
return (size < hdr_len) ? 0 : len;
}

static int bt_hci_acl_out_cb(struct usbd_class_data *const c_data,
Expand All @@ -305,8 +333,10 @@
goto restart_out_transfer;
}

hci_data->acl_len = hci_acl_pkt_len(hci_data->acl_buf);
hci_data->acl_len = hci_pkt_get_len(BT_HCI_H4_ACL,
buf->data,
buf->len);

Check notice on line 339 in subsys/usb/device_next/class/bt_hci.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/bt_hci.c:339 - hci_data->acl_len = hci_pkt_get_len(BT_HCI_H4_ACL, - buf->data, - buf->len); + hci_data->acl_len = hci_pkt_get_len(BT_HCI_H4_ACL, buf->data, buf->len);
LOG_DBG("acl_len %u, chunk %u", hci_data->acl_len, buf->len);

if (hci_data->acl_len == 0) {
Expand All @@ -330,7 +360,11 @@
LOG_INF("len %u, chunk %u", hci_data->acl_buf->len, buf->len);
}

if (hci_data->acl_buf != NULL && hci_data->acl_len == hci_data->acl_buf->len) {
/*
* The buffer obtained from bt_buf_get_tx() stores the type at the top.
* Take this into account when comparing received data length.
*/
if (hci_data->acl_buf != NULL && hci_data->acl_len == hci_data->acl_buf->len - 1) {
k_fifo_put(&bt_hci_rx_queue, hci_data->acl_buf);
hci_data->acl_buf = NULL;
hci_data->acl_len = 0;
Expand Down
23 changes: 23 additions & 0 deletions subsys/usb/device_next/class/usbd_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
struct usbd_class_data *c_data;
struct net_buf_pool *pool_out;
struct net_buf_pool *pool_in;
struct usbd_desc_node *const if_desc_data;
const struct usb_desc_header **fs_desc;
const struct usb_desc_header **hs_desc;
};
Expand Down Expand Up @@ -488,8 +489,21 @@

static int usbd_hid_init(struct usbd_class_data *const c_data)
{
struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
const struct device *dev = usbd_class_get_private(c_data);
const struct hid_device_config *dcfg = dev->config;
struct usbd_hid_descriptor *const desc = dcfg->desc;

LOG_DBG("HID class %s init", c_data->name);

if (dcfg->if_desc_data != NULL && desc->if0.iInterface == 0) {
if (usbd_add_descriptor(uds_ctx, dcfg->if_desc_data)) {
LOG_ERR("Failed to add interface string descriptor");
} else {
desc->if0.iInterface = usbd_str_desc_get_idx(dcfg->if_desc_data);
}
}

return 0;
}

Expand Down Expand Up @@ -750,6 +764,12 @@
HID_OUT_POOL_DEFINE(n); \
USBD_HID_INTERFACE_DEFINE(n); \
\
IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \
USBD_DESC_STRING_DEFINE(hid_if_desc_data_##n, \
DT_INST_PROP(n, label), \
USBD_DUT_STRING_INTERFACE); \
)) \
\
USBD_DEFINE_CLASS(hid_##n, \
&usbd_hid_api, \
(void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \
Expand All @@ -761,6 +781,9 @@
.pool_out = HID_OUT_POOL_ADDR(n), \
.fs_desc = hid_fs_desc_##n, \
.hs_desc = hid_hs_desc_##n, \
IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \
.if_desc_data = &hid_if_desc_data_##n, \
)) \
}; \
\
static struct hid_device_data hid_data_##n; \
Expand All @@ -769,5 +792,5 @@
&hid_data_##n, &hid_config_##n, \
POST_KERNEL, CONFIG_USBD_HID_INIT_PRIORITY, \
&hid_device_api);

Check notice on line 795 in subsys/usb/device_next/class/usbd_hid.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_hid.c:795 -#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); \ - \ - HID_OUT_POOL_DEFINE(n); \ - USBD_HID_INTERFACE_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); \ + \ + HID_OUT_POOL_DEFINE(n); \ + USBD_HID_INTERFACE_DEFINE(n); \ + \ IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \ USBD_DESC_STRING_DEFINE(hid_if_desc_data_##n, \ DT_INST_PROP(n, label), \ USBD_DUT_STRING_INTERFACE); \ - )) \ - \ - USBD_DEFINE_CLASS(hid_##n, \ - &usbd_hid_api, \ - (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \ - \ - static const struct hid_device_config hid_config_##n = { \ - .desc = &hid_desc_##n, \ - .c_data = &hid_##n, \ - .pool_in = &hid_buf_pool_in_##n, \ - .pool_out = HID_OUT_POOL_ADDR(n), \ - .fs_desc = hid_fs_desc_##n, \ - .hs_desc = hid_hs_desc_##n, \ + )) \ + \ + USBD_DEFINE_CLASS(hid_##n, &usbd_hid_api, (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \ + \ + static const struct hid_device_config hid_config_##n = { \ + .desc = &hid_desc_##n, \ + .c_data = &hid_##n, \ + .pool_in = &hid_buf_pool_in_##n, \ + .pool_out = HID_OUT_POOL_ADDR(n), \ + .fs_desc = hid_fs_desc_##n, \ + .hs_desc = hid_hs_desc_##n, \ IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \ .if_desc_data = &hid_if_desc_data_##n, \ - )) \ - }; \ - \ - static struct hid_device_data hid_data_##n; \ - \ - DEVICE_DT_INST_DEFINE(n, hid_device_init, NULL, \ - &hid_data_##n, &hid_config_##n, \ - POST_KERNEL, CONFIG_USBD_HID_INIT_PRIORITY, \ - &hid_device_api); + )) }; \ + \ + static struct hid_device_data hid_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, hid_device_init, NULL, &hid_data_##n, &hid_config_##n, \ + POST_KERNEL, CONFIG_USBD_HID_INIT_PRIORITY, &hid_device_api);
DT_INST_FOREACH_STATUS_OKAY(USBD_HID_INSTANCE_DEFINE);
17 changes: 11 additions & 6 deletions subsys/usb/device_next/usbd_ch9.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,12 +683,6 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx,
struct usb_device_qualifier_descriptor q_desc = {
.bLength = sizeof(struct usb_device_qualifier_descriptor),
.bDescriptorType = USB_DESC_DEVICE_QUALIFIER,
.bcdUSB = d_desc->bcdUSB,
.bDeviceClass = d_desc->bDeviceClass,
.bDeviceSubClass = d_desc->bDeviceSubClass,
.bDeviceProtocol = d_desc->bDeviceProtocol,
.bMaxPacketSize0 = d_desc->bMaxPacketSize0,
.bNumConfigurations = d_desc->bNumConfigurations,
.bReserved = 0U,
};
size_t len;
Expand All @@ -703,6 +697,17 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx,
return 0;
}

if (d_desc == NULL) {
return -EINVAL;
}

q_desc.bcdUSB = d_desc->bcdUSB;
q_desc.bDeviceClass = d_desc->bDeviceClass;
q_desc.bDeviceSubClass = d_desc->bDeviceSubClass;
q_desc.bDeviceProtocol = d_desc->bDeviceProtocol;
q_desc.bMaxPacketSize0 = d_desc->bMaxPacketSize0;
q_desc.bNumConfigurations = d_desc->bNumConfigurations;

LOG_DBG("Get Device Qualifier");
len = MIN(setup->wLength, net_buf_tailroom(buf));
net_buf_add_mem(buf, &q_desc, MIN(len, q_desc.bLength));
Expand Down
10 changes: 10 additions & 0 deletions subsys/usb/device_next/usbd_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ int usbd_device_set_bcd_usb(struct usbd_context *const uds_ctx,
}

desc = get_device_descriptor(uds_ctx, speed);
if (desc == NULL) {
ret = -EINVAL;
goto set_bcd_exit;
}

desc->bcdUSB = sys_cpu_to_le16(bcd);

set_bcd_exit:
Expand Down Expand Up @@ -167,6 +172,11 @@ int usbd_device_set_code_triple(struct usbd_context *const uds_ctx,
}

desc = get_device_descriptor(uds_ctx, speed);
if (desc == NULL) {
ret = -EINVAL;
goto set_code_triple_exit;
}

desc->bDeviceClass = base_class;
desc->bDeviceSubClass = subclass;
desc->bDeviceProtocol = protocol;
Expand Down
Loading