📄 driver.cpp
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
Module Name:
driver.cpp
Abstract:
USB Human Interface Device (HID) class driver sample.
Functions:
Notes:
--*/
// There are four warnings that I like from Warning level 4. Since we build
// at warning level 3, I'm setting these four down to level 3 so I still get
// them.
// C4101 unrefrenced local variable
// C4705 statement has no effect
// C4706 assignment in conditional
#pragma warning (3 : 4101 4705 4706)
#include <windows.h>
#include <usbdi.h>
#include <hiddi.hpp>
#include "hid.hpp"
/*
* Debug Zones.
*/
#ifdef DEBUG
#define DBG_INIT 0x0001
#define DBG_ATTACH 0x0002
#define DBG_CONFIG 0x0004
#define DBG_REPORT 0x0008
#define DBG_MOUSE 0x0010
#define DBG_KEYBD 0x0020
#define DBG_JOYSTICK 0x0040
#define DBG_EVENTS 0x0080
#define DBG_FUNCTION 0x2000
#define DBG_WARNING 0x4000
#define DBG_ERROR 0x8000
DBGPARAM dpCurSettings = {
TEXT("Hid"), {
TEXT("Init"), TEXT("Attach"), TEXT("Config"), TEXT("Report"),
TEXT("Mouse"), TEXT("Keyboard"), TEXT("Joystick"), TEXT("Events"),
TEXT(""), TEXT(""), TEXT(""), TEXT(""),
TEXT(""), TEXT("Function"), TEXT("Warnings"), TEXT("Errors") },
DBG_INIT | DBG_ATTACH | DBG_ERROR };
#endif
extern CHid *gpobHid;
const WCHAR gcszRegisterClientDriverId[] = L"RegisterClientDriverID";
const WCHAR gcszRegisterClientSettings[] = L"RegisterClientSettings";
const WCHAR gcszUnRegisterClientDriverId[] = L"UnRegisterClientDriverID";
const WCHAR gcszUnRegisterClientSettings[] = L"UnRegisterClientSettings";
const WCHAR gcszHidDriverId[] = L"Generic_Sample_Hid_Class_Driver";
/*
* DLL entry point
*/
extern "C" BOOL
DllEntry( HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HINSTANCE)hDllHandle);
DEBUGMSG(ZONE_INIT, (TEXT("+Hid DriverEntry\r\n")));
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (TEXT("-Hid DriverEntry\r\n")));
default:
break;
}
return TRUE ;
}
/*
* Routine to initialize driver settings structure that determines how this
* driver is to be loaded. As specified in the HID spec, HID class devices
* are identified in the interface descriptor, so we only need to specify
* the dwInterfaceClass field.
*/
static void
SetupHIDDriverSettings(USB_DRIVER_SETTINGS *pDriverSettings)
{
pDriverSettings->dwCount = sizeof(USB_DRIVER_SETTINGS);
pDriverSettings->dwVendorId = USB_NO_INFO;
pDriverSettings->dwProductId = USB_NO_INFO;
pDriverSettings->dwReleaseNumber = USB_NO_INFO;
pDriverSettings->dwDeviceClass = USB_NO_INFO;
pDriverSettings->dwDeviceSubClass = USB_NO_INFO;
pDriverSettings->dwDeviceProtocol = USB_NO_INFO;
pDriverSettings->dwInterfaceClass = USB_DEVICE_CLASS_HUMAN_INTERFACE;
pDriverSettings->dwInterfaceSubClass = USB_NO_INFO;
pDriverSettings->dwInterfaceProtocol = USB_NO_INFO;
}
/*
* USBInstallDriver
*
* USB driver install routine - set up client registry settings so we will be loaded
* by USBD for HID devices. This function should not be called for systems in which the
* OEM ships the HID driver.
*
* Return value:
* Return TRUE if install succeeds, or FALSE if there is some error.
*/
extern "C" BOOL
USBInstallDriver(
LPCWSTR szDriverLibFile) // Contains client driver DLL name
{
BOOL fRet = FALSE;
HINSTANCE hInst = LoadLibrary(L"USBD.DLL");
DEBUGMSG(ZONE_INIT,(TEXT("HID: Install function called (driver: %s)\r\n"),szDriverLibFile));
// This is the install routine for the HID sample driver.
if(hInst)
{
LPREGISTER_CLIENT_DRIVER_ID pRegisterId =
(LPREGISTER_CLIENT_DRIVER_ID) GetProcAddress(hInst, gcszRegisterClientDriverId);
LPREGISTER_CLIENT_SETTINGS pRegisterSettings =
(LPREGISTER_CLIENT_SETTINGS) GetProcAddress(hInst,gcszRegisterClientSettings);
if (pRegisterId && pRegisterSettings) {
USB_DRIVER_SETTINGS DriverSettings;
SetupHIDDriverSettings(&DriverSettings);
fRet = (*pRegisterId)(gcszHidDriverId);
if(fRet)
{
fRet = (*pRegisterSettings)(szDriverLibFile,gcszHidDriverId, NULL, &DriverSettings);
if(!fRet)
{
LPUN_REGISTER_CLIENT_DRIVER_ID pUnregisterId =
(LPUN_REGISTER_CLIENT_DRIVER_ID) GetProcAddress(hInst,gcszUnRegisterClientDriverId);
if (pUnregisterId)
(*pUnregisterId)(gcszHidDriverId);
}
}
}
else
{
RETAILMSG(1,(TEXT("!Hid: Error getting USBD function pointers\r\n")));
}
FreeLibrary(hInst);
}
return fRet;
}
/*
* USBUnInstallDriver
*
* This function can be called by a client driver to deregister itself
* with USBD.
*/
extern "C" BOOL
USBUnInstallDriver()
{
BOOL fRet = FALSE;
HINSTANCE hInst = LoadLibrary(L"USBD.DLL");
if(hInst)
{
LPUN_REGISTER_CLIENT_DRIVER_ID pUnRegisterId =
(LPUN_REGISTER_CLIENT_DRIVER_ID) GetProcAddress(hInst, gcszUnRegisterClientDriverId);
LPUN_REGISTER_CLIENT_SETTINGS pUnRegisterSettings =
(LPUN_REGISTER_CLIENT_SETTINGS) GetProcAddress(hInst, gcszUnRegisterClientSettings);
if(pUnRegisterSettings)
{
USB_DRIVER_SETTINGS DriverSettings;
// This structure must be filled out the same as we registered with
SetupHIDDriverSettings(&DriverSettings);
fRet = (*pUnRegisterSettings)(gcszHidDriverId, NULL,&DriverSettings);
}
if(pUnRegisterId)
{
BOOL fRetTemp = (*pUnRegisterId)(gcszHidDriverId);
fRet = fRet ? fRetTemp : fRet;
}
FreeLibrary(hInst);
}
return fRet;
}
/*
* USBDeviceNotifications
*
* Process notifications from USBD. Currently, the only notification
* supported is a device removal. Unused parameters are reserved for
* future use.
*/
extern "C" BOOL USBDeviceNotifications(LPVOID lpvNotifyParameter, DWORD dwCode,
LPDWORD * dwInfo1, LPDWORD * dwInfo2, LPDWORD * dwInfo3,
LPDWORD * dwInfo4)
{
SHidDevice *pHidDevice = (SHidDevice *)lpvNotifyParameter;
switch(dwCode)
{
case USB_CLOSE_DEVICE:
gpobHid->HidCloseDevice(pHidDevice);
if (gpobHid->m_curDevices == 0)
{
// If this is the last device, clean up
delete gpobHid;
gpobHid = NULL;
}
return TRUE;
}
return FALSE;
}
/*
* USBDeviceAttach
*
* USB device attach routine. This function is called by USBD when a device is attached
* to the USB, and a matching registry key is found off the LoadClients registry key.
* We must determine whether the device may be controlled by this driver, and load
* drivers for any uncontrolled interfaces.
*
* Return Value:
* Return TRUE upon success, or FALSE if an error occurs.
*/
extern "C" BOOL
USBDeviceAttach(
USB_HANDLE hDevice, // USB device handle
LPCUSB_FUNCS lpUsbFuncs, // Pointer to USBDI function table.
LPCUSB_INTERFACE lpInterface, // If client is being loaded as an interface driver, contains a pointer to the USB_INTERFACE
// structure that contains interface information. If client is not loaded for a specific interface,
// this parameter will be NULL.
LPCWSTR szUniqueDriverId, // Contains client driver id string.
LPBOOL fAcceptControl, // Filled in with TRUE if we accept control of the device,
// or FALSE if USBD should continue to try to load client drivers.
LPCUSB_DRIVER_SETTINGS lpDriverSettings,// Contains pointer to USB_DRIVER_SETTINGS struct that indicates how we were loaded.
DWORD dwUnused) // Reserved for use with future versions of USBD
{
LPCUSB_CONFIGURATION lpActiveConfig;
LPCUSB_DEVICE lpDeviceInfo;
int iInterface;
*fAcceptControl = FALSE;
if (lpInterface) {
// If loaded as an interface driver, ignore non HID interfaces
if (lpInterface->Descriptor.bInterfaceClass != USB_DEVICE_CLASS_HUMAN_INTERFACE) {
DEBUGMSG(ZONE_ATTACH,(TEXT("USBHid: DeviceAttach, ignoring non HID interface class %u\r\n"),
lpInterface->Descriptor.bInterfaceClass));
return FALSE;
}
DEBUGMSG(ZONE_ATTACH,
(TEXT("USBHid: DeviceAttach, IF %u, #EP:%u, Class:%u, Sub:%u, Prot:%u\r\n"),
lpInterface->Descriptor.bInterfaceNumber,lpInterface->Descriptor.bNumEndpoints,
lpInterface->Descriptor.bInterfaceClass,lpInterface->Descriptor.bInterfaceSubClass,
lpInterface->Descriptor.bInterfaceProtocol));
}
else {
DEBUGMSG(ZONE_ATTACH,(TEXT("USBHid: DeviceAttach, lpInterface == NULL\r\n")));
}
// If this is the first device, init our global data
if (gpobHid == NULL)
{
DEBUGMSG(ZONE_INIT,(TEXT("USBHid: DeviceAttach, creating new CHid instance...\r\n")));
gpobHid = new CHid();
if (gpobHid == NULL)
return FALSE;
if (!gpobHid->Initialize(lpUsbFuncs)) {
DEBUGMSG(ZONE_ERROR, (TEXT("HID: Error initializing driver. Exiting.\r\n")));
goto Error;
}
}
// Retrieve device descriptor information
lpDeviceInfo = (*lpUsbFuncs->lpGetDeviceInfo)(hDevice);
if (lpDeviceInfo == NULL) {
DEBUGMSG(ZONE_ERROR,(TEXT("!HID: Error in GetDeviceInfo()\r\n")));
goto Error;
}
lpActiveConfig = lpDeviceInfo->lpActiveConfig;
if ((lpActiveConfig == NULL) ||
(lpActiveConfig->lpInterfaces == NULL) ||
(lpActiveConfig->lpInterfaces->lpEndpoints == NULL))
{
DEBUGMSG(ZONE_ERROR,(TEXT("!HID: DeviceAttach - missing descriptor information!\r\n")));
goto Error;
}
// HCD should guarantee this
ASSERT(lpDeviceInfo->Descriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE);
ASSERT(lpActiveConfig->Descriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
ASSERT(lpActiveConfig->lpInterfaces->Descriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
// Check all interfaces on device. If we find at least one HID class interface, we'll accept
// control of the device.
for (iInterface = 0; iInterface < (int)lpActiveConfig->dwNumInterfaces; iInterface++) {
LPCUSB_INTERFACE lpIF = &lpActiveConfig->lpInterfaces[iInterface];
SHidDevice *pHidDevice;
// HCD should guarantee this
ASSERT(lpIF);
ASSERT(lpIF->Descriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
// Ignore alternate interfaces
if (lpIF->Descriptor.bAlternateSetting != 0) {
DEBUGMSG(ZONE_ATTACH,(TEXT("HID:DeviceAttach Skipping alternate interface %u\r\n"),iInterface));
continue;
}
// We only care about HID interfaces (load drivers for other interfaces later if we decide to accept
// control of this device).
if (lpIF->Descriptor.bInterfaceClass != USB_DEVICE_CLASS_HUMAN_INTERFACE) {
DEBUGMSG(ZONE_ATTACH,(TEXT("HID:DeviceAttach Skipping interface %u (class 0x%X not HID)\r\n"),
iInterface,lpIF->Descriptor.bInterfaceClass));
continue;
}
if ((pHidDevice = gpobHid->HidNewDevice(hDevice,lpIF,lpDeviceInfo->Descriptor.bMaxPacketSize0)) == NULL) {
goto Error;
}
else {
// Register notification routine for device status changes.
(*lpUsbFuncs->lpRegisterNotificationRoutine)(hDevice,USBDeviceNotifications, pHidDevice);
// Tell USBD to stop looking for drivers
*fAcceptControl = TRUE;
}
}
if (*fAcceptControl) {
// OK, we want control of this device, let's load drivers for other interfaces
for (iInterface = 0; iInterface < (int)lpActiveConfig->dwNumInterfaces; iInterface++) {
LPCUSB_INTERFACE lpIF = &lpActiveConfig->lpInterfaces[iInterface];
if ((lpIF->Descriptor.bAlternateSetting != 0) &&
(lpIF->Descriptor.bInterfaceClass != USB_DEVICE_CLASS_HUMAN_INTERFACE)) {
// This will go through the standard client driver search algorithm. Note that
// we are prevented from looping since we reject non HID interfaces immediately.
(*lpUsbFuncs->lpLoadGenericInterfaceDriver)(hDevice,lpIF);
}
}
}
return TRUE;
Error:
// Clean up
RETAILMSG(1,(TEXT("!HID: Could not configure HID device\r\n")));
if (gpobHid->m_curDevices == 0) {
delete gpobHid;
gpobHid = NULL;
}
return FALSE;
}
extern "C" DWORD
HID_Init (DWORD dwCtx)
{
// Unnecessary to init here; this is only so we can register ourselves to the OS for the benefit of DI.
return 1;
}
extern "C" BOOL
HID_Deinit (DWORD dwCtx)
{
return TRUE;
}
extern "C" BOOL
HID_Open (DWORD dwCtx, DWORD dwAccMode, DWORD dwShrMode)
{
#if 0
// We should only open the HID for purposes of ioctl.
if (dwAccMode || dwShrMode) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
#endif
return TRUE;
}
extern "C" BOOL
HID_Close (DWORD)
{
return TRUE;
}
extern "C" DWORD
HID_Read (DWORD,LPVOID,DWORD)
{
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
}
extern "C" DWORD
HID_Write (DWORD,LPCVOID,DWORD)
{
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
}
extern "C" DWORD
HID_Seek (DWORD,long,DWORD)
{
SetLastError(ERROR_NOT_SUPPORTED);
return -1;
}
extern "C" BOOL
HID_IOControl (DWORD hCtx, DWORD dwCode,
PBYTE pInpBuf, DWORD dwInpLen,
PBYTE pOutBuf, DWORD dwOutLen, PDWORD pdwActualOutLen)
{
ASSERT(gpobHid);
return gpobHid->IOControl(dwCode, pInpBuf, dwInpLen, pOutBuf, dwOutLen, pdwActualOutLen);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -