📄 hclient.c
字号:
case DBT_DEVICEQUERYREMOVE:
//
// If this message is received, the device is either
// being disabled or removed through device manager.
// To properly handle this request, we need to close
// the handle to the device.
//
broadcastHdr = (PDEV_BROADCAST_HDR) lParam;
if (DBT_DEVTYP_HANDLE == broadcastHdr -> dbch_devicetype)
{
PDEV_BROADCAST_HANDLE broadcastHandle;
PDEVICE_LIST_NODE currNode;
HANDLE deviceHandle;
broadcastHandle = (PDEV_BROADCAST_HANDLE) lParam;
//
// Get the file handle of the device that was removed
// from the system
//
deviceHandle = (HANDLE) broadcastHandle -> dbch_handle;
//
// Search the physical device list for the handle that
// was removed...
//
currNode = (PDEVICE_LIST_NODE) GetListHead(&PhysicalDeviceList);
//
// This loop should always terminate since the device
// handle should be somewhere in the physical device list
//
while (currNode -> HidDeviceInfo.HidDevice != deviceHandle)
{
currNode = (PDEVICE_LIST_NODE) GetNextEntry(currNode);
}
CloseHidDevice(&(currNode -> HidDeviceInfo));
currNode -> DeviceOpened = FALSE;
}
return (TRUE);
case DBT_DEVICEREMOVEPENDING:
case DBT_DEVICEREMOVECOMPLETE:
//
// Do the same steps for DBT_DEVICEREMOVEPENDING and
// DBT_DEVICEREMOVECOMPLETE. We do not receive the
// remove complete request for a device if it is
// disabled or removed via Device Manager. However,
// in that case will receive the remove pending.
// We remove the device from our currently displayed
// list of devices and unregister notification.
//
broadcastHdr = (PDEV_BROADCAST_HDR) lParam;
if (DBT_DEVTYP_HANDLE == broadcastHdr -> dbch_devicetype)
{
PDEV_BROADCAST_HANDLE broadcastHandle;
PDEVICE_LIST_NODE currNode;
HANDLE deviceHandle;
broadcastHandle = (PDEV_BROADCAST_HANDLE) lParam;
//
// Get the file handle of the device that was removed
// from the system
//
deviceHandle = (HANDLE) broadcastHandle -> dbch_handle;
//
// Search the physical device list for the handle that
// was removed...
//
currNode = (PDEVICE_LIST_NODE) GetListHead(&PhysicalDeviceList);
//
// This loop should always terminate since the device
// handle should be somewhere in the physical device list
//
while (currNode -> HidDeviceInfo.HidDevice != deviceHandle)
{
currNode = (PDEVICE_LIST_NODE) GetNextEntry(currNode);
}
//
// Node in PhysicalDeviceList has been found, do:
// 1) Unregister notification
// 2) Close the hid device
// 3) Remove the entry from the list
// 4) Free the memory for the entry
//
//
PostMessage(hDlg,
WM_UNREGISTER_HANDLE,
0,
(LPARAM) currNode -> NotificationHandle);
//
// Close the device if still opened...This would
// occur on surprise removal.
//
if (currNode -> DeviceOpened)
{
CloseHidDevice(&(currNode -> HidDeviceInfo));
}
RemoveNode(currNode);
free(currNode);
//
// Reload the device list
//
vLoadDevices(GetDlgItem(hDlg,IDC_DEVICES));
PostMessage(hDlg,
WM_COMMAND,
IDC_DEVICES + (CBN_SELCHANGE << 16),
(LPARAM) GetDlgItem(hDlg,IDC_DEVICES));
}
break;
default:
break;
}
break;
//
// Application specific message used to defer the unregistering of a
// file object for device change notification. This separte message
// is sent when a WM_DEVICECHANGE (DBT_DEVICEREMOVECOMPLETE) has been
// received. The Unregistering of the notification must be deferred
// until after the WM_DEVICECHANGE message has been processed or the
// system will deadlock. The handle that is to be freed will be passed
// in as lParam for this message
//
case WM_UNREGISTER_HANDLE:
UnregisterDeviceNotification ( (HDEVNOTIFY) lParam );
break;
} // end switch message
return FALSE;
} // end MainDlgProc
BOOL
bParseData(
PHID_DATA pData,
rWriteDataStruct rWriteData[],
int iCount,
int *piErrorLine
)
{
INT iCap;
PHID_DATA pWalk;
BOOL noError = TRUE;
pWalk = pData;
for (iCap = 0; (iCap < iCount) && noError; iCap++)
{
//
// Check to see if our data is a value cap or not
//
if (!pWalk->IsButtonData)
{
pWalk -> ValueData.Value = atol(rWriteData[iCap].szValue);
}
else
{
if (!bSetButtonUsages(pWalk, rWriteData[iCap].szValue) )
{
*piErrorLine = iCap;
noError = FALSE;
}
}
pWalk++;
}
return (noError);
}
BOOL
bSetButtonUsages(
PHID_DATA pCap,
PCHAR pszInputString
)
{
CHAR szTempString[SMALL_BUFF];
CHAR pszDelimiter[] = " ";
PCHAR pszToken;
INT iLoop;
PUSAGE pUsageWalk;
BOOL bNoError=TRUE;
HRESULT stringReturn;
stringReturn = StringCbCopy(szTempString, SMALL_BUFF, pszInputString);
pszToken = strtok(szTempString, pszDelimiter);
pUsageWalk = pCap -> ButtonData.Usages;
memset(pUsageWalk, 0, pCap->ButtonData.MaxUsageLength * sizeof(USAGE));
for (iLoop = 0; ((ULONG) iLoop < pCap->ButtonData.MaxUsageLength) && (pszToken != NULL) && bNoError; iLoop++)
{
*pUsageWalk = (USAGE) atoi(pszToken);
pszToken = strtok(NULL, pszDelimiter);
pUsageWalk++;
}
return bNoError;
} //end function bSetButtonUsages//
INT
iPrepareDataFields(
PHID_DATA pData,
ULONG ulDataLength,
rWriteDataStruct rWriteData[],
int iMaxElements
)
{
INT i;
PHID_DATA pWalk;
HRESULT stringReturn;
pWalk = pData;
for (i = 0; (i < iMaxElements) && ((unsigned) i < ulDataLength); i++)
{
if (!pWalk->IsButtonData)
{
stringReturn = StringCbPrintf(rWriteData[i].szLabel,
MAX_LABEL,
"ValueCap; ReportID: 0x%x, UsagePage=0x%x, Usage=0x%x",
pWalk->ReportID,
pWalk->UsagePage,
pWalk->ValueData.Usage);
}
else
{
stringReturn = StringCbPrintf(rWriteData[i].szLabel,
MAX_LABEL,
"Button; ReportID: 0x%x, UsagePage=0x%x, UsageMin: 0x%x, UsageMax: 0x%x",
pWalk->ReportID,
pWalk->UsagePage,
pWalk->ButtonData.UsageMin,
pWalk->ButtonData.UsageMax);
}
pWalk++;
}
return i;
} //end function iPrepareDataFields//
INT_PTR CALLBACK
bReadDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
static INT iLbCounter;
static CHAR szTempBuff[1024];
static READ_THREAD_CONTEXT readContext;
static HANDLE readThread;
static HID_DEVICE syncDevice;
static HID_DEVICE asyncDevice;
static BOOL doAsyncReads;
static BOOL doSyncReads;
PHID_DEVICE pDevice;
DWORD threadID;
INT iIndex;
PHID_DATA pData;
UINT uLoop;
switch(message)
{
case WM_INITDIALOG:
//
// Initialize the list box counter, the readThread, and the
// readContext.DisplayEvent.
//
iLbCounter = 0;
readThread = NULL;
readContext.DisplayEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL == readContext.DisplayEvent)
{
EndDialog(hDlg, 0);
}
//
// Get the opened device information for the device to perform
// reads upon
//
pDevice = (PHID_DEVICE) lParam;
//
// To do sync and async reads requires file handles with different
// attributes (ie. an async must be opened with the OVERLAPPED flag
// set). The device node that was passed in the context parameter
// was not opened for reading. Therefore, two more devices will
// be opened, one for async reads and one for sync reads.
//
doSyncReads = OpenHidDevice(pDevice -> DevicePath,
TRUE,
FALSE,
FALSE,
FALSE,
&syncDevice);
if (!doSyncReads)
{
MessageBox(hDlg,
"Unable to open device for synchronous reading",
HCLIENT_ERROR,
MB_ICONEXCLAMATION);
}
//
// For asynchronous read, default to using the same information
// passed in as the lParam. This is because data related to
// Ppd and such cannot be retrieved using the standard HidD_
// functions. However, it is necessary to parse future reports.
//
doAsyncReads = OpenHidDevice(pDevice -> DevicePath,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -