研究了一个星期的winceUSB设备驱动开发,我主要是研究了两个源代码OV511的摄像头驱动和鼠标驱动;刚开始就是看天数似的,不过万事开头难,只要你砸进去没天都会又突破的,为了不让各位走弯路,我谈下我的学习感受和要注意的问题。1.首先要知道USB协议,这是最基本的,如果大家觉得复杂那就简单的看下http://www.juqingshow.com/jsjyuanli/200703/7893.html;2.要知道USB设备驱动开发的结构,具体我就不说了,网上很多;3.很关键的就是要弄清USB描述符,特别是一层层的关系,如一个USB设备有一个设备描述符,设备描述符里面决定了该设备有多少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;端点描述符定义了端点的大小,类型等等。由此我们可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。其中可能还会有获取设备序列号,厂商字符串,产品字符串等。http://hi.baidu.com/angle3839/blog/item/1f4707fa39309f63024f564a.html这些明确后我们就可以开始看程序了,一般网上说得很多的就是除了驱动的标准接口函数外还有三个入口函数,其实网上搜索到的关于WinceUSB驱动开发的文章都有介绍这些函数,这些函数干什么用的,里面调用了那些东东都有说明,但是似乎天下文章一大抄的原则永远没有改变,每篇文章说的内容都差不多,还有些该说明的细节根本没有一篇提到过,根本就不是给新手入门看的,再次我结合自己的理解对这三个函数,希望对大家又帮助。入口点的设置是为了实现USB驱动程序和USBD之间的交互,我们在动态连接库中设置入口点。
设备插入后,系统在取得设备信息后将自动在注册表中寻找是否有这一项,如果没有,则出现提示输入设备名称对话框,输入设备名称后USBInstallDriver这个函数在驱动程序DLL被加载的时候会被调用,但不是任何情况下加载驱动都会调用这个函数入口,当系统能够根据注册表定位到驱动程序dll并且成功加载的话,这个函数就不会被调用了,但是我们一般都需要这个函数,因为怕注册表子键和设备信息不一样,有了这个函数后我们就能够正确的加载驱动了,其实这个函数的功能就是写注册表,为下次插入设备后能真确找到驱动。这函数里主要用到的就是RegisterClientDriverID和RegisterClientSettings函数注册,也少不了少不了LoadLibrary,GetProcAddress,FreeLibrary函数;提醒下:大家有没注意到USBInstallDriver的那个参数就是驱动的名称,也就是对话框要输入的设备驱动名称。也许大家问怎么用RegisterClientDriverID和RegisterClientSettings函数写注册表的,初次看过代码的人肯定有这样的疑问,其实很简单的就是用到了函数指针,是通过函数指针调用的。这两函数是USBD接口函数,已经都被下层实现了的,只要传参数就可以了。对于RegisterClientSettings的参数USB_DRIVER_SETTINGS的结构我就不讲了,是与注册表的子键相同的。
这样我们就把第一个要调用的函数讲清楚了,主要是写注册表,为下次插入设备自动定位到我们的驱动设备。接着就是调用第二个函数USBDeviceAttach()函数的基本定义如下:
USBDeviceAttach(
USB_HANDLE hDevice, // USB设备句柄
LPCUSB_FUNCS lpUsbFuncs, // USBDI的函数集合
LPCUSB_INTERFACE lpInterface, // 设备接口描述信息
LPCWSTR szUniqueDriverId, // 设备ID描述字符串。
LPBOOL fAcceptControl, // 返回TRUE,标识我们可以控制此设备,反之表示不能控制参数看起来还是比较清楚的,提醒下大家要注意的是这些参数的具体值怎么来(系统传来的),其实这个函数是个回调函数,我们填好后系统会自动调用。函数里面会有这样的语句LPCUSB_DEVICE lpDeviceInfo = (*m_lpUsbFuncs->lpGetDeviceInfo)(m_hDevice);很重要的,我们应该知道USB的0端点是控制端点,是默认的,只要找到驱动就可以开始主机和设备的控制传输,这样我们就得到设备描述符等描述符相关值。下面我们就可以保存我们的接口了,当我们要传输时就可以通过选择接口就可以找到端点,再就可打开管道了,就可以通信了。但是第二个函数里怎么实现驱动的加载呢?ActiveDevice函数调用的时候,依据参数lpszDevKey找到驱动程序文件,在注册表的HKEY_LOCAL_MACHINE\Drivers\Active键中增加这个设备,并且将USB驱动程序的上下文指针放到这里(即该函数的第2个参数),并且指定一个索引(设备序号),将驱动程序加载到Device Manager的进程空间。这时Device Manager将发送一个新设备插入的消息,调用该流接口驱动的CAM_Init函数;
本文分享了作者一周内研究WinCE USB设备驱动的心得,包括USB协议的基础知识、USB描述符的理解及其与驱动程序的关系。文章重点介绍了USB驱动开发中的关键函数USBInstallDriver和USBDeviceAttach的作用及其实现细节。
845

被折叠的 条评论
为什么被折叠?



