WinCE下所有的驅動都是以DLL的形式,被device.exe進程加載的,所以每個驅動程序中都要實現DllEntry函數。
在注冊表的HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\鍵下保存了USB Host的驅動程序信息。當我們第一次插入USB設備時。因為不存在這樣的信息,所以系統會彈出一個“
未能識別的USB設備”的對話框,要求用戶輸入驅動程序的名稱。該名稱就是USB Host驅動DLL的文件名。在輸入了名稱后,系統會自動調用該DLL的USBInstallDriver函數。該函數
負責向注冊表添加USB Host驅動的信息,以便再次插入設備時,能夠識別該USB設備。其原型如下:
BOOL USBInstallDriver(LPCWSTR szDriverLibFile); 其中szDriverLibFile就是輸入的DLL文件名稱。返回TRUE表示注冊成功。 在向注冊表注冊USB Host信息時,不能使用普通的注冊表函數,只能使用USBD提供的注冊函數。 BOOL RegisterClientDriverID(LPCWSTR szUniqueDriverId); BOOL RegisterClientSettings(LPCWSTR szDriverLibFile, LPCWSTR szUniqueDriverId, LPCWSTR erved, LPCUSB_DRIVER_SETTINGS lpDriverSettings); 這兩個函數在USBD.DLL中,可以通過動態方式調用,也可以通過靜態方式調用。
動態方式如下: HINSTANCE hInst = LoadLibrary(L"USBD.DLL"); if(hInst) { LPREGISTER_CLIENT_DRIVER_ID lpRegisterClientId = (LPREGISTER_CLIENT_DRIVER_ID)GetProcAddress( hInst, L"RegisterClientDriverID"); if(!lpRegisterClientId) return FALSE; LPREGISTER_CLIENT_SETTINGS lpRegisterClientSetting = (LPREGISTER_CLIENT_SETTINGS)GetProcAddress( hInst, L"RegisterClientSettings"); if(!lpRegisterClientSetting) return FALSE; else return FALSE; 此后,就可以通過lpRegisterClientId和lpRegisterClientSetting函數指針調用這些函數,最后記得要FreeLibrary。
靜態方式: 在.cpp源文件中加入 #pragma comment(lib,"usbd.lib") 并在source文件的TARGETLIBS變量中加入$(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\usbd.lib 如此一來,就可以直接使用這兩個函數了。
1) BOOL RegisterClientDriverID(LPCWSTR szUniqueDriverId) 該函數注冊USB Host驅動程序的ID。 2) BOOL RegisterClientSettings(LPCWSTR szDriverLibFile, LPCWSTR szUniqueDriverId, LPCWSTR erved, LPCUSB_DRIVER_SETTINGS lpDriverSettings) 該函數負責注冊驅動程序的信息。 szDriverLibFile 設置為USBInstallDriver函數傳入的DLL驅動程序名稱。 szUniqueDriverId 設置為調用RegisterClientDriverID注冊的驅動程序ID。 erved 設置為NULL lpDriverSettings 該參數是一個USB_DRIVER_SETTINGS結構體。其聲明如下: typedef struct { DWORD dwCount; DWORD dwVendorId; DWORD dwProductId; DWORD dwReleaseNumber; DWORD dwDeviceClass; DWORD dwDeviceSubClass; DWORD dwDeviceProtocol; DWORD dwInterfaceClass; DWORD dwInterfaceSubClass; DWORD dwInterfaceProtocol; } USB_DRIVER_SETTINGS; Count為結構體大小,其他項對應USB描述符。 其中除Count外的各字段,如果不設置具體的值,可以設置為USB_NO_INFO。 這個結構體中的信息講反應到注冊表的HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\鍵下,用于在USB設備插入時,查找USB驅動。下面以一個例子說明: BOOL USBInstallDriver(LPCWSTR szDriverLibFile) { RETAILMSG(1,(TEXT("USBInstallDriver\r\n"))); RETAILMSG(1,(TEXT("USBInstallDriver:%s\r\n"), szDriverLibFile)); BOOL fRet = FALSE; USB_DRIVER_SETTINGS DriverSettings; DriverSettings.dwCount = sizeof(DriverSettings); DriverSettings.dwVendorId = 0x10C4; DriverSettings.dwProductId = 0x0003; DriverSettings.dwReleaseNumber = USB_NO_INFO; DriverSettings.dwDeviceClass = USB_NO_INFO; DriverSettings.dwDeviceSubClass = USB_NO_INFO; DriverSettings.dwDeviceProtocol = USB_NO_INFO; DriverSettings.dwInterfaceClass = 0; DriverSettings.dwInterfaceSubClass = 0; DriverSettings.dwInterfaceProtocol = 0; fRet = RegisterClientDriverID(L"USBTest"); if (fRet) { fRet = RegisterClientSettings( szDriverLibFile, L"USBTest", NULL, &DriverSettings); if(!fRet) RETAILMSG(1,(TEXT("RegisterClientSettings error\r\n"))); } else RETAILMSG(1,(TEXT("RegisterClientDriverID error\r\n")));
return fRet; }
在WinCE中,將設置信息分為了三組,每組3個值, 第一組: dwVendorId、dwProductId、dwReleaseNumber 第二組: dwDeviceClass、dwDeviceSubClass、dwDeviceProtocol 第三組: dwInterfaceClass、dwInterfaceSubClass、dwInterfaceProtocol 如果注冊成功,將會在HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\鍵下出現 “第一組\第二組\第三組\注冊ID\DLL”這樣的建,鍵值為DLL驅動名稱。其中每組又是由三個值中間加下劃線組成。如果有一個值設置為USB_NO_INFO,則鍵名不包括該值。如果整個組中每個值都設置成USB_NO_INFO,則鍵名為Default。
據上面的例子,在我的系統下,將會生成如下鍵名: HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\4292_3\Default\0_0_0\USBTest\DLL = "MyUSBTest" (我的驅動程序為MyUSBTest.dll) 當用戶插入USB設備時,它會讀取USB設備的描述符,根據描述符中的值在注冊表中查找驅動程序名稱。
現在假設,我們要WinCE只支持USB鍵盤,另外我們自己實現一個USB鼠標驅動程序。如果不加注意,我們的USB鼠標驅動程序將不能被調用。原因正是在于這個查找USB設備驅動的過程。WINCE提供的USBHID驅動程序的注冊表信息是 HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\Default\Default\3\Hid_Class\DLL = "USBHID.DLL"
其中第三組信息只使用了dwInterfaceClass,而USB鍵盤和USB鼠標只有dwInterfaceProtocol不同。所以,一個3概括了所有的HID,當我們的USB鼠標插入系統后,將會調用USBHID.DLL驅動程序處理,但是它只包括鍵盤的驅動,沒有鼠標的驅動,所以鼠標不能使用。要想使得自定義的USB鼠標可以使用,則將第三組的值都設置上,如下: HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\Default\Default\3_1_1\Hid_Class\DLL = "USBHID.DLL"
如此一來,當值為3_1_2的鼠標插入后,因為找不到對應的鍵值,將提示要求我們輸入USB鼠標的驅動。
|