V4L2 UVC事件
2025-12-12
本文链接为:http://www.usbzh.com/article/detail-1606.html ,欢迎转载,转载请附上本文链接。
UVC事件包括两类,分别为数据事件(读写)和异常事件。这两类事件可通过select函数查看。
事件的注册可见:
struct v4l2_event_subscription sub;
memset(&sub, 0, sizeof sub);
sub.type = UVC_EVENT_SETUP;
ioctl(dev->uvc_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
sub.type = UVC_EVENT_DATA;
ioctl(dev->uvc_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
sub.type = UVC_EVENT_STREAMON;
ioctl(dev->uvc_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
sub.type = UVC_EVENT_STREAMOFF;
ioctl(dev->uvc_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);

数据事件
数据事件对应于select函数的读写事件。
对于UVC Gadget 应用写数据,当事件来到时。应
struct v4l2_buffer ubuf;
ret = ioctl(dev->uvc_fd, VIDIOC_DQBUF, &ubuf); //获取空闲队列
uvc_video_fill_buffer(dev, &ubuf);//自定义函数,填充数据缓冲区
ret = ioctl(dev->uvc_fd, VIDIOC_QBUF, &ubuf); //重新入队列等待数据发送
异常事件
异常事件包括UVC本身的控制请求和设备的事件。
首先应先通过VIDIOC_DQEVENT ioctl获取事件v4l2_event。
//事件本身
struct v4l2_event {
__u32 type;
union {
struct v4l2_event_vsync vsync;
struct v4l2_event_ctrl ctrl;
struct v4l2_event_frame_sync frame_sync;
struct v4l2_event_src_change src_change;
struct v4l2_event_motion_det motion_det;
__u8 data[64];
} u;
__u32 pending;
__u32 sequence;
struct timespec timestamp;
__u32 id;
__u32 reserved[8];
};
//事件响应
struct uvc_request_data {
__s32 length;
__u8 data[60];
};
其中type为事件类型
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
| 重要性 | 事件类型 | 原因 |
|---|---|---|
| 最高 | UVC_EVENT_SETUP | 所有控制和配置的基础,需要UVCIOC_SEND_RESPONSE请求返回uvc_request_data |
| 高 | UVC_EVENT_DATA | 配合SETUP完成控制传输(实际为SET_CUR) |
| 中 | UVC_EVENT_STREAMON/OFF | 控制数据流启停 |
| 低 | UVC_EVENT_CONNECT/DISCONNECT | 设备物理状态变化 |
| 无 | UVC_EVENT_FIRST/LAST | 仅为枚举标记 |
当为UVC_EVENT_SETUP或UVC_EVENT_DATA事件时,v4l2_event.u.data类型为uvc_event
struct uvc_event {
union {
enum usb_device_speed speed;
struct usb_ctrlrequest req;
struct uvc_request_data data;
};
};
故
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
uvc_event分为2类:
truct uvc_event {
union {
enum usb_device_speed speed;
struct usb_ctrlrequest req; //UVC_EVENT_SETUP
struct uvc_request_data data; //UVC_EVENT_DATA
};
};
struct usb_ctrlrequest {
__u8 bRequestType;
__u8 bRequest;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
} __attribute__ ((packed));
struct uvc_request_data {
__s32 length;
__u8 data[60];
};
UVC_EVENT_SETUP
UVC_EVENT_SETUP事件就是标准的SETUP事务,USB控制请求,所以从理论上包括标准请求、类请求和Vendor自定义请求,这里需要关注的是类请求。
UVC的类请求分为两类:VC和VS的区别可以通过wIndex & 0xff来获取对应的接口描述符ID来判断。
- 第一类为UVC视频控制接口的GET_CUR,SET_CUR,GET_DEF等标准类请求,主要是相机终端、处理单元、扩展单元的请求。
- 第二类为UVC类视频流控制请求,主要涉及的是数据流接口的PROB COMMIT请求,也是一大堆的GET_CUR和SET_CUR等。
对于UVC控制接口,当unitId=0时,cs=UVC_VC_REQUEST_ERROR_CODE_CONTROL表求请求错误代码信息,通常由主机(如PC)向UVC设备(如摄像头)发送,以查询或清除设备报告的错误状态。
static void uvc_events_process_control(
struct uvc_device *dev, uint8_t req, uint8_t cs, uint8_t entity_id, uint8_t len, struct uvc_request_data *resp)
{
switch (entity_id) {
case 0:
switch (cs) {
case UVC_VC_REQUEST_ERROR_CODE_CONTROL:
/* Send the request error code last prepared. */
resp->data[0] = dev->request_error_code.data[0];
resp->length = dev->request_error_code.length;
break;
default:
/*
* If we were not supposed to handle this
* 'cs', prepare an error code response.
*/
dev->request_error_code.data[0] = 0x06;
dev->request_error_code.length = 1;
break;
}
break;
本文链接为:http://www.usbzh.com/article/detail-1606.html ,欢迎转载,转载请附上本文链接。
V4L2学习笔记





