📄 hid.cpp
字号:
}
DWORD CALLBACK
CHid::ControlCompletionStub(LPVOID lpvNotifyParameter)
{
SHidDevice *pstHidDevice = (SHidDevice *)lpvNotifyParameter;
DEBUGCHK(pstHidDevice->signalStatus & gcSignalStatusCtrlPending);
pstHidDevice->signalStatus |= gcSignalStatusCtrlSignaled;
SetEvent(gpobHid->m_hEvent);
return 0;
}
DWORD CALLBACK
CHid::InterruptCompletionStub(LPVOID lpvNotifyParameter)
{
SHidDevice *pstHidDevice = (SHidDevice *)lpvNotifyParameter;
DEBUGCHK(pstHidDevice->signalStatus & gcSignalStatusIntrPending);
pstHidDevice->signalStatus |= gcSignalStatusIntrSignaled;
RETAILMSG(RETAIL_ZONE_HID,(TEXT("Hid::InterruptCompletionStub: device %08x, signalling event %08x.\r\n"), pstHidDevice, gpobHid->m_hEvent ));
SetEvent(gpobHid->m_hEvent);
return 0;
}
#ifdef DEBUG
static TCHAR *TagDesc[] =
{
L"!RSVD!",
L"Usage Page", //x01
L"Usage", //x02
L"!RSVD!",
L"!RSVD!",
L"Logical Min", //x05
L"Usage Min", //x06
L"!RSVD!",
L"!RSVD!",
L"Logical Max", //x09
L"Usage Max", //x0a
L"!RSVD!",
L"!RSVD!",
L"Physical Min", //x0d
L"Designator Index", //x0e
L"!RSVD!",
L"!RSVD!",
L"Physical Max", //x11
L"Designator Min", //x12
L"!RSVD!",
L"!RSVD!",
L"Unit Exponent", //x15
L"Designator Max", //x16
L"!RSVD!",
L"!RSVD!",
L"Unit", //x19
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"Report Size", //x1d
L"String Index", //x1e
L"!RSVD!",
L"Input", //x20
L"Report ID", //x21
L"String Min", //x22
L"!RSVD!",
L"Output", //x24
L"Report Count", //x25
L"String Max", //x26
L"!RSVD!",
L"Collection", //x28
L"Push", //x29
L"Delimiter", //x2a
L"!RSVD!",
L"Feature", //x2c
L"Pop", //x2d
L"!RSVD!",
L"!RSVD!",
L"End Collection", //x30
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
L"!RSVD!",
};
#endif
BOOL
CHid::ParseReportDescriptor(
SHidDevice *pstHidDevice)
{
PUCHAR pBuffer = pstHidDevice->pDataBuffer;
UINT descriptorLength = pstHidDevice->wReportDescriptorLength;
UINT byte;
UINT8 infoByte;
int dataLength;
int collectionDepth = 0;
PFN_PARSE_HANDLER pfnHandler;
BOOL fRet;
BOOL bDidSomething = FALSE;
UINT32 dwData;
INT32 sigData;
SParseState *pstState = new SParseState;
SParseState *pstStateTemp;
memset(pstState, 0, sizeof(SParseState));
DEBUGMSG(ZONE_FUNCTION,(TEXT("+CHid::ParseReportDescriptor\r\n")));
// Gotta go through all this because each debug message may be prefixed by the thread ID...
#ifdef DEBUGNEVER // ever try to read the raw dump? yech. i have a better dump below.
if (ZONE_REPORT) {
WCHAR szFmtBuf[2000];
int iLen;
iLen = wsprintf(szFmtBuf,TEXT("%d byte Report Descriptor:"), descriptorLength);
for (byte = 0; (byte < descriptorLength) &&
(iLen < (sizeof(szFmtBuf)/sizeof(szFmtBuf[0]) - 10)); byte++) {
if (byte % 8 == 0)
iLen += wsprintf(szFmtBuf+iLen,TEXT("\r\n "));
iLen += wsprintf(szFmtBuf+iLen,TEXT(" %02X"), pBuffer[byte]);
}
wcscpy(szFmtBuf+iLen,TEXT("\r\n"));
DEBUGMSG(ZONE_REPORT, (TEXT("%s"), szFmtBuf));
}
#endif //DEBUG
for (byte = 0; byte < descriptorLength; byte++) {
infoByte = pBuffer[byte];
dataLength = GetDataSize(infoByte);
if (dataLength < 0) {
// It's a long data item.
DEBUGMSG(ZONE_ERROR,
(TEXT("HID: Parse error, long data items not supported.\r\n")));
dataLength = 1 + pBuffer[byte + 1];
continue;
}
ConvertData(&pBuffer[byte + 1], dataLength, &dwData, &sigData);
#ifdef DEBUG
DEBUGMSG(ZONE_REPORT, (TEXT("RDesc idx %3d (%02X) len=%d tag=%02X (%s) data=%04X or %04X\r\n"),
byte, infoByte, dataLength, infoByte>>2, TagDesc[infoByte>>2], dwData, sigData));
#endif
byte += dataLength;
// We've already got the length info. Mask off those bits now.
infoByte &= ~gcParseShortItemLengthMask;
switch (infoByte) {
case gcParseGlobalUsagePage:
pstState->usagePage = dwData;
if (pstState->usagePage != gcParseUsagePageGenericDesktop &&
pstState->usagePage != gcParseUsagePageKeyboard &&
pstState->usagePage != gcParseUsagePageLEDs &&
pstState->usagePage != gcParseUsagePageButtons) {
DEBUGMSG(ZONE_ERROR,
(TEXT("HID: Parse error, %02X is an unsupported usage page\r\n"),
pstState->usagePage));
}
break;
case gcParseLocalUsage:
pstState->usage[pstState->nextFreeUsage] = dwData;
pstState->nextFreeUsage++;
if (pstState->usagePage == gcParseUsagePageGenericDesktop) {
if (dwData == gcParseDesktopUsageMouse ||
dwData == gcParseDesktopUsageKeyboard ||
dwData == gcParseDesktopUsageJoystick ||
dwData == gcParseDesktopUsageGamePad) {
pstState->nextFreeUsage--;
pstState->pstData =
AllocateDescriptionStruct(
&pstHidDevice->pstDataDescriptionHead);
if (pstState->pstData == NULL) {
return (FALSE);
}
bDidSomething = TRUE;
pstHidDevice->wDeviceUsagePage = pstState->usagePage;
pstHidDevice->wDeviceUsage = dwData;
if (pstState->reportId == 0) {
pstState->curBit = 0;
}
else {
pstState->curBit = 8;
}
if (dwData == gcParseDesktopUsageMouse) {
pstState->pstData->deviceType = gcDeviceTypeMouse;
pstState->pstData->pfnParseHandler = ParseMouse;
pstState->pstData->mouse.pButtonOffsets = NULL;
pstHidDevice->dwDeviceType = DIDEVTYPE_MOUSE;
}
else if (dwData == gcParseDesktopUsageKeyboard) {
pstState->pstData->deviceType = gcDeviceTypeKeyboard;
pstState->pstData->pfnParseHandler = ParseKeyboard;
pstHidDevice->dwDeviceType = DIDEVTYPE_KEYBOARD;
}
else { // Joystick or Gamepad
pstState->pstData->deviceType = gcDeviceTypeJoystick;
pstState->pstData->pfnParseHandler = ParseJoystick;
pstState->pstData->joy.pButtonOffsets = NULL;
pstHidDevice->dwDeviceType = DIDEVTYPE_JOYSTICK;
}
}
}
break;
case gcParseGlobalReportId:
pstState->reportId = dwData;
if (pstState->curBit == 0) {
pstState->curBit = 8;
}
break;
case gcParseMainCollection:
collectionDepth++;
break;
case gcParseMainEndCollection:
collectionDepth--;
break;
case gcParseGlobalReportSize:
pstState->reportSize = dwData;
break;
case gcParseGlobalReportCount:
pstState->reportCount = dwData;
break;
case gcParseGlobalLogicalMinimum:
pstState->logicalMin = sigData;
break;
case gcParseGlobalLogicalMaximum:
#ifdef DONT_USE_MIN_MAX_WORKAROUND
pstState->logicalMax = sigData;
#else
if (sigData < pstState->logicalMin) {
// If max < min, they forgot this was a signed value
// and said something like min = 0 max = 0xFF
pstState->logicalMax = dwData;
}
else {
pstState->logicalMax = sigData;
}
#endif //DONT_USE_MIN_MAX_WORKAROUND
break;
case gcParseGlobalPhysicalMinimum:
pstState->physicalMin = sigData;
break;
case gcParseGlobalPhysicalMaximum:
#ifdef DONT_USE_MIN_MAX_WORKAROUND
pstState->physicalMax = sigData;
#else
if (sigData < pstState->physicalMin) {
// If max < min, they forgot this was a signed value
// and said something like min = 0 max = 0xFF
pstState->physicalMax = dwData;
}
else {
pstState->physicalMax = sigData;
}
#endif //DONT_USE_MIN_MAX_WORKAROUND
break;
case gcParseLocalUsageMinimum:
pstState->usageMin = sigData;
break;
case gcParseLocalUsageMaximum:
pstState->usageMax = sigData;
break;
case gcParseMainOutput:
case gcParseMainInput:
case gcParseMainFeature:
if (pstState->pstData == NULL ||
pstState->pstData->pfnParseHandler == NULL) {
DEBUGMSG(ZONE_ERROR,
(TEXT("Parse error. Main before Usage\r\n")));
return (FALSE);
}
// pfnHandler points to one of the Parse handler functions
// (ie, ParseKeyboard or ParseJoystick). This value was set
// in the gcParseLocalUsage case above.
pfnHandler = pstState->pstData->pfnParseHandler;
fRet = (this->*pfnHandler)(pstState, infoByte, dwData);
if (!fRet)
return (FALSE);
break;
case gcParseGlobalPush:
pstStateTemp = new SParseState;
memcpy(pstStateTemp, pstState, sizeof(SParseState));
pstState->pNext = pstStateTemp;
break;
case gcParseGlobalPop:
CopyStateGlobals(pstState, pstStateTemp);
pstState->pNext = pstStateTemp->pNext;
delete pstStateTemp;
break;
}
}
pstHidDevice->intrBufferSize = pstState->curBit / 8;
if (pstState->curBit % 8 != 0) {
pstHidDevice->intrBufferSize++;
}
#ifdef DEBUG
if (ZONE_REPORT) {
DumpDataDescription(pstState->pstData);
}
#endif
// Deallocate the state info structures. There SHOULD only be one, but
// it's always possible that an IHV did a push without a pop.
while (pstState != NULL) {
pstStateTemp = pstState;
pstState = pstState->pNext;
delete pstStateTemp;
}
DEBUGMSG(ZONE_FUNCTION,(TEXT("-CHid::ParseReportDescriptor\r\n")));
if (!bDidSomething) {
return (FALSE);
}
return (TRUE);
}
BOOL
CHid::ParseMouse(
SParseState *pstState,
UINT8 type,
UINT32 data)
{
UINT curUsage;
UINT offset;
BOOL bFoundAxis;
UINT axisNum;
SDataDescription *pstData = pstState->pstData;
DEBUGMSG(ZONE_FUNCTION,(TEXT("+CHid::ParseMouse\r\n")));
if (type != gcParseMainInput) {
// We don't do anything with anything but inputs, so ignore these.
return (TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -