From b0791400f61fc26d45b5cf95849f218955e47633 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 15 Jan 2025 23:12:54 +0000 Subject: [PATCH] usb: device_next: cdc_acm: allow setting the interface description Add a interface-name string for the CDC-ACM node, this allow setting a string that is then set as iInterface, which can then be used downstream in an udev rule such as: SUBSYSTEM=="tty", ACTION=="add", ATTRS{interface}=="my interface descriptor", SYMLINK+="tty-my-device" To create known aliases for these ports. Signed-off-by: Fabio Baltieri --- dts/bindings/serial/zephyr,cdc-acm-uart.yaml | 5 +++++ samples/subsys/usb/cdc_acm/app.overlay | 1 + subsys/usb/device_next/class/usbd_cdc_acm.c | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/dts/bindings/serial/zephyr,cdc-acm-uart.yaml b/dts/bindings/serial/zephyr,cdc-acm-uart.yaml index 8e0a0030978..6b7ad36d1d1 100644 --- a/dts/bindings/serial/zephyr,cdc-acm-uart.yaml +++ b/dts/bindings/serial/zephyr,cdc-acm-uart.yaml @@ -21,3 +21,8 @@ properties: default: 1024 description: | Size of the virtual CDC ACM UART RX FIFO + + label: + description: | + The string defined by the label property is also used for the USB + interface string descriptor. diff --git a/samples/subsys/usb/cdc_acm/app.overlay b/samples/subsys/usb/cdc_acm/app.overlay index c50d0fd9d69..56ed8d4b43f 100644 --- a/samples/subsys/usb/cdc_acm/app.overlay +++ b/samples/subsys/usb/cdc_acm/app.overlay @@ -7,5 +7,6 @@ &zephyr_udc0 { cdc_acm_uart0 { compatible = "zephyr,cdc-acm-uart"; + label = "Zephyr USB CDC-ACM"; }; }; diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index 45da1a10a35..fe7dd30d7a7 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -83,6 +83,8 @@ struct usbd_cdc_acm_desc { struct cdc_acm_uart_data { /* Pointer to the associated USBD class node */ struct usbd_class_data *c_data; + /* Pointer to the interface description node or NULL */ + struct usbd_desc_node *const if_desc_data; /* Pointer to the class interface descriptors */ struct usbd_cdc_acm_desc *const desc; const struct usb_desc_header **const fs_desc; @@ -488,6 +490,7 @@ static int usbd_cdc_acm_ctd(struct usbd_class_data *const c_data, static int usbd_cdc_acm_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); struct cdc_acm_uart_data *data = dev->data; struct usbd_cdc_acm_desc *desc = data->desc; @@ -495,6 +498,14 @@ static int usbd_cdc_acm_init(struct usbd_class_data *const c_data) desc->if0_union.bControlInterface = desc->if0.bInterfaceNumber; desc->if0_union.bSubordinateInterface0 = desc->if1.bInterfaceNumber; + if (data->if_desc_data != NULL) { + if (usbd_add_descriptor(uds_ctx, data->if_desc_data)) { + LOG_ERR("Failed to add interface string descriptor"); + } else { + desc->if0.iInterface = usbd_str_desc_get_idx(data->if_desc_data); + } + } + return 0; } @@ -1259,12 +1270,21 @@ const static struct usb_desc_header *cdc_acm_hs_desc_##n[] = { \ &usbd_cdc_acm_api, \ (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \ \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \ + USBD_DESC_STRING_DEFINE(cdc_acm_if_desc_data_##n, \ + DT_INST_PROP(n, label), \ + USBD_DUT_STRING_INTERFACE); \ + )) \ + \ RING_BUF_DECLARE(cdc_acm_rb_rx_##n, DT_INST_PROP(n, rx_fifo_size)); \ RING_BUF_DECLARE(cdc_acm_rb_tx_##n, DT_INST_PROP(n, tx_fifo_size)); \ \ static struct cdc_acm_uart_data uart_data_##n = { \ .line_coding = CDC_ACM_DEFAULT_LINECODING, \ .c_data = &cdc_acm_##n, \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \ + .if_desc_data = &cdc_acm_if_desc_data_##n, \ + )) \ .rx_fifo.rb = &cdc_acm_rb_rx_##n, \ .tx_fifo.rb = &cdc_acm_rb_tx_##n, \ .flow_ctrl = DT_INST_PROP(n, hw_flow_control), \