📄 hid.cpp
字号:
}
}
else {
pUsbHid->fSendToInterface = TRUE;
}
DUMP_USB_HID_DESCRIPTOR((*pHidDescriptor));
pUsbHid->pUsbFuncs = pUsbFuncs;
pUsbHid->Flags.Open = FALSE;
pUsbHid->Flags.UnloadPending = FALSE;
// set the USB interface/pipes
if (SetUsbInterface(pUsbHid) == FALSE) {
DEBUGMSG(ZONE_ERROR, (_T("%s: SetUsbInterface failed!\r\n"), pszFname));
goto EXIT;
}
// create endpoint 0 event
pUsbHid->hEP0Event = CreateEvent(NULL, MANUAL_RESET_EVENT, FALSE, NULL);
if (pUsbHid->hEP0Event == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: CreateEvent error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
// Get the report descriptor for our interface.
if (GetReportDescriptor(pUsbHid, pHidDescriptor->wDescriptorLength) == FALSE) {
goto EXIT;
}
// Set up our data structres for each top level collection.
if (InitializeTLCStructures(pUsbHid) == FALSE) {
goto EXIT;
}
// Create the thread that receives the data from the device.
if (CreateInterruptThread(pUsbHid) == FALSE) {
goto EXIT;
}
ValidateHidContext(pUsbHid);
// NKDbgPrintfW(TEXT("Before LoadHidClients\r\n"));
// Load client drivers for our top level collections
if (LoadHidClients(pUsbHid) == FALSE) {
goto EXIT;
}
// NKDbgPrintfW(TEXT("After LoadHidClients\r\n"));
// Mouse and keyboard HID devices might have a boot protocol that can be
// used at boot time. We never use the boot protocol and the devices
// should default to the standard report format, but they are not
// guaranteed to. Therefore, we will manually set the report protocol here.
if (pUsbInterface->Descriptor.bInterfaceSubClass == HID_INTERFACE_BOOT_SUBCLASS) {
SetReportProtocol(pUsbHid);
}
//NKDbgPrintfW(TEXT("SetReportProtocol\r\n"));
// According to the HID spec, keyboards are set to idle 500 ms before
// sending an empty report. We want infinite idling.
// SetIdle(pUsbHid, NULL);
//NKDbgPrintfW(TEXT("SetIdle\r\n"));
// Set this device to wake the system if applicable. We don't care if it fails.
if (pDeviceInfo->lpActiveConfig->Descriptor.bmAttributes & USB_CONFIG_REMOTE_WAKEUP) {
// EnableRemoteWakeup(pUsbHid);
}
//NKDbgPrintfW(TEXT("EnableRemoteWakeup\r\n"));
// We can now start our interrupt thread.
ResumeThread(pUsbHid->hThread);
//NKDbgPrintfW(TEXT("ResumeThread\r\n"));
fErr = FALSE;
EXIT:
if ((fErr == TRUE) && (pUsbHid != NULL)) {
RemoveDeviceContext(pUsbHid);
pUsbHid = NULL;
}
NKDbgPrintfW(TEXT("Hid CreateHidDevice:%d\r\n"),GetLastError());
DEBUGMSG(ZONE_INIT, (_T("-%s\r\n"), pszFname));
return pUsbHid;
}
// Receives the interrupt reports from the device
static
DWORD
WINAPI
InterruptThreadProc(
LPVOID lpParameter
)
{
SETFNAME(_T("InterruptThreadProc"));
PUSBHID_CONTEXT pUsbHid = (PUSBHID_CONTEXT) lpParameter;
BOOL fNoReportID;
DWORD dwBytesTransferred;
DWORD dwErr;
USB_ERROR usbError;
PBYTE pbDataBuffer = NULL, pbToTransfer;
DWORD cbBuffer, cbToTransfer;
BOOL fUnloadPending = FALSE;
DEBUGCHK(pUsbHid != NULL);
ValidateHidContext(pUsbHid);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
cbBuffer = cbToTransfer = pUsbHid->InterruptIn.wMaxPacketSize;
// If there is only one report for an interface, including the report ID
// at the start of each report is optional. We need to know whether
// a report is coming or not, because when we hand off the report
// a report ID must be included.
fNoReportID = (pUsbHid->phidpDeviceDesc->ReportIDs[0].ReportID == 0);
if (fNoReportID == TRUE) {
// We will always include the report ID so add another byte for it.
++cbBuffer;
}
pbDataBuffer = pbToTransfer = (BYTE*) HidAlloc(cbBuffer);
if (pbDataBuffer == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
if (fNoReportID == TRUE) {
// Leave the starting byte empty for the ID of 0
pbDataBuffer[0] = 0;
++pbToTransfer;
}
while (fUnloadPending == FALSE)
{
#ifdef DEBUG
FillMemory(pbToTransfer, cbToTransfer, 0xCC);
#endif
dwErr = IssueInterruptTransfer(
pUsbHid->pUsbFuncs,
pUsbHid->InterruptIn.hPipe,
DefaultTransferComplete,
pUsbHid->InterruptIn.hEvent,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
pbToTransfer,
NULL,
cbToTransfer,
&dwBytesTransferred,
INFINITE,
&usbError
);
if ( (usbError == USB_DEVICE_NOT_RESPONDING_ERROR) ||
(dwErr == ERROR_GEN_FAILURE) )
{
// Device has been unplugged. Allow time for USBDeviceNotifications
// to get the news.
Sleep(25);
}
if ((dwErr == ERROR_SUCCESS) && (usbError == USB_NO_ERROR))
{
// All is good. Send off the report.
if (fNoReportID == TRUE) {
// Increment the count of bytes transferred to include the ID.
DEBUGCHK(pbDataBuffer[0] == 0);
++dwBytesTransferred;
}
ProcessReport(pUsbHid, pbDataBuffer, dwBytesTransferred);
}
fUnloadPending = pUsbHid->Flags.UnloadPending;
}
EXIT:
if (pbDataBuffer) HidFree(pbDataBuffer);
return 0;
}
// Create the thread that will receive the device's interrupt data
BOOL
CreateInterruptThread(
PUSBHID_CONTEXT pUsbHid
)
{
SETFNAME(_T("CreateInterruptThread"));
BOOL fRet = FALSE;
DEBUGCHK(pUsbHid != NULL);
DEBUGCHK(VALID_CONTEXT(pUsbHid));
pUsbHid->hThread = CreateThread(NULL, 0, InterruptThreadProc, pUsbHid, CREATE_SUSPENDED, NULL);
if (pUsbHid->hThread == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: CreateThread error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
else
{
ThreadInfo TI;
TI.ThreadHandle = pUsbHid->hThread;
strcpy((char *)TI.ThreadName, "USB InterruptThreadProc");
KernelIoControl(IOCTL_SET_THREAD, (LPVOID)&TI, sizeof(ThreadInfo), NULL, 0, NULL);
}
fRet = TRUE;
EXIT:
NKDbgPrintfW(TEXT("Hid CreateInterruptThread Fail:%d\r\n"),GetLastError());
return fRet;
}
// Adds a new device to the list of HID devices. On failure, the list is
// in the original state.
BOOL
AddDeviceToList(
PUSBHID_CONTEXT pUsbHid
)
{
SETFNAME(_T("AddDeviceToList"));
BOOL fRet = FALSE;
DWORD dwSize, dwIdx;
PUSBHID_CONTEXT *rgpUsbHid;
DEBUGCHK(pUsbHid != NULL);
LockHidData();
DEBUGCHK(g_fInitialized == TRUE);
ValidateHidGlobals();
dwSize = g_cpUsbHid;
for (dwIdx = 0; dwIdx < dwSize; ++dwIdx) {
if (g_rgpUsbHid[dwIdx] == NULL) {
break;
}
}
if (dwIdx == dwSize)
{
// Time to enlarge the array
dwSize *= 2;
rgpUsbHid = (PUSBHID_CONTEXT*) HidReAlloc(g_rgpUsbHid,
HID_ARRAY_BYTE_SIZE(dwSize), LMEM_ZEROINIT | LMEM_MOVEABLE);
if (rgpUsbHid == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
g_rgpUsbHid = rgpUsbHid;
g_cpUsbHid = dwSize;
ValidateHidGlobals();
}
DEBUGCHK(dwIdx < g_cpUsbHid);
g_rgpUsbHid[dwIdx] = pUsbHid;
fRet = TRUE;
EXIT:
ValidateHidGlobals();
ReleaseHidData();
NKDbgPrintfW(TEXT("Hid AddDeviceToList Fail:%d\r\n"),GetLastError());
return fRet;
}
//
// ***** HID Stream Interface *****
//
#define HID_DEVICE_CONTEXT_HANDLE 0xCAFE
#ifdef DEBUG
static DWORD g_dwInitCount = 0;
#endif
extern "C"
DWORD
HID_Init (DWORD dwCtx)
{
#ifdef DEBUG
// Be sure that only one instance of this DLL is initialized.
DEBUGCHK(g_dwInitCount == 0);
++g_dwInitCount;
#endif
return HID_DEVICE_CONTEXT_HANDLE;
}
extern "C"
BOOL
HID_Deinit (DWORD dwCtx)
{
#ifdef DEBUG
// Be sure that only one instance of this DLL is initialized.
DEBUGCHK(g_dwInitCount == 1);
--g_dwInitCount;
#endif
return dwCtx == HID_DEVICE_CONTEXT_HANDLE;
}
extern "C"
DWORD
HID_Open (DWORD dwCtx, DWORD dwAccMode, DWORD dwShrMode)
{
SETFNAME(_T("HID_Open"));
DWORD dwRet = 0;
LockHidData();
if (dwCtx == HID_DEVICE_CONTEXT_HANDLE)
{
if (g_fInitialized == FALSE) {
DEBUGMSG(ZONE_ERROR, (_T("%s: ERROR_ACCESS_DENIED\r\n"), pszFname));
SetLastError(ERROR_ACCESS_DENIED);
goto EXIT;
}
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s: ERROR_FILE_NOT_FOUND\r\n"), pszFname));
SetLastError(ERROR_FILE_NOT_FOUND);
goto EXIT;
}
dwRet = HID_DEVICE_CONTEXT_HANDLE;
EXIT:
ReleaseHidData();
NKDbgPrintfW(TEXT("Hid Open Fail:%d\r\n"),GetLastError());
return dwRet;
}
extern "C"
BOOL
HID_Close (DWORD dwCtx)
{
SETFNAME(_T("HID_Close"));
BOOL fRet = FALSE;
if (dwCtx != HID_DEVICE_CONTEXT_HANDLE) {
DEBUGMSG(ZONE_ERROR, (_T("%s: ERROR_INVALID_HANDLE\r\n"), pszFname));
SetLastError(ERROR_INVALID_HANDLE);
goto EXIT;
}
fRet = TRUE;
EXIT:
NKDbgPrintfW(TEXT("Hid Close Fail:%d\r\n"),GetLastError());
return fRet;
}
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 dwCtx, DWORD dwCode,
PBYTE pInpBuf, DWORD dwInpLen,
PBYTE pOutBuf, DWORD dwOutLen, PDWORD pdwActualOutLen)
{
SETFNAME(_T("HID_IOControl"));
BOOL fRet = FALSE;
if (dwCtx != HID_DEVICE_CONTEXT_HANDLE) {
DEBUGMSG(ZONE_ERROR, (_T("%s: ERROR_INVALID_HANDLE\r\n"), pszFname));
SetLastError(ERROR_INVALID_HANDLE);
goto EXIT;
}
// No supported HID IOControl values
DEBUGMSG(ZONE_ERROR, (_T("%s(0x%x) ERROR_NOT_SUPPORTED\r\n"), pszFname));
SetLastError(ERROR_NOT_SUPPORTED);
EXIT:
NKDbgPrintfW(TEXT("Hid IOControl Fail:%d\r\n"),GetLastError());
return fRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -