Skip to content

usb: device_next: uvc: Initial ISO EP Descriptors#104619

Draft
zacck wants to merge 2 commits intozephyrproject-rtos:mainfrom
Gaiaocho:pr_uvc_iso_ep
Draft

usb: device_next: uvc: Initial ISO EP Descriptors#104619
zacck wants to merge 2 commits intozephyrproject-rtos:mainfrom
Gaiaocho:pr_uvc_iso_ep

Conversation

@zacck
Copy link
Contributor

@zacck zacck commented Feb 26, 2026

Additional UVC descriptors for catering to the Isochronous Video Streaming Endpoint

@zacck zacck force-pushed the pr_uvc_iso_ep branch 2 times, most recently from 72e50fe to f237315 Compare March 1, 2026 05:59
Additional UVC descriptors for catering to the Isochronous
Video Streaming Endpoint

Signed-off-by: Zacck Osiemo <coderv63@gmail.com>
To save bandwidth the UVC class has an alternate setting (0) with no
endpoints, switching to which frees all the allocated bandwidth on the
bus, This enables it to switch into and out of this alternate setting

Signed-off-by: Zacck Osiemo <coderv63@gmail.com>
@zacck zacck marked this pull request as ready for review March 1, 2026 07:30
@zacck
Copy link
Contributor Author

zacck commented Mar 1, 2026

Ok I think we can start actually considering this code now.

@zephyrbot zephyrbot added the area: USB Universal Serial Bus label Mar 1, 2026
Copy link
Contributor

@josuah josuah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this first round!
Given the amount of notifications the USB area has (i.e. as opposed to Video), I am converting it as a draft until it works, I hope that's ok.

Feel free to ping me individually on i.e. Discord.

Edit: we also need to update the way buffers are chopped down and sent to the USB stack.
There is a header on every ISO frame whereas BULK on the first packet of the transfer only

const uint8_t alternate)
{
LOG_DBG("Select alternate %u for interface %u", alternate, iface);
struct uvc_data *data = usbd_class_get_private(c_data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For USB in particular, you would need to add a const after pointers, to guarantee that data will not be assigned to another pointer in the body, just to get a compiler warning if this happens.

Suggested change
struct uvc_data *data = usbd_class_get_private(c_data);
struct uvc_data *const data = usbd_class_get_private(c_data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might also want to keep all variables declaration at the top of the block with an empty line after them.

I do not see that in https://kernel.org/doc/html/latest/process/coding-style.html but there is a checkpatch.pl check IIRC, and otherwise recommended during reviews on USB I receive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe possible to reduce even more by not re-defining the endpoint, but having macros for the content of the fields that change, i.e. wMaxPacketSize = UVC_EP_MPS, bmAttributes = UVC_EP_TYPE.

Comment on lines +14 to +17
config USBD_VIDEO_ISO
bool "USB Video Class ISO EP Implementation"
help
This allows the USB Video class to use an ISO Endpoint Implementation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a choice instead of boolean?

Also, making isochronous the default is not bad idea.

Comment on lines +1916 to +1917
LOG_DBG("Instance %p, interface %u alternate %u changed",
c_data, iface, alternate);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already logged above?

LOG_DBG("Select alternate %u for interface %u", alternate, iface);
struct uvc_data *data = usbd_class_get_private(c_data);

data->alternate = alternate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just updated but not used?
Likely this is all what can be done for now, as there is no API for sending events to the application.

This needs either a custom API or just dropping that variable for now as not in use.

}

#if CONFIG_USBD_VIDEO_ISO
#define USBD_VIDEO_ENDPOINT_DESC \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not just endpoints there?

It could be helping if you de-duplicate everything that could be: if1, if1_hdr...

I think you would only need to customize the endpoint descriptor and add add a define either empty either AltSettings 1?

Comment on lines 2274 to 2304
struct usb_desc_header *uvc_fs_desc_##n[UVC_MAX_FS_DESC] = { \
(struct usb_desc_header *) &uvc_desc_##n.iad, \
(struct usb_desc_header *) &uvc_desc_##n.if0, \
(struct usb_desc_header *) &uvc_desc_##n.if0_hdr, \
(struct usb_desc_header *) &uvc_desc_##n.if0_ct, \
(struct usb_desc_header *) &uvc_desc_##n.if0_su, \
(struct usb_desc_header *) &uvc_desc_##n.if0_pu, \
(struct usb_desc_header *) &uvc_desc_##n.if0_xu, \
(struct usb_desc_header *) &uvc_desc_##n.if0_ot, \
(struct usb_desc_header *) &uvc_desc_##n.if1, \
(struct usb_desc_header *) &uvc_desc_##n.if1_hdr, \
/* More pointers are generated here at runtime */ \
(struct usb_desc_header *) &uvc_desc_##n.if1_ep_fs, \
(struct usb_desc_header *) NULL, \
}; \
\
struct usb_desc_header *uvc_hs_desc_##n[UVC_MAX_HS_DESC] = { \
(struct usb_desc_header *) &uvc_desc_##n.iad, \
(struct usb_desc_header *) &uvc_desc_##n.if0, \
(struct usb_desc_header *) &uvc_desc_##n.if0_hdr, \
(struct usb_desc_header *) &uvc_desc_##n.if0_ct, \
(struct usb_desc_header *) &uvc_desc_##n.if0_su, \
(struct usb_desc_header *) &uvc_desc_##n.if0_pu, \
(struct usb_desc_header *) &uvc_desc_##n.if0_xu, \
(struct usb_desc_header *) &uvc_desc_##n.if0_ot, \
(struct usb_desc_header *) &uvc_desc_##n.if1, \
(struct usb_desc_header *) &uvc_desc_##n.if1_hdr, \
/* More pointers are generated here at runtime */ \
(struct usb_desc_header *) &uvc_desc_##n.if1_ep_hs, \
(struct usb_desc_header *) NULL, \
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the place where the selection of descriptors actually used is happening, where it points to struct fields defined above.

Here there would need a UVC_DESC_ISO_ALT_SETTINGS_PTRS (or some other nice name) that is either empty or contains the extra AltSettings.

Comment on lines +131 to +132
/* Currently selected interface alternate setting */
uint8_t alternate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is possible to make it all work without this variable, not used at the moment, and nothing requires knowing if things are on/off in the current API AFAIU.

@josuah josuah marked this pull request as draft March 1, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: USB Universal Serial Bus

4 participants