31
Windows CE.net USB Windows CE.net USB 摄摄摄摄摄摄摄 摄摄摄摄摄摄摄 ( ( 摄摄 摄摄 ) ) 摄摄 摄摄 :Ominivision OV511+ :Ominivision OV511+ (USB-Camera Bridge) (USB-Camera Bridge)

Windows CE USB 摄像头驱动开发 ( 初步 )

  • Upload
    tillie

  • View
    146

  • Download
    9

Embed Size (px)

DESCRIPTION

Windows CE.net USB 摄像头驱动开发 ( 初步 ). 型号 :Ominivision OV511+ (USB-Camera Bridge). 摄像头型号. 网眼 Webeye 2000 VID 0x05A9 PID 0xA511 输出格式: RAW-YUV 等. USB 驱动程序的功能. 1. 通过对 Windows CE.net 提供的 USBD 等函数的调用,控制设备以及读取设备数据; 2. 外加的摄像头做成流接口驱动比较方便,驱动程序要向系统注册设备接口,和应用程序交互。. OV511+ 芯片的控制. - PowerPoint PPT Presentation

Citation preview

Page 1: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.net USBWindows CE.net USB摄像头驱动开发摄像头驱动开发 (( 初步初步 ))

型号型号 :Ominivision OV511+:Ominivision OV511+(USB-Camera Bridge)(USB-Camera Bridge)

Page 2: Windows CE USB 摄像头驱动开发 ( 初步 )

摄像头型号摄像头型号

网眼 网眼 Webeye 2000Webeye 2000VID 0x05A9VID 0x05A9PID 0xA511PID 0xA511输出格式:输出格式: RAW-YUVRAW-YUV 等等

Page 3: Windows CE USB 摄像头驱动开发 ( 初步 )

USBUSB 驱动程序的功能驱动程序的功能1.1. 通过对通过对 Windows CE.netWindows CE.net 提供的提供的 USBDUSBD 等等函数的调用,控制设备以及读取设备数据;函数的调用,控制设备以及读取设备数据;2.2. 外加的摄像头做成流接口驱动比较方便,外加的摄像头做成流接口驱动比较方便,驱动程序要向系统注册设备接口,和应用驱动程序要向系统注册设备接口,和应用程序交互。程序交互。

Page 4: Windows CE USB 摄像头驱动开发 ( 初步 )

OV511+OV511+ 芯片的控制芯片的控制 依据依据 OV511OV511 的的 DatasheetDatasheet ,里面有,里面有 10h10h 到到 49h49h 这样这样 5757个寄存器,通过对这些积存器赋值,就能够对个寄存器,通过对这些积存器赋值,就能够对 Camera InCamera Interfaceterface 、、 DRAM InterfaceDRAM Interface 和和 ISO FIFOISO FIFO 等进行设置。等进行设置。 通过端点通过端点 00 进行控制传输,就可以读写这些寄存器,在进行控制传输,就可以读写这些寄存器,在LinuxLinux 下,使用下,使用 usb_control_msgusb_control_msg 函数(无函数(无 URBURB 的传的传输)。后面将讲解如何在输)。后面将讲解如何在 Windows CE.netWindows CE.net 下实现。下实现。 /* Write an OV51x register *//* Write an OV51x register */ static int reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)static int reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value) {{ …… rc = usb_control_msg(ov->dev,usb_sndctrlpipe(ov->dev, 0),(ov->bclass == BCL_rc = usb_control_msg(ov->dev,usb_sndctrlpipe(ov->dev, 0),(ov->bclass == BCL_OV518)?1:2 /* REG_IO */,OV518)?1:2 /* REG_IO */, USB_TYPE_VENDOR | USB_RE USB_TYPE_VENDOR | USB_RECIP_DEVICE,0, (__u16)reg, &ov->cbuf[0], 1, HZ);CIP_DEVICE,0, (__u16)reg, &ov->cbuf[0], 1, HZ); … …

Page 5: Windows CE USB 摄像头驱动开发 ( 初步 )

开发工具开发工具 测试系统为测试系统为 Windows CE.net 4.2Windows CE.net 4.2 ,驱动程序,驱动程序形式为流接口驱动,基本框架是一个形式为流接口驱动,基本框架是一个 dlldll 动态连接动态连接库。库。 使用使用 Embedded Visual C++ 4.0Embedded Visual C++ 4.0 或者或者 Platform Platform Builder 4.2Builder 4.2 都可以编译,推荐使用都可以编译,推荐使用 EVCEVC ,, EVCEVC用起来比较快,只要将调用用起来比较快,只要将调用 USBUSB 函数需要的头文函数需要的头文件以及件以及 LibLib 文件的路径设置好就可以。文件的路径设置好就可以。 开发板的硬件配置为开发板的硬件配置为 Samsung ARM9 S3C2410Samsung ARM9 S3C2410 ,,故连接的故连接的 LibLib 为为 ArmV4ReleaseArmV4Release 版本的版本的 usbclient.usbclient.liblib 。。

Page 6: Windows CE USB 摄像头驱动开发 ( 初步 )

流接口流接口 USBUSB 驱动程序驱动程序步骤:步骤: 1.1. 建立一个建立一个 WCE Dynamic-Link LibraryWCE Dynamic-Link Library ;; 2.2. 书写一个书写一个 Export defExport def 文件文件 (( 不是必要的,有这不是必要的,有这个可以保证符号的导出个可以保证符号的导出 )) ,输出各个驱动需要的,输出各个驱动需要的函数符号;函数符号; 3.3. 依据依据 USBUSB 驱动加载的流程,添加完成各个函数,驱动加载的流程,添加完成各个函数,并进行测试……并进行测试……

Page 7: Windows CE USB 摄像头驱动开发 ( 初步 )

第一部分 使驱动程序能够被加载第一部分 使驱动程序能够被加载 这部分,将填写这部分,将填写 USBInstallDriverUSBInstallDriver USBDeviceAttachUSBDeviceAttach USBUnInstallDriverUSBUnInstallDriver CAM_InitCAM_Init CAM_DeinitCAM_Deinit 这些函数正确填写之后,驱动程序就可以加载这些函数正确填写之后,驱动程序就可以加载了。了。

Page 8: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下流接口流接口 USBUSB 驱动程序加载的流程驱动程序加载的流程 1.1. 设备插入后,系统在取得设备插入后,系统在取得 VID/PIDVID/PID 后将自动后将自动在注册表中寻找是否有这一项,如果没有,则出在注册表中寻找是否有这一项,如果没有,则出现提示输入设备名称对话框;现提示输入设备名称对话框; 2. 2. 依据注册表或者输入名称找到驱动程序依据注册表或者输入名称找到驱动程序 dlldll文件后,将首先调用文件后,将首先调用 USBInstallDriverUSBInstallDriver 函数,该函数,该函数使用函数使用 USBD.dllUSBD.dll 中的函数注册设备,并依据中的函数注册设备,并依据 VVID/PIDID/PID 设置注册表项,这样在这个项不丢失的时设置注册表项,这样在这个项不丢失的时候,下次插入将能够自动找到,如果这个函数的候,下次插入将能够自动找到,如果这个函数的VID/PIDVID/PID 和实际设备不符,将返回失败;和实际设备不符,将返回失败; 3.USBInstallDriver3.USBInstallDriver 成功之后,系统才调用成功之后,系统才调用 USUSBDeviceAttachBDeviceAttach 函数;函数;

Page 9: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下流接口流接口 USBUSB 驱动程序加载的流程驱动程序加载的流程 4.4. 对于对于 USBUSB 设备,在设备,在 USBDeviceAttachUSBDeviceAttach 函数中,主要进行函数中,主要进行 33 个个工作:工作: (1)USB(1)USB 设备接口配置的枚举和保存,备后面传输工作使用;设备接口配置的枚举和保存,备后面传输工作使用;(2)(2) 调用调用 ActiveDeviceActiveDevice 函数激活一个流接口,使应用程序可以和驱函数激活一个流接口,使应用程序可以和驱动交互;动交互; (3)(3) 调用调用 RegisterNotificationRoutineRegisterNotificationRoutine 函数注册一个设函数注册一个设备状态回调函数,这里被注册的函数的主要功能是在设备移除时通备状态回调函数,这里被注册的函数的主要功能是在设备移除时通知驱动程序停止设备,释放占用的资源;知驱动程序停止设备,释放占用的资源; 5.ActiveDevice5.ActiveDevice 函数调用的时候,依据参数函数调用的时候,依据参数 lpszDevKeylpszDevKey 找到驱找到驱动程序文件,在注册表的动程序文件,在注册表的 HKEY_LOCAL_MACHINE\Drivers\ActivHKEY_LOCAL_MACHINE\Drivers\Activee键中增加这个设备,并且将键中增加这个设备,并且将 USBUSB 驱动程序的上下文指针放到这驱动程序的上下文指针放到这里里 ((即该函数的第即该函数的第 22 个参数个参数 )) ,并且指定一个索引,并且指定一个索引 (( 设备序号设备序号 )) ,,将驱动程序加载到将驱动程序加载到 Device ManagerDevice Manager 的进程空间。这时的进程空间。这时 Device MaDevice Managernager 将发送一个新设备插入的消息,调用该流接口驱动的将发送一个新设备插入的消息,调用该流接口驱动的 CAM_ICAM_Initnit 函数;函数;

Page 10: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下流接口流接口 USBUSB 驱动程序加载的流程驱动程序加载的流程 6.6. 接着接着 CAM_InitCAM_Init 函数被调用,参数就是函数被调用,参数就是 ActiveDeviceActiveDevice 函数的参函数的参数数 11 ,然后依据这个参数,在注册表中找到,然后依据这个参数,在注册表中找到 USBUSB 驱动程序的上下驱动程序的上下文,并返回,这样对该流接口驱动的操作,就可以找到文,并返回,这样对该流接口驱动的操作,就可以找到 USBUSB 驱动驱动的上下文,并且交换数据。的上下文,并且交换数据。 以上这些工作完成之后,以上这些工作完成之后, USBUSB 设备的信息被保存,并且设备的信息被保存,并且 USBUSB 驱驱动程序上下文也被流接口驱动所记载。流接口动程序上下文也被流接口驱动所记载。流接口 USBUSB 驱动的加载完驱动的加载完成。我们就看见那个输入驱动程序名称的对话框消失了。如果前面成。我们就看见那个输入驱动程序名称的对话框消失了。如果前面66 个步骤中任何一步不成功,将不会使用这个驱动程序,会反复弹个步骤中任何一步不成功,将不会使用这个驱动程序,会反复弹出这个对话框,提示输入驱动程序名称,直到这些过程全部正确完出这个对话框,提示输入驱动程序名称,直到这些过程全部正确完成。成。 驱动加载完成后,用户程序再用驱动加载完成后,用户程序再用 CreateFileCreateFile 打开设备的时打开设备的时候,将返回驱动程序上下文给用户程序,这样用户程序和驱候,将返回驱动程序上下文给用户程序,这样用户程序和驱动就可以交互了,并且这个驱动程序上下文是含有该动就可以交互了,并且这个驱动程序上下文是含有该 USBUSB 设设备相关信息的,所以,可以使用备相关信息的,所以,可以使用 USBDUSBD 函数来操作函数来操作 USBUSB 设备,设备,并且将并且将 USBUSB 设备的数据返回给应用程序。 设备的数据返回给应用程序。

Page 11: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下流接口流接口 USBUSB 驱动程序卸载的流程驱动程序卸载的流程 在加载的时候,我们已经注册了在加载的时候,我们已经注册了 USBDeviceNotificationUSBDeviceNotification回调函数,在回调函数,在 USBUSB 设设备移除的时候,将调用这个函数。注册回调时候使用的函数备移除的时候,将调用这个函数。注册回调时候使用的函数 lpRegisterNotificatilpRegisterNotificationRoutineonRoutine 的第的第 33 个参数是驱动程序上下文指针,就是在调用这个回调函数时候个参数是驱动程序上下文指针,就是在调用这个回调函数时候的参数。的参数。 USBDeviceNotificationUSBDeviceNotification 传入的参数是驱动程序上下文,我们依据这个就可以传入的参数是驱动程序上下文,我们依据这个就可以向设备发送信息以停止设备,停止驱动程序正在进行的线程,关闭事件、临界区向设备发送信息以停止设备,停止驱动程序正在进行的线程,关闭事件、临界区等信号,释放申请的内存。这样,就完成了驱动程序的卸载。等信号,释放申请的内存。这样,就完成了驱动程序的卸载。 对于流接口驱动,在卸载的时候会调用对于流接口驱动,在卸载的时候会调用 CAM_DeinitCAM_Deinit 函数,这个函数的参数也函数,这个函数的参数也是驱动程序上下文,我们也可以在这里完成资源释放工作,这里选择在是驱动程序上下文,我们也可以在这里完成资源释放工作,这里选择在 USBDeviUSBDeviceNotificationceNotification释放,所以释放,所以 CAM_DeinitCAM_Deinit 就不用填写了。就不用填写了。 再设备资源释放之后,将调用再设备资源释放之后,将调用 USB_UninstallDriverUSB_UninstallDriver 函数,使用函数,使用 USBDUSBD 里面的里面的操作注册表的函数清理注册表中添加的操作注册表的函数清理注册表中添加的 HKEY_LOCAL_MACHINE\Drivers\AcHKEY_LOCAL_MACHINE\Drivers\Activetive 中的项目。中的项目。 注意:注意: USBUSB 驱动程序不通过注册表驱动程序不通过注册表 APIAPI 来操作注册表,而是通过来操作注册表,而是通过 USBUSBDD 提供的函数。提供的函数。

Page 12: Windows CE USB 摄像头驱动开发 ( 初步 )

第二部分 保存第二部分 保存 USBUSB 设备的信息设备的信息 在第一部分,有一个函数尚未填写完成,在第一部分,有一个函数尚未填写完成, USBUSBDeviceAttachDeviceAttach 函数中的第一个工作——函数中的第一个工作—— USBUSB 设备设备接口配置的枚举和保存。接口配置的枚举和保存。 这个主要和这个主要和 USBUSB 规范,以及规范,以及 OV511+OV511+ 的规格相关,的规格相关,所以在这个部分单独讲解。所以在这个部分单独讲解。

Page 13: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下USBUSB 设备接口的枚举和保存设备接口的枚举和保存

USBUSB 协议本身很复杂,但方便在提供了统一的接口方式,使得驱动程序在使用协议本身很复杂,但方便在提供了统一的接口方式,使得驱动程序在使用设备的时候,工作简化到了类似操作串行接口。设备的时候,工作简化到了类似操作串行接口。 USBUSB 设备可以看作提供了多个串口的设备,依据设备可以看作提供了多个串口的设备,依据 USBUSB 的规范,我们将每个串口的规范,我们将每个串口称作端点称作端点 (Endpoint)(Endpoint) ,要和这个端点通信,我们就要打开到这个端点的连接,这,要和这个端点通信,我们就要打开到这个端点的连接,这个连接就是管道个连接就是管道 (Pipe)(Pipe) 。。

USB主设备

USB从设备

端点管道

Page 14: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下USBUSB 设备接口的枚举和保存设备接口的枚举和保存

打开端点之后,就可以像串口一样进行数据传输打开端点之后,就可以像串口一样进行数据传输了。了。 USBUSB 有有 44种不同类型的传输方式:控制传输种不同类型的传输方式:控制传输 (C(Control Transfer)ontrol Transfer) ,批量传输,批量传输 (Bulk Transfer)(Bulk Transfer) ,中,中断传输断传输 (Interrupt Transfer)(Interrupt Transfer) 和实时传输和实时传输((IsochTransferIsochTransfer)) 。。

对应每种传输, 对应每种传输, Windows CE.netWindows CE.net 下都提供了函下都提供了函数。数。

Page 15: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下USBUSB 设备接口的枚举和保存设备接口的枚举和保存

由于一个设备可能要适应多种情况,端点的设置会有多套,由于一个设备可能要适应多种情况,端点的设置会有多套,以备使用。端点设置称为接口以备使用。端点设置称为接口 (Interface)(Interface) 。。 USBUSB 设备展现设备展现给我们能够找到的东西就是这些给我们能够找到的东西就是这些 InterfaceInterface ,我们选择要用,我们选择要用的的 InterfaceInterface ,就可以找到,就可以找到 EndpointEndpoint ,再打开,再打开 EndpointEndpoint ,,就可以传输数据了。所以,在驱动程序开始的时候,需要记就可以传输数据了。所以,在驱动程序开始的时候,需要记录下这些录下这些 InterfaceInterface 。。 OV511+OV511+ 的端点的端点 00 是控制端点,用来设置参数以及起停设备;是控制端点,用来设置参数以及起停设备;端点端点 11 是实时传输端点,用来传输视频。是实时传输端点,用来传输视频。 端点端点 11 有有 88套不同的设置,主要区别就在于一次传输的数套不同的设置,主要区别就在于一次传输的数据帧的大小,所以在据帧的大小,所以在 USBDeviceAttachUSBDeviceAttach 的时候,要记录这些的时候,要记录这些设置到驱动程序中,后面才能够选用。设置到驱动程序中,后面才能够选用。

Page 16: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下USBUSB 设备接口的枚举和保存设备接口的枚举和保存

USBDeviceAttachUSBDeviceAttach 函数传入的第一个参数函数传入的第一个参数 LPCUSLPCUSB_DEVICE lpUsbDevB_DEVICE lpUsbDev ,里面就包含了这些设置信息,,里面就包含了这些设置信息,OV511+OV511+ 芯片在这里就有芯片在这里就有 88 个个 InterfaceInterface ,通过,通过 lpUslpUsbDevbDev指针,把这指针,把这 88 个个 InterfaceInterface 的内容读出来,存的内容读出来,存到驱动程序的变量中,这个工作就完成了。到驱动程序的变量中,这个工作就完成了。 后面,传输视频的时候,就从驱动程序变量中选后面,传输视频的时候,就从驱动程序变量中选择一个择一个 InterfaceInterface ,然后依据这个,然后依据这个 InterfaceInterface ,就找,就找到了端点,接着就可以打开管道,传输数据了。到了端点,接着就可以打开管道,传输数据了。

Page 17: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下下USBUSB 设备接口的枚举和保存设备接口的枚举和保存

OV511+OV511+ 这这 88 个个 InterfaceInterface 设置见设置见 DatasheetDatasheet USBDeviceAttachUSBDeviceAttach 函数中,通过函数中,通过 ParseStreamInterfacesParseStreamInterfaces 函数来保存函数来保存这些这些 InterfaceInterface 。详细内容的参见代码。。详细内容的参见代码。 主要结构如下主要结构如下 :: for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++)for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++) {{ lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];if ((lpIF->Descriptor.bInterfaceClass == bIFStrm) && (lpIF->Descriptor.bInterfaceSubClass == bIFSubStif ((lpIF->Descriptor.bInterfaceClass == bIFStrm) && (lpIF->Descriptor.bInterfaceSubClass == bIFSubStrm))rm)) {{ //// 保存接口保存接口}} }} 其中其中 dwNumInterfacesdwNumInterfaces 为折纸总数,为折纸总数, lpInterfaces[i]lpInterfaces[i] 存放的就是设置存放的就是设置的内容,本身是一个复杂的结构体,里面有描述端点等信息的相关内容。的内容,本身是一个复杂的结构体,里面有描述端点等信息的相关内容。OV511+OV511+ 的的 InterfaceClassInterfaceClass 值为值为 0xff0xff,, InterfaceSubClassInterfaceSubClass 值为值为 0xff(0xff(见见Datasheet)Datasheet) 。。

Page 18: Windows CE USB 摄像头驱动开发 ( 初步 )

第三部分 控制第三部分 控制 OV511OV511

OV511OV511 通过端点通过端点 00 来控制其寄存器。来控制其寄存器。 LinuxLinux 中,写寄存器函数如下:中,写寄存器函数如下: /* Write an OV51x register *//* Write an OV51x register */ static int reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned chastatic int reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)r value) {{ …… rc = usb_control_msg(ov->dev,usb_sndctrlpipe(ov->dev, 0),(ov->bclarc = usb_control_msg(ov->dev,usb_sndctrlpipe(ov->dev, 0),(ov->bclass == BCL_OV518)?1:2 /* REG_IO */,ss == BCL_OV518)?1:2 /* REG_IO */, USB_TYP USB_TYPE_VENDOR | USB_RECIP_DEVICE,0, (__u16)reg, &ov->cbuf[0], 1, HZ);E_VENDOR | USB_RECIP_DEVICE,0, (__u16)reg, &ov->cbuf[0], 1, HZ); … … 这部分讲解如何在这部分讲解如何在 Windows CE.netWindows CE.net 下实现一下实现一样的功能。样的功能。

Page 19: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 的控制传输的控制传输 查看查看 MSDNMSDN ,, IssueControlTransferIssueControlTransfer 和和 IssueVendorTraIssueVendorTransfernsfer 是用来进行控制传输的,但两个函数有什么区别呢? 是用来进行控制传输的,但两个函数有什么区别呢? 看看 MSDNMSDN ,, IssueControlTransferIssueControlTransfer 的第一个参数是的第一个参数是 hPipehPipe ,,就是说,在使用就是说,在使用 IssueControlTransferIssueControlTransfer 之前,必须用之前,必须用 OpenOpenPipePipe打开管道。打开管道。 OpenPipeOpenPipe 函数需要端点描述作为参数。但是,端点函数需要端点描述作为参数。但是,端点 00 是没是没有这个描述可以用的有这个描述可以用的 (MSDN:(MSDN: However, endpoint zero However, endpoint zero

(0) never has a USB_ENDPOINT structure(0) never has a USB_ENDPOINT structure)) 。。 我没测试自己指定描述是否可以,但是,我没测试自己指定描述是否可以,但是, IssueVendorTraIssueVendorTransfernsfer 提供了更为方便的途径。这个函数默认从端点提供了更为方便的途径。这个函数默认从端点 00 进行控进行控制传输。制传输。 如果是其他端点的控制传输,是要用如果是其他端点的控制传输,是要用 IssueControlTransfIssueControlTransferer 的。的。

Page 20: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下读写控制管道下读写控制管道 00 这样,这样, Windows CE.netWindows CE.net 写寄存器代码如下:写寄存器代码如下:int RegisterWrite(PDRVCONTEXT pDrv, unsigned char reg, unsigned char value)int RegisterWrite(PDRVCONTEXT pDrv, unsigned char reg, unsigned char value){{

USB_DEVICE_REQUEST req;USB_DEVICE_REQUEST req;......// Get our pdd specific context// Get our pdd specific contextPDEVICECONTEXT pPDD = (PDEVICECONTEXT)pDrv->dwDeviceContext; PDEVICECONTEXT pPDD = (PDEVICECONTEXT)pDrv->dwDeviceContext;

req.bmRequestType = USB_TYPE_VENDOR | USB_RECIP_DEVICE;req.bmRequestType = USB_TYPE_VENDOR | USB_RECIP_DEVICE;

req.bRequest = 2;req.bRequest = 2;req.wValue = 0;req.wValue = 0;req.wIndex = (USHORT)reg;req.wIndex = (USHORT)reg;req.wLength = 1;req.wLength = 1;

unsigned char buf=value;unsigned char buf=value;

dwBytes = 0;dwBytes = 0;dwErr = USB_NO_ERROR;dwErr = USB_NO_ERROR;dw = IssueVendorTransfer (pDrv->lpUsbFuncs, pDrv->hDevice, DefaultTransferComplete, pPDD->hVendordw = IssueVendorTransfer (pDrv->lpUsbFuncs, pDrv->hDevice, DefaultTransferComplete, pPDD->hVendorEvent,Event, USB_OUT_TRANSFER | USB_SHORT_TRANSFER_OK,&req, &buf, NULL, &dwBytes, 2000, &dwErr);USB_OUT_TRANSFER | USB_SHORT_TRANSFER_OK,&req, &buf, NULL, &dwBytes, 2000, &dwErr);......

}}

Page 21: Windows CE USB 摄像头驱动开发 ( 初步 )

第四部分 读取第四部分 读取 OV511OV511视频数据视频数据 第二部分,已经保存了第二部分,已经保存了 OV511OV511 的视频接口,现的视频接口,现在,是用的时候了。在,是用的时候了。 LinuxLinux 下,实时传输通过创建下,实时传输通过创建 URBURB ,提交到,提交到 USUSBB 传送队列来完成实时传输。传送队列来完成实时传输。 Windows CE.netWindows CE.net 下,下, URBURB 不用我们自己创建,不用我们自己创建,只要准备好数据缓冲,使用只要准备好数据缓冲,使用 IssueIsochTransferIssueIsochTransfer函数,系统就帮我们完成了这个过程。函数,系统就帮我们完成了这个过程。

Page 22: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 先看先看 LinuxLinux 下的过程下的过程

Page 23: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 LinuxLinux 下通过填写一系列下通过填写一系列 URBURB 包,在包中包,在包中指定传输参数,数据缓冲,最后指定传输参数,数据缓冲,最后 usb_submitusb_submit_urb_urb 将这些将这些 URBURB 提交到系统的提交到系统的 USBUSB 数据队数据队列。列。 Windows CE.netWindows CE.net 的的 USBDUSBD 层以下完成层以下完成 USUSBB 数据队列的功能,而呈现给驱动程序使用的数据队列的功能,而呈现给驱动程序使用的函数就是函数就是 IssueIsochTransferIssueIsochTransfer 。。

Page 24: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 IssueIsochTransferIssueIsochTransfer 函数需要的参数之一函数需要的参数之一为为 USB_PIPEUSB_PIPE ,所以,在进行传输之前,先,所以,在进行传输之前,先要打开对应端点的管道。要打开对应端点的管道。 在在 USBDeviceAttachUSBDeviceAttach 的时候,已经保存了的时候,已经保存了这个设备的若干这个设备的若干 InterfaceInterface 接口接口 ((包含了端点包含了端点设置的信息设置的信息 )) ,打开管道,就是选择一个,打开管道,就是选择一个 InteInterfacerface ,找到端点描述符,然后,找到端点描述符,然后 OpenPipeOpenPipe 。。 这个部分的代码在程序的这个部分的代码在程序的 SetStreamInterfSetStreamInterfaceace 函数中。函数中。

Page 25: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 IssueIsochTransferIssueIsochTransfer 函数需要的参数之一为函数需要的参数之一为 USB_USB_PIPEPIPE ,所以,在进行传输之前,先要设置接口,所以,在进行传输之前,先要设置接口 (SetI(SetInterface)nterface) ,并且打开到对应端点的管道,并且打开到对应端点的管道 (OpenPip(OpenPipe)e) 。。 在在 USBDeviceAttachUSBDeviceAttach 的时候,已经保存了这个设的时候,已经保存了这个设备的若干备的若干 InterfaceInterface 接口接口 ((包含了端点设置的信息包含了端点设置的信息 )) 。。依据这个信息,使用依据这个信息,使用 SetInterfaceSetInterface 设置接口设置接口 ,,选择选择一个一个 Interface Interface ;使用;使用 OpenPipeOpenPipe打开管道,依据打开管道,依据选择的选择的 InterfaceInterface 找到端点描述符,然后找到端点描述符,然后 OpenPipeOpenPipe 。。 这个部分的代码在程序的这个部分的代码在程序的 SetStreamInterfaceSetStreamInterface 函函数中。数中。

Page 26: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 设置接口和打开管道完成之后,就可以进设置接口和打开管道完成之后,就可以进行实时传输了。行实时传输了。 这个程序里面这个程序里面 IssueIsochTransferIssueIsochTransfer 是来源是来源于微软的一个例子程序,这个函数是仿照于微软的一个例子程序,这个函数是仿照 usbusbclient.cppclient.cpp 里面的里面的 IssueVendorTransferIssueVendorTransfer 写写出来的。出来的。

Page 27: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 和和 LinuxLinux 下类似,首先要准备足够的缓冲,这里下类似,首先要准备足够的缓冲,这里只做了每次传输只做了每次传输 961961字节,一次字节,一次 IssueIsochTransfeIssueIsochTransferr 传输传输 1010次这样的编写。因为实时传输的帧本身也次这样的编写。因为实时传输的帧本身也包含丰富的信息和设置工作。这里先不做深入的讨包含丰富的信息和设置工作。这里先不做深入的讨论,只从论,只从 OV511OV511 的角度来讲一些使用。的角度来讲一些使用。 在程序的在程序的 Ov51xReadOneFrameOv51xReadOneFrame 函数中,函数中, pDatapDataBuffBuff 申请了申请了 96109610字节的空间,字节的空间, dwFrameLen[10]dwFrameLen[10]为为 1010次传输每次的长度,这里都设置为次传输每次的长度,这里都设置为 961961 。实测。实测的时候并不是每次传输都能够有的时候并不是每次传输都能够有 96109610字节的。这个字节的。这个问题可以放到后面的应用程序中处理。问题可以放到后面的应用程序中处理。

Page 28: Windows CE USB 摄像头驱动开发 ( 初步 )

Windows CE.netWindows CE.net 下的实时传输下的实时传输 在在 IssueIsochTransferIssueIsochTransfer 中,中, pUsbFuncs->lpIssupUsbFuncs->lpIssueIsochTransfereIsochTransfer 可能是同步或者异步的。可能是同步或者异步的。 对于同步的情况,不用判断是否传输超时,直接对于同步的情况,不用判断是否传输超时,直接用用 GetIsochResultsGetIsochResults 来取得传输结果,然后统计传来取得传输结果,然后统计传输的字节数等数据。输的字节数等数据。 NotifyContextNotifyContext 和和 NotifyRoutineNotifyRoutine指定的情况下,指定的情况下,是异步的,在调用后会立即返回,我们要等待传输是异步的,在调用后会立即返回,我们要等待传输完成,即等待调用时传入的一个事件完成,即等待调用时传入的一个事件 NotifyContextNotifyContext 。。这个时候,如果成功返回,那么就和同步类似处理;这个时候,如果成功返回,那么就和同步类似处理;如果超时或者其他情况,则认为传输失败,数据是如果超时或者其他情况,则认为传输失败,数据是无效的。无效的。 详细的过程全部在详细的过程全部在 IssueIsochTransferIssueIsochTransfer 函数中。函数中。

Page 29: Windows CE USB 摄像头驱动开发 ( 初步 )

第五部分 视频数据的处理和显示第五部分 视频数据的处理和显示 这个示范程序中,设置画面大小为这个示范程序中,设置画面大小为 320X240320X240 ,使,使用接口用接口 77 ,输出格式为,输出格式为 RAW-YUV420RAW-YUV420 。后面的部分。后面的部分是参考一个是参考一个 VC+WinDriverVC+WinDriver 下的程序得来。下的程序得来。 这样,至少一次传输这样,至少一次传输 240250240250 个字节,便于在里面个字节,便于在里面查找帧开始标记。应用程序通过查找帧开始标记。应用程序通过 DeviceIoControlDeviceIoControl读取视频数据,在读取的时候,驱动程序循环运行读取视频数据,在读取的时候,驱动程序循环运行 2255次次 GetFrameGetFrame ,得到足够的数据,并复制到应用,得到足够的数据,并复制到应用程序的缓冲中。程序的缓冲中。 再进行再进行 RAW-YUV420->RAW-YUV420->标准标准 YUV420->RGBYUV420->RGB ,就,就可以显示了。可以显示了。 全部代码都在测试应用程序全部代码都在测试应用程序 TestOv511TestOv511 中,为了中,为了调试快速起见用调试快速起见用 MFCMFC 写的。写的。

Page 30: Windows CE USB 摄像头驱动开发 ( 初步 )

需要继续完善需要继续完善 前面的工作,我只是使摄像头工作并且取得了数前面的工作,我只是使摄像头工作并且取得了数据,但是时间仓促,有很多细节还未完善。例如驱据,但是时间仓促,有很多细节还未完善。例如驱动的事件和临界区还没有回收,以及停止设备代码动的事件和临界区还没有回收,以及停止设备代码等等都有相关问题,后面的问题,将在以后的时间等等都有相关问题,后面的问题,将在以后的时间陆续细致解决。 陆续细致解决。 这个这个 PPTPPT主要是作为一个开发的笔记,给准备做主要是作为一个开发的笔记,给准备做这个以及做这个遇到问题的同行一点参考,本人才这个以及做这个遇到问题的同行一点参考,本人才疏学浅,难免有错漏之处,还望不吝赐教,批评指疏学浅,难免有错漏之处,还望不吝赐教,批评指正!正! 欢迎大家和我交流!欢迎大家和我交流! E-mail:[email protected]:[email protected]

Page 31: Windows CE USB 摄像头驱动开发 ( 初步 )

参考资料参考资料 这个工作花了我将近一个星期的空闲时间,如果没有丰富的参考资料和这个工作花了我将近一个星期的空闲时间,如果没有丰富的参考资料和周围多个高手的帮助,是不可能完成的。在此对提供资料和帮助我的人周围多个高手的帮助,是不可能完成的。在此对提供资料和帮助我的人表示深深的感谢!表示深深的感谢! 我也提供自己的程序全部代码,希望能够发挥到一些参考作用!我也提供自己的程序全部代码,希望能够发挥到一些参考作用! 参考资料:参考资料: 1. 1. Microsoft Windows CE .NETMicrosoft Windows CE .NET MSDN MSDN 2. 2. 《《 LinuxLinux 设备驱动设备驱动 (( 第三版第三版 ))》》 3. Linux2.4.183. Linux2.4.18 内核源代码内核源代码 (Ov511.c Ov511.h)(Ov511.c Ov511.h) 4. Windows CE.net4. Windows CE.net 的的 LogitechLogitech 摄像驱动代码摄像驱动代码 ((http://www.gotdotnet.com/workspaces/workspace.aspx?id=0eb87ehttp://www.gotdotnet.com/workspaces/workspace.aspx?id=0eb87e35-13e4-4fa3-9fde-71e9136f47de35-13e4-4fa3-9fde-71e9136f47de)) 5. 5. 《《初试驱动初试驱动---OV511+---OV511+摄像头驱动开发摄像头驱动开发 》》 ((http://www.vckbase.com/code/listcode.asp?mclsid=13&sclsid=1311http://www.vckbase.com/code/listcode.asp?mclsid=13&sclsid=1311的解码部分的解码部分 )) 6. OV511 Datasheet6. OV511 Datasheet