From c16e58621cd89dd3d91640474d100421daa59514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Fri, 9 Jan 2026 11:30:38 +0100 Subject: [PATCH 1/2] usb: device_next: Allocate data IN stage in handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For control transfers with data stage from device to host, only the handler knows how large buffer is necessary (by specification host is allowed to request up to 65535 bytes for every control read transfer). While generally hosts do keep wLength relatively low, there are cases where the value is big enough that the buffer cannot be allocated with default UDC_BUF_POOL_SIZE value. Right now the only workaround is to increase UDC_BUF_POOL_SIZE to large enough value but this is not a visable solution on memory constrained targets. For example USB3CV Mass Storage tests read string descriptor 0 with wLength set to 4096, while the Zephyr response to this request is 4 bytes (and therefore 4 byte long buffer is enough). Move the allocation to handler to allow the code to allocate as small buffer as possible to handle the transfer. This allows MSC sample to pass USB3CV with default UDC_BUF_POOL_SIZE value. Signed-off-by: Tomasz Moń --- include/zephyr/usb/usbd.h | 19 +- samples/subsys/dap/src/msosv2.h | 15 +- samples/subsys/dap/src/webusb.h | 15 +- samples/subsys/usb/webusb/src/msosv2.h | 16 +- samples/subsys/usb/webusb/src/webusb.h | 15 +- subsys/usb/device_next/class/loopback.c | 19 +- subsys/usb/device_next/class/usbd_cdc_acm.c | 9 +- subsys/usb/device_next/class/usbd_cdc_ncm.c | 25 ++- subsys/usb/device_next/class/usbd_dfu.c | 57 ++++-- subsys/usb/device_next/class/usbd_hid.c | 16 +- subsys/usb/device_next/class/usbd_midi2.c | 12 +- subsys/usb/device_next/class/usbd_msc.c | 12 +- subsys/usb/device_next/class/usbd_uac2.c | 44 ++++- subsys/usb/device_next/class/usbd_uvc.c | 12 +- subsys/usb/device_next/usbd_ch9.c | 189 +++++++++++++------- subsys/usb/device_next/usbd_class_api.h | 6 +- 16 files changed, 360 insertions(+), 121 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 4527f417483ee..af725c0435aa1 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -103,17 +103,26 @@ struct usbd_str_desc_data { * @code{.c} * static int foo_to_host_cb(const struct usbd_context *const ctx, * const struct usb_setup_packet *const setup, - * struct net_buf *const buf) + * struct net_buf **const pbuf) * { * if (setup->wIndex == WEBUSB_REQ_GET_URL) { + * struct net_buf *buf; + * uint16_t len; * uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); * * if (index != SAMPLE_WEBUSB_LANDING_PAGE) { * return -ENOTSUP; * } * - * net_buf_add_mem(buf, &webusb_origin_url, - * MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url))); + * len = MIN(setup->wLength, sizeof(webusb_origin_url)); + * buf = usbd_ep_ctrl_data_in_alloc(ctx, len); + * if (buf == NULL) { + * return -ENOMEM; + * } + * + * *pbuf = buf; + * + * net_buf_add_mem(buf, &webusb_origin_url, len); * * return 0; * } @@ -130,7 +139,7 @@ struct usbd_vreq_node { /** Vendor request callback for device-to-host direction */ int (*to_host)(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, - struct net_buf *const buf); + struct net_buf **const pbuf); /** Vendor request callback for host-to-device direction */ int (*to_dev)(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, @@ -344,7 +353,7 @@ struct usbd_class_api { /** USB control request handler to host */ int (*control_to_host)(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf); + struct net_buf **const pbuf); /** Endpoint request completion event handler */ int (*request)(struct usbd_class_data *const c_data, diff --git a/samples/subsys/dap/src/msosv2.h b/samples/subsys/dap/src/msosv2.h index c00d614c3508e..182bec4e01bc6 100644 --- a/samples/subsys/dap/src/msosv2.h +++ b/samples/subsys/dap/src/msosv2.h @@ -115,16 +115,25 @@ struct bos_msosv2_descriptor bos_msosv2_desc = { static int msosv2_to_host_cb(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { LOG_INF("Vendor callback to host"); if (setup->bRequest == SAMPLE_MSOS2_VENDOR_CODE && setup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { + struct net_buf *buf; + uint16_t len = MIN(setup->wLength, sizeof(msosv2_desc)); + LOG_INF("Get MS OS 2.0 Descriptor Set"); - net_buf_add_mem(buf, &msosv2_desc, - MIN(net_buf_tailroom(buf), sizeof(msosv2_desc))); + buf = usbd_ep_ctrl_data_in_alloc(ctx, len); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + + net_buf_add_mem(buf, &msosv2_desc, len); return 0; } diff --git a/samples/subsys/dap/src/webusb.h b/samples/subsys/dap/src/webusb.h index c1cda8924ec12..73d2a2dd5092a 100644 --- a/samples/subsys/dap/src/webusb.h +++ b/samples/subsys/dap/src/webusb.h @@ -65,20 +65,29 @@ static const uint8_t webusb_origin_url[] = { static int webusb_to_host_cb(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { LOG_INF("Vendor callback to host"); if (setup->wIndex == WEBUSB_REQ_GET_URL) { + struct net_buf *buf; + uint16_t len; uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); if (index != SAMPLE_WEBUSB_LANDING_PAGE) { return -ENOTSUP; } + len = MIN(setup->wLength, sizeof(webusb_origin_url)); + buf = usbd_ep_ctrl_data_in_alloc(ctx, len); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + LOG_INF("Get URL request, index %u", index); - net_buf_add_mem(buf, &webusb_origin_url, - MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url))); + net_buf_add_mem(buf, &webusb_origin_url, len); return 0; } diff --git a/samples/subsys/usb/webusb/src/msosv2.h b/samples/subsys/usb/webusb/src/msosv2.h index 88fc592737fa4..2bd2273d17872 100644 --- a/samples/subsys/usb/webusb/src/msosv2.h +++ b/samples/subsys/usb/webusb/src/msosv2.h @@ -115,16 +115,26 @@ struct bos_msosv2_descriptor bos_msosv2_desc = { static int msosv2_to_host_cb(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { LOG_INF("Vendor callback to host"); if (setup->bRequest == SAMPLE_MSOS2_VENDOR_CODE && setup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { + struct net_buf *buf; + uint16_t len; + LOG_INF("Get MS OS 2.0 Descriptor Set"); - net_buf_add_mem(buf, &msosv2_desc, - MIN(net_buf_tailroom(buf), sizeof(msosv2_desc))); + len = MIN(setup->wLength, sizeof(msosv2_desc)); + buf = usbd_ep_ctrl_data_in_alloc(ctx, len); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + + net_buf_add_mem(buf, &msosv2_desc, len); return 0; } diff --git a/samples/subsys/usb/webusb/src/webusb.h b/samples/subsys/usb/webusb/src/webusb.h index 329626d4587b6..2300e32c999d5 100644 --- a/samples/subsys/usb/webusb/src/webusb.h +++ b/samples/subsys/usb/webusb/src/webusb.h @@ -63,20 +63,29 @@ static const uint8_t webusb_origin_url[] = { static int webusb_to_host_cb(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { LOG_INF("Vendor callback to host"); if (setup->wIndex == WEBUSB_REQ_GET_URL) { + struct net_buf *buf; + uint16_t len; uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); if (index != SAMPLE_WEBUSB_LANDING_PAGE) { return -ENOTSUP; } + len = MIN(setup->wLength, sizeof(webusb_origin_url)); + buf = usbd_ep_ctrl_data_in_alloc(ctx, len); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + LOG_INF("Get URL request, index %u", index); - net_buf_add_mem(buf, &webusb_origin_url, - MIN(net_buf_tailroom(buf), sizeof(webusb_origin_url))); + net_buf_add_mem(buf, &webusb_origin_url, len); return 0; } diff --git a/subsys/usb/device_next/class/loopback.c b/subsys/usb/device_next/class/loopback.c index 911a3f060b632..8575c7a701c66 100644 --- a/subsys/usb/device_next/class/loopback.c +++ b/subsys/usb/device_next/class/loopback.c @@ -204,7 +204,7 @@ static void lb_update(struct usbd_class_data *c_data, static int lb_control_to_host(struct usbd_class_data *c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_DEVICE) { errno = -ENOTSUP; @@ -212,11 +212,20 @@ static int lb_control_to_host(struct usbd_class_data *c_data, } if (setup->bRequest == LB_VENDOR_REQ_IN) { - net_buf_add_mem(buf, lb_buf, - MIN(sizeof(lb_buf), setup->wLength)); + struct net_buf *buf; + uint16_t len = MIN(sizeof(lb_buf), setup->wLength); - LOG_WRN("Device-to-Host, wLength %u | %zu", setup->wLength, - MIN(sizeof(lb_buf), setup->wLength)); + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), len); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + + net_buf_add_mem(buf, lb_buf, len); + + LOG_WRN("Device-to-Host, wLength %u | %zu", setup->wLength, len); return 0; } diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index cff61406d68c8..8743a748d4027 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -486,19 +486,24 @@ static void cdc_acm_update_linestate(struct cdc_acm_uart_data *const data) static int usbd_cdc_acm_cth(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; + struct net_buf *buf; size_t min_len; if (setup->bRequest == GET_LINE_CODING) { + min_len = MIN(sizeof(data->line_coding), setup->wLength); + + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), min_len); if (buf == NULL) { errno = -ENOMEM; return 0; } - min_len = MIN(sizeof(data->line_coding), setup->wLength); + *pbuf = buf; + net_buf_add_mem(buf, &data->line_coding, min_len); return 0; diff --git a/subsys/usb/device_next/class/usbd_cdc_ncm.c b/subsys/usb/device_next/class/usbd_cdc_ncm.c index 7bd04a42b068c..8a06dc21db3c5 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ncm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ncm.c @@ -918,9 +918,28 @@ static int usbd_cdc_ncm_ctd(struct usbd_class_data *const c_data, return 0; } +static void cdc_ncm_cth_response(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup, + struct net_buf **const pbuf, + const void *data, uint16_t data_len) +{ + struct net_buf *buf; + uint16_t len = MIN(setup->wLength, data_len); + + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), len); + if (buf == NULL) { + errno = -ENOMEM; + return; + } + + *pbuf = buf; + + net_buf_add_mem(buf, data, len); +} + static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { LOG_DBG("%d: %d %d %d %d", setup->RequestType.type, setup->bRequest, setup->wLength, setup->wIndex, setup->wValue); @@ -948,7 +967,7 @@ static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, }; LOG_DBG("GET_NTB_PARAMETERS"); - net_buf_add_mem(buf, &ntb_params, sizeof(ntb_params)); + cdc_ncm_cth_response(c_data, setup, pbuf, &ntb_params, sizeof(ntb_params)); break; } @@ -960,7 +979,7 @@ static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, }; LOG_DBG("GET_NTB_INPUT_SIZE"); - net_buf_add_mem(buf, &input_size, sizeof(input_size)); + cdc_ncm_cth_response(c_data, setup, pbuf, &input_size, sizeof(input_size)); break; } diff --git a/subsys/usb/device_next/class/usbd_dfu.c b/subsys/usb/device_next/class/usbd_dfu.c index de9e924b9b520..5b999067e5611 100644 --- a/subsys/usb/device_next/class/usbd_dfu.c +++ b/subsys/usb/device_next/class/usbd_dfu.c @@ -518,16 +518,23 @@ static int dfu_set_next_state(struct usbd_class_data *const c_data, static int handle_get_status(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); - size_t len = MIN(setup->wLength, net_buf_tailroom(buf)); + struct net_buf *buf; const size_t getstatus_len = 6; - if (len != getstatus_len) { + if (setup->wLength != getstatus_len) { return -ENOTSUP; } + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), getstatus_len); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + /* * Add GET_STATUS response consisting of * bStatus, bwPollTimeout, bStatus, iString (no strings defined) @@ -543,16 +550,23 @@ static int handle_get_status(struct usbd_class_data *const c_data, static int handle_get_state(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); - size_t len = MIN(setup->wLength, net_buf_tailroom(buf)); + struct net_buf *buf; const size_t getstate_len = 1; - if (len != getstate_len) { + if (setup->wLength != getstate_len) { return -ENOTSUP; } + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), getstate_len); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + net_buf_add_u8(buf, data->state); return 0; @@ -560,7 +574,7 @@ static int handle_get_state(struct usbd_class_data *const c_data, static int runtime_mode_control_to_host(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); @@ -569,10 +583,10 @@ static int runtime_mode_control_to_host(struct usbd_class_data *const c_data, if (errno == 0) { switch (setup->bRequest) { case USB_DFU_REQ_GETSTATUS: - errno = handle_get_status(c_data, setup, buf); + errno = handle_get_status(c_data, setup, pbuf); break; case USB_DFU_REQ_GETSTATE: - errno = handle_get_state(c_data, setup, buf); + errno = handle_get_state(c_data, setup, pbuf); break; default: break; @@ -639,13 +653,26 @@ USBD_DEFINE_CLASS(dfu_runtime, &runtime_mode_api, &dfu_data, NULL); static int handle_upload(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); - uint16_t size = MIN(setup->wLength, net_buf_tailroom(buf)); + uint16_t size; struct usbd_dfu_image *const image = data->image; + struct net_buf *buf; int ret; + /* read_cb() requires buffer size CONFIG_USBD_DFU_TRANSFER_SIZE */ + size = CONFIG_USBD_DFU_TRANSFER_SIZE; + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), size); + if (buf == NULL) { + return -ENOMEM; + } + + *pbuf = buf; + + /* Do not return more than requested */ + size = MIN(setup->wLength, size); + ret = image->read_cb(image->priv, setup->wValue, size, buf->data); if (ret >= 0) { net_buf_add(buf, ret); @@ -680,7 +707,7 @@ static int handle_download(struct usbd_class_data *const c_data, static int dfu_mode_control_to_host(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); @@ -689,13 +716,13 @@ static int dfu_mode_control_to_host(struct usbd_class_data *const c_data, if (errno == 0) { switch (setup->bRequest) { case USB_DFU_REQ_GETSTATUS: - errno = handle_get_status(c_data, setup, buf); + errno = handle_get_status(c_data, setup, pbuf); break; case USB_DFU_REQ_GETSTATE: - errno = handle_get_state(c_data, setup, buf); + errno = handle_get_state(c_data, setup, pbuf); break; case USB_DFU_REQ_UPLOAD: - errno = handle_upload(c_data, setup, buf); + errno = handle_upload(c_data, setup, pbuf); break; default: break; diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index 54da756a6293b..29d94ba2ca47a 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -399,11 +399,25 @@ static int usbd_hid_ctd(struct usbd_class_data *const c_data, static int usbd_hid_cth(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { const struct device *dev = usbd_class_get_private(c_data); + struct net_buf *buf; int ret = 0; + /* Get Report is problematic because ops->get_report() currently does + * not make it possible to determine report size without passing + * sufficiently large buffer first. For the time being, just allocate + * setup->wLength bytes. + */ + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), setup->wLength); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + switch (setup->bRequest) { case USB_HID_GET_IDLE: ret = handle_get_idle(dev, setup, buf); diff --git a/subsys/usb/device_next/class/usbd_midi2.c b/subsys/usb/device_next/class/usbd_midi2.c index 78b8fa4ccc41c..143ce14c329a6 100644 --- a/subsys/usb/device_next/class/usbd_midi2.c +++ b/subsys/usb/device_next/class/usbd_midi2.c @@ -289,11 +289,12 @@ static void usbd_midi_class_resumed(struct usbd_class_data *const class_data) static int usbd_midi_class_cth(struct usbd_class_data *const class_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { const struct device *dev = usbd_class_get_private(class_data); const struct usbd_midi_config *config = dev->config; struct usbd_midi_data *data = dev->data; + struct net_buf *buf; size_t head_len = config->desc->grptrm_header.bLength; size_t total_len = sys_le16_to_cpu(config->desc->grptrm_header.wTotalLength); @@ -313,6 +314,15 @@ static int usbd_midi_class_cth(struct usbd_class_data *const class_data, return 0; } + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(class_data), + MIN(total_len, setup->wLength)); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + /* Group terminal block header */ net_buf_add_mem(buf, (void *) &config->desc->grptrm_header, MIN(head_len, setup->wLength)); diff --git a/subsys/usb/device_next/class/usbd_msc.c b/subsys/usb/device_next/class/usbd_msc.c index 0d336f75e8821..d6b3fdb08d1ef 100644 --- a/subsys/usb/device_next/class/usbd_msc.c +++ b/subsys/usb/device_next/class/usbd_msc.c @@ -827,9 +827,10 @@ static int msc_bot_control_to_dev(struct usbd_class_data *const c_data, /* USB control request handler to host */ static int msc_bot_control_to_host(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); + struct net_buf *buf; uint8_t max_lun; if (setup->bRequest == GET_MAX_LUN && @@ -839,6 +840,15 @@ static int msc_bot_control_to_host(struct usbd_class_data *const c_data, * support multiple LUNs and host should only address LUN 0. */ max_lun = ctx->registered_luns ? ctx->registered_luns - 1 : 0; + + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), 1); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + net_buf_add_mem(buf, &max_lun, 1); } else { errno = -ENOTSUP; diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index 0c2585e0400a2..25cd2d25206cc 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -571,14 +571,25 @@ static uint32_t find_closest(const uint32_t input, const uint32_t *values, } /* Table 5-6: 4-byte Control CUR Parameter Block */ -static void layout3_cur_response(struct net_buf *const buf, uint16_t length, +static void layout3_cur_response(struct usbd_class_data *const c_data, + struct net_buf **const pbuf, uint16_t length, const uint32_t value) { + struct net_buf *buf; uint8_t tmp[4]; + length = MIN(length, 4); + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), length); + if (buf == NULL) { + errno = -ENOMEM; + return; + } + + *pbuf = buf; + /* dCUR */ sys_put_le32(value, tmp); - net_buf_add_mem(buf, tmp, MIN(length, 4)); + net_buf_add_mem(buf, tmp, length); } static int layout3_cur_request(const struct net_buf *const buf, uint32_t *out) @@ -595,15 +606,30 @@ static int layout3_cur_request(const struct net_buf *const buf, uint32_t *out) } /* Table 5-7: 4-byte Control RANGE Parameter Block */ -static void layout3_range_response(struct net_buf *const buf, uint16_t length, +static void layout3_range_response(struct usbd_class_data *const c_data, + struct net_buf **const pbuf, uint16_t length, const uint32_t *min, const uint32_t *max, const uint32_t *res, int n) { + struct net_buf *buf; uint16_t to_add; uint8_t tmp[4]; int i; int item; + /* Host can set wLength as large as it wants, but we only need to + * allocate memory for maximum number of entries consisting of: + * 2 (wNumSubRanges) + 12 (dMIN, dMAX, dRES) * n + */ + length = MIN(2 + 12 * n, length); + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), length); + if (buf == NULL) { + errno = -ENOMEM; + return; + } + + *pbuf = buf; + /* wNumSubRanges */ sys_put_le16(n, tmp); to_add = MIN(length, 2); @@ -639,7 +665,7 @@ static void layout3_range_response(struct net_buf *const buf, uint16_t length, static int get_clock_source_request(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { const struct device *dev = usbd_class_get_private(c_data); struct uac2_ctx *ctx = dev->data; @@ -660,7 +686,7 @@ static int get_clock_source_request(struct usbd_class_data *const c_data, if (CONTROL_SELECTOR(setup) == CS_SAM_FREQ_CONTROL) { if (CONTROL_ATTRIBUTE(setup) == CUR) { if (count == 1) { - layout3_cur_response(buf, setup->wLength, + layout3_cur_response(c_data, pbuf, setup->wLength, frequencies[0]); return 0; } @@ -670,11 +696,11 @@ static int get_clock_source_request(struct usbd_class_data *const c_data, hz = ctx->ops->get_sample_rate(dev, clock_id, ctx->user_data); - layout3_cur_response(buf, setup->wLength, hz); + layout3_cur_response(c_data, pbuf, setup->wLength, hz); return 0; } } else if (CONTROL_ATTRIBUTE(setup) == RANGE) { - layout3_range_response(buf, setup->wLength, frequencies, + layout3_range_response(c_data, pbuf, setup->wLength, frequencies, frequencies, NULL, count); return 0; } @@ -771,7 +797,7 @@ static int uac2_control_to_dev(struct usbd_class_data *const c_data, static int uac2_control_to_host(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { entity_type_t entity_type; @@ -784,7 +810,7 @@ static int uac2_control_to_host(struct usbd_class_data *const c_data, if (setup->bmRequestType == GET_CLASS_REQUEST_TYPE) { entity_type = id_type(c_data, CONTROL_ENTITY_ID(setup)); if (entity_type == ENTITY_TYPE_CLOCK_SOURCE) { - return get_clock_source_request(c_data, setup, buf); + return get_clock_source_request(c_data, setup, pbuf); } } diff --git a/subsys/usb/device_next/class/usbd_uvc.c b/subsys/usb/device_next/class/usbd_uvc.c index 40b507ed81669..109f49f7cada3 100644 --- a/subsys/usb/device_next/class/usbd_uvc.c +++ b/subsys/usb/device_next/class/usbd_uvc.c @@ -1018,10 +1018,12 @@ static int uvc_get_control_op(const struct device *dev, const struct usb_setup_p static int uvc_control_to_host(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { const struct device *dev = usbd_class_get_private(c_data); const struct uvc_control_map *map = NULL; + struct net_buf *buf; + const size_t size = MIN(sizeof(struct uvc_probe), setup->wLength); uint8_t request = setup->bRequest; LOG_INF("Host sent a %s request, wValue 0x%04x, wIndex 0x%04x, wLength %u", @@ -1031,6 +1033,14 @@ static int uvc_control_to_host(struct usbd_class_data *const c_data, request == UVC_GET_INFO ? "GET_INFO" : "bad", setup->wValue, setup->wIndex, setup->wLength); + buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), size); + if (buf == NULL) { + errno = ENOMEM; + return 0; + } + + *pbuf = buf; + switch (uvc_get_control_op(dev, setup, &map)) { case UVC_OP_VS_PROBE: errno = -uvc_get_vs_probe(dev, buf, setup); diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 666a9ba49d739..695d6b3dff51f 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -28,7 +28,7 @@ LOG_MODULE_REGISTER(usbd_ch9, CONFIG_USBD_LOG_LEVEL); #define SF_TEST_LOWER_BYTE(wIndex) ((uint8_t)(wIndex)) static int nonstd_request(struct usbd_context *const uds_ctx, - struct net_buf *const dbuf); + struct net_buf **const pbuf); static bool reqtype_is_to_host(const struct usb_setup_packet *const setup) { @@ -381,9 +381,10 @@ static int std_request_to_device(struct usbd_context *const uds_ctx, } static int sreq_get_status(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); + struct net_buf *buf; uint8_t ep = setup->wIndex; uint16_t response = 0; @@ -427,11 +428,14 @@ static int sreq_get_status(struct usbd_context *const uds_ctx, break; } - if (net_buf_tailroom(buf) < setup->wLength) { + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, sizeof(response)); + if (buf == NULL) { errno = -ENOMEM; return 0; } + *pbuf = buf; + LOG_DBG("Get Status response 0x%04x", response); net_buf_add_le16(buf, response); @@ -443,7 +447,7 @@ static int sreq_get_status(struct usbd_context *const uds_ctx, * descriptor type requests. */ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx, - struct net_buf *const buf, + struct net_buf **const pbuf, const uint8_t idx, const bool other_cfg) { @@ -454,6 +458,7 @@ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx, struct usbd_config_node *cfg_nd; enum usbd_speed get_desc_speed; struct usbd_class_node *c_nd; + struct net_buf *buf; uint16_t len; /* @@ -493,6 +498,15 @@ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx, cfg_desc = cfg_nd->desc; } + len = MIN(sys_le16_to_cpu(cfg_desc->wTotalLength), setup->wLength); + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, len); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + net_buf_add_mem(buf, cfg_desc, MIN(net_buf_tailroom(buf), cfg_desc->bLength)); SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) { @@ -549,13 +563,15 @@ static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_SN_ASCII7_LENGTH]) } /* Copy and convert ASCII-7 string descriptor to UTF16-LE */ -static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, - struct net_buf *const buf, const uint16_t wLength) +static void string_ascii7_to_utf16le(struct usbd_context *const uds_ctx, + struct usbd_desc_node *const dn, + struct net_buf **const pbuf, const uint16_t wLength) { uint8_t sn_ascii7_str[USBD_SN_ASCII7_LENGTH]; struct usb_desc_header head = { .bDescriptorType = dn->bDescriptorType, }; + struct net_buf *buf; const uint8_t *ascii7_str; size_t len; size_t i; @@ -576,10 +592,16 @@ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, ascii7_str = (uint8_t *)dn->ptr; } - LOG_DBG("wLength %u, bLength %u, tailroom %zu", - wLength, head.bLength, net_buf_tailroom(buf)); + LOG_DBG("wLength %u, bLength %u", wLength, head.bLength); - len = MIN(net_buf_tailroom(buf), MIN(head.bLength, wLength)); + len = MIN(head.bLength, wLength); + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, len); + if (buf == NULL) { + errno = -ENOMEM; + return; + } + + *pbuf = buf; /* Add bLength and bDescriptorType */ net_buf_add_mem(buf, &head, MIN(len, sizeof(head))); @@ -598,14 +620,13 @@ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, } static int sreq_get_desc_dev(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usb_desc_header *head; + struct net_buf *buf; size_t len; - len = MIN(setup->wLength, net_buf_tailroom(buf)); - switch (usbd_bus_speed(uds_ctx)) { case USBD_SPEED_FS: head = uds_ctx->fs_desc; @@ -622,13 +643,22 @@ static int sreq_get_desc_dev(struct usbd_context *const uds_ctx, return -EINVAL; } - net_buf_add_mem(buf, head, MIN(len, head->bLength)); + len = MIN(setup->wLength, head->bLength); + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, len); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + + net_buf_add_mem(buf, head, len); return 0; } static int sreq_get_desc_str(struct usbd_context *const uds_ctx, - struct net_buf *const buf, const uint8_t idx) + struct net_buf **const pbuf, const uint8_t idx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usbd_desc_node *d_nd; @@ -648,19 +678,28 @@ static int sreq_get_desc_str(struct usbd_context *const uds_ctx, .bDescriptorType = d_nd->bDescriptorType, .bString = *(uint16_t *)d_nd->ptr, }; + struct net_buf *buf; + + len = MIN(setup->wLength, langid.bLength); + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, len); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } - len = MIN(setup->wLength, net_buf_tailroom(buf)); - net_buf_add_mem(buf, &langid, MIN(len, langid.bLength)); + *pbuf = buf; + + net_buf_add_mem(buf, &langid, len); } else { /* String descriptors in ASCII7 format */ - string_ascii7_to_utf16le(d_nd, buf, setup->wLength); + string_ascii7_to_utf16le(uds_ctx, d_nd, pbuf, setup->wLength); } return 0; } static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); /* At Full-Speed we want High-Speed descriptor and vice versa */ @@ -672,6 +711,7 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, .bDescriptorType = USB_DESC_DEVICE_QUALIFIER, .bReserved = 0U, }; + struct net_buf *buf; size_t len; /* @@ -696,8 +736,17 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, 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)); + + len = MIN(setup->wLength, q_desc.bLength); + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, len); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + + net_buf_add_mem(buf, &q_desc, len); return 0; } @@ -721,12 +770,13 @@ static void desc_fill_bos_root(struct usbd_context *const uds_ctx, } static int sreq_get_desc_bos(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usb_device_descriptor *dev_dsc; struct usb_bos_descriptor bos; struct usbd_desc_node *desc_nd; + struct net_buf *buf; size_t len; if (!IS_ENABLED(CONFIG_USBD_BOS_SUPPORT)) { @@ -756,13 +806,23 @@ static int sreq_get_desc_bos(struct usbd_context *const uds_ctx, } desc_fill_bos_root(uds_ctx, &bos); - len = MIN(net_buf_tailroom(buf), MIN(setup->wLength, bos.wTotalLength)); + + len = MIN(setup->wLength, bos.wTotalLength); + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, len); + if (buf == NULL) { + errno = -ENOMEM; + return 0; + } + + *pbuf = buf; + LOG_DBG("wLength %u, bLength %u, wTotalLength %u, tailroom %zu", setup->wLength, bos.bLength, bos.wTotalLength, net_buf_tailroom(buf)); + bos.wTotalLength = sys_le16_to_cpu(bos.wTotalLength); net_buf_add_mem(buf, &bos, MIN(len, bos.bLength)); - len -= MIN(len, sizeof(bos)); + len -= MIN(len, bos.bLength); if (len == 0) { return 0; } @@ -784,7 +844,7 @@ static int sreq_get_desc_bos(struct usbd_context *const uds_ctx, } static int sreq_get_descriptor(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); uint8_t desc_type = USB_GET_DESCRIPTOR_TYPE(setup->wValue); @@ -800,22 +860,22 @@ static int sreq_get_descriptor(struct usbd_context *const uds_ctx, * number or endpoint and not the language ID. e.g. HID * Class Get Descriptor request. */ - return nonstd_request(uds_ctx, buf); + return nonstd_request(uds_ctx, pbuf); } switch (desc_type) { case USB_DESC_DEVICE: - return sreq_get_desc_dev(uds_ctx, buf); + return sreq_get_desc_dev(uds_ctx, pbuf); case USB_DESC_CONFIGURATION: - return sreq_get_desc_cfg(uds_ctx, buf, desc_idx, false); + return sreq_get_desc_cfg(uds_ctx, pbuf, desc_idx, false); case USB_DESC_OTHER_SPEED: - return sreq_get_desc_cfg(uds_ctx, buf, desc_idx, true); + return sreq_get_desc_cfg(uds_ctx, pbuf, desc_idx, true); case USB_DESC_STRING: - return sreq_get_desc_str(uds_ctx, buf, desc_idx); + return sreq_get_desc_str(uds_ctx, pbuf, desc_idx); case USB_DESC_DEVICE_QUALIFIER: - return sreq_get_dev_qualifier(uds_ctx, buf); + return sreq_get_dev_qualifier(uds_ctx, pbuf); case USB_DESC_BOS: - return sreq_get_desc_bos(uds_ctx, buf); + return sreq_get_desc_bos(uds_ctx, pbuf); case USB_DESC_INTERFACE: case USB_DESC_ENDPOINT: default: @@ -827,10 +887,11 @@ static int sreq_get_descriptor(struct usbd_context *const uds_ctx, } static int sreq_get_configuration(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); + struct net_buf *buf; uint8_t cfg = usbd_get_config_value(uds_ctx); /* Not specified in default state, treat as error */ @@ -844,22 +905,26 @@ static int sreq_get_configuration(struct usbd_context *const uds_ctx, return 0; } - if (net_buf_tailroom(buf) < setup->wLength) { + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, sizeof(cfg)); + if (buf == NULL) { errno = -ENOMEM; return 0; } + *pbuf = buf; + net_buf_add_u8(buf, cfg); return 0; } static int sreq_get_interface(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usb_cfg_descriptor *cfg_desc; struct usbd_config_node *cfg_nd; + struct net_buf *buf; uint8_t cur_alt; if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_INTERFACE) { @@ -895,34 +960,37 @@ static int sreq_get_interface(struct usbd_context *const uds_ctx, return 0; } - if (net_buf_tailroom(buf) < setup->wLength) { + buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, sizeof(cur_alt)); + if (buf == NULL) { errno = -ENOMEM; return 0; } + *pbuf = buf; + net_buf_add_u8(buf, cur_alt); return 0; } static int std_request_to_host(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); int ret; switch (setup->bRequest) { case USB_SREQ_GET_STATUS: - ret = sreq_get_status(uds_ctx, buf); + ret = sreq_get_status(uds_ctx, pbuf); break; case USB_SREQ_GET_DESCRIPTOR: - ret = sreq_get_descriptor(uds_ctx, buf); + ret = sreq_get_descriptor(uds_ctx, pbuf); break; case USB_SREQ_GET_CONFIGURATION: - ret = sreq_get_configuration(uds_ctx, buf); + ret = sreq_get_configuration(uds_ctx, pbuf); break; case USB_SREQ_GET_INTERFACE: - ret = sreq_get_interface(uds_ctx, buf); + ret = sreq_get_interface(uds_ctx, pbuf); break; default: errno = -ENOTSUP; @@ -934,7 +1002,7 @@ static int std_request_to_host(struct usbd_context *const uds_ctx, } static int vendor_device_request(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usbd_vreq_node *vreq_nd; @@ -952,13 +1020,13 @@ static int vendor_device_request(struct usbd_context *const uds_ctx, if (reqtype_is_to_device(setup) && vreq_nd->to_dev != NULL) { LOG_DBG("Vendor request 0x%02x to device", setup->bRequest); - errno = vreq_nd->to_dev(uds_ctx, setup, buf); + errno = vreq_nd->to_dev(uds_ctx, setup, *pbuf); return 0; } if (reqtype_is_to_host(setup) && vreq_nd->to_host != NULL) { LOG_DBG("Vendor request 0x%02x to host", setup->bRequest); - errno = vreq_nd->to_host(uds_ctx, setup, buf); + errno = vreq_nd->to_host(uds_ctx, setup, pbuf); return 0; } @@ -967,7 +1035,7 @@ static int vendor_device_request(struct usbd_context *const uds_ctx, } static int nonstd_request(struct usbd_context *const uds_ctx, - struct net_buf *const dbuf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct usbd_class_node *c_nd = NULL; @@ -989,19 +1057,19 @@ static int nonstd_request(struct usbd_context *const uds_ctx, if (c_nd != NULL) { if (reqtype_is_to_device(setup)) { - ret = usbd_class_control_to_dev(c_nd->c_data, setup, dbuf); + ret = usbd_class_control_to_dev(c_nd->c_data, setup, *pbuf); } else { - ret = usbd_class_control_to_host(c_nd->c_data, setup, dbuf); + ret = usbd_class_control_to_host(c_nd->c_data, setup, pbuf); } } else { - return vendor_device_request(uds_ctx, dbuf); + return vendor_device_request(uds_ctx, pbuf); } return ret; } static int handle_setup_request(struct usbd_context *const uds_ctx, - struct net_buf *const buf) + struct net_buf **const pbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); int ret; @@ -1011,14 +1079,14 @@ static int handle_setup_request(struct usbd_context *const uds_ctx, switch (setup->RequestType.type) { case USB_REQTYPE_TYPE_STANDARD: if (reqtype_is_to_device(setup)) { - ret = std_request_to_device(uds_ctx, buf); + ret = std_request_to_device(uds_ctx, *pbuf); } else { - ret = std_request_to_host(uds_ctx, buf); + ret = std_request_to_host(uds_ctx, pbuf); } break; case USB_REQTYPE_TYPE_CLASS: case USB_REQTYPE_TYPE_VENDOR: - ret = nonstd_request(uds_ctx, buf); + ret = nonstd_request(uds_ctx, pbuf); break; default: errno = -ENOTSUP; @@ -1180,25 +1248,16 @@ int usbd_handle_ctrl_xfer(struct usbd_context *const uds_ctx, ret = usbd_ep_ctrl_enqueue(uds_ctx, next_buf); return ret; } - - if (setup->wLength) { - /* Stack is supposed to allocate buffer */ - next_buf = usbd_ep_ctrl_data_in_alloc(uds_ctx, setup->wLength); - if (next_buf == NULL) { - err = -ENOMEM; - goto ctrl_xfer_stall; - } - } } else { /* Data OUT received */ next_buf = buf; } /* - * Handle request and data stage, next_buf is either - * data buffer or is NULL. + * Handle request and data stage, next_buf holds either received + * data OUT buffer or is NULL. */ - ret = handle_setup_request(uds_ctx, next_buf); + ret = handle_setup_request(uds_ctx, &next_buf); if ((ret || errno) && next_buf) { net_buf_unref(next_buf); } @@ -1224,6 +1283,10 @@ int usbd_handle_ctrl_xfer(struct usbd_context *const uds_ctx, ret = usbd_enqueue_status_in(uds_ctx); } else { /* Enqueue Data IN */ + if (next_buf == NULL) { + goto ctrl_xfer_stall; + } + ret = usbd_ep_ctrl_enqueue(uds_ctx, next_buf); if (ret) { net_buf_unref(next_buf); diff --git a/subsys/usb/device_next/usbd_class_api.h b/subsys/usb/device_next/usbd_class_api.h index 88207ccc39cd6..734cd586dd17a 100644 --- a/subsys/usb/device_next/usbd_class_api.h +++ b/subsys/usb/device_next/usbd_class_api.h @@ -55,18 +55,18 @@ static inline int usbd_class_request(struct usbd_class_data *const c_data, * * @param[in] c_data Pointer to USB device class data * @param[in] setup Pointer to USB Setup Packet - * @param[in] buf Control Request Data buffer + * @param[in] pbuf Pointer to handler allocated Control Request Data buffer * * @return 0 on success, other values on fail. */ static inline int usbd_class_control_to_host(struct usbd_class_data *const c_data, struct usb_setup_packet *const setup, - struct net_buf *const buf) + struct net_buf **const pbuf) { const struct usbd_class_api *api = c_data->api; if (api->control_to_host != NULL) { - return api->control_to_host(c_data, setup, buf); + return api->control_to_host(c_data, setup, pbuf); } errno = -ENOTSUP; From 1bc35b73c5e25ecc81320b0c60555e4a8fe7af94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 19 Jan 2026 10:44:38 +0100 Subject: [PATCH 2/2] usb: device_next: Return data IN buffer instead of error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When USB control request cannot be handled the endpoint should be stalled regardless of the reason. Simplify control request to host handlers by changing the return type to the allocated buffer. Returning NULL is enough to indicate to device stack that the request should be stalled. Keep the errno for the time being, but in my opinion it is not necessary at all. Signed-off-by: Tomasz Moń --- include/zephyr/usb/usbd.h | 28 ++++---- samples/subsys/dap/src/msosv2.h | 15 ++--- samples/subsys/dap/src/webusb.h | 18 +++--- samples/subsys/usb/webusb/src/msosv2.h | 15 ++--- samples/subsys/usb/webusb/src/webusb.h | 18 +++--- subsys/usb/device_next/class/loopback.c | 15 ++--- subsys/usb/device_next/class/usbd_cdc_acm.c | 13 ++-- subsys/usb/device_next/class/usbd_cdc_ncm.c | 25 +++----- subsys/usb/device_next/class/usbd_dfu.c | 71 ++++++++++----------- subsys/usb/device_next/class/usbd_hid.c | 11 ++-- subsys/usb/device_next/class/usbd_midi2.c | 13 ++-- subsys/usb/device_next/class/usbd_msc.c | 13 ++-- subsys/usb/device_next/class/usbd_uac2.c | 58 ++++++++--------- subsys/usb/device_next/class/usbd_uvc.c | 14 ++-- subsys/usb/device_next/usbd_ch9.c | 10 ++- subsys/usb/device_next/usbd_class_api.h | 13 ++-- 16 files changed, 160 insertions(+), 190 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index af725c0435aa1..7220ac16b77cb 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -101,9 +101,8 @@ struct usbd_str_desc_data { * Example callback code fragment: * * @code{.c} - * static int foo_to_host_cb(const struct usbd_context *const ctx, - * const struct usb_setup_packet *const setup, - * struct net_buf **const pbuf) + * static net_buf *foo_to_host_cb(const struct usbd_context *const ctx, + * const struct usb_setup_packet *const setup) * { * if (setup->wIndex == WEBUSB_REQ_GET_URL) { * struct net_buf *buf; @@ -111,23 +110,24 @@ struct usbd_str_desc_data { * uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); * * if (index != SAMPLE_WEBUSB_LANDING_PAGE) { - * return -ENOTSUP; + * errno = -ENOTSUP; + * return NULL; * } * * len = MIN(setup->wLength, sizeof(webusb_origin_url)); * buf = usbd_ep_ctrl_data_in_alloc(ctx, len); * if (buf == NULL) { - * return -ENOMEM; + * errno = -ENOMEM; + * return NULL; * } * - * *pbuf = buf; - * * net_buf_add_mem(buf, &webusb_origin_url, len); * - * return 0; + * return buf; * } * - * return -ENOTSUP; + * errno = -ENOTSUP; + * return NULL; * } * @endcode */ @@ -137,9 +137,8 @@ struct usbd_vreq_node { /** Vendor code (bRequest value) */ const uint8_t code; /** Vendor request callback for device-to-host direction */ - int (*to_host)(const struct usbd_context *const ctx, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf); + struct net_buf *(*to_host)(const struct usbd_context *const ctx, + const struct usb_setup_packet *const setup); /** Vendor request callback for host-to-device direction */ int (*to_dev)(const struct usbd_context *const ctx, const struct usb_setup_packet *const setup, @@ -351,9 +350,8 @@ struct usbd_class_api { const struct net_buf *const buf); /** USB control request handler to host */ - int (*control_to_host)(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf); + struct net_buf *(*control_to_host)(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup); /** Endpoint request completion event handler */ int (*request)(struct usbd_class_data *const c_data, diff --git a/samples/subsys/dap/src/msosv2.h b/samples/subsys/dap/src/msosv2.h index 182bec4e01bc6..684e6f51ab333 100644 --- a/samples/subsys/dap/src/msosv2.h +++ b/samples/subsys/dap/src/msosv2.h @@ -113,9 +113,8 @@ struct bos_msosv2_descriptor bos_msosv2_desc = { }, }; -static int msosv2_to_host_cb(const struct usbd_context *const ctx, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *msosv2_to_host_cb(const struct usbd_context *const ctx, + const struct usb_setup_packet *const setup) { LOG_INF("Vendor callback to host"); @@ -128,17 +127,17 @@ static int msosv2_to_host_cb(const struct usbd_context *const ctx, buf = usbd_ep_ctrl_data_in_alloc(ctx, len); if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - net_buf_add_mem(buf, &msosv2_desc, len); - return 0; + return buf; } - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_msosv2, sizeof(bos_msosv2_desc), &bos_msosv2_desc, diff --git a/samples/subsys/dap/src/webusb.h b/samples/subsys/dap/src/webusb.h index 73d2a2dd5092a..f632e514d508b 100644 --- a/samples/subsys/dap/src/webusb.h +++ b/samples/subsys/dap/src/webusb.h @@ -63,9 +63,8 @@ static const uint8_t webusb_origin_url[] = { 'o', 'r', 'g', '/', }; -static int webusb_to_host_cb(const struct usbd_context *const ctx, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *webusb_to_host_cb(const struct usbd_context *const ctx, + const struct usb_setup_packet *const setup) { LOG_INF("Vendor callback to host"); @@ -75,24 +74,25 @@ static int webusb_to_host_cb(const struct usbd_context *const ctx, uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); if (index != SAMPLE_WEBUSB_LANDING_PAGE) { - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } len = MIN(setup->wLength, sizeof(webusb_origin_url)); buf = usbd_ep_ctrl_data_in_alloc(ctx, len); if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - LOG_INF("Get URL request, index %u", index); net_buf_add_mem(buf, &webusb_origin_url, len); - return 0; + return buf; } - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_webusb, sizeof(bos_cap_webusb), &bos_cap_webusb, diff --git a/samples/subsys/usb/webusb/src/msosv2.h b/samples/subsys/usb/webusb/src/msosv2.h index 2bd2273d17872..a00a3543fdb77 100644 --- a/samples/subsys/usb/webusb/src/msosv2.h +++ b/samples/subsys/usb/webusb/src/msosv2.h @@ -113,9 +113,8 @@ struct bos_msosv2_descriptor bos_msosv2_desc = { }, }; -static int msosv2_to_host_cb(const struct usbd_context *const ctx, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *msosv2_to_host_cb(const struct usbd_context *const ctx, + const struct usb_setup_packet *const setup) { LOG_INF("Vendor callback to host"); @@ -129,17 +128,17 @@ static int msosv2_to_host_cb(const struct usbd_context *const ctx, len = MIN(setup->wLength, sizeof(msosv2_desc)); buf = usbd_ep_ctrl_data_in_alloc(ctx, len); if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - net_buf_add_mem(buf, &msosv2_desc, len); - return 0; + return buf; } - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_msosv2, sizeof(bos_msosv2_desc), &bos_msosv2_desc, diff --git a/samples/subsys/usb/webusb/src/webusb.h b/samples/subsys/usb/webusb/src/webusb.h index 2300e32c999d5..1c9d388b2f98e 100644 --- a/samples/subsys/usb/webusb/src/webusb.h +++ b/samples/subsys/usb/webusb/src/webusb.h @@ -61,9 +61,8 @@ static const uint8_t webusb_origin_url[] = { 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', ':', '8', '0', '0', '0' }; -static int webusb_to_host_cb(const struct usbd_context *const ctx, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *webusb_to_host_cb(const struct usbd_context *const ctx, + const struct usb_setup_packet *const setup) { LOG_INF("Vendor callback to host"); @@ -73,24 +72,25 @@ static int webusb_to_host_cb(const struct usbd_context *const ctx, uint8_t index = USB_GET_DESCRIPTOR_INDEX(setup->wValue); if (index != SAMPLE_WEBUSB_LANDING_PAGE) { - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } len = MIN(setup->wLength, sizeof(webusb_origin_url)); buf = usbd_ep_ctrl_data_in_alloc(ctx, len); if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - LOG_INF("Get URL request, index %u", index); net_buf_add_mem(buf, &webusb_origin_url, len); - return 0; + return buf; } - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } USBD_DESC_BOS_VREQ_DEFINE(bos_vreq_webusb, sizeof(bos_cap_webusb), &bos_cap_webusb, diff --git a/subsys/usb/device_next/class/loopback.c b/subsys/usb/device_next/class/loopback.c index 8575c7a701c66..9fa27db49d71d 100644 --- a/subsys/usb/device_next/class/loopback.c +++ b/subsys/usb/device_next/class/loopback.c @@ -202,13 +202,12 @@ static void lb_update(struct usbd_class_data *c_data, c_data, iface, alternate); } -static int lb_control_to_host(struct usbd_class_data *c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *lb_control_to_host(struct usbd_class_data *c_data, + const struct usb_setup_packet *const setup) { if (setup->RequestType.recipient != USB_REQTYPE_RECIPIENT_DEVICE) { errno = -ENOTSUP; - return 0; + return NULL; } if (setup->bRequest == LB_VENDOR_REQ_IN) { @@ -218,22 +217,20 @@ static int lb_control_to_host(struct usbd_class_data *c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), len); if (buf == NULL) { errno = -ENOMEM; - return 0; + return NULL; } - *pbuf = buf; - net_buf_add_mem(buf, lb_buf, len); LOG_WRN("Device-to-Host, wLength %u | %zu", setup->wLength, len); - return 0; + return buf; } LOG_ERR("Class request 0x%x not supported", setup->bRequest); errno = -ENOTSUP; - return 0; + return NULL; } static int lb_control_to_dev(struct usbd_class_data *c_data, diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index 8743a748d4027..dd6afef74f62c 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -484,9 +484,8 @@ static void cdc_acm_update_linestate(struct cdc_acm_uart_data *const data) } } -static int usbd_cdc_acm_cth(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *usbd_cdc_acm_cth(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; @@ -499,21 +498,19 @@ static int usbd_cdc_acm_cth(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), min_len); if (buf == NULL) { errno = -ENOMEM; - return 0; + return NULL; } - *pbuf = buf; - net_buf_add_mem(buf, &data->line_coding, min_len); - return 0; + return buf; } LOG_DBG("bmRequestType 0x%02x bRequest 0x%02x unsupported", setup->bmRequestType, setup->bRequest); errno = -ENOTSUP; - return 0; + return NULL; } static int usbd_cdc_acm_ctd(struct usbd_class_data *const c_data, diff --git a/subsys/usb/device_next/class/usbd_cdc_ncm.c b/subsys/usb/device_next/class/usbd_cdc_ncm.c index 8a06dc21db3c5..86b525db50772 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ncm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ncm.c @@ -918,10 +918,9 @@ static int usbd_cdc_ncm_ctd(struct usbd_class_data *const c_data, return 0; } -static void cdc_ncm_cth_response(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf, - const void *data, uint16_t data_len) +static struct net_buf *cdc_ncm_cth_response(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup, + const void *data, uint16_t data_len) { struct net_buf *buf; uint16_t len = MIN(setup->wLength, data_len); @@ -929,17 +928,15 @@ static void cdc_ncm_cth_response(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), len); if (buf == NULL) { errno = -ENOMEM; - return; + return NULL; } - *pbuf = buf; - net_buf_add_mem(buf, data, len); + return buf; } -static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { LOG_DBG("%d: %d %d %d %d", setup->RequestType.type, setup->bRequest, setup->wLength, setup->wIndex, setup->wValue); @@ -967,8 +964,7 @@ static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, }; LOG_DBG("GET_NTB_PARAMETERS"); - cdc_ncm_cth_response(c_data, setup, pbuf, &ntb_params, sizeof(ntb_params)); - break; + return cdc_ncm_cth_response(c_data, setup, &ntb_params, sizeof(ntb_params)); } case GET_NTB_INPUT_SIZE: { @@ -979,8 +975,7 @@ static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, }; LOG_DBG("GET_NTB_INPUT_SIZE"); - cdc_ncm_cth_response(c_data, setup, pbuf, &input_size, sizeof(input_size)); - break; + return cdc_ncm_cth_response(c_data, setup, &input_size, sizeof(input_size)); } default: @@ -990,7 +985,7 @@ static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data, } out: - return 0; + return NULL; } static int usbd_cdc_ncm_init(struct usbd_class_data *const c_data) diff --git a/subsys/usb/device_next/class/usbd_dfu.c b/subsys/usb/device_next/class/usbd_dfu.c index 5b999067e5611..d40c282642fe5 100644 --- a/subsys/usb/device_next/class/usbd_dfu.c +++ b/subsys/usb/device_next/class/usbd_dfu.c @@ -516,25 +516,24 @@ static int dfu_set_next_state(struct usbd_class_data *const c_data, /* Run-Time mode instance implementation, for instance "dfu_runtime" */ -static int handle_get_status(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *handle_get_status(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); struct net_buf *buf; const size_t getstatus_len = 6; if (setup->wLength != getstatus_len) { - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), getstatus_len); if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - /* * Add GET_STATUS response consisting of * bStatus, bwPollTimeout, bStatus, iString (no strings defined) @@ -545,48 +544,48 @@ static int handle_get_status(struct usbd_class_data *const c_data, net_buf_add_u8(buf, data->state); net_buf_add_u8(buf, 0); - return 0; + return buf; } -static int handle_get_state(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *handle_get_state(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); struct net_buf *buf; const size_t getstate_len = 1; if (setup->wLength != getstate_len) { - return -ENOTSUP; + errno = -ENOTSUP; + return NULL; } buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), getstate_len); + if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - net_buf_add_u8(buf, data->state); - return 0; + return buf; } -static int runtime_mode_control_to_host(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *runtime_mode_control_to_host(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); + struct net_buf *buf = NULL; errno = dfu_set_next_state(c_data, setup); if (errno == 0) { switch (setup->bRequest) { case USB_DFU_REQ_GETSTATUS: - errno = handle_get_status(c_data, setup, pbuf); + buf = handle_get_status(c_data, setup); break; case USB_DFU_REQ_GETSTATE: - errno = handle_get_state(c_data, setup, pbuf); + buf = handle_get_state(c_data, setup); break; default: break; @@ -595,7 +594,7 @@ static int runtime_mode_control_to_host(struct usbd_class_data *const c_data, data->state = data->next; - return 0; + return buf; } static int runtime_mode_control_to_dev(struct usbd_class_data *const c_data, @@ -651,9 +650,8 @@ USBD_DEFINE_CLASS(dfu_runtime, &runtime_mode_api, &dfu_data, NULL); /* DFU mode instance implementation, for instance "dfu_dfu" */ -static int handle_upload(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *handle_upload(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); uint16_t size; @@ -665,11 +663,10 @@ static int handle_upload(struct usbd_class_data *const c_data, size = CONFIG_USBD_DFU_TRANSFER_SIZE; buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), size); if (buf == NULL) { - return -ENOMEM; + errno = -ENOMEM; + return NULL; } - *pbuf = buf; - /* Do not return more than requested */ size = MIN(setup->wLength, size); @@ -681,10 +678,10 @@ static int handle_upload(struct usbd_class_data *const c_data, } } else { dfu_error(c_data, DFU_ERROR, ERR_UNKNOWN); - return -ENOTSUP; + errno = -ENOTSUP; } - return 0; + return buf; } static int handle_download(struct usbd_class_data *const c_data, @@ -705,24 +702,24 @@ static int handle_download(struct usbd_class_data *const c_data, return 0; } -static int dfu_mode_control_to_host(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *dfu_mode_control_to_host(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { struct usbd_dfu_data *data = usbd_class_get_private(c_data); + struct net_buf *buf = NULL; errno = dfu_set_next_state(c_data, setup); if (errno == 0) { switch (setup->bRequest) { case USB_DFU_REQ_GETSTATUS: - errno = handle_get_status(c_data, setup, pbuf); + buf = handle_get_status(c_data, setup); break; case USB_DFU_REQ_GETSTATE: - errno = handle_get_state(c_data, setup, pbuf); + buf = handle_get_state(c_data, setup); break; case USB_DFU_REQ_UPLOAD: - errno = handle_upload(c_data, setup, pbuf); + buf = handle_upload(c_data, setup); break; default: break; @@ -731,7 +728,7 @@ static int dfu_mode_control_to_host(struct usbd_class_data *const c_data, data->state = data->next; - return 0; + return buf; } static int dfu_mode_control_to_dev(struct usbd_class_data *const c_data, diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index 29d94ba2ca47a..168a844c559d6 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -397,9 +397,8 @@ static int usbd_hid_ctd(struct usbd_class_data *const c_data, return ret; } -static int usbd_hid_cth(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *usbd_hid_cth(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { const struct device *dev = usbd_class_get_private(c_data); struct net_buf *buf; @@ -413,11 +412,9 @@ static int usbd_hid_cth(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), setup->wLength); if (buf == NULL) { errno = -ENOMEM; - return 0; + return NULL; } - *pbuf = buf; - switch (setup->bRequest) { case USB_HID_GET_IDLE: ret = handle_get_idle(dev, setup, buf); @@ -436,7 +433,7 @@ static int usbd_hid_cth(struct usbd_class_data *const c_data, break; } - return ret; + return buf; } static void usbd_hid_sof(struct usbd_class_data *const c_data) diff --git a/subsys/usb/device_next/class/usbd_midi2.c b/subsys/usb/device_next/class/usbd_midi2.c index 143ce14c329a6..0121e7f028046 100644 --- a/subsys/usb/device_next/class/usbd_midi2.c +++ b/subsys/usb/device_next/class/usbd_midi2.c @@ -287,9 +287,8 @@ static void usbd_midi_class_resumed(struct usbd_class_data *const class_data) k_work_submit(&data->rx_work); } -static int usbd_midi_class_cth(struct usbd_class_data *const class_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *usbd_midi_class_cth(struct usbd_class_data *const class_data, + const struct usb_setup_packet *const setup) { const struct device *dev = usbd_class_get_private(class_data); const struct usbd_midi_config *config = dev->config; @@ -311,18 +310,16 @@ static int usbd_midi_class_cth(struct usbd_class_data *const class_data, setup->bRequest != USB_SREQ_GET_DESCRIPTOR || setup->wValue != ((CS_GR_TRM_BLOCK << 8) | MIDI2_ALTERNATE)) { errno = -ENOTSUP; - return 0; + return NULL; } buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(class_data), MIN(total_len, setup->wLength)); if (buf == NULL) { errno = -ENOMEM; - return 0; + return NULL; } - *pbuf = buf; - /* Group terminal block header */ net_buf_add_mem(buf, (void *) &config->desc->grptrm_header, MIN(head_len, setup->wLength)); @@ -334,7 +331,7 @@ static int usbd_midi_class_cth(struct usbd_class_data *const class_data, } LOG_HEXDUMP_DBG(buf->data, buf->len, "Control to host"); - return 0; + return buf; } static int usbd_midi_class_init(struct usbd_class_data *const class_data) diff --git a/subsys/usb/device_next/class/usbd_msc.c b/subsys/usb/device_next/class/usbd_msc.c index d6b3fdb08d1ef..1f83102ae2676 100644 --- a/subsys/usb/device_next/class/usbd_msc.c +++ b/subsys/usb/device_next/class/usbd_msc.c @@ -825,12 +825,11 @@ static int msc_bot_control_to_dev(struct usbd_class_data *const c_data, } /* USB control request handler to host */ -static int msc_bot_control_to_host(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *msc_bot_control_to_host(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); - struct net_buf *buf; + struct net_buf *buf = NULL; uint8_t max_lun; if (setup->bRequest == GET_MAX_LUN && @@ -844,17 +843,15 @@ static int msc_bot_control_to_host(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), 1); if (buf == NULL) { errno = -ENOMEM; - return 0; + return NULL; } - *pbuf = buf; - net_buf_add_mem(buf, &max_lun, 1); } else { errno = -ENOTSUP; } - return 0; + return buf; } /* Endpoint request completion event handler */ diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index 25cd2d25206cc..347b4de396478 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -571,9 +571,8 @@ static uint32_t find_closest(const uint32_t input, const uint32_t *values, } /* Table 5-6: 4-byte Control CUR Parameter Block */ -static void layout3_cur_response(struct usbd_class_data *const c_data, - struct net_buf **const pbuf, uint16_t length, - const uint32_t value) +static struct net_buf *layout3_cur_response(struct usbd_class_data *const c_data, + uint16_t length, const uint32_t value) { struct net_buf *buf; uint8_t tmp[4]; @@ -582,14 +581,14 @@ static void layout3_cur_response(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), length); if (buf == NULL) { errno = -ENOMEM; - return; + return NULL; } - *pbuf = buf; - /* dCUR */ sys_put_le32(value, tmp); net_buf_add_mem(buf, tmp, length); + + return buf; } static int layout3_cur_request(const struct net_buf *const buf, uint32_t *out) @@ -606,10 +605,10 @@ static int layout3_cur_request(const struct net_buf *const buf, uint32_t *out) } /* Table 5-7: 4-byte Control RANGE Parameter Block */ -static void layout3_range_response(struct usbd_class_data *const c_data, - struct net_buf **const pbuf, uint16_t length, - const uint32_t *min, const uint32_t *max, - const uint32_t *res, int n) +static struct net_buf *layout3_range_response(struct usbd_class_data *const c_data, + uint16_t length, + const uint32_t *min, const uint32_t *max, + const uint32_t *res, int n) { struct net_buf *buf; uint16_t to_add; @@ -625,11 +624,9 @@ static void layout3_range_response(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), length); if (buf == NULL) { errno = -ENOMEM; - return; + return NULL; } - *pbuf = buf; - /* wNumSubRanges */ sys_put_le16(n, tmp); to_add = MIN(length, 2); @@ -661,11 +658,12 @@ static void layout3_range_response(struct usbd_class_data *const c_data, i++; } } + + return buf; } -static int get_clock_source_request(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *get_clock_source_request(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { const struct device *dev = usbd_class_get_private(c_data); struct uac2_ctx *ctx = dev->data; @@ -678,7 +676,7 @@ static int get_clock_source_request(struct usbd_class_data *const c_data, LOG_DBG("Clock source control with channel %d", CONTROL_CHANNEL_NUMBER(setup)); errno = -EINVAL; - return 0; + return NULL; } count = clock_frequencies(c_data, clock_id, &frequencies); @@ -686,9 +684,8 @@ static int get_clock_source_request(struct usbd_class_data *const c_data, if (CONTROL_SELECTOR(setup) == CS_SAM_FREQ_CONTROL) { if (CONTROL_ATTRIBUTE(setup) == CUR) { if (count == 1) { - layout3_cur_response(c_data, pbuf, setup->wLength, - frequencies[0]); - return 0; + return layout3_cur_response(c_data, setup->wLength, + frequencies[0]); } if (ctx->ops->get_sample_rate) { @@ -696,13 +693,11 @@ static int get_clock_source_request(struct usbd_class_data *const c_data, hz = ctx->ops->get_sample_rate(dev, clock_id, ctx->user_data); - layout3_cur_response(c_data, pbuf, setup->wLength, hz); - return 0; + return layout3_cur_response(c_data, setup->wLength, hz); } } else if (CONTROL_ATTRIBUTE(setup) == RANGE) { - layout3_range_response(c_data, pbuf, setup->wLength, frequencies, - frequencies, NULL, count); - return 0; + return layout3_range_response(c_data, setup->wLength, frequencies, + frequencies, NULL, count); } } else { LOG_DBG("Unhandled clock control selector 0x%02x", @@ -710,7 +705,7 @@ static int get_clock_source_request(struct usbd_class_data *const c_data, } errno = -ENOTSUP; - return 0; + return NULL; } static int set_clock_source_request(struct usbd_class_data *const c_data, @@ -795,27 +790,26 @@ static int uac2_control_to_dev(struct usbd_class_data *const c_data, return 0; } -static int uac2_control_to_host(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *uac2_control_to_host(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { entity_type_t entity_type; if ((CONTROL_ATTRIBUTE(setup) != CUR) && (CONTROL_ATTRIBUTE(setup) != RANGE)) { errno = -ENOTSUP; - return 0; + return NULL; } if (setup->bmRequestType == GET_CLASS_REQUEST_TYPE) { entity_type = id_type(c_data, CONTROL_ENTITY_ID(setup)); if (entity_type == ENTITY_TYPE_CLOCK_SOURCE) { - return get_clock_source_request(c_data, setup, pbuf); + return get_clock_source_request(c_data, setup); } } errno = -ENOTSUP; - return 0; + return NULL; } static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *buf, diff --git a/subsys/usb/device_next/class/usbd_uvc.c b/subsys/usb/device_next/class/usbd_uvc.c index 109f49f7cada3..ad7f04c743baf 100644 --- a/subsys/usb/device_next/class/usbd_uvc.c +++ b/subsys/usb/device_next/class/usbd_uvc.c @@ -1016,9 +1016,8 @@ static int uvc_get_control_op(const struct device *dev, const struct usb_setup_p return UVC_OP_RETURN_ERROR; } -static int uvc_control_to_host(struct usbd_class_data *const c_data, - const struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static struct net_buf *uvc_control_to_host(struct usbd_class_data *const c_data, + const struct usb_setup_packet *const setup) { const struct device *dev = usbd_class_get_private(c_data); const struct uvc_control_map *map = NULL; @@ -1036,11 +1035,9 @@ static int uvc_control_to_host(struct usbd_class_data *const c_data, buf = usbd_ep_ctrl_data_in_alloc(usbd_class_get_ctx(c_data), size); if (buf == NULL) { errno = ENOMEM; - return 0; + return NULL; } - *pbuf = buf; - switch (uvc_get_control_op(dev, setup, &map)) { case UVC_OP_VS_PROBE: errno = -uvc_get_vs_probe(dev, buf, setup); @@ -1056,7 +1053,8 @@ static int uvc_control_to_host(struct usbd_class_data *const c_data, break; case UVC_OP_RETURN_ERROR: errno = EINVAL; - return 0; + net_buf_unref(buf); + return NULL; default: LOG_WRN("Unhandled operation, stalling control command"); errno = EINVAL; @@ -1064,7 +1062,7 @@ static int uvc_control_to_host(struct usbd_class_data *const c_data, uvc_set_errno(dev, errno); - return 0; + return buf; } static int uvc_control_to_dev(struct usbd_class_data *const c_data, diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 695d6b3dff51f..3c8dde6304892 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -1026,7 +1026,10 @@ static int vendor_device_request(struct usbd_context *const uds_ctx, if (reqtype_is_to_host(setup) && vreq_nd->to_host != NULL) { LOG_DBG("Vendor request 0x%02x to host", setup->bRequest); - errno = vreq_nd->to_host(uds_ctx, setup, pbuf); + *pbuf = vreq_nd->to_host(uds_ctx, setup); + if (*pbuf == NULL && errno == 0) { + errno = -ENODATA; + } return 0; } @@ -1059,7 +1062,10 @@ static int nonstd_request(struct usbd_context *const uds_ctx, if (reqtype_is_to_device(setup)) { ret = usbd_class_control_to_dev(c_nd->c_data, setup, *pbuf); } else { - ret = usbd_class_control_to_host(c_nd->c_data, setup, pbuf); + *pbuf = usbd_class_control_to_host(c_nd->c_data, setup); + if (*pbuf == NULL && errno == 0) { + errno = -ENODATA; + } } } else { return vendor_device_request(uds_ctx, pbuf); diff --git a/subsys/usb/device_next/usbd_class_api.h b/subsys/usb/device_next/usbd_class_api.h index 734cd586dd17a..28aad59b1d102 100644 --- a/subsys/usb/device_next/usbd_class_api.h +++ b/subsys/usb/device_next/usbd_class_api.h @@ -55,22 +55,21 @@ static inline int usbd_class_request(struct usbd_class_data *const c_data, * * @param[in] c_data Pointer to USB device class data * @param[in] setup Pointer to USB Setup Packet - * @param[in] pbuf Pointer to handler allocated Control Request Data buffer * - * @return 0 on success, other values on fail. + * @return Buffer with data to send to host on success, NULL on fail. */ -static inline int usbd_class_control_to_host(struct usbd_class_data *const c_data, - struct usb_setup_packet *const setup, - struct net_buf **const pbuf) +static inline struct net_buf * +usbd_class_control_to_host(struct usbd_class_data *const c_data, + struct usb_setup_packet *const setup) { const struct usbd_class_api *api = c_data->api; if (api->control_to_host != NULL) { - return api->control_to_host(c_data, setup, pbuf); + return api->control_to_host(c_data, setup); } errno = -ENOTSUP; - return 0; + return NULL; } /**