📄 hid.cpp
字号:
hKeyVendor = OpenSpecificClientRegKey(hKeyRoot, pdwVendorVals, cCurrVendor);
if (hKeyVendor != NULL)
{
for (cCurrInterface = (INT) cdwInterfaceVals;
cCurrInterface >= 0;
--cCurrInterface)
{
hKeyInterface = OpenSpecificClientRegKey(hKeyVendor, pdwInterfaceVals, cCurrInterface);
if (hKeyInterface != NULL)
{
for (cCurrTLC = (INT) cdwTLCVals; cCurrTLC >= 0; --cCurrTLC)
{
hKeyRet = OpenSpecificClientRegKey(hKeyInterface, pdwTLCVals, cCurrTLC);
if (hKeyRet != NULL) {
// We found our key
break;
}
}
RegCloseKey(hKeyInterface);
if (hKeyRet != NULL) {
// We found our key
break;
}
}
}
RegCloseKey(hKeyVendor);
if (hKeyRet != NULL) {
// We found our key.
break;
}
}
}
if (hKeyRet != NULL) {
// We found a match. Fill in the driver settings used.
PDWORD rgpdwDriverSettings[] = {
&pDriverSettingsUsed->dwVendorId,
&pDriverSettingsUsed->dwProductId,
&pDriverSettingsUsed->dwReleaseNumber,
&pDriverSettingsUsed->dwInterfaceNumber,
&pDriverSettingsUsed->dwCollection,
&pDriverSettingsUsed->dwUsagePage,
&pDriverSettingsUsed->dwUsage,
};
// Fill in the matching vendor info
for (iIdx = 0; iIdx < cCurrVendor; ++iIdx) {
*rgpdwDriverSettings[iIdx] = pdwVendorVals[iIdx];
}
// Fill in the matching interface info
for (iIdx = 0; iIdx < cCurrInterface; ++iIdx) {
*rgpdwDriverSettings[iIdx + cdwVendorVals] = pdwInterfaceVals[iIdx];
}
// Fill in the matching TLC info
for (iIdx = 0; iIdx < cCurrTLC; ++iIdx) {
*rgpdwDriverSettings[iIdx + cdwVendorVals + cdwInterfaceVals]
= pdwTLCVals[iIdx];
}
}
return hKeyRet;
}
// Get the registry key for the HID client that will best service the device
// descripted in pDriverSettings.
// Returns the registry key and the actual driver settings that matched the key.
static
HKEY
FindClientRegKey(
const HID_DRIVER_SETTINGS *pDriverSettings,
PHID_DRIVER_SETTINGS pDriverSettingsUsed
)
{
SETFNAME(_T("FindClientRegKey"));
const DWORD rgdwVendorVals[] = {
pDriverSettings->dwVendorId,
pDriverSettings->dwProductId,
pDriverSettings->dwReleaseNumber
};
const DWORD rgdwInterfaceVals[] = {
pDriverSettings->dwInterfaceNumber,
pDriverSettings->dwCollection
};
const DWORD rgdwTLCVals[] = {
pDriverSettings->dwUsagePage,
pDriverSettings->dwUsage
};
HKEY hKeyRoot = NULL;
HKEY hKeyRet = NULL;
LONG iErr;
DEBUGCHK(pDriverSettings != NULL);
DEBUGCHK(pDriverSettingsUsed != NULL);
memset(pDriverSettingsUsed, (BYTE) HID_NO_INFO, sizeof(HID_DRIVER_SETTINGS));
iErr = RegOpenKey(HKEY_LOCAL_MACHINE, LOAD_CLIENTS_PATH_SZ, &hKeyRoot);
if (iErr != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Failed opening HID client key [HKLM\\%s]\r\n"),
pszFname, LOAD_CLIENTS_PATH_SZ));
goto EXIT;
}
// Now find the most specific match.
hKeyRet = OpenClientRegKey(hKeyRoot,
rgdwVendorVals, dim(rgdwVendorVals),
rgdwInterfaceVals, dim(rgdwInterfaceVals),
rgdwTLCVals, dim(rgdwTLCVals),
pDriverSettingsUsed);
if (hKeyRet == NULL) {
DEBUGMSG(ZONE_WARNING, (_T("%s: Could not find a suitable HID client driver\r\n"), pszFname));
goto EXIT;
}
EXIT:
if (hKeyRoot != NULL) RegCloseKey(hKeyRoot);
NKDbgPrintfW(TEXT("Hid FindClientRegKey Fail:%d\r\n"),GetLastError());
return hKeyRet;
}
// Load a HID client for each top level collection, if possible.
// Returns FALSE if there was a major error. Returns TRUE even
// if certain TLC's do not have clients. This is not an error
// because internal processing will still be performed on unhandled
// reports (like power events).
static
BOOL
LoadHidClients(
PUSBHID_CONTEXT pUsbHid
)
{
SETFNAME(_T("LoadHidClients"));
BOOL fRet = FALSE;
PCUSB_DEVICE pDeviceInfo;
DWORD cCollections;
DWORD dwIdx;
DWORD dwType;
LONG iErr;
HID_DRIVER_SETTINGS driverSettings;
DEBUGCHK(pUsbHid != NULL);
ValidateHidContext(pUsbHid);
cCollections = pUsbHid->phidpDeviceDesc->CollectionDescLength;
pDeviceInfo = pUsbHid->pUsbFuncs->lpGetDeviceInfo(pUsbHid->hUsbDevice);
if (pDeviceInfo == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Failure getting USB device info\r\n"), pszFname));
goto EXIT;
}
driverSettings.dwVendorId = pDeviceInfo->Descriptor.idVendor;
driverSettings.dwProductId = pDeviceInfo->Descriptor.idProduct;
driverSettings.dwReleaseNumber = pDeviceInfo->Descriptor.bcdDevice;
driverSettings.dwInterfaceNumber =
pUsbHid->pUsbInterface->Descriptor.bInterfaceNumber;
for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
{
PHIDP_COLLECTION_DESC pCollection = &pUsbHid->phidpDeviceDesc->CollectionDesc[dwIdx];
PHID_CLIENT_HANDLE pClientHandle = &pUsbHid->pClientHandles[dwIdx];
TCHAR szBuf[MAX_PATH];
DWORD cchBuf = dim(szBuf);
HKEY hKey;
HKEY hSubKey = NULL;
HINSTANCE hInst = NULL;
LPHID_CLIENT_ATTACH pfnAttach;
BOOL fSuccess = FALSE;
DEBUGCHK(pClientHandle->hInst == NULL);
DEBUGCHK(pClientHandle->pQueue != NULL);
driverSettings.dwCollection = pCollection->CollectionNumber;
driverSettings.dwUsagePage = pCollection->UsagePage;
driverSettings.dwUsage = pCollection->Usage;
hKey = FindClientRegKey(&driverSettings, &pClientHandle->driverSettings);
if (hKey == NULL) {
// No match for top level collection. Just continue.
goto CONTINUE;
}
iErr = RegEnumKeyEx(hKey, 0, szBuf, &cchBuf, NULL, NULL, NULL, NULL);
if (iErr != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Could not enumerate subkey of LoadClient key. Error %i\r\n"),
pszFname, iErr));
goto CONTINUE;
}
iErr = RegOpenKey(hKey, szBuf, &hSubKey);
if (iErr != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Could not open subkey \"%s\"of LoadClient key. Error %i\r\n"),
pszFname, szBuf, iErr));
goto CONTINUE;
}
cchBuf = dim(szBuf);
iErr = RegQueryValueEx(hSubKey, DLL_VALUE_SZ, NULL, &dwType, (PBYTE) szBuf, &cchBuf);
if (iErr != ERROR_SUCCESS || dwType != REG_SZ) {
DEBUGMSG(ZONE_ERROR, (_T("s: Could not get %s value in LoadClient key.\r\n"),
pszFname, DLL_VALUE_SZ));
goto CONTINUE;
}
hInst = LoadDriver(szBuf);
if (hInst == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Could not load client DLL %s\r\n"), pszFname, szBuf));
goto CONTINUE;
}
pfnAttach = (LPHID_CLIENT_ATTACH) GetProcAddress(hInst, SZ_HID_CLIENT_ATTACH);
if (pfnAttach == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Could not get the address of %s from %s\r\n"),
pszFname, SZ_HID_CLIENT_ATTACH, szBuf));
goto CONTINUE;
}
__try {
fSuccess = (*pfnAttach)(
(HID_HANDLE) pClientHandle,
&g_HidFuncs,
&pClientHandle->driverSettings,
pCollection->PreparsedData,
&pClientHandle->lpvNotifyParameter,
0);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Exception in attach procedure %s in %s\r\n"),
pszFname, SZ_HID_CLIENT_ATTACH, szBuf));
}
if (fSuccess != TRUE) {
DEBUGMSG(ZONE_INIT, (_T("%s: Failure in attach procedure %s in %s\r\n"),
pszFname, SZ_HID_CLIENT_ATTACH, szBuf));
goto CONTINUE;
}
// Turn on this client's queue.
pClientHandle->pQueue->AcceptNewReports(TRUE);
// Finally this client has been initialized. Save our hInst.
pClientHandle->hInst = hInst;
CONTINUE:
if (hKey != NULL) RegCloseKey(hKey);
if (hSubKey != NULL) RegCloseKey(hSubKey);
if (pClientHandle->hInst == NULL) {
// We did not successfully initialize the client.
if (hInst != NULL) FreeLibrary(hInst);
DEBUGMSG(ZONE_INIT, (_T("%s: No client found for HID top level collection 0x%X-0x%X on interface 0x%X\r\n"),
pszFname, pCollection->UsagePage, pCollection->Usage,
pUsbHid->pUsbInterface->Descriptor.bInterfaceNumber));
}
}
fRet = TRUE;
EXIT:
NKDbgPrintfW(TEXT("In LoadHidClients\r\n"));
NKDbgPrintfW(TEXT("Hid LoadHidClients Fail:%d\r\n"),GetLastError());
return fRet;
}
// We have data structures for each top level collection. This initializes them.
static
BOOL
InitializeTLCStructures(
PUSBHID_CONTEXT pUsbHid
)
{
SETFNAME(_T("InitializeTLCStructures"));
BOOL fRet = FALSE;
DWORD cCollections;
DWORD dwIdx;
DEBUGCHK(pUsbHid != NULL);
// Allocate our HID queues. One for each top level collection.
cCollections = pUsbHid->phidpDeviceDesc->CollectionDescLength;
pUsbHid->pQueues = new HidTLCQueue[cCollections];
if (pUsbHid->pQueues == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Memory allocation error\r\n"), pszFname));
goto EXIT;
}
// Allocate our HID client handles. One for each TLC.
pUsbHid->pClientHandles = (PHID_CLIENT_HANDLE) HidAlloc(sizeof(HID_CLIENT_HANDLE) * cCollections);
if (pUsbHid->pClientHandles == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
// Initialize our HID queues and client handles.
for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
{
BOOL fSucceeded;
PHIDP_COLLECTION_DESC phidpCollection = &pUsbHid->phidpDeviceDesc->CollectionDesc[dwIdx];
PHID_CLIENT_HANDLE pClientHandle = &pUsbHid->pClientHandles[dwIdx];
fSucceeded = pUsbHid->pQueues[dwIdx].Initialize(
HID_TLC_QUEUE_DEFAULT_CAPACITY,
phidpCollection->InputLength);
pClientHandle->Sig = USB_HID_CLIENT_SIG;
pClientHandle->hInst = NULL;
pClientHandle->lpvNotifyParameter = NULL;
pClientHandle->pUsbHid = pUsbHid;
pClientHandle->pQueue = &pUsbHid->pQueues[dwIdx];
pClientHandle->phidpPreparsedData = phidpCollection->PreparsedData;
if (fSucceeded == FALSE) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Failed initializing queue\r\n"), pszFname));
goto EXIT;
}
}
fRet = TRUE;
EXIT:
NKDbgPrintfW(TEXT("Hid InitializeTLCStructures:%d\r\n"),GetLastError());
return fRet;
}
// Creates and returns the HID device context.
// Returns NULL if error.
PUSBHID_CONTEXT
CreateHidDevice(
USB_HANDLE hUsbDevice,
PCUSB_FUNCS pUsbFuncs,
PCUSB_INTERFACE pUsbInterface
)
{
SETFNAME(_T("CreateHidInterface"));
PUSBHID_CONTEXT pUsbHid = NULL;
BOOL fErr = TRUE;
PCUSB_DEVICE pDeviceInfo = NULL;
PHID_DESCRIPTOR pHidDescriptor = NULL;
PCUSB_ENDPOINT pEndpoint = NULL;
DEBUGMSG(ZONE_INIT, (_T("+%s\r\n"), pszFname));
DEBUGCHK(pUsbFuncs != NULL);
DEBUGCHK(pUsbInterface != NULL);
pDeviceInfo = (*pUsbFuncs->lpGetDeviceInfo)(hUsbDevice);
if (pDeviceInfo == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Failure getting USB device info\r\n"), pszFname));
goto EXIT;
}
DUMP_USB_DEVICE_DESCRIPTOR(pDeviceInfo->Descriptor);
DUMP_USB_CONFIGURATION_DESCRIPTOR(pDeviceInfo->lpActiveConfig->Descriptor);
pUsbHid = (PUSBHID_CONTEXT)HidAlloc(sizeof(USBHID_CONTEXT));
if (pUsbHid == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
ZeroMemory(pUsbHid, sizeof(USBHID_CONTEXT));
pUsbHid->Sig = USB_HID_SIG;
InitializeCriticalSection(&pUsbHid->csLock);
pUsbHid->hUsbDevice = hUsbDevice;
pUsbHid->pUsbInterface = pUsbInterface;
DUMP_USB_INTERFACE_DESCRIPTOR(pUsbHid->pUsbInterface->Descriptor,
pUsbHid->pUsbInterface->Descriptor.bInterfaceNumber);
if (pUsbInterface->lpEndpoints == NULL) {
DEBUGMSG(ZONE_ERROR,(TEXT("%s: Missing endpoint descriptors\r\n"), pszFname));
goto EXIT;
}
pEndpoint = &pUsbInterface->lpEndpoints[0];
DEBUGCHK(pEndpoint != NULL);
// Regarding bSendToInterface. The original HID spec said that the Hid
// descriptor would come after the interface and endpoint descriptors.
// It also said that class specific commands should be sent to the endpoint.
// The next spec said that the HID descriptor would come after the interface
// descriptor (not at the end) and that commands should be sent to the
// interface, not to the endpoint. So, I'm assuming that if I find the
// Hid descriptor after the interface, the device is following the new spec
// and I should send commands to the interface. Otherwise, I'll send them
// to the endpoint, as stated in the old spec.
pHidDescriptor = (PHID_DESCRIPTOR) pUsbInterface->lpvExtended;
if (pHidDescriptor == NULL) {
pHidDescriptor = (PHID_DESCRIPTOR) pUsbInterface->lpEndpoints->lpvExtended;
if (pHidDescriptor == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Missing HID descriptor\r\n"), pszFname));
goto EXIT;
}
else {
pUsbHid->fSendToInterface = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -