📄 hid.cpp
字号:
// Yes, this will result in the report Id getting reset multiple times, but
// that's cheaper than wrapping an
// if (pstData->reportId != pstState->reportId) around this.
pstData->reportId = pstState->reportId;
// if this is not true, the input is a constant and we don't need to do
// anything but update the curBit setting.
if ((data & gcParseInputData_ConstantBit) == 0) {
offset = 0;
for (curUsage = 0; curUsage < pstState->nextFreeUsage; curUsage++) {
bFoundAxis = FALSE;
if (pstState->usagePage == gcParseUsagePageGenericDesktop) {
switch (pstState->usage[curUsage]) {
case gcParseDesktopUsageX:
bFoundAxis = TRUE;
axisNum = gcXAxis;
break;
case gcParseDesktopUsageY:
bFoundAxis = TRUE;
axisNum = gcYAxis;
break;
case gcParseDesktopUsageZ:
bFoundAxis = TRUE;
axisNum = gcZAxis;
break;
}
}
if (bFoundAxis) {
if (pstData->mouse.pAxes[axisNum] == NULL) {
pstData->mouse.pAxes[axisNum] = new SAxisInfo;
}
pstData->mouse.pAxes[axisNum]->startBit =
pstState->curBit + (offset * pstState->reportSize);
pstData->mouse.pAxes[axisNum]->length = pstState->reportSize;
pstData->mouse.pAxes[axisNum]->wUsagePage =
pstState->usagePage;
pstData->mouse.pAxes[axisNum]->wUsage =
pstState->usage[curUsage];
pstData->mouse.pAxes[axisNum]->min = pstState->logicalMin;
pstData->mouse.pAxes[axisNum]->max = pstState->logicalMax;
}
// This is an attempt to deal with missing Usage(Pointer) etc
// but catch strange usages I didn't forsee (why's the mouse
// doing stylus pressure? etc).
if ((pstState->usagePage == gcParseUsagePageGenericDesktop &&
pstState->usage[curUsage] >= gcParseDesktopUsageX)) {
offset++;
}
}
pstState->nextFreeUsage -= curUsage;
// Deal with Buttons.
// This code assumes the button information is in separate Main items
// than the axis info (it basically has to be that way anyhow).
if (pstState->usagePage == gcParseUsagePageButtons) {
if (pstData->mouse.buttonsLength == 0) {
pstData->mouse.buttonsStartBit = pstState->curBit;
pstData->mouse.buttonsLength =
pstState->reportCount * pstState->reportSize;
pstData->mouse.prevButtons = 0;
}
else {
DEBUGMSG(ZONE_ERROR,
(TEXT("HID: Parse Error, more than one button group\r\n")));
}
}
}
pstState->curBit += pstState->reportSize * pstState->reportCount;
DEBUGMSG(ZONE_FUNCTION,(TEXT("-CHid::ParseMouse\r\n")));
return (TRUE);
}
BOOL
CHid::ParseKeyboard(
SParseState *pstState,
UINT8 type,
UINT32 data)
{
UINT curByte;
SDataDescription *pstData = pstState->pstData;
if (type != gcParseMainInput) {
// We don't do anything with anything but inputs, so ignore these.
return (TRUE);
}
// Yes, this will result in the report Id getting reset multiple times, but
// that's cheaper than wrapping an
// if (pstData->reportId != pstState->reportId) around this.
pstData->reportId = pstState->reportId;
// if this is not true, the input is a constant and we don't need to do
// anything but update the curBit setting.
if ((data & gcParseInputData_ConstantBit) == 0) {
// We made an assumption that the data would be byte aligned. Hid
// doesn't actually require that, but it'll really suck if anyone
// ever does a keyboard that doesn't byte align its data.
if (pstState->curBit % 8 != 0) {
DEBUGMSG(ZONE_ERROR, (TEXT("!CHid::ParseKeyboard: Data on byte alignment assumption violated\r\n")));
return (FALSE);
}
curByte = pstState->curBit / 8;
// In a keyboard, there are two types of data. Variable data is for
// the chordable buttons and array data is for the rest.
if ((data & gcParseInputArray_VariableBit) == 0) {
// Array
pstData->keybd.arrayStartByte = curByte;
if (pstData->keybd.pressedKeys != NULL) {
delete[] pstData->keybd.pressedKeys;
}
pstData->keybd.pressedKeys = new UINT8[pstState->reportCount];
pstData->keybd.arrayLength = pstState->reportCount;
// Initialize the pressed keys array to zero
memset(pstData->keybd.pressedKeys, 0, pstState->reportCount);
}
else {
// Variable
pstData->keybd.chordStartByte = curByte;
// There are only 8 chordable keys defined, so we assumed this
// would be a byte.
if (pstState->reportSize * pstState->reportCount > 8) {
DEBUGMSG(ZONE_ERROR, (TEXT("!CHid::ParseKeyboard error Num Chord keys <= 8 assumption violated\r\n.")));
return (FALSE);
}
pstData->keybd.chordLength = 1;
pstData->keybd.pressedChords = 0x00;
}
}
pstState->curBit += pstState->reportSize * pstState->reportCount;
return (TRUE);
}
BOOL
CHid::ParseJoystick(
SParseState *pstState,
UINT8 type,
UINT32 data)
{
UINT curUsage;
UINT offset;
BOOL bFoundAxis;
UINT axisNum;
SDataDescription *pstData = pstState->pstData;
if (type != gcParseMainInput) {
// We don't do anything with anything but inputs, so ignore these.
return (TRUE);
}
// Yes, this will result in the report Id getting reset multiple times, but
// that's cheaper than wrapping an
// if (pstData->reportId != pstState->reportId) around this.
pstData->reportId = pstState->reportId;
// if this is not true, the input is a constant and we don't need to do
// anything but update the curBit setting.
if ((data & gcParseInputData_ConstantBit) == 0) {
offset = 0;
for (curUsage = 0; curUsage < pstState->nextFreeUsage; curUsage++) {
bFoundAxis = FALSE;
if (pstState->usagePage == gcParseUsagePageGenericDesktop) {
switch (pstState->usage[curUsage]) {
case gcParseDesktopUsageX:
bFoundAxis = TRUE;
axisNum = gcXAxis;
break;
case gcParseDesktopUsageY:
bFoundAxis = TRUE;
axisNum = gcYAxis;
break;
case gcParseDesktopUsageZ:
bFoundAxis = TRUE;
axisNum = gcZAxis;
break;
case gcParseDesktopUsageRx:
bFoundAxis = TRUE;
axisNum = gcRxAxis;
break;
case gcParseDesktopUsageRy:
bFoundAxis = TRUE;
axisNum = gcRyAxis;
break;
case gcParseDesktopUsageRz:
bFoundAxis = TRUE;
axisNum = gcRzAxis;
break;
case gcParseDesktopUsageSlider:
case gcParseDesktopUsageDial:
case gcParseDesktopUsageWheel:
bFoundAxis = TRUE;
axisNum = gcThrottleAxis;
break;
}
}
else if (pstState->usagePage == gcParseUsagePageSimulation) {
// IHVs really shouldn't use these extraneous pages.
// A "rudder" or a "turret direction" is much better
// described as Rz and a "throttle" is much better described
// as slider.
switch (pstState->usage[curUsage]) {
case gcParseSimulationUsageRudder:
case gcParseSimulationUsageTurret:
bFoundAxis = TRUE;
axisNum = gcRzAxis;
break;
case gcParseSimulationUsageThrottle:
bFoundAxis = TRUE;
axisNum = gcThrottleAxis;
break;
}
}
if (bFoundAxis) {
#ifdef USE_BROKEN_JOYSTICKS
DEBUGMSG(1, (TEXT("**** don't code for broken joysticks! ***\r\n")));
// If this is defined, the code assumes all joysticks have
// their physical and logical values reversed.
// Except that they tend to get the hatswitch right.
if (!(pstState->usagePage == gcParseUsagePageGenericDesktop &&
pstState->usage[0] == gcParseDesktopUsageHatSwitch)) {
pstState->logicalMin = pstState->physicalMin;
pstState->logicalMax = pstState->physicalMax;
}
#endif USE_BROKEN_JOYSTICKS
if (pstData->joy.pAxes[axisNum] == NULL) {
pstData->joy.pAxes[axisNum] = new SAxisInfo;
}
pstData->joy.pAxes[axisNum]->startBit =
pstState->curBit + (offset * pstState->reportSize);
pstData->joy.pAxes[axisNum]->length = pstState->reportSize;
pstData->joy.pAxes[axisNum]->wUsagePage = pstState->usagePage;
pstData->joy.pAxes[axisNum]->wUsage =
pstState->usage[curUsage];
pstData->joy.pAxes[axisNum]->min = pstState->logicalMin;
pstData->joy.pAxes[axisNum]->max = pstState->logicalMax;
}
// This is an attempt to deal with missing Usage(Pointer) etc
// but catch strange usages I didn't forsee (why's the joystick
// doing stylus pressure? etc).
if ((pstState->usagePage == gcParseUsagePageGenericDesktop &&
pstState->usage[curUsage] >= gcParseDesktopUsageX)
||
(pstState->usagePage == gcParseUsagePageSimulation &&
pstState->usage[curUsage] >= gcParseSimulationUsageAileron)) {
offset++;
}
}
pstState->nextFreeUsage -= curUsage;
// Deal with Buttons and Hat Switches.
// This code assumes the button and hat switch information is in
// separate Main items than the axis info (it basically has to be
// that way anyhow).
if (pstState->usagePage == gcParseUsagePageButtons) {
if (pstData->joy.buttonsLength == 0) {
pstData->joy.buttonsStartBit = pstState->curBit;
pstData->joy.buttonsLength =
pstState->reportCount * pstState->reportSize;
}
else if (pstData->joy.altButtonsLength == 0) {
pstData->joy.altButtonsStartBit = pstState->curBit;
pstData->joy.altButtonsLength =
pstState->reportCount * pstState->reportSize;
}
else {
DEBUGMSG(ZONE_ERROR,
(TEXT("!CHid::ParseJoystick: Parse Error, more than two button groups\r\n")));
}
}
else if (pstState->usagePage == gcParseUsagePageGenericDesktop &&
pstState->usage[0] == gcParseDesktopUsageHatSwitch) {
pstData->joy.hatStartBit = pstState->curBit;
pstData->joy.hatLength = pstState->reportSize;
pstData->joy.hatMin = pstState->logicalMin;
pstData->joy.hatMax = pstState->logicalMax;
}
}
pstState->curBit += pstState->reportSize * pstState->reportCount;
return (TRUE);
}
void
CHid::DumpDataDescription(SDataDescription *pstData)
{
#ifdef DEBUG
int index;
if (pstData == NULL) {
DEBUGMSG(1,(TEXT("Error, asked to dump null data description\r\n")));
return;
}
DEBUGMSG(1,(TEXT("Data Description:\r\n")));
DEBUGMSG(1,(TEXT(" H %08X N %08X id %d type %d\r\n"), pstData->pfnParseHandler,
pstData->pNext, pstData->reportId, pstData->deviceType));
switch (pstData->deviceType) {
case gcDeviceTypeKeyboard:
DEBUGMSG(1,(TEXT(" keybd, csb %02X cl %02X pc %02X asb %02X")
TEXT(" al %02X pk %08X\r\n"),
pstData->keybd.chordStartByte, pstData->keybd.chordLength,
pstData->keybd.pressedChords, pstData->keybd.arrayStartByte,
pstData->keybd.arrayLength, pstData->keybd.pressedKeys));
if (pstData->keybd.pressedKeys != NULL) {
DEBUGMSG(1,(TEXT(" Keys:\r\n")));
for (index = 0; index < pstData->keybd.arrayLength; index++) {
DEBUGMSG(1,(TEXT("\t%02X\r\n"), pstData->keybd.pressedKeys[index]));
}
}
break;
case gcDeviceTypeJoystick:
DEBUGMSG(1,(TEXT(" joystick bsb %d bl %d absb %d abl %d hsb %d")
TEXT(" hl %d hm %d hM %d\r\n"),
pstData->joy.buttonsStartBit, pstData->joy.buttonsLength,
pstData->joy.altButtonsStartBit, pstData->joy.altButtonsLength,
pstData->joy.hatStartBit, pstData->joy.hatLength,
pstData->joy.hatMin, pstData->joy.hatMax));
for (index = 0; index < gcMaxJoyAxes; index++) {
if (pstData->joy.pAxes[index] != NULL) {
DEBUGMSG(1,(TEXT(" Axis%d %08X sb %d L %d of %08X M %08X up %04X u %04X\r\n"),
index, pstData->joy.pAxes[index],
pstData->joy.pAxes[index]->startBit,
pstData->joy.pAxes[index]->length,
pstData->joy.pAxes[index]->min,
pstData->joy.pAxes[index]->max,
pstData->joy.pAxes[index]->wUsagePage,
pstData->joy.pAxes[index]->wUsage));
}
}
break;
case gcDeviceTypeMouse:
DEBUGMSG(1,(TEXT(" mouse bsb %d bl %d\r\n"),
pstData->mouse.buttonsStartBit, pstData->mouse.buttonsLength));
for (index = 0; index < gcMaxMouseAxes; index++) {
if (pstData->mouse.pAxes[index] != NULL) {
DEBUGMSG(1,(TEXT(" Axis%d %08X sb %d L %d of %08X M %08X up %04X u %04X\r\n"),
index, pstData->mouse.pAxes[index],
pstData->mouse.pAxes[index]->startBit,
pstData->mouse.pAxes[index]->length,
pstData->mouse.pAxes[index]->min,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -