转载:http://blog.csdn.net/chyuanzheng/article/details/7903214
0,前言:
1, 本篇文章只讲wince下的usb host驱动,并深入解析HID驱动。本博客的目的并不是只是为了讲怎么写驱动, 更重要的是:
1,了解wince驱动的架构。
2,学习微软的写作方法,如何去架构一个非常复杂的程序(USB驱动的确是有点复杂,但是微软的代码写的非常的具有条理,是不可多得的学习资料)。
2,学习wince usb驱动,必须对usb的协议有一定了解,可以看看《USB2.0 硬件设计(第2版)》
1,USB驱动的总体结构
这个方面的资料很多,其实也很简单,其实从总体来看,不管细节,USB驱动就那么三层架构而已。如下图:
由于我们只专注于usb host端的驱动,所以只要看左边就可以了,最底层是硬件,硬件上面的第一层是HCD驱动,第二层是USBD,再上面就对应不同的usb设备来,print对应usb打印机,Mass Storage对应U盘,HID对应USB鼠标,USB键盘和其他符合HID设备,HID并不是一个驱动,而是一个类别,所以USB鼠标,USB键盘都要单独的驱动。
下面我们从最底层往上来学习USB驱动。
2,USB Host Controller Hardware (HC 硬件)
就如同串口一样,USB需要有硬件来支持,串口有RS232,RS485……,USB host controller 有OHCI,UHCI……,这个没什么好说的,到底不同那个的硬件有什么不同的特性,这里就不讨论了。赶紧看 下一小节。
3,USB Host Controller Driver(HCD驱动)
BOOL HcdAttach(LPVOID lpvHcd, LPCHCD_FUNCS lpHcdFuncs, LPLPVOID lppvContext);BOOL HcdDetach(LPVOID lpvContext);BOOL HcdDeviceAttached(LPVOID lpvContext, UINT iDevice, UINT iEndpointZero,LPCUSB_DEVICE lpDeviceInfo, LPLPVOID lppvDeviceDetach);BOOL HcdDeviceDetached(LPVOID lpvDeviceDetach);
struct _HCD_FUNCS {DWORD dwCount;LPHCD_GET_FRAME_NUMBER lpGetFrameNumber;LPHCD_GET_FRAME_LENGTH lpGetFrameLength;LPHCD_SET_FRAME_LENGTH lpSetFrameLength;LPHCD_STOP_ADJUSTING_FRAME lpStopAdjustingFrame;LPHCD_OPEN_PIPE lpOpenPipe;LPHCD_CLOSE_PIPE lpClosePipe;LPHCD_RESET_PIPE lpResetPipe;LPHCD_IS_PIPE_HALTED lpIsPipeHalted;LPHCD_ISSUE_TRANSFER lpIssueTransfer;LPHCD_ABORT_TRANSFER lpAbortTransfer;LPHCD_DISABLE_DEVICE lpDisableDevice;LPHCD_SUSPEND_RESUME lpSuspendResume;};
4,USB Core Driver(USBD驱动)
1,学习了HCD层的驱动,这一层就相对简单了。还是先看目录。哦,简单了,只有一个目录,USBD!在D:\WINCE600\public\common\oak\drivers\usb\usbd!BOOL USBDeviceAttach(USB_HANDLE hDevice, LPCUSB_FUNCS lpUsbFuncs,LPCUSB_INTERFACE lpInterface, LPCWSTR szUniqueDriverId,LPBOOL fAcceptControl,LPCUSB_DRIVER_SETTINGS lpDriverSettings, DWORD dwUnused);BOOL USBInstallDriver(LPCWSTR szDriverLibFile);BOOL USBUnInstallDriver();
5,Mass Storage驱动
6,HID驱动
HID驱动是非常复杂的一层,但是它是建立在USBD层之上,也就是说HID驱动必须按照usbdi.h中的接口规范来写。打开目录:D:\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\USB\CLASS\HID\HIDCLASS1,可以看到目录结构如下。所以可以很明显的看出来,HID分成了两层,一个是MDD层,一个是USBPDD层。因为USBD层调用的USBPDD层,所以我们来看看USBPDD这个文件夹。
1)在USBPDD文件夹中,你会发现对usbdi.h中接口必须实现的函数,和对usbdi.h提供的服务的使用,这里就不多说了。2)在source文件内发现USBPDD编译为USBHID_LIB,实际是编译为usbhid.dll,至于是如何编译的,看makefile,如下(就没截图了):usbhid:: usbclient usbd hidparse hidmdd所以usbhid直接包含usbd。而usbclient,是所有USBD的上层一个共有的静态库。而 hidparse提供对hid中的描述符进行解析的一个库,这个库没有提供源代码(我没有找到,难道在private文件夹中?),不过不影响我们对程序的理解。那么 hidmdd是什么呢, hidmdd就是上面所说的MDD层。在它的同名文件夹中。
9,再次结尾
10,再次再次结尾
11,再次再次再次结尾
参考:wince下的USB驱动要点总结 http://blog.csdn.net/chyuanzheng/article/details/7858782
补充,HID的启动与注册表在hidmdd.cpp中 见 OpenClientRegKey函数:
// Contains most of the logic to find and open the proper HID client key.
// The algorithm searches for the most specific vendor key of the form
// idVendor_idProduct_bcdDevice. Then its subkeys are searched for the most
// specific interface key of the form bInterface_bCollection. Then its
// subkeys are searched for the most specific top level collection key
// of the form UsagePage_Usage.
//
// The order of vendor precedence is described below.
//
// idVendor_idProduct_bcdDevice
// idVendor_idProduct
// idVendor
// Default
//
// The order of interface precedence is described below.
//
// bInterface_bCollection
// bInterface
// Default
//
// The order of TLC precedence is
//
// UsagePage_Usage
// UsagePage
// Default
//
// So the order of checking would be
// 1. idVendor_idProduct_bcdDevice\bInterface_bCollection\UsagePage_Usage
// 2. idVendor_idProduct_bcdDevice\bInterface_bCollection\UsagePage
// 3. idVendor_idProduct_bcdDevice\bInterface_bCollection\Default
// 4. idVendor_idProduct_bcdDevice\bInterface\UsagePage_Usage
// ...
// 7. idVendor_idProduct_bcdDevice\Default\UsagePage_Usage
// ...
// 10. idVendor_idProduct\bInterface_bCollection\UsagePage_Usage
// ...
// 42. Default\bInterface_bCollection\Default
// 43. Default\bInterface\UsagePage_Usage
// 44. Default\bInterface\UsagePage
// 45. Default\bInterface\Default
// 46. Default\Default\UsagePage_Usage
// 47. Default\Default\UsagePage
// 48. Default\Default\Default
//