📄 hidparser.cxx
字号:
if (LoadHidClients() == FALSE)
goto EXIT;
ForceReportProtocol();
SetIdle();
iErr = ERROR_SUCCESS;
m_fIsInitialized = TRUE;
EXIT:
if (!m_fIsInitialized)
Deinitialize();
return iErr;
}
void BTHHIDParser::Deinitialize()
{
DWORD cCollections = 0;
DWORD dwIdx;
LockHidContextEx();
m_UsbHid.Flags.UnloadPending = TRUE;
ReleaseHidContextEx();
if (m_UsbHid.hThread != NULL)
{
WaitForSingleObject(m_UsbHid.hThread, INFINITE);
CloseHandle(m_UsbHid.hThread);
}
if (m_UsbHid.phidpDeviceDesc != NULL)
cCollections = m_UsbHid.phidpDeviceDesc->CollectionDescLength;
if (m_UsbHid.pQueues != NULL)
{
// Tell each queue that it is closing.
for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
{
HidTLCQueue *pQueue = &m_UsbHid.pQueues[dwIdx];
if (pQueue->IsInitialized() == TRUE)
pQueue->Close();
}
}
if (m_UsbHid.pClientHandles != NULL)
{
// Notify each client that its device has been removed.
for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
{
PHID_CLIENT_HANDLE pHidClient = &m_UsbHid.pClientHandles[dwIdx];
if (pHidClient->hInst != NULL)
{
LPHID_CLIENT_NOTIFICATIONS lpNotifications;
lpNotifications = (LPHID_CLIENT_NOTIFICATIONS)
GetProcAddress(pHidClient->hInst, SZ_HID_CLIENT_NOTIFICATIONS);
if (lpNotifications == NULL)
{
DEBUGMSG(ZONE_ERROR, (_T("Could not get client address of %s\r\n"), SZ_HID_CLIENT_NOTIFICATIONS));
}
else
{
__try
{
(*lpNotifications)(HID_CLOSE_DEVICE, 0,
pHidClient->lpvNotifyParameter);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(ZONE_ERROR,(TEXT("Exception in notification proc\r\n")));
}
}
FreeLibrary(pHidClient->hInst);
}
}
LocalFree(m_UsbHid.pClientHandles);
}
if (m_UsbHid.pQueues != NULL)
delete[] m_UsbHid.pQueues;
if (m_UsbHid.hEP0Event != NULL)
CloseHandle(m_UsbHid.hEP0Event);
if (m_UsbHid.pClientHandles != NULL)
LocalFree(m_UsbHid.pClientHandles);
if (m_UsbHid.phidpDeviceDesc != NULL)
{
HidP_FreeCollectionDescription(m_UsbHid.phidpDeviceDesc);
LocalFree(m_UsbHid.phidpDeviceDesc);
}
DeleteCriticalSection(&m_UsbHid.csLock);
ZeroMemory((void*) &m_UsbHid, sizeof(m_UsbHid));
m_fIsInitialized = FALSE;
}
// We have data structures for each top level collection. This initializes them.
BOOL BTHHIDParser::InitializeTLCStructures()
{
BOOL fRet = FALSE;
DWORD cCollections;
DWORD dwIdx;
// Allocate our HID queues. One for each top level collection.
cCollections = m_UsbHid.phidpDeviceDesc->CollectionDescLength;
m_UsbHid.pQueues = new HidTLCQueue[cCollections];
if (m_UsbHid.pQueues == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("Memory allocation error\r\n")));
goto EXIT;
}
// Allocate our HID client handles. One for each TLC.
m_UsbHid.pClientHandles = (PHID_CLIENT_HANDLE) LocalAlloc(LMEM_FIXED, sizeof(HID_CLIENT_HANDLE) * cCollections);
if (m_UsbHid.pClientHandles == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("LocalAlloc error:%d\r\n"), GetLastError()));
goto EXIT;
}
// Initialize our HID queues and client handles.
for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
{
BOOL fSucceeded;
PHIDP_COLLECTION_DESC phidpCollection = &m_UsbHid.phidpDeviceDesc->CollectionDesc[dwIdx];
PHID_CLIENT_HANDLE pClientHandle = &m_UsbHid.pClientHandles[dwIdx];
fSucceeded = m_UsbHid.pQueues[dwIdx].Initialize(
HID_TLC_QUEUE_DEFAULT_CAPACITY,
phidpCollection->InputLength);
pClientHandle->Sig = USB_HID_CLIENT_SIG;
pClientHandle->hInst = NULL;
pClientHandle->lpvNotifyParameter = NULL;
pClientHandle->pUsbHid = &m_UsbHid;
pClientHandle->pQueue = &m_UsbHid.pQueues[dwIdx];
pClientHandle->lpvContext = (LPVOID) this;
pClientHandle->phidpPreparsedData = phidpCollection->PreparsedData;
if (fSucceeded == FALSE) {
DEBUGMSG(ZONE_ERROR, (_T("Failed initializing queue\r\n")));
goto EXIT;
}
}
fRet = TRUE;
EXIT:
return fRet;
}
// 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).
BOOL BTHHIDParser::LoadHidClients()
{
BOOL fRet = FALSE;
DWORD cCollections;
DWORD dwIdx;
DWORD dwType;
LONG iErr;
HID_DRIVER_SETTINGS driverSettings;
cCollections = m_UsbHid.phidpDeviceDesc->CollectionDescLength;
// this should come from SDP attributes
memset(&driverSettings, 0, sizeof(driverSettings));
for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
{
PHIDP_COLLECTION_DESC pCollection = &m_UsbHid.phidpDeviceDesc->CollectionDesc[dwIdx];
PHID_CLIENT_HANDLE pClientHandle = &m_UsbHid.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.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("Could not enumerate subkey of LoadClient key. Error %i\r\n"), iErr));
goto CONTINUE;
}
iErr = RegOpenKeyEx(hKey, szBuf, 0, 0, &hSubKey);
if (iErr != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR, (_T("Could not open subkey \"%s\"of LoadClient key. Error %i\r\n"), 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"), DLL_VALUE_SZ));
goto CONTINUE;
}
hInst = LoadDriver(szBuf);
if (hInst == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("Could not load client DLL %s\r\n"), szBuf));
goto CONTINUE;
}
pfnAttach = (LPHID_CLIENT_ATTACH) GetProcAddress(hInst, SZ_HID_CLIENT_ATTACH);
if (pfnAttach == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("Could not get the address of %s from %s\r\n"), 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("Exception in attach procedure %s in %s\r\n"), SZ_HID_CLIENT_ATTACH, szBuf));
}
if (fSuccess != TRUE) {
DEBUGMSG(ZONE_ERROR, (_T("Failure in attach procedure %s in %s\r\n"), 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);
}
}
fRet = TRUE;
//EXIT:
return fRet;
}
void BTHHIDParser::LockHidContextEx()
{
EnterCriticalSection(&m_UsbHid.csLock);
}
void BTHHIDParser::ReleaseHidContextEx()
{
LeaveCriticalSection(&m_UsbHid.csLock);
}
// Return a report descriptor given the ID.
PHIDP_REPORT_IDS BTHHIDParser::GetReportDesc(PHIDP_DEVICE_DESC phidpDeviceDesc, DWORD dwReportID)
{
PHIDP_REPORT_IDS pCurrReport = NULL;
DWORD dwIdx;
DEBUGCHK(phidpDeviceDesc != NULL);
DEBUGCHK(phidpDeviceDesc->ReportIDs != NULL);
for (dwIdx = 0; dwIdx < phidpDeviceDesc->ReportIDsLength; ++dwIdx)
{
pCurrReport = &phidpDeviceDesc->ReportIDs[dwIdx];
DEBUGCHK(pCurrReport != NULL);
if (pCurrReport->ReportID == dwReportID)
break;
}
DEBUGCHK(pCurrReport != NULL);
return pCurrReport;
}
// Return a collection decriptor given the collection number. Also returns the
// index of the collection in the device context's array.
PHIDP_COLLECTION_DESC BTHHIDParser::GetCollectionDesc(PHIDP_DEVICE_DESC phidpDeviceDesc, DWORD dwCollectionNumber, PDWORD pdwCollectionIndex)
{
PHIDP_COLLECTION_DESC pCurrColl = NULL;
DWORD dwIdx;
DEBUGCHK(phidpDeviceDesc != NULL);
DEBUGCHK(phidpDeviceDesc->CollectionDesc != NULL);
for (dwIdx = 0; dwIdx < phidpDeviceDesc->CollectionDescLength; ++dwIdx)
{
pCurrColl = &phidpDeviceDesc->CollectionDesc[dwIdx];
DEBUGCHK(pCurrColl != NULL);
if (pCurrColl->CollectionNumber == dwCollectionNumber)
break;
}
DEBUGCHK(pCurrColl != NULL);
if (pdwCollectionIndex != NULL)
*pdwCollectionIndex = dwIdx;
return pCurrColl;
}
// If this report includes power events, perform them.
void BTHHIDParser::PerformPowerEvents(
PHIDP_COLLECTION_DESC phidpCollection,
BYTE *pbHidPacket,
DWORD cbHidPacket
)
{
NTSTATUS status;
ULONG uPowerEvents = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -