分享

uvc camera--使用v4l2架构

 新用户8389DdzY 2021-09-22

法一:直接使用dev/bus/usb节点做应用

法二:使用v4l2架构

该文档描述法二

Usb设备的检测: 

Usb枚举过程:

Bus Hound抓包工具

   USB设备都会有设备描述符、配置描述符、接口描述符、端点描述符四种描述符,主机通过读取这些描述符来获得USB Device信息,从而以这些描述符所描述的方式与其通信。

UVC摄像头插入PC USB接口,直到PC识别其为视频设备,打开设备管理器,能够发现多了一个摄像头设备,如上图红线部分所示,将BUS Hound抓取的数据包保存为txt文件。

       先看第一行,CTL意为“USB control transfer”,即控制传输,熟悉USB通信的朋友应该都知道USB有四种数据传输方式,其中“控制传输”为仅有的双向传输方式,USB枚举过程中就是用的控制传输方式与USB从机的端点0进行通信的,Device那一列“25.0”,表示通信端点为UVC设备的端点0。

 

      UVC摄像头插入PC后,PC向其端点0发送了8个Byte的数据:80 06 00 01  00 00 12 00,第四字节“01”与第七字节“12”代表PC请求UVC设备发送“设备描述符至主机,设备描述符长度为18Byte”。

     再看第二行,“IN”表示数据传输方向为输入,即PC接收UVC摄像头返回的18Byte数据:12 01 00 02  ef 02 01 40  71 18 70 76  12 03 01 02 00 01,关于这18Byte的定义,UVC官方文档给出了很详细的解释,如下图所示,其中PC就是通过画红圈的那三个字节数据知道该设备为UVC设备的。

 

 

       PC收到UVC摄像头返回的18Byte配置描述符后,紧接着又发出了第二条控制命令:

80 06 00 02  00 00 09 00,第四字节“02”与第七字节“09”表示“请求UVC发送自己的配置描述符至PC,数据长度9Byte”。

       随后UVC摄像头返回了9Byte数据至PC:09 02 a3 01  02 01 00 80  fa,关于配置描述符的详细信息,UVC官方文档给出了如下描述。

 

       其中,我们暂时先关注下第3、4字节,即“wTotalLength”参数,由于USB传输是低字节先传输,故我们知道,该配置描述符以及其下所有的接口描述符和端点描述符的总字节长度为0x1a3字节。

       紧接着,PC开始向UVC摄像头端点0发送第三次控制命令啦:80 06 00 02  00 00 a3 01,第7、8字节是不是很眼熟啊?没错,第4字节还是“02”,PC这次还是发送的读取UVC设备“配置描述符”命令,但是这次读取的字节长度是“0x1a3”字节,那这次就是将“接口描述符”和“端点描述符”全都读出来啦!数据量比较大,如下图所示。

 

      至此为止,PC与UVC设备之间的枚举过程大体已经分析完了

Usb总线介绍:

Bustype是usb_bus_type,上面可以挂两种device和两种driver。

usb_device/usb_device_driverusb_driver/usb_interface。其中usb_driver/usb_interface就是接口设备和接口驱动,例如uvc。

一般的每个usb设备可能有很多种配置,很多个接口,很多中设置,很多端口

Uvc驱动框架:

首先,因为要用USB传数据,入口函数中注册usb_driver结构体,出口函数反之

static int myuvc_init(void)

{

usb_register(&myuvc_driver);

return 0;

}

static void myuvc_exit(void)

{

usb_deregister(&myuvc_driver);

}

usb_driver结构体中提供probe函数和id_table

static struct usb_driver myuvc_driver = {

.name = "myuvc",

.probe = myuvc_probe,

.disconnect = myuvc_disconnect,

.id_table = myuvc_ids,

}

id_table用来判断此驱动是否支持某USB设备
static struct usb_device_id myuvc_ids[] = {

/* Generic USB Video Class */

{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, /* VideoControl Interface */

{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 2, 0) }, /* VideoStreaming Interface */

{}

}

如果插入一个USB设备,判断id_table通过则会调用此驱动的probe函数

UVC的probe函数主要做这几件事:

1. 分配video_device结构体

2. 设置video_device结构体

3. 注册video_device结构体

video_register_device(myuvc_vdev, VFL_TYPE_GRABBER, -1)

这里UVC驱动程序把video_device结构体注册给上一层的v4l2-dev.c文件,在v4l2-dev.c中会注册字符设备等一些操作,上一层的操作我们不关心,我们只需要在UVC设备驱动层提供一个video_device结构体就行了

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多