Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ supported:
- gpio
- spi
- i2c
- usbd
vendor: arduino
2 changes: 2 additions & 0 deletions doc/connectivity/usb/device/usb_device.rst
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,8 @@ The following Product IDs are currently used:
+----------------------------------------------------+--------+
| :zephyr:code-sample:`uac2-implicit-feedback` | 0x000F |
+----------------------------------------------------+--------+
| :zephyr:code-sample:`uvc` | 0x0011 |
+----------------------------------------------------+--------+
| :zephyr:code-sample:`usb-dfu` (DFU Mode) | 0xFFFF |
+----------------------------------------------------+--------+

Expand Down
4 changes: 4 additions & 0 deletions doc/connectivity/usb/device_next/usb_device.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Samples

* :zephyr:code-sample:`uac2-implicit-feedback`

* :zephyr:code-sample:`uvc`

Samples ported to new USB device support
----------------------------------------

Expand Down Expand Up @@ -223,6 +225,8 @@ instance (``n``) and is used as an argument to the :c:func:`usbd_register_class`
+-----------------------------------+-------------------------+-------------------------+
| Bluetooth HCI USB transport layer | :ref:`bt_hci_raw` | :samp:`bt_hci_{n}` |
+-----------------------------------+-------------------------+-------------------------+
| USB Video Class (UVC) | Video device | :samp:`uvc_{n}` |
+-----------------------------------+-------------------------+-------------------------+

CDC ACM UART
============
Expand Down
12 changes: 12 additions & 0 deletions dts/bindings/usb/zephyr,uvc-device.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2025 tinyVision.ai Inc.
# SPDX-License-Identifier: Apache-2.0

description: |
Declare an USB Video Class (UVC) device instance.

Each UVC instance added to the USB Device Controller (UDC) node will be visible
as a new camera from the host point of view.

compatible: "zephyr,uvc-device"

include: base.yaml
21 changes: 21 additions & 0 deletions include/zephyr/usb/class/usbd_uvc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2025 tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief USB Device Firmware Upgrade (DFU) public header
*
* Header exposes API for registering DFU images.
*/

#ifndef ZEPHYR_INCLUDE_USB_CLASS_USBD_UVC_H
#define ZEPHYR_INCLUDE_USB_CLASS_USBD_UVC_H

#include <zephyr/kernel.h>

void uvc_set_video_dev(const struct device *const dev, const struct device *const video_dev);

#endif /* ZEPHYR_INCLUDE_USB_CLASS_USBD_UVC_H */
3 changes: 2 additions & 1 deletion samples/subsys/usb/common/sample_usbd_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ static void sample_fix_code_triple(struct usbd_context *uds_ctx,
IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) ||
IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) ||
IS_ENABLED(CONFIG_USBD_MIDI2_CLASS) ||
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) {
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS) ||
IS_ENABLED(CONFIG_USBD_VIDEO_CLASS)) {
/*
* Class with multiple interfaces have an Interface
* Association Descriptor available, use an appropriate triple
Expand Down
8 changes: 8 additions & 0 deletions samples/subsys/usb/uvc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(usb_video)

include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
target_sources(app PRIVATE src/main.c)
9 changes: 9 additions & 0 deletions samples/subsys/usb/uvc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright The Zephyr Project Contributors
# SPDX-License-Identifier: Apache-2.0

# Source common USB sample options used to initialize new experimental USB
# device stack. The scope of these options is limited to USB samples in project
# tree, you cannot use them in your own application.
source "samples/subsys/usb/common/Kconfig.sample_usbd"

source "Kconfig.zephyr"
189 changes: 189 additions & 0 deletions samples/subsys/usb/uvc/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
.. zephyr:code-sample:: uvc
:name: USB Video sample
:relevant-api: usbd_api video_interface

Send video frames over USB.

Overview
********

This sample demonstrates how to use a USB Video Class instance to
send video data over USB.

Upon connection, a video device will show-up on the host,
usable like a regular webcam device.

Any software on the host can then access the video stream as a local video source.

Requirements
************

This sample uses the new USB device stack and requires the USB device
controller ported to the :ref:`udc_api`.

Building and Running
********************

If a board is equipped with a supported video sensor, and ``zephyr,camera``
node is chosen for the board, it will be used as the video source.
The sample can be built as follows:

.. zephyr-app-commands::
:zephyr-app: samples/subsys/usb/uvc
:board: arduino_nicla_vision/stm32h747xx/m7
:goals: build flash
:compact:

If the video sensor is not present, the software test pattern generator can be used
instead, and the sample can be built for any board with a supported USB device
controller and sufficient RAM as follows:

.. zephyr-app-commands::
:zephyr-app: samples/subsys/usb/uvc
:board: rpi_pico
:goals: build flash
:gen-args: -DEXTRA_DTC_OVERLAY_FILE=video-emul.overlay
:compact:

The device is expected to be detected as a webcam device:

.. tabs::

.. group-tab:: Ubuntu

The ``dmesg`` logs are expected to mention a ``generic UVC device``.

The ``lsusb`` is expected to show an entry for a Zephyr device.

Refers to `Ideas on board FAQ <https://www.ideasonboard.org/uvc/faq/>`_
for how to get more debug information.

.. group-tab:: MacOS

The ``dmesg`` logs are expected to mention a video device.

The ``ioreg -p IOUSB`` command list the USB devices including cameras.

The ``system_profiler SPCameraDataType`` command list video input devices.

.. group-tab:: Windows

The Device Manager or USBView utilities permit to list the USB devices.

The 3rd-party USB Tree View allows to review and debug the descriptors.

In addition, the `USB3CV <https://www.usb.org/document-library/usb3cv>`_ tool
from USB-IF can check that the device is compliant with the UVC standard.


Playing the Stream
==================

The device is recognized by the system as a native webcam and can be used by any video application.

For instance with VLC:
``Media`` > ``Open Capture Device`` > ``Capture Device`` > ``Video device name``.

Or with Gstreamer and FFmpeg:

.. tabs::

.. group-tab:: Ubuntu

Assuming ``/dev/video0`` is your Zephyr device.

.. code-block:: console

ffplay -i /dev/video0

.. code-block:: console

gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! autovideosink

.. group-tab:: MacOS

Assuming ``0:0`` is your Zephyr device.

.. code-block:: console

ffplay -f avfoundation -i 0:0

.. code-block:: console

gst-launch-1.0 avfvideosrc device-index=0 ! autovideosink

.. group-tab:: Windows

Assuming ``UVC sample`` is your Zephyr device.

.. code-block:: console

ffplay.exe -f dshow -i video="UVC sample"

.. code-block:: console

gst-launch-1.0.exe ksvideosrc device-name="UVC sample" ! videoconvert ! autovideosink

The video device can also be used by web and video call applications systems.

Android and iPad (but not yet iOS) are also expected to work via dedicated applications.

Accessing the Video Controls
============================

On the host system, the controls would be available as video source
control through various applications, like any webcam.

.. tabs::

.. group-tab:: Ubuntu

Assuming ``/dev/video0`` is your Zephyr device.

.. code-block:: console

$ v4l2-ctl --device /dev/video0 --list-ctrls

Camera Controls

auto_exposure 0x009a0901 (menu) : min=0 max=3 default=1 value=1 (Manual Mode)
exposure_dynamic_framerate 0x009a0903 (bool) : default=0 value=0
exposure_time_absolute 0x009a0902 (int) : min=10 max=2047 step=1 default=384 value=384 flags=inactive

$ v4l2-ctl --device /dev/video0 --set-ctrl auto_exposure=1
$ v4l2-ctl --device /dev/video0 --set-ctrl exposure_time_absolute=1500

.. group-tab:: Windows

The `VLC <https://www.videolan.org/vlc/>`_ client and `Pot Player <https://potplayer.tv/>`_
client permit to further access the video controls.

.. group-tab:: MacOS

The `VLC <https://www.videolan.org/vlc/>`_ client and the system Webcam Settings panel
allows adjustment of the supported video controls.


Software Processing
===================

Software processing tools can also use the video interface directly.

Here is an example with OpenCV (``pip install opencv-python``):

.. code-block:: python

import cv2

# Number of the /dev/video# interface
devnum = 2

cv2.namedWindow("preview")
vc = cv2.VideoCapture(devnum)

while (val := vc.read())[0]:
cv2.waitKey(20)
cv2.imshow("preview", val[1])

cv2.destroyWindow("preview")
vc.release()
23 changes: 23 additions & 0 deletions samples/subsys/usb/uvc/app.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2025 tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

/ {
uvc: uvc {
compatible = "zephyr,uvc-device";
};
};

&ov7670 {
status = "disabled";
};

&smartdma {
status = "disabled";
};

&video_sdma {
status = "disabled";
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Enough two 320x240 YUYV frames
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=163840
19 changes: 19 additions & 0 deletions samples/subsys/usb/uvc/boards/frdm_mcxn947_mcxn947_cpu0.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025 tinyVision.ai Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "../app.overlay"

&ov7670 {
status = "disabled";
};

&smartdma {
status = "disabled";
};

&video_sdma {
status = "disabled";
};
14 changes: 14 additions & 0 deletions samples/subsys/usb/uvc/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CONFIG_LOG=y
CONFIG_POLL=y
CONFIG_VIDEO=y
CONFIG_VIDEO_SW_GENERATOR=y
CONFIG_VIDEO_LOG_LEVEL_WRN=y
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=2
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=24576
CONFIG_USB_DEVICE_STACK_NEXT=y
CONFIG_USBD_LOG_LEVEL_WRN=y
CONFIG_USBD_VIDEO_CLASS=y
CONFIG_USBD_VIDEO_LOG_LEVEL_WRN=y
CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y
CONFIG_SAMPLE_USBD_PID=0x0011
CONFIG_SAMPLE_USBD_PRODUCT="UVC sample"
24 changes: 24 additions & 0 deletions samples/subsys/usb/uvc/sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
sample:
name: USB Video sample
tests:
sample.subsys.usb.uvc:
depends_on:
- usbd
tags: usb
integration_platforms:
- nrf52840dk/nrf52840
- nrf54h20dk/nrf54h20/cpuapp
- frdm_k64f
- stm32f723e_disco
- nucleo_f413zh
- mimxrt685_evk/mimxrt685s/cm33
- mimxrt1060_evk/mimxrt1062/qspi
extra_args:
- EXTRA_DTC_OVERLAY_FILE="video-emul.overlay"
sample.subsys.usb.uvc.camera:
depends_on:
- usbd
tags: usb video
filter: dt_chosen_enabled("zephyr,camera")
integration_platforms:
- arduino_nicla_vision/stm32h747xx/m7
Loading
Loading