📄 hid.cpp
字号:
(TEXT("!CHid::SubmitInterrupt: Error, interrupt buffer size set to 0\r\n")));
return FALSE;
}
memset(pstHidDevice->pDataBuffer, 0, size);
pstHidDevice->signalStatus |= gcSignalStatusIntrPending;
RETAILMSG(RETAIL_ZONE_HID,(TEXT("HID::SubmitInterrupt: Calling IssueTransfer for device %08x, buf: %08x.\r\n"), pstHidDevice, pstHidDevice->pDataBuffer ));
pstHidDevice->hIntrTransfer =
m_lpUsbFuncs->lpIssueInterruptTransfer(pstHidDevice->hIntrPipe,
InterruptCompletionStub,
pstHidDevice,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
size,
pstHidDevice->pDataBuffer,
NULL);
if (pstHidDevice->hIntrTransfer == NULL) {
DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::SubmitInterrupt, Error %u in IssueInterruptTransfer\r\n"),
GetLastError()));
pstHidDevice->signalStatus &= ~gcSignalStatusIntrPending;
return FALSE;
}
return TRUE;
}
BOOL
CHid::InterpretData(
SHidDevice *pstHidDevice)
{
SDataDescription *pstData = pstHidDevice->pstDataDescriptionHead;
UINT8 reportId = pstHidDevice->pDataBuffer[0];
PBYTE pDataBuffer = pstHidDevice->pDataBuffer;
if (pstData == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("!HID: Error receiving data before parsing the report descriptor.\r\n")));
return (FALSE);
}
if (pstData->reportId != 0x00) {
while (pstData != NULL && pstData->reportId != reportId) {
pstData = pstData->pNext;
}
if (pstData == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("HID: Error receiving data with bad reportId\r\n")));
return (FALSE);
}
}
// Keyboards and mice are special because they give data to windows even if
// Direct Input isn't running.
if (pstData->deviceType == gcDeviceTypeKeyboard) {
EnterCriticalSection(&pstHidDevice->csLock);
InterpretDataAsKeyboard(pstHidDevice, pstHidDevice->pDataBuffer,
pstData);
LeaveCriticalSection(&pstHidDevice->csLock);
return (TRUE);
}
else if (pstData->deviceType == gcDeviceTypeMouse) {
EnterCriticalSection(&pstHidDevice->csLock);
InterpretDataAsMouse(pstHidDevice, pstHidDevice->pDataBuffer,
pstData);
LeaveCriticalSection(&pstHidDevice->csLock);
return (TRUE);
}
else if (!pstHidDevice->bAcquired) {
// If we're not a keyboard and we're not acquired, pitch the data.
return (TRUE);
}
// pUserData is allocated on SetFormat, and it is required that they
// set format before they acquire the device.
ASSERT(pstHidDevice->pUserData != NULL);
// TMPTMPTMP
if (pstHidDevice->pUserData == NULL) {
pstHidDevice->pUserData = new BYTE[100];
}
switch (pstData->deviceType) {
case gcDeviceTypeJoystick:
EnterCriticalSection(&pstHidDevice->csLock);
InterpretDataAsJoystick(pstHidDevice, pstHidDevice->pDataBuffer,
pstData);
LeaveCriticalSection(&pstHidDevice->csLock);
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("!HID: Error, device type 0x%X unknown\r\n"),pstData->deviceType));
return (FALSE);
break;
}
return (TRUE);
}
DWORD
CHid::ConvertDataToDword(
UINT startBit,
UINT length,
BOOL bSigned,
BYTE *pBuffer)
{
UINT startByte;
UINT remainingBits;
DWORD dwData;
startByte = startBit / gcBitsPerByte;
remainingBits = startBit % gcBitsPerByte;
dwData = *(DWORD UNALIGNED *)&pBuffer[startByte];
if (length + remainingBits <= gcBitsPerInt32) {
// Normal case, data did NOT span 5 bytes
dwData <<= gcBitsPerInt32 - length - remainingBits;
if (bSigned) {
dwData = (signed)dwData >> (gcBitsPerInt32 - length);
}
else {
dwData >>= gcBitsPerInt32 - length;
}
}
else {
// Annoying case. Couldn't they have planned this better?
dwData >>= remainingBits;
dwData |= (pBuffer[startByte + 4]) <<
(gcBitsPerInt32 - gcBitsPerByte);
if (remainingBits + length < gcBitsPerInt32) {
// Argh! Now I've got to clear the top bits.
UINT shiftAmount = gcBitsPerInt32 -
(length + remainingBits);
dwData <<= shiftAmount;
if (bSigned) {
dwData = (signed)dwData >> shiftAmount;
}
else {
dwData >>= shiftAmount;
}
}
}
return (dwData);
}
BOOL
CHid::InterpretDataAsJoystick(
SHidDevice *pstHidDevice,
PBYTE pDataBuffer,
SDataDescription *pstData)
{
UnusedParameter(pstHidDevice);
UINT axis, button;
UINT32 joyButtons = 0;
UINT32 joyHat = DWORD(-1);
SAxisInfo *pAxis;
UINT32 dwData;
BOOL bSigned;
BYTE offset;
DEBUGMSG(ZONE_JOYSTICK,(TEXT("Joystick Data")));
for (axis = 0; axis < gcMaxJoyAxes; axis++) {
pAxis = pstData->joy.pAxes[axis];
if (pAxis == NULL) {
DEBUGMSG(ZONE_JOYSTICK,(TEXT(" XX")));
continue;
}
if (pAxis->length > gcBitsPerInt32) {
DEBUGMSG(ZONE_ERROR,
(TEXT("HID: Error. Ignoring >32bit data field\r\n")));
continue;
}
bSigned = pAxis->min < 0;
dwData = ConvertDataToDword(pAxis->startBit, pAxis->length, bSigned,
pDataBuffer);
// normalize the value to the range 0 - max
dwData -= pAxis->min;
offset = pstData->joy.pAxes[axis]->offset;
if (offset != gcInvalidOffset) {
*(DWORD*)(&pstHidDevice->pUserData[offset]) = dwData;
}
DEBUGMSG(ZONE_JOYSTICK,(TEXT(" %d"), dwData));
}
if (pstData->joy.buttonsLength != 0) {
UINT numButtons =
pstData->joy.buttonsLength + pstData->joy.altButtonsLength;
joyButtons = ConvertDataToDword(pstData->joy.buttonsStartBit,
pstData->joy.buttonsLength, FALSE, pDataBuffer);
if (pstData->joy.altButtonsLength != 0) {
dwData = ConvertDataToDword(pstData->joy.altButtonsStartBit,
pstData->joy.altButtonsLength, FALSE, pDataBuffer);
joyButtons |= dwData << pstData->joy.buttonsLength;
}
DEBUGMSG(ZONE_JOYSTICK,(TEXT(" %08X"), joyButtons));
for (button = 0; button < numButtons; button++) {
offset = pstData->joy.pButtonOffsets[button];
if (offset != gcInvalidOffset) {
if ((joyButtons & 0x01) != 0) {
pstHidDevice->pUserData[offset] = DI_BUTTON_DOWN;
}
else {
pstHidDevice->pUserData[offset] = DI_BUTTON_UP;
}
}
joyButtons >>= 1;
}
}
if (pstData->joy.hatLength != 0) {
DWORD increment;
DWORD range = pstData->joy.hatMax - pstData->joy.hatMin + 1;
increment = gcHatIncrements / range;
dwData = ConvertDataToDword(pstData->joy.hatStartBit,
pstData->joy.hatLength, FALSE, pDataBuffer);
if (dwData < pstData->joy.hatMin || dwData > pstData->joy.hatMax) {
joyHat = DWORD(-1);
}
else {
joyHat = (dwData - pstData->joy.hatMin) * increment;
}
#ifdef DEBUG
if (ZONE_JOYSTICK) {
DEBUGMSG(ZONE_JOYSTICK,(TEXT(" %d"), joyHat));
}
#endif // DEBUG
offset = pstData->joy.hatOffset;
if (offset != gcInvalidOffset) {
*(DWORD*)(&pstHidDevice->pUserData[offset]) = joyHat;
}
}
#ifdef DEBUG
if (ZONE_JOYSTICK) {
DEBUGMSG(ZONE_JOYSTICK,(TEXT("\r\n")));
}
#endif // DEBUG
return (TRUE);
}
BOOL
CHid::InterpretDataAsMouse(
SHidDevice *pstHidDevice,
PBYTE pDataBuffer,
SDataDescription *pstData)
{
UnusedParameter(pstHidDevice);
UINT axis, button;
UINT32 mouseButtons = 0;
SAxisInfo *pAxis;
UINT32 dwData;
BOOL bSigned;
BYTE offset;
DWORD dx = 0;
DWORD dy = 0;
DWORD dwFlags = 0;
DWORD prevButtons;
#ifdef DEBUG
if (ZONE_MOUSE) {
DEBUGMSG(1,(TEXT("Mouse Data")));
}
#endif // DEBUG
for (axis = 0; axis < gcMaxMouseAxes; axis++) {
pAxis = pstData->mouse.pAxes[axis];
if (pAxis == NULL) {
#ifdef DEBUG
if (ZONE_MOUSE) {
DEBUGMSG(1,(TEXT(" XX")));
}
#endif // DEBUG
continue;
}
if (pAxis->length > gcBitsPerInt32) {
DEBUGMSG(ZONE_ERROR,
(TEXT("HID: Error. Ignoring >32bit data field\r\n")));
continue;
}
bSigned = pAxis->min < 0;
dwData = ConvertDataToDword(pAxis->startBit, pAxis->length, bSigned,
pDataBuffer);
if (axis == gcXAxis) {
dx = dwData;
dwFlags |= MOUSEEVENTF_MOVE;
}
else if (axis == gcYAxis) {
dy = dwData;
dwFlags |= MOUSEEVENTF_MOVE;
}
#ifdef DEBUG
if (ZONE_MOUSE) {
DEBUGMSG(1,(TEXT(" %d"), dwData));
}
#endif // DEBUG
// Only do Direct Input stuff if we're acquired by DI.
if (pstHidDevice->bAcquired) {
offset = pstData->mouse.pAxes[axis]->offset;
if (offset != gcInvalidOffset) {
// We want to accumulate mouse moves so we'll add rather than
// set. When Direct Input reads this I zero it.
*(LONG*)(&pstHidDevice->pUserData[offset]) += (LONG)dwData;
}
}
}
if (pstData->mouse.buttonsLength != 0) {
UINT numButtons = pstData->mouse.buttonsLength;
mouseButtons = ConvertDataToDword(pstData->mouse.buttonsStartBit,
pstData->mouse.buttonsLength, FALSE, pDataBuffer);
prevButtons = pstData->mouse.prevButtons;
pstData->mouse.prevButtons = mouseButtons;
#ifdef DEBUG
if (ZONE_MOUSE) {
DEBUGMSG(1,(TEXT(" %08X"), mouseButtons));
}
#endif // DEBUG
for (button = 0; button < numButtons; button++) {
if ((mouseButtons & 0x01) && !(prevButtons & 0x01)) {
switch (button) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -