WindowsCE下USB摄像头驱动开发以OV511为例附带全部源代码以及讲解

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

WindowsCE.netUSB摄像头驱动开发(初步)型号:OminivisionOV511+(USB-CameraBridge)摄像头型号网眼Webeye2000VID0x05A9PID0xA511输出格式:RAW-YUV等USB驱动程序的功能1.通过对WindowsCE.net提供的USBD等函数的调用,控制设备以及读取设备数据;2.外加的摄像头做成流接口驱动比较方便,驱动程序要向系统注册设备接口,和应用程序交互。OV511+芯片的控制依据OV511的Datasheet,里面有10h到49h这样57个寄存器,通过对这些积存器赋值,就能够对CameraInterface、DRAMInterface和ISOFIFO等进行设置。通过端点0进行控制传输,就可以读写这些寄存器,在Linux下,使用usb_control_msg函数(无URB的传输)。后面将讲解如何在WindowsCE.net下实现。/*WriteanOV51xregister*/staticintreg_w(structusb_ov511*ov,unsignedcharreg,unsignedcharvalue){…rc=usb_control_msg(ov-dev,usb_sndctrlpipe(ov-dev,0),(ov-bclass==BCL_OV518)?1:2/*REG_IO*/,USB_TYPE_VENDOR|USB_RECIP_DEVICE,0,(__u16)reg,&ov-cbuf[0],1,HZ);…开发工具测试系统为WindowsCE.net4.2,驱动程序形式为流接口驱动,基本框架是一个dll动态连接库。使用EmbeddedVisualC++4.0或者PlatformBuilder4.2都可以编译,推荐使用EVC,EVC用起来比较快,只要将调用USB函数需要的头文件以及Lib文件的路径设置好就可以。开发板的硬件配置为SamsungARM9S3C2410,故连接的Lib为ArmV4Release版本的usbclient.lib。流接口USB驱动程序步骤:1.建立一个WCEDynamic-LinkLibrary;2.书写一个Exportdef文件(不是必要的,有这个可以保证符号的导出),输出各个驱动需要的函数符号;3.依据USB驱动加载的流程,添加完成各个函数,并进行测试……第一部分使驱动程序能够被加载这部分,将填写USBInstallDriverUSBDeviceAttachUSBUnInstallDriverCAM_InitCAM_Deinit这些函数正确填写之后,驱动程序就可以加载了。WindowsCE.net下流接口USB驱动程序加载的流程1.设备插入后,系统在取得VID/PID后将自动在注册表中寻找是否有这一项,如果没有,则出现提示输入设备名称对话框;2.依据注册表或者输入名称找到驱动程序dll文件后,将首先调用USBInstallDriver函数,该函数使用USBD.dll中的函数注册设备,并依据VID/PID设置注册表项,这样在这个项不丢失的时候,下次插入将能够自动找到,如果这个函数的VID/PID和实际设备不符,将返回失败;3.USBInstallDriver成功之后,系统才调用USBDeviceAttach函数;WindowsCE.net下流接口USB驱动程序加载的流程4.对于USB设备,在USBDeviceAttach函数中,主要进行3个工作:(1)USB设备接口配置的枚举和保存,备后面传输工作使用;(2)调用ActiveDevice函数激活一个流接口,使应用程序可以和驱动交互;(3)调用RegisterNotificationRoutine函数注册一个设备状态回调函数,这里被注册的函数的主要功能是在设备移除时通知驱动程序停止设备,释放占用的资源;5.ActiveDevice函数调用的时候,依据参数lpszDevKey找到驱动程序文件,在注册表的HKEY_LOCAL_MACHINE\Drivers\Active键中增加这个设备,并且将USB驱动程序的上下文指针放到这里(即该函数的第2个参数),并且指定一个索引(设备序号),将驱动程序加载到DeviceManager的进程空间。这时DeviceManager将发送一个新设备插入的消息,调用该流接口驱动的CAM_Init函数;WindowsCE.net下流接口USB驱动程序加载的流程6.接着CAM_Init函数被调用,参数就是ActiveDevice函数的参数1,然后依据这个参数,在注册表中找到USB驱动程序的上下文,并返回,这样对该流接口驱动的操作,就可以找到USB驱动的上下文,并且交换数据。以上这些工作完成之后,USB设备的信息被保存,并且USB驱动程序上下文也被流接口驱动所记载。流接口USB驱动的加载完成。我们就看见那个输入驱动程序名称的对话框消失了。如果前面6个步骤中任何一步不成功,将不会使用这个驱动程序,会反复弹出这个对话框,提示输入驱动程序名称,直到这些过程全部正确完成。驱动加载完成后,用户程序再用CreateFile打开设备的时候,将返回驱动程序上下文给用户程序,这样用户程序和驱动就可以交互了,并且这个驱动程序上下文是含有该USB设备相关信息的,所以,可以使用USBD函数来操作USB设备,并且将USB设备的数据返回给应用程序。WindowsCE.net下流接口USB驱动程序卸载的流程在加载的时候,我们已经注册了USBDeviceNotification回调函数,在USB设备移除的时候,将调用这个函数。注册回调时候使用的函数lpRegisterNotificationRoutine的第3个参数是驱动程序上下文指针,就是在调用这个回调函数时候的参数。USBDeviceNotification传入的参数是驱动程序上下文,我们依据这个就可以向设备发送信息以停止设备,停止驱动程序正在进行的线程,关闭事件、临界区等信号,释放申请的内存。这样,就完成了驱动程序的卸载。对于流接口驱动,在卸载的时候会调用CAM_Deinit函数,这个函数的参数也是驱动程序上下文,我们也可以在这里完成资源释放工作,这里选择在USBDeviceNotification释放,所以CAM_Deinit就不用填写了。再设备资源释放之后,将调用USB_UninstallDriver函数,使用USBD里面的操作注册表的函数清理注册表中添加的HKEY_LOCAL_MACHINE\Drivers\Active中的项目。注意:USB驱动程序不通过注册表API来操作注册表,而是通过USBD提供的函数。第二部分保存USB设备的信息在第一部分,有一个函数尚未填写完成,USBDeviceAttach函数中的第一个工作——USB设备接口配置的枚举和保存。这个主要和USB规范,以及OV511+的规格相关,所以在这个部分单独讲解。WindowsCE.net下USB设备接口的枚举和保存USB协议本身很复杂,但方便在提供了统一的接口方式,使得驱动程序在使用设备的时候,工作简化到了类似操作串行接口。USB设备可以看作提供了多个串口的设备,依据USB的规范,我们将每个串口称作端点(Endpoint),要和这个端点通信,我们就要打开到这个端点的连接,这个连接就是管道(Pipe)。USB主设备USB从设备端点管道WindowsCE.net下USB设备接口的枚举和保存打开端点之后,就可以像串口一样进行数据传输了。USB有4种不同类型的传输方式:控制传输(ControlTransfer),批量传输(BulkTransfer),中断传输(InterruptTransfer)和实时传输(IsochTransfer)。对应每种传输,WindowsCE.net下都提供了函数。WindowsCE.net下USB设备接口的枚举和保存由于一个设备可能要适应多种情况,端点的设置会有多套,以备使用。端点设置称为接口(Interface)。USB设备展现给我们能够找到的东西就是这些Interface,我们选择要用的Interface,就可以找到Endpoint,再打开Endpoint,就可以传输数据了。所以,在驱动程序开始的时候,需要记录下这些Interface。OV511+的端点0是控制端点,用来设置参数以及起停设备;端点1是实时传输端点,用来传输视频。端点1有8套不同的设置,主要区别就在于一次传输的数据帧的大小,所以在USBDeviceAttach的时候,要记录这些设置到驱动程序中,后面才能够选用。WindowsCE.net下USB设备接口的枚举和保存USBDeviceAttach函数传入的第一个参数LPCUSB_DEVICElpUsbDev,里面就包含了这些设置信息,OV511+芯片在这里就有8个Interface,通过lpUsbDev指针,把这8个Interface的内容读出来,存到驱动程序的变量中,这个工作就完成了。后面,传输视频的时候,就从驱动程序变量中选择一个Interface,然后依据这个Interface,就找到了端点,接着就可以打开管道,传输数据了。WindowsCE.net下USB设备接口的枚举和保存OV511+这8个Interface设置见DatasheetUSBDeviceAttach函数中,通过ParseStreamInterfaces函数来保存这些Interface。详细内容的参见代码。主要结构如下:for(i=0;ilpUsbDev-lpConfigs-dwNumInterfaces;i++){lpIF=&lpUsbDev-lpConfigs-lpInterfaces[i];if((lpIF-Descriptor.bInterfaceClass==bIFStrm)&&(lpIF-Descriptor.bInterfaceSubClass==bIFSubStrm)){//保存接口}}其中dwNumInterfaces为折纸总数,lpInterfaces[i]存放的就是设置的内容,本身是一个复杂的结构体,里面有描述端点等信息的相关内容。OV511+的InterfaceClass值为0xff,InterfaceSubClass值为0xff(见Datasheet)。第三部分控制OV511OV511通过端点0来控制其寄存器。Linux中,写寄存器函数如下:/*WriteanOV51xregister*/staticintreg_w(structusb_ov511*ov,unsignedcharreg,unsignedcharvalue){…rc=usb_control_msg(ov-dev,usb_sndctrlpipe(ov-dev,0),(ov-bclass==BCL_OV518)?1:2/*REG_IO*/,USB_TYPE_VENDOR|USB_RECIP_DEVICE,0,(__u16)reg,&ov-cbuf[0],1,HZ);…这部分讲解如何在WindowsCE.net下实现一样的功能。WindowsCE.net的控制传输查看MSDN,IssueControlTransfer和IssueVendorTransfer是用来进行控制传输的,但两个函数有什么区别呢?看MSDN,IssueControlTransfer的第一个参数是hPipe,就是说,在使用IssueControlTransfer之前,必须用OpenPipe打开管道。OpenPipe函数需要端点描述作为参数。但是,端点0是没有这个描述可以用的(MSDN:However,endpointzero(0)neverhasaUSB_ENDPOINTstructure)。我没测试自己指定描述是否可以,但是,IssueVendorTransfer提供了更为方便的途径。这个函数默认从端点0进行控制传输。如果是其他端点的控制传输,是要用IssueControlTransfer的。WindowsCE.net下读写控制管道0这样,WindowsCE.

1 / 31
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功