diff --git a/include/zephyr/usb/class/usbd_uac2.h b/include/zephyr/usb/class/usbd_uac2.h index 80c2d503c73..45965d648d5 100644 --- a/include/zephyr/usb/class/usbd_uac2.h +++ b/include/zephyr/usb/class/usbd_uac2.h @@ -47,6 +47,7 @@ struct uac2_ops { * @brief Start of Frame callback * * Notifies application about SOF event on the bus. + * This callback is mandatory to register. * * @param dev USB Audio 2 device * @param user_data Opaque user data pointer @@ -56,6 +57,7 @@ struct uac2_ops { * @brief Terminal update callback * * Notifies application that host has enabled or disabled a terminal. + * This callback is mandatory to register. * * @param dev USB Audio 2 device * @param terminal Terminal ID linked to AudioStreaming interface @@ -73,6 +75,7 @@ struct uac2_ops { * AudioStreaming interface. The buffer is owned by USB stack until * @ref data_recv_cb callback is called. The buffer must be sufficiently * aligned and otherwise suitable for use by UDC driver. + * This callback is mandatory to register for devices receiving USB audio from the USB host. * * @param dev USB Audio 2 device * @param terminal Input Terminal ID linked to AudioStreaming interface @@ -86,6 +89,7 @@ struct uac2_ops { * * This function releases buffer obtained in @ref get_recv_buf after USB * has written data to the buffer and/or no longer needs it. + * This callback is mandatory to register for devices receiving USB audio from the USB host. * * @param dev USB Audio 2 device * @param terminal Input Terminal ID linked to AudioStreaming interface @@ -100,6 +104,7 @@ struct uac2_ops { * * This function releases buffer provided in @ref usbd_uac2_send when * the class no longer needs it. + * This callback is mandatory to register if calling @ref usbd_uac2_send. * * @param dev USB Audio 2 device * @param terminal Output Terminal ID linked to AudioStreaming interface @@ -118,6 +123,9 @@ struct uac2_ops { * capable device is operating at Full-Speed (microframes was false), * the format is Q10.14 stored on 24 least significant bits (i.e. 8 most * significant bits are ignored). + * This callback is mandatory to register if there is USB Audio Streaming interface linked + * to Input Terminal clocked from asynchronous clock (i.e. clock source without + * sof-synchronized;) and there is no implicit-feedback; on the interface. * * @param dev USB Audio 2 device * @param terminal Input Terminal ID whose feedback should be returned diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index 2be79098a88..77bfde9c472 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -4,7 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include +#include #include #include @@ -209,9 +213,49 @@ static int terminal_to_as_interface(const struct device *dev, uint8_t terminal) void usbd_uac2_set_ops(const struct device *dev, const struct uac2_ops *ops, void *user_data) { + const struct uac2_cfg *cfg = dev->config; struct uac2_ctx *ctx = dev->data; __ASSERT(ops->sof_cb, "SOF callback is mandatory"); + __ASSERT(ops->terminal_update_cb, "terminal_update_cb is mandatory"); + + for (uint8_t i = 0U; i < cfg->num_ifaces; i++) { + const uint16_t ep_idx = cfg->ep_indexes[i]; + + if (cfg->fb_indexes[i] != 0U) { + __ASSERT(ops->feedback_cb, "feedback_cb is mandatory"); + } + + if (ep_idx) { + const struct usb_ep_descriptor *desc = NULL; + + if (cfg->fs_descriptors != NULL) { + /* If fs_descriptors is non-NULL and ep_idx is non-zero then + * cfg->fs_descriptors[ep_idx] is non-NULL + */ + desc = (const struct usb_ep_descriptor *) + cfg->fs_descriptors[ep_idx]; + } else if (cfg->hs_descriptors != NULL) { + /* If hs_descriptors is non-NULL and ep_idx is non-zero then + * cfg->hs_descriptors[ep_idx] is non-NULL + */ + desc = (const struct usb_ep_descriptor *) + cfg->hs_descriptors[ep_idx]; + } + + if (desc != NULL) { + if (USB_EP_DIR_IS_OUT(desc->bEndpointAddress)) { + __ASSERT(ops->get_recv_buf, "get_recv_buf is mandatory"); + __ASSERT(ops->data_recv_cb, "data_recv_cb is mandatory"); + } + + if (USB_EP_DIR_IS_IN(desc->bEndpointAddress)) { + __ASSERT(ops->buf_release_cb, + "buf_release_cb is mandatory"); + } + } + } + } ctx->ops = ops; ctx->user_data = user_data;