Linux摄像头UVC驱动第一篇--UVC驱动简析

目录:

一 USB摄像头驱动整体框架
二 UVC驱动简析
  • 2.1 USB摄像头硬件结构简析
  • 2.2 分析UVC驱动调用过程

一 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.注册: usb_register

二 UVC驱动简析

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

2.1 USB摄像头硬件结构简析

在这里插入图片描述
UVC 1.5 Class specification.pdf :

Video functions are addressed through their video interfaces. Each video function has a single VideoControl (VC) interface and can have several VideoStreaming (VS) interfaces. TheVideoControl (VC) interface is used to access the device controls of the function whereas the VideoStreaming (VS) interfaces are used to transport data streams into and out of the function

VC内部抽象出两个基本的模块 Units 和 Terminals,Terminals用于“内外连接”,Units 是VC 内部功能模块,IT用于输入,OT用于输出,SU用于多路选择,PU控制属性。

The Input Terminal (IT) is used as an interface between the video function’s “outside world” and other Units inside the video function.

The Output Terminal (OT) is used as an interface between Units inside the video function and the “outside world”.

The Camera Terminal (CT) controls mechanical (or equivalent digital) features of the device component that transmits the video stream.

The Selector Unit (SU) selects from n input data streams and routes them unaltered to the single output stream. It represents a source selector, capable of selecting among a number of sources. It has an Input Pin for each source stream and a single Output Pin
在这里插入图片描述

The Processing Unit (PU) controls image attributes of the video being streamed through it. It has a single input and output pin. It provides support for the following features:

在这里插入图片描述

User Controls
 Brightness
 Hue
 Saturation
 Sharpness
 Gamma
 Digital Multiplier (Zoom)

VC 
	Units
		SU : Select Units
		PU : Process Units
		
	Terminals
		IT : Input Terminals
		CT : Camera Terminals
		OT : Output Terminals
		
VS

小结:
1 通过VideoControl Interface来控制,
2 通过VideoStreaming Interface来读视频数据,
3 VC里含有多个Unit/Terminal等功能模块,可以通过访问这些模块进行控制,比如调亮度

2.2 分析UVC驱动调用过程:

const struct v4l2_file_operations uvc_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
.ioctl = uvc_v4l2_ioctl,
.read = uvc_v4l2_read,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
};

  1. open:

     uvc_v4l2_open
    
  2. VIDIOC_QUERYCAP // video->streaming->type 应该是在设备被枚举时分析描述符时设置的

     if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
     	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
     			  | V4L2_CAP_STREAMING;
     else
     	cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
     			  | V4L2_CAP_STREAMING;
    
  3. VIDIOC_ENUM_FMT // format数组应是在设备被枚举时设置的

     format = &video->streaming->format[fmt->index];
    
  4. VIDIOC_G_FMT

     uvc_v4l2_get_format  // USB摄像头支持多种格式fromat, 每种格式下有多种frame(比如分辨率)
         	struct uvc_format *format = video->streaming->cur_format;
         	struct uvc_frame *frame = video->streaming->cur_frame;
    
  5. VIDIOC_TRY_FMT

    uvc_v4l2_try_format
        /* Check if the hardware supports the requested format. */
    
    	/* Find the closest image size. The distance between image sizes is
    	 * the size in pixels of the non-overlapping regions between the
    	 * requested size and the frame-specified size.
    	 */
    
  6. VIDIOC_S_FMT // 只是把参数保存起来,还没有发给USB摄像头

       uvc_v4l2_set_format
           uvc_v4l2_try_format
       			video->streaming->cur_format = format;
       			video->streaming->cur_frame = frame;
    
  7. VIDIOC_REQBUFS

     uvc_alloc_buffers
        	for (; nbuffers > 0; --nbuffers) {
     		mem = vmalloc_32(nbuffers * bufsize);
     		if (mem != NULL)
     			break;
    
  8. VIDIOC_QUERYBUF

     uvc_query_buffer
         __uvc_query_buffer
             memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);  // 复制参数
    
  9. mmap

     uvc_v4l2_mmap
    
  10. VIDIOC_QBUF

    uvc_queue_buffer
    	list_add_tail(&buf->stream, &queue->mainqueue);
    	list_add_tail(&buf->queue, &queue->irqqueue);
    
  11. VIDIOC_STREAMON

    uvc_video_enable(video, 1)  // 把所设置的参数发给硬件,然后启动摄像头
        /* Commit the streaming parameters. */
        uvc_commit_video
            uvc_set_video_ctrl  /* 设置格式fromat, frame */
                	ret = __uvc_query_ctrl(video->dev /* 哪一个USB设备 */, SET_CUR, 0,
                		video->streaming->intfnum  /* 哪一个接口: VS */,
                		probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
                		uvc_timeout_param);
                
        /* 启动:Initialize isochronous/bulk URBs and allocate transfer buffers. */
        uvc_init_video(video, GFP_KERNEL);
                uvc_init_video_isoc / uvc_init_video_bulk
                    urb->complete = uvc_video_complete; (收到数据后此函数被调用,它又调用video->decode(urb, video, buf); ==> uvc_video_decode_isoc/uvc_video_encode_bulk => uvc_queue_next_buffer => wake_up(&buf->wait);)
                    
                usb_submit_urb    
    
  12. poll

    uvc_v4l2_poll            
        uvc_queue_poll
            poll_wait(file, &buf->wait, wait);  // 休眠等待有数据
    
  13. VIDIOC_DQBUF

    uvc_dequeue_buffer
    	list_del(&buf->stream);
    
  14. VIDIOC_STREAMOFF

    uvc_video_enable(video, 0);
    	usb_kill_urb(urb);
    	usb_free_urb(urb);
    

分析设置亮度过程:

ioctl: VIDIOC_S_CTRL
            uvc_ctrl_set
            uvc_ctrl_commit
                __uvc_ctrl_commit(video, 0);
                    uvc_ctrl_commit_entity(video->dev, entity, rollback);
                			ret = uvc_query_ctrl(dev  /* 哪一个USB设备 */, SET_CUR, ctrl->entity->id  /* 哪一个unit/terminal */,
                				dev->intfnum /* 哪一个接口: VC interface */, ctrl->info->selector,
                				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
                				ctrl->info->size);

小结:
1 UVC设备有2个interface: VideoControl Interface, VideoStreaming Interface

2 VideoControl Interface用于控制,比如设置亮度。它内部有多个Unit/Terminal(在程序里Unit/Terminal都称为entity)可以通过类似的函数来访问:

   ret = uvc_query_ctrl(dev  /* 哪一个USB设备 */, SET_CUR, ctrl->entity->id  /* 哪一个unit/terminal */,
                				dev->intfnum /* 哪一个接口: VC interface */, ctrl->info->selector,
                				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
                				ctrl->info->size);

3 VideoStreaming Interface用于获得视频数据,也可以用来选择fromat/frame(VS可能有多种format, 一个format支持多种frame, frame用来表示分辨率等信息) 可以通过类似的函数来访问:

  ret = __uvc_query_ctrl(video->dev /* 哪一个USB设备 */, SET_CUR, 0,
                    		video->streaming->intfnum  /* 哪一个接口: VS */,
                    		probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
                    		uvc_timeout_param);

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

5 UVC驱动的重点在于:

   描述符的分析
   属性的控制: 通过VideoControl Interface来设置
   格式的选择:通过VideoStreaming Interface来设置
   数据的获得:通过VideoStreaming Interface的URB来获得
  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值