(2)流驱动程序的分类和函数结构
WinCE驱动程序是介于内核系统和物理设备之间的一个代码层,它的主要作用是为内核系统提供一个接口用来操作不同的外围设备,包括物理设备和虚拟设备。驱动程序提供给内核系统的接口一般可以分为:本地驱动(Native Drivers)和流驱动(Stream Drivers)。我从这次项目实践中得到的经验是,WinCE下的所有驱动都可以归类到这两个里面,二者必居其一。
流驱动是指通过为内核系统提供流接口函数来实现驱动外围设备,如XXX_Init()、XXX_Open()、XXX_Read()、XXX_Write()、XXX_Close()等。这一类的驱动由Device Manager来管理,它是通过调用ActivateDeviceEx()函数来实现加载流驱动的。ActivateDeviceEx()的参数是注册表中相应的键,用来设定加载流驱动的属性,如Index、Order、Prefix等等。流驱动加载成功后,应用程序就可以通过调用CreateFile()、ReadFile()、WirteFile()等函数来访问流驱动设备了。而与流驱动相反,本地驱动提供给内核系统的不是标准的流接口,而是事先约定好的特定接口。因此不同的本地驱动设备,接口也是不一样的。在WinCE中,常见的本地驱动有LCD显示驱动、触摸屏驱动、鼠标和键盘驱动及打印机驱动等。从这里可以看出,本地驱动主要是涉及与人机界面相关的驱动。它们是由GWES来管理的,由于他们在注册表中有各自相应的配置信息,因此它们会在系统启动时自动加载。简单的说,就是本地驱动是由内核系统操作和调用的,一般的应用程序是不能访问和调用的。
在上一段描述中我们提到自动加载的概念,这是从驱动加载时间来区分的。主要分为两种:一是系统启动时自动加载;二是需要时才加载。一般来说,本地驱动都是在启动时自动加载的。而需要时才加载的方式,顾名思义就是想加载时才加载、想卸载时就可卸载。USB设备的驱动加载都是属于需要时才加载的驱动,例如USB摄像头的驱动程序。而从驱动的接口来看,USB摄像头驱动又属于流驱动接口。但相对于普通的流驱动接口,它增加了几个特有的接口函数:如USBDeviceAttach()、USBInstallDriver()、USBUnInstallDriver()等。在这次项目的调试中,我们发现需要时才加载的驱动程序有一个非常实用的好处,就是能在不修改嵌入式内核系统的情况下,应用程序可以动态加载该驱动以完成对硬件的操作,而操作完成后又可卸载其驱动程序以节省有限的内存。
(3)USB设备驱动程序入口点函数分析
大部分USB外围设备由于功能性的原因会更适合使用流接口驱动结构,所以一般都会采用加载式流接口驱动程序模型来开发USB设备驱动程序。流驱动是指通过流接口函数来实现驱动外围设备的。因此,编写流驱动程序实际上就是对各种流函数进行调用。
又由于USB摄像头驱动程序主要是和USBD打交道,所以我们必须详细的了解USBD提供的函数。让人感到幸运的是在WinCE下微软已经提供了通用串行总线驱动程序(USBD)模块、USBD接口函数全集、样本主机控制器驱动程序(HCD)模块。所以,我们只需要根据USB摄像头的硬件特性,利用USBD提供的不同函数就能实现流接口函数与外围摄像头设备的交互。就能大大的节省开发时间,从而能更快速地进行嵌入式开发。