写一个USB摄像头驱动程序:

怎么写摄像头驱动程序:

1.分配video_device结构体:video_device_alloc函数

2.设置 .fops  .ioctl_ops(里面需要设置11项) 如果要用内核提供的缓冲区操作函数,还需要构造一个videobuf_queue_ops结构体。

3.注册:video_register_device函数

 

怎么写USB摄像头驱动程序:

1.构造一个usb_driver

2.设置 

.probe:

/***把摄像头驱动程序放在里面*******/

2.1分配video_device结构体:video_device_alloc函数

2.2设置 .fops  .ioctl_ops(里面需要设置11项) 如果要用内核提供的缓冲区操作函数,还需要构造一个videobuf_queue_ops结构体。

2.3注册:video_register_device函数

/**********/

.id_table:表示支持哪些USB设备

3.注册

 

UVC驱动:USB Video Class 路径:drivers\media\video\uvc\

 

Uvc_driver.c分析:

1.usb_register(&uvc_driver.driver);

2.uvc_probe

Uvc_register_video

Vdev=video_device_alloc();

Vdev->fops=&uvc_fops;

Video_register_device

//分析可知,UVC驱动中的probe函数还是包含了之前说的摄像头驱动程序的主体。

 

uvc_specification UVC示例文档中:

USB摄像头示例中阐述:一定有用于控制的VideoControl Interface(VC),但是不一定有用于传输的VideoStreaming Interface(VS)。

VC内部抽象出Unit和Terminal两个概念。

Units有Select Unit(SU)和Process Unit(PU),Terminal有Input terminal(IT),Camera terminal(CT),Output terminal(OT)。SU用于选择哪一路信号,PU用于设置亮度、白平衡等。terminal用于内外连接,里面的称为unit。一般经常使用IT,而不用CT,SU为多路选择器。

 

通过VidiocControl Interface来控制,通过VideoStreaming Interface 来读视频数据。

VC里有多个Unit/Terminal等功能模块,可以通过访问这些模块来控制,比如调亮度。

 

Ioctl中VIDIOC_S_FMT对应函数中,先调用VIDIOC_TRY_FMT所对应的函数,然后再调用进行设置。但是注意VIDIOC_S_FMT对应的函数进行的操作将格式保存在数组中,还未发给USB摄像头。

 

上面提及的ioctl操作并没有涉及与硬件的交互,只有执行VIDIOC_STREAMON命令才会将之前设置的格式发送给USB,然后启动摄像头。这里通过的是UVC 的video streaming 接口来发送格式等数据。

 

如果想对摄像头的属性进行设置,如亮度、白平衡等,需要调用VIDIOC_S_CTRL ioctl操作,并通过video control interface 接口来发送属性数据。除此之外还需要entity_id变量标记需要发送到VC中的哪一个units/terminals。

 

总结:

1.UVC设备有2个interface:videocontrol interface 和videostream interface。

2.VideoControl Interface 用于控制,比如设置亮度,它内部有多个units/terminals,程序中都称为entity,每一个都有一个entity_id进行标识。

3.VideoStreaming Interface用于获得视频数据,也可以用来设置format/frame(格式/分辨率、位宽等)(VS可能有多种format,一个format有多种frame,frame用来表示分辨率等多种信息)。

4.我们在设置format时只是简单的使用video->streaming->format[fmt->index]等数据,这些数据哪来的?应是设备被枚举时设置的,也就是分析它的描述符时设置。

5.UVC驱动的重点在于:

描述符的分析

属性的控制:通过VideoControl Interface来控制。

格式的选择:通过VideoStreaming Interface来设置。

数据的获得:通过VideoStreaming Interface的URB来获得。