mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
drivers/usbdev: add UVC gadget class driver
Add USB Video Class 1.1 gadget driver supporting Bulk transport with uncompressed YUY2 video streaming. Resolution and frame interval are negotiated dynamically via PROBE/COMMIT control. - uvc.h: protocol constants, streaming control struct, public API - uvc.c: class driver with PROBE/COMMIT, bulk EP, /dev/uvc0 chardev - Kconfig/Make.defs: USBUVC config and build rules - boardctl.c: BOARDIOC_USBDEV_UVC standalone init path Hardened against host disconnect: - Removed nxmutex_lock from USB interrupt context paths - Added 30s semaphore timeout in uvc_write with EP_CANCEL fallback - Drain stale wrsem counts in VS_COMMIT before new stream - Guard uvc_streaming_stop() against double EP_CANCEL race - Handle EP_SUBMIT returning -ESHUTDOWN gracefully Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
committed by
Alan C. Assis
parent
99afb5ee34
commit
4775b36316
@@ -44,6 +44,7 @@ following section.
|
||||
syslog.rst
|
||||
sdio.rst
|
||||
usbdev.rst
|
||||
uvc.rst
|
||||
usbhost.rst
|
||||
usbmisc.rst
|
||||
usbmonitor.rst
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
======================================
|
||||
USB Video Class (UVC) Gadget Driver
|
||||
======================================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The UVC gadget driver (``drivers/usbdev/uvc.c``) implements a USB Video Class
|
||||
1.1 device that makes NuttX appear as a USB webcam to the host. The driver
|
||||
exposes a character device (``/dev/uvc0``) that applications write video frames
|
||||
to. It handles all UVC class-specific control requests (PROBE / COMMIT)
|
||||
internally and uses bulk transfers for video data.
|
||||
|
||||
The driver supports two modes:
|
||||
|
||||
- **Standalone** – the UVC function is the only USB class on the bus.
|
||||
- **Composite** – the UVC function is combined with other USB class drivers
|
||||
(e.g. CDC/ACM) via the NuttX composite device framework.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
- UVC 1.1 compliant (uncompressed YUY2 format)
|
||||
- Bulk transfer mode for video data
|
||||
- Automatic PROBE / COMMIT negotiation with the host
|
||||
- ``poll()`` support – applications can wait for the host to start streaming
|
||||
(``POLLOUT``) and detect disconnection (``POLLHUP``)
|
||||
- Runtime video parameters – resolution and frame rate are passed at
|
||||
initialization time, so USB descriptors always match the actual sensor
|
||||
- ``boardctl()`` integration for easy application-level bring-up
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
The driver is enabled through the following Kconfig options:
|
||||
|
||||
.. code-block:: kconfig
|
||||
|
||||
CONFIG_USBUVC=y # Enable UVC gadget support
|
||||
CONFIG_USBUVC_COMPOSITE=n # Set y for composite device mode
|
||||
CONFIG_USBUVC_EPBULKIN=1 # Bulk IN endpoint number (standalone)
|
||||
CONFIG_USBUVC_EP0MAXPACKET=64 # EP0 max packet size (standalone)
|
||||
CONFIG_USBUVC_EPBULKIN_FSSIZE=64 # Bulk IN full-speed max packet size
|
||||
CONFIG_USBUVC_NWRREQS=4 # Number of pre-allocated write requests
|
||||
CONFIG_USBUVC_NPOLLWAITERS=2 # Number of poll waiters
|
||||
|
||||
Header Files
|
||||
============
|
||||
|
||||
- ``include/nuttx/usb/uvc.h`` – Public API, UVC descriptor constants, and
|
||||
data structures.
|
||||
|
||||
Data Structures
|
||||
===============
|
||||
|
||||
``struct uvc_params_s``
|
||||
-----------------------
|
||||
|
||||
Passed to the initialization function so that USB descriptors reflect the
|
||||
actual sensor capabilities::
|
||||
|
||||
struct uvc_params_s
|
||||
{
|
||||
uint16_t width; /* Frame width in pixels */
|
||||
uint16_t height; /* Frame height in pixels */
|
||||
uint8_t fps; /* Frames per second */
|
||||
};
|
||||
|
||||
Public Interfaces
|
||||
=================
|
||||
|
||||
Standalone Mode
|
||||
---------------
|
||||
|
||||
``usbdev_uvc_initialize()``
|
||||
Initialize the UVC gadget and register ``/dev/uvc0``. *params* may be
|
||||
``NULL`` to use defaults (320 × 240 @ 5 fps). Returns a handle for later
|
||||
``usbdev_uvc_uninitialize()``.
|
||||
|
||||
``usbdev_uvc_uninitialize()``
|
||||
Tear down the UVC gadget and unregister the character device.
|
||||
|
||||
Composite Mode
|
||||
--------------
|
||||
|
||||
``usbdev_uvc_classobject()``
|
||||
Create a UVC class driver instance for use inside a composite device.
|
||||
|
||||
``usbdev_uvc_classuninitialize()``
|
||||
Destroy a class driver instance created by ``usbdev_uvc_classobject()``.
|
||||
|
||||
``usbdev_uvc_get_composite_devdesc()``
|
||||
Fill a ``composite_devdesc_s`` for the composite framework.
|
||||
|
||||
boardctl Integration
|
||||
--------------------
|
||||
|
||||
Applications can manage the UVC gadget through ``boardctl()``::
|
||||
|
||||
struct boardioc_usbdev_ctrl_s ctrl;
|
||||
struct uvc_params_s params = { .width = 320, .height = 240, .fps = 15 };
|
||||
FAR void *handle = (FAR void *)¶ms;
|
||||
|
||||
ctrl.usbdev = BOARDIOC_USBDEV_UVC;
|
||||
ctrl.action = BOARDIOC_USBDEV_CONNECT;
|
||||
ctrl.instance = 0;
|
||||
ctrl.config = 0;
|
||||
ctrl.handle = &handle;
|
||||
|
||||
boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
|
||||
|
||||
/* ... use /dev/uvc0 ... */
|
||||
|
||||
ctrl.action = BOARDIOC_USBDEV_DISCONNECT;
|
||||
boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
|
||||
|
||||
Device Operation
|
||||
================
|
||||
|
||||
1. The application opens ``/dev/uvc0`` for writing.
|
||||
2. Use ``poll()`` with ``POLLOUT`` to wait for the USB host to start streaming
|
||||
(i.e. the host sends a VS_COMMIT_CONTROL SET_CUR request).
|
||||
3. Write complete video frames via ``write()``. The driver prepends a 2-byte
|
||||
UVC payload header (with FID / EOF bits) automatically.
|
||||
4. When the host stops streaming, ``write()`` returns ``-EAGAIN``. The
|
||||
application can ``poll()`` again to wait for the host to restart.
|
||||
5. ``POLLHUP`` is reported when the host explicitly stops streaming.
|
||||
Reference in New Issue
Block a user