<span id='jmxlj'></span>

      <ins id='jmxlj'></ins>
      <dl id='jmxlj'></dl>

      <code id='jmxlj'><strong id='jmxlj'></strong></code>

      1. <tr id='jmxlj'><strong id='jmxlj'></strong><small id='jmxlj'></small><button id='jmxlj'></button><li id='jmxlj'><noscript id='jmxlj'><big id='jmxlj'></big><dt id='jmxlj'></dt></noscript></li></tr><ol id='jmxlj'><table id='jmxlj'><blockquote id='jmxlj'><tbody id='jmxlj'></tbody></blockquote></table></ol><u id='jmxlj'></u><kbd id='jmxlj'><kbd id='jmxlj'></kbd></kbd>
      2. <i id='jmxlj'></i>
        <fieldset id='jmxlj'></fieldset><acronym id='jmxlj'><em id='jmxlj'></em><td id='jmxlj'><div id='jmxlj'></div></td></acronym><address id='jmxlj'><big id='jmxlj'><big id='jmxlj'></big><legend id='jmxlj'></legend></big></address>

            <i id='jmxlj'><div id='jmxlj'><ins id='jmxlj'></ins></div></i>

            Linux中开发USB摄像头驱动详解

            • 时间:
            • 浏览:4
            • 来源:124软件资讯网

              USB摄像头以其优秀的性能和低廉的价钱获得普遍应用 。同时因其天真、利便的特征  ,易于集成到嵌入式系统中  。可是若是使用现有的切合Video for Linux尺度的驱动法式配合通用应用法式 ,难以充实使用USB带宽  ,帧速不高 ,不易知足实时监控等要求 。本文首先先容在Linux系统下USB摄像头驱动体例的一样平常要领  ,然后说明在此基础上怎样提高帧速 。

                1 Linux系统中的USB摄像头驱动法式

                USB装备驱动法式完全切合通用装备驱动的准则  ,差别的是内核提供了一些特殊的API函数  ,利便驱动注册、销毁自己  ,例如usb_reSister()和usb_dereSister();2.4版的内核还提供了对于hotplug的支持  。

                1.1 USB摄像头驱动的一样平常编写要领

                摄像头属于视频类装备 。在现在的Linux焦点中 ,视频部门的尺度是Video for Linux(简称V4L)  。这个尺度实在界说了一套接口  ,内核、驱动、应用法式以这个接口为尺度举行交流  。现在的V4L涵盖了视、音频流捕捉及处置惩罚等内容 ,USB摄像头也属于它支持的领域 。

                因此  ,USB摄像头的驱动应当与内核提供的视频驱动挂钩 。即首先在驱动中声明一个video_device结构  ,并为其指定文件操作函数指针数组.fops  ,向系统注册  。在应用法式发出文件操作的相关下令时  ,焦点凭据这些指针挪用响应函数  ,并将该结构作为参数通报给它们  。这样 ,就完成了驱动和焦点之间的通讯  。例如:

                static struct video_device vdev_template={……};

                //声明video_device ,指出挂接驱动

                static struct file_operations ov511_fops={……};

                //声明本驱动的文件操作函数指针

                struct video_device*vdev=video_devdata(file);

                //从文件指针中提取出video_device结构

                在video_device结构中  ,有一个私有指针priv  ,可以将它指向一块保留内存 。在这块内存中  ,生存着本驱动、本装备的相关初始化信息  。这块内存的申请、初始化、指针指向等事情都是在USB驱动的枚举函数.probe中完成  。这样  ,在枚举函数将控制权返还给系统后  ,由于内核不销毁保留内存  ,以是驱动仍然保留着自己的信息  。这点与Windows系统中WDM驱动有异曲同工之处 。固然  ,在驱动卸载函数中 ,应当将申请的各块内存所有释放  。

                1.2 使用双URB轮流通讯

                众所周知 ,USBl.1总线尺度界说了控制、中止、批量、等时等四种管道 。对于时间性极强可是准确度要求不高的视频捕捉应用来说  ,摄像头应当使用等时传输方式 。为了尽可能快地获得图像数据  ,应当在URB中指定USB_ISO_ASAP标志  。

                urb->transfer_flags=USB_ISO_ASAP;//尽可能快地发出本URB

                Linux系统中任何USB传输都通过URB实现  。为提高速率  ,可以思量扩大URB的缓冲  ,这样可以降低每个USB事务中握手信息所占比例  ,提高有用数据的传输速率  。可是受限于总线带宽和详细的USB装备芯片  ,单纯扩大URB的缓冲不能无限制地解决问题  。详细剖析一下USB传输在操作系统中的实现:每次传输都要包罗URB的建设、发出、接纳、数据整理等阶段 ,这些时间不发生有用数据  。因此可以建设两个URB  ,在等候一个URB被接纳时  ,也就是图像正在被传感器收罗时  ,处置惩罚、初始化另一个URB ,并在接纳后连忙将其发出 。两个URB交替使用 ,大大淘汰了分外时间 。事情流程如图1所示 。

                这个历程是在URB的完成例程中实现的  ,有两点需要注重:首先处置惩罚再次初始化的代码时间不能长  ,否则会造成完成例程的重人 ,若是确实来不及  ,可以在完成例程中设定标志 ,例如“数据收罗好”旗语  ,由应用法式使用壅闭ioctl()来查询该旗语并做处置惩罚;其次由于CPU可能会在完成例程中停留较长时间  ,系统肩负较大  ,可以在.open函数中初始化两个URB并将其发出  ,有限度地减轻系统肩负  。

                1.3 使用双帧缓冲提高效率

                Linux系统中  ,文件操作通常是由read、write等系统挪用来完成  。这些系统挪用在驱动中的解决要领就是用copy_to_user()、copy_from_user()等函数在核态、户态内存空间中相互拷贝  。可是对于大批量的图像数据  ,接纳拷贝的要领显然会增添时间开销 ,因此用内存映射的要领解决 。首先使用vmalloc()申请足够大的核态内存  ,将其作为图像数据缓冲空间  ,两个URB带回的图像数据在这里暂存;然后使用remap_page_range()函数将其逐页映射到用户空间中  。户态的图像处置惩罚法式使用mmap()函数 ,直接读写核态图像缓冲内存 ,大大淘汰分外开销