Skip to content

Conversation

josuah
Copy link
Contributor

@josuah josuah commented Jul 24, 2025

This is a draft implementation not meant to be merged, but as a work bench and support for discussion around #93517.

It uses UVB and the virtual USB device and host back-ends to experiment with the USB APIs.

This permit to run the device class and host class without requiring USB hardware.

To build and run on native sim:

west build -b native_sim -S video-sw-generator -t run samples/subsys/usb/uvc_uvb
output
[00:00:00.000,000]  udc_vrt: Device 0x8060e98 (max. speed 1) belongs to uhc-virtual
*** Booting Zephyr OS build v4.2.0-559-g5eb38f5daeb4 ***
[00:00:00.000,000]  usbd_init: interface 0 alternate 0
[00:00:00.000,000]  usbd_init: interface 1 alternate 0
[00:00:00.000,000]  usbd_init:     ep 0x81 mps 0x0040 interface ep-bm 0x00020000
[00:00:00.000,000]  usbd_init: Instance iface-bm 0x00000003 ep-bm 0x00020000
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #1 for 'RGB3'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #2 for 'YUYV'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #3 for 'RGBP'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #4 for 'BX24'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #5 for 'RGGB'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #6 for 'GRBG'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #7 for 'BA81'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_uvc: Adding format descriptor #8 for 'GBRG'
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #1 for 64x64
[00:00:00.000,000]  usbd_uvc: Adding frame descriptor #2 for 1920x1080
[00:00:00.000,000]  usbd_init: Init class node 0x8065264, descriptor length 943
[00:00:00.000,000]  usbd_init: bNumInterfaces 2 wTotalLength 952
[00:00:00.000,000]  usbd_init: FS bNumConfigurations 1
[00:00:00.000,000]  udc: ep 0x80 is not halted|disabled
[00:00:00.000,000]  usbd_core: Actual device speed 1
[00:00:00.070,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.070,000]  usbd_ch9: Handle control 0x806b464 ep 0x00, len 0, s:0 d:0 s:1
[00:00:00.070,000]  usbd_ch9: s-in-status finished
[00:00:00.080,000]  usbd_ch9: Handle control 0x806b464 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.080,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 0, s:0 d:0 s:1
[00:00:00.080,000]  usbd_ch9: s-in-status finished
[00:00:00.090,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.090,000]  usbd_ch9: Handle control 0x806b464 ep 0x80, len 0, s:0 d:0 s:1
[00:00:00.090,000]  usbd_ch9: s-(out)-status finished
[00:00:00.090,000]  usbh_dev: New device with address 1 state 2
[00:00:00.100,000]  usbd_ch9: Handle control 0x806b464 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.100,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 0, s:0 d:0 s:1
[00:00:00.100,000]  usbd_ch9: s-in-status finished
[00:00:00.110,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.110,000]  usbd_ch9: Set Configuration Request value 1
[00:00:00.110,000]  usbd_iface: No endpoints, skip interface
[00:00:00.110,000]  usbd_iface: Modify interface 1 ep 0x81 by op 1 ep_bm 20000
[00:00:00.110,000]  usbd_ch9: Handle control 0x806b464 ep 0x80, len 0, s:0 d:0 s:1
[00:00:00.110,000]  usbd_ch9: s-(out)-status finished
[00:00:00.120,000]  usbd_ch9: Handle control 0x806b464 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.120,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 0, s:0 d:0 s:1
[00:00:00.120,000]  usbd_ch9: s-in-status finished
[00:00:00.120,000]  usbh_dev: Configuration 1 bNumInterfaces 2
[00:00:00.130,000]  usbd_ch9: Handle control 0x806b440 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.130,000]  usbd_ch9: Handle control 0x806b464 ep 0x00, len 0, s:0 d:0 s:1
[00:00:00.130,000]  usbd_ch9: s-in-status finished
[00:00:00.130,000]  app_main: buf
                                   12 01 00 02 ef 02 01 40  e3 2f 99 99 02 04 01 02 |.......@ ./......
                                   00 01                                            |..

@josuah
Copy link
Contributor Author

josuah commented Jul 24, 2025

The way this works:

  1. USB UVC Device and Host are added to the sample and configured
  2. USB UVC Device and Host are enabled
  3. USB Host currently goes through the enumeration steps in this function:
    if (usbh_device_init(ctx->root)) {
  4. This function was not doing anything at the end, so a new placeholder function temporarily called usbh_class_init() is added:
    if (usbh_class_init(ctx->root)) {
  5. The implementation is for now a placeholder that directly parses the UVC class regardless, without implementing a real USB host class support:
    int usbh_class_init(struct usb_device *udev)

The UVC class implementation can now start, before the USB Host class API is present.

@MarkWangChinese
Copy link
Contributor

@josuah We (@AidenHu) are try to enable the basic codes in first step and try to get audio stream from one commercial usb camera in second step. We will create draft pr too later, then you can provide comments about USB host video part. Thanks.

@josuah josuah force-pushed the pr_sample_uvc_uvb branch 4 times, most recently from e524c88 to 692cd97 Compare July 25, 2025 21:09
@josuah josuah changed the title Sample connecting a stub UVC host to UVC device Unit test connecting UVC host to UVC device Jul 25, 2025
@josuah josuah force-pushed the pr_sample_uvc_uvb branch 3 times, most recently from baf895e to b319828 Compare July 25, 2025 21:33
@josuah
Copy link
Contributor Author

josuah commented Jul 25, 2025

Thank you for your answer @MarkWangChinese.

get audio stream from one commercial usb camera

If I understand correctly, you would be working on an USB Audio Class (such as UAC2) support?

It seems like we have a skeleton of functions in usbh.h to implement a class, which I reused in a stub usbh_uvc.c.

/**
* @brief USB host class data and class instance API
*/
struct usbh_class_data {
/** Class code supported by this instance */
struct usbh_code_triple code;
/** Initialization of the class implementation */
/* int (*init)(struct usbh_contex *const uhs_ctx); */
/** Request completion event handler */
int (*request)(struct usbh_contex *const uhs_ctx,
struct uhc_transfer *const xfer, int err);
/** Device connected handler */
int (*connected)(struct usbh_contex *const uhs_ctx);
/** Device removed handler */
int (*removed)(struct usbh_contex *const uhs_ctx);
/** Bus remote wakeup handler */
int (*rwup)(struct usbh_contex *const uhs_ctx);
/** Bus suspended handler */
int (*suspended)(struct usbh_contex *const uhs_ctx);
/** Bus resumed handler */
int (*resumed)(struct usbh_contex *const uhs_ctx);
};

This current PR is turned into an unit test.
For now, it is empty, only the twister configuration and basic code layout:

west twister -p native_sim -T tests/subsys/usb/uvc

Thank you for the update! I will do my best to adapt my local version to what you built, so feel free to go ahead implementing things differently.

@josuah josuah force-pushed the pr_sample_uvc_uvb branch 3 times, most recently from b9fa4dd to 1a68f6d Compare July 26, 2025 20:37
@MarkWangChinese
Copy link
Contributor

MarkWangChinese commented Jul 28, 2025

If I understand correctly, you would be working on an USB Audio Class (such as UAC2) support?

Yes, we are working on the usb host video class and usb host stack with NXP platforms, and connect with actual usb camera.
Our plan is: Firstly writing the basic codes and create the draft pr; secondly plugging usb camera, enumerating and transferring the video stream.

@josuah josuah force-pushed the pr_sample_uvc_uvb branch 2 times, most recently from 771738e to cf4ed33 Compare August 9, 2025 19:22
Copy link

sonarqubecloud bot commented Aug 9, 2025

Please retry analysis of this Pull-Request directly on SonarQube Cloud

Josuah Demangeon and others added 7 commits October 1, 2025 22:02
Add a "struct usbh_status" that contains a bitmask of flags to keep
track of the global state of the host context, like done for the
device_next implementation.

Signed-off-by: Josuah Demangeon <[email protected]>
Add a "struct usbh_class_api" for the host implementation, and move all
the function poitners to it. Add more fields to "struct usbh_class_data".

Signed-off-by: Josuah Demangeon <[email protected]>
Add API wrappers around the function pointers in struct usbh_class_api,
while also documenting the USB host class internal API.

Signed-off-by: Josuah Demangeon <[email protected]>
Add functions to probe/remove all classes as part of a new usbh_class.c
and a matching usbh_class.h. These functions are called from the function
usbh_init_device_intl() in usbh_core.c to initialize every class upon
connection of a device. The class instances are registered and connected
together as a linked list.

Co-authored-by: Aiden Hu <[email protected]>
Signed-off-by: Josuah Demangeon <[email protected]>
Add utilities to filter a class and search the next descriptor of
a given type. This can be used to in combination to seek device
information from the USB descriptors and try to match a host class
instance given a set of filters.

Co-authored-by: Aiden Hu <[email protected]>
Signed-off-by: Josuah Demangeon <[email protected]>
Move the UVC header with all the definitions from the UVC standard to
share it between USB host and device class implementation.

Signed-off-by: Josuah Demangeon <[email protected]>
Add tests making sure the USB Host class APIs introduced build
and run as expected.

Signed-off-by: Josuah Demangeon <[email protected]>
Copy link

github-actions bot commented Oct 9, 2025

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Oct 9, 2025
Allocate extra room at the end of the USB descriptor buffer to ensure
that the device ends with `desc->bLength == 0`. For now, validating
`desc->bLength` from the device to ensure no access past the buffer
is still not done.

Signed-off-by: Josuah Demangeon <[email protected]>
Josuah Demangeon added 3 commits October 9, 2025 17:40
Move the UVC header with all the definitions from the UVC standard to
share it between USB host and device class implementation.

Signed-off-by: Josuah Demangeon <[email protected]>
When USB device is not defined, there is no macro for the maximum number
of dwFrameInterval[] defined, so default to 1 instead of
CONFIG_USBD_VIDEO_MAX_FRMIVAL.

Signed-off-by: Josuah Demangeon <[email protected]>
Move UVC helper functions to a file shared between UVC host and device.
The arrays are not visible anymore from either USB host or device, but
instead accessed through a front-end funciton.

Signed-off-by: Josuah Demangeon <[email protected]>
@josuah josuah force-pushed the pr_sample_uvc_uvb branch from cf4ed33 to 377298b Compare October 9, 2025 21:45
Josuah Demangeon added 2 commits October 9, 2025 23:02
Loop through each of the VideoStreaming and VideoControl descriptor
to parse them.

Signed-off-by: Josuah Demangeon <[email protected]>
Add a test to run the USB Video Class host support by using
the existing Zephyr USB Video Class device support.
This allows running implementing the host side from the device side.
A draft implementation of UVC is added leveraging this test.

Signed-off-by: Josuah Demangeon <[email protected]>
@josuah josuah force-pushed the pr_sample_uvc_uvb branch from 377298b to e4d4cf9 Compare October 9, 2025 23:20
Copy link

sonarqubecloud bot commented Oct 9, 2025

@github-actions github-actions bot removed the Stale label Oct 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants