494 lines
14 KiB
C
494 lines
14 KiB
C
/*****************************************************************************
|
|
*
|
|
* DIRaw.c
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* Abstract:
|
|
*
|
|
* DirectInput Raw Input Device processor.
|
|
*
|
|
* Contents:
|
|
*
|
|
* CDIRaw_RegisterRawInputDevice
|
|
* CDIRaw_UnregisterRawInputDevice
|
|
* CDIRaw_ProcessInput
|
|
* CDIRaw_OnInput
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "dinputpr.h"
|
|
|
|
#ifdef USE_WM_INPUT
|
|
|
|
#include "ntddkbd.h"
|
|
|
|
#define sqfl sqflRaw
|
|
|
|
extern DIMOUSESTATE_INT s_msEd; //in diemm.c
|
|
extern ED s_edMouse; //in diemm.c
|
|
extern ED s_edKbd; //in diemk.c
|
|
extern LPBYTE g_pbKbdXlat; //in diemk.c
|
|
|
|
static RAWMOUSE s_absrm;
|
|
static BOOL s_fFirstRaw;
|
|
|
|
#ifndef RIDEV_INPUTSINK
|
|
// RIDEV_INPUTSINK is defined in winuserp.h
|
|
#define RIDEV_INPUTSINK 0x00000100
|
|
#endif
|
|
|
|
#ifndef RIDEV_NOHOTKEYS
|
|
#define RIDEV_NOHOTKEYS 0x00000200
|
|
#endif
|
|
|
|
RAWINPUTDEVICE ridOn[] = {
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_INPUTSINK },
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE },
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_INPUTSINK },
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_NOLEGACY | RIDEV_NOHOTKEYS },
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_NOHOTKEYS },
|
|
};
|
|
|
|
RAWINPUTDEVICE ridOff[] = {
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_REMOVE },
|
|
{ HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_REMOVE },
|
|
};
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULE | CDIRaw_RegisterRawInputDevice |
|
|
*
|
|
* register raw input device.
|
|
*
|
|
* @parm IN UINT | uirim |
|
|
*
|
|
* the type of device: RIM_TYPEMOUSE or RIM_TYPEKEYBOARD
|
|
*
|
|
* @parm IN DWORD | dwOrd |
|
|
*
|
|
* dwOrd determines which item of ridOn will be used for registration.
|
|
*
|
|
* @parm IN HWND | hwnd |
|
|
*
|
|
* the window handler used by RegisterRawInputDevices.
|
|
*
|
|
* @returns
|
|
*
|
|
* S_OK - successful
|
|
* E_FAIL - otherwise
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CDIRaw_RegisterRawInputDevice( UINT uirim, DWORD dwOrd, HWND hwnd)
|
|
{
|
|
HRESULT hres;
|
|
|
|
AssertF( (uirim == RIM_TYPEMOUSE) || (uirim == RIM_TYPEKEYBOARD) );
|
|
|
|
if( hwnd ) {
|
|
ridOn[uirim*2+dwOrd].hwndTarget = hwnd;
|
|
}
|
|
|
|
if( RegisterRawInputDevices &&
|
|
RegisterRawInputDevices(&ridOn[uirim*2+dwOrd], 1, sizeof(RAWINPUTDEVICE)) ) {
|
|
SquirtSqflPtszV(sqfl, TEXT("RegisterRawInputDevice: %s, mode: %s, hwnd: 0x%08lx"),
|
|
uirim==0 ? TEXT("mouse"):TEXT("keyboard"),
|
|
dwOrd==0 ? TEXT("NONEXCL") : dwOrd==1 ? TEXT("EXCL") : TEXT("NOWIN"),
|
|
hwnd);
|
|
hres = S_OK;
|
|
} else {
|
|
hres = E_FAIL;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULE | CDIRaw_UnregisterRawInputDevice |
|
|
*
|
|
* unregister raw input device.
|
|
*
|
|
* @parm IN UINT | uirim |
|
|
*
|
|
* the type of device: RIM_TYPEMOUSE or RIM_TYPEKEYBOARD
|
|
*
|
|
* @parm IN HWND | hwnd |
|
|
*
|
|
* the window handler used by RegisterRawInputDevices.
|
|
*
|
|
* @returns
|
|
*
|
|
* S_OK - successful
|
|
* E_FAIL - otherwise
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CDIRaw_UnregisterRawInputDevice( UINT uirim, HWND hwnd )
|
|
{
|
|
HRESULT hres;
|
|
|
|
AssertF( (uirim == RIM_TYPEMOUSE) || (uirim == RIM_TYPEKEYBOARD) );
|
|
|
|
if( hwnd ) {
|
|
ridOn[uirim].hwndTarget = hwnd;
|
|
}
|
|
|
|
if( RegisterRawInputDevices &&
|
|
RegisterRawInputDevices(&ridOff[uirim], 1, sizeof(RAWINPUTDEVICE)) ) {
|
|
SquirtSqflPtszV(sqfl, TEXT("UnregisterRawInputDevice: %s, hwnd: 0x%08lx"),
|
|
uirim==0 ? TEXT("mouse"):TEXT("keyboard"), hwnd);
|
|
hres = S_OK;
|
|
} else {
|
|
hres = E_FAIL;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | CDIRaw_ProcessInput |
|
|
*
|
|
* Process raw input device data.
|
|
*
|
|
* @parm IN PRAWINPUT | pRawInput |
|
|
*
|
|
* pointer to RAWINPUT data
|
|
*
|
|
* @returns
|
|
*
|
|
* void
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void CDIRaw_ProcessInput(PRAWINPUT pRawInput)
|
|
{
|
|
HANDLE hDevice = pRawInput->header.hDevice;
|
|
|
|
if ( g_plts ) {
|
|
if( g_plts->rglhs[LLTS_MSE].cHook && pRawInput->header.dwType == RIM_TYPEMOUSE )
|
|
{
|
|
DIMOUSESTATE_INT ms;
|
|
RAWMOUSE *prm = &pRawInput->data.mouse;
|
|
|
|
memcpy(ms.rgbButtons, s_msEd.rgbButtons, cbX(ms.rgbButtons));
|
|
|
|
if( prm->usFlags & MOUSE_MOVE_ABSOLUTE ) {
|
|
if( s_fFirstRaw ) {
|
|
memcpy( &s_absrm, prm, sizeof(RAWMOUSE) );
|
|
s_fFirstRaw = FALSE;
|
|
return;
|
|
} else {
|
|
RAWMOUSE rm;
|
|
|
|
memcpy( &rm, prm, sizeof(RAWMOUSE) );
|
|
|
|
prm->lLastX -= s_absrm.lLastX;
|
|
prm->lLastY -= s_absrm.lLastY;
|
|
if ( prm->usButtonFlags & RI_MOUSE_WHEEL ) {
|
|
prm->usButtonData -= s_absrm.usButtonData;
|
|
}
|
|
|
|
memcpy( &s_absrm, &rm, sizeof(RAWMOUSE) );
|
|
}
|
|
}
|
|
|
|
ms.lX = prm->lLastX;
|
|
ms.lY = prm->lLastY;
|
|
if ( prm->usButtonFlags & RI_MOUSE_WHEEL ) {
|
|
ms.lZ = (short)prm->usButtonData;
|
|
} else {
|
|
ms.lZ = 0;
|
|
}
|
|
|
|
if( prm->usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN ) {
|
|
ms.rgbButtons[0] = 0x80;
|
|
} else if (prm->usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP ) {
|
|
ms.rgbButtons[0] = 0x00;
|
|
}
|
|
|
|
if( prm->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN ) {
|
|
ms.rgbButtons[1] = 0x80;
|
|
} else if (prm->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) {
|
|
ms.rgbButtons[1] = 0x00;
|
|
}
|
|
|
|
if( prm->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN ) {
|
|
ms.rgbButtons[2] = 0x80;
|
|
} else if( prm->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP ) {
|
|
ms.rgbButtons[2] = 0x00;
|
|
}
|
|
|
|
if( prm->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN ) {
|
|
ms.rgbButtons[3] = 0x80;
|
|
} else if( prm->usButtonFlags & RI_MOUSE_BUTTON_4_UP ) {
|
|
ms.rgbButtons[3] = 0x00;
|
|
}
|
|
|
|
if( prm->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN ) {
|
|
ms.rgbButtons[4] = 0x80;
|
|
} else if ( prm->usButtonFlags & RI_MOUSE_BUTTON_5_UP ) {
|
|
ms.rgbButtons[4] = 0x00;
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
char buf[128];
|
|
static DWORD cnt = 0;
|
|
|
|
wsprintfA(buf, "%d: x: %ld (%ld), y: %ld (%ld), z: %ld, rgb[0]: 0x%lx, rgb[4]: 0x%lx", cnt, prm->lLastX,ms.lX, prm->lLastY, ms.lY, (short)prm->usButtonData,*(DWORD *)ms.rgbButtons,*(DWORD *)&ms.rgbButtons[4]);
|
|
RPF(buf);
|
|
cnt++;
|
|
}
|
|
#endif
|
|
|
|
CEm_Mouse_AddState(&ms, GetTickCount());
|
|
|
|
} else
|
|
if ( g_plts->rglhs[LLTS_KBD].cHook && pRawInput->header.dwType == RIM_TYPEKEYBOARD ) {
|
|
RAWKEYBOARD *prk = &pRawInput->data.keyboard;
|
|
BYTE bAction, bScan;
|
|
static BOOL fE1 = FALSE;
|
|
|
|
bAction = (prk->Flags & KEY_BREAK) ? 0 : 0x80;
|
|
bScan = (BYTE)prk->MakeCode;
|
|
|
|
if( prk->Flags & KEY_E0 ) {
|
|
if( bScan == 0x2A ) { //special extra scancode when pressing PrtScn
|
|
return;
|
|
} else {
|
|
bScan |= 0x80;
|
|
}
|
|
} else if( prk->Flags & KEY_E1 ) { //special key: PAUSE
|
|
fE1 = TRUE;
|
|
|
|
// now, we need to bypass 0x1d key for compitibility with low level hook.
|
|
if( bScan == 0x1d ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( fE1 ) {
|
|
// This is the work around for bug 288535.
|
|
// But we really don't want to fix it in this way.
|
|
//if( !bAction ) {
|
|
// Sleep(80);
|
|
//}
|
|
bScan |= 0x80;
|
|
fE1 = FALSE;
|
|
}
|
|
|
|
AssertF(g_pbKbdXlat);
|
|
if( bScan != 0x45 && bScan != 0xc5 ) {
|
|
bScan = g_pbKbdXlat[bScan];
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
char buf[128];
|
|
static DWORD cnt = 0;
|
|
|
|
wsprintfA(buf, "%d: bAction: 0x%lx, bScan: 0x%lx, Flags: 0x%lx, Make: 0x%lx", cnt, bAction, bScan, prk->Flags,prk->MakeCode);
|
|
RPF(buf);
|
|
cnt++;
|
|
}
|
|
#endif
|
|
|
|
CEm_AddEvent(&s_edKbd, bAction, bScan, GetTickCount());
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | CDIRaw_OnInput |
|
|
*
|
|
* WM_INPUT message handler used by CEm_LL_ThreadProc (in diem.c).
|
|
*
|
|
* @parm IN MSG * | pmsg |
|
|
*
|
|
* pointer to MSG
|
|
*
|
|
* @returns
|
|
*
|
|
* TRUE = Successful
|
|
* FALSE = otherwise
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL CDIRaw_OnInput(MSG *pmsg)
|
|
{
|
|
BOOL fRtn = FALSE;
|
|
HRAWINPUT hRawInput = (HRAWINPUT)pmsg->lParam;
|
|
PRAWINPUT pRawInput;
|
|
UINT cbSize;
|
|
BYTE pbBuf[512];
|
|
BOOL fMalloc;
|
|
UINT uiRtn;
|
|
|
|
//
|
|
// Firstly, get the size of this Raw Input.
|
|
//
|
|
if ( (uiRtn = GetRawInputData(hRawInput, RID_INPUT, NULL, &cbSize, sizeof(RAWINPUTHEADER))) != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Allocate required memory.
|
|
//
|
|
if( cbSize < cbX(pbBuf) ) {
|
|
pRawInput = (PRAWINPUT)pbBuf;
|
|
fMalloc = FALSE;
|
|
} else {
|
|
pRawInput = (PRAWINPUT)malloc(cbSize);
|
|
if (pRawInput == NULL) {
|
|
RPF("Failed to allocate pRawInput\n");
|
|
return FALSE;
|
|
}
|
|
fMalloc = TRUE;
|
|
}
|
|
|
|
//
|
|
// Receive the content of the Raw Input.
|
|
//
|
|
if (GetRawInputData(hRawInput, RID_INPUT, pRawInput, &cbSize, sizeof(RAWINPUTHEADER)) > 0) {
|
|
//
|
|
// Call the handler of ours, to start/continue/stop drawing.
|
|
//
|
|
CDIRaw_ProcessInput(pRawInput);
|
|
}
|
|
|
|
// no longer needed.
|
|
if( fMalloc ) {
|
|
free(pRawInput);
|
|
pRawInput = NULL;
|
|
}
|
|
|
|
return fRtn;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULT | CDIRaw_Mouse_InitButtons |
|
|
*
|
|
* Initialize the mouse state in preparation for acquisition.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT INTERNAL
|
|
CDIRaw_Mouse_InitButtons(void)
|
|
{
|
|
if (s_edMouse.cAcquire < 0) {
|
|
s_fFirstRaw = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc EXTERNAL
|
|
*
|
|
* @func int | DIRaw_GetKeyboardType |
|
|
*
|
|
* Return keyboard type (nTypeFlag==0) or subtype (nTypeFlag==1).
|
|
*
|
|
*****************************************************************************/
|
|
|
|
int EXTERNAL
|
|
DIRaw_GetKeyboardType(int nTypeFlag)
|
|
{
|
|
PRAWINPUTDEVICELIST pList = NULL;
|
|
UINT uiNumDevices = 0;
|
|
DWORD dwType;
|
|
int nResult = 0;
|
|
|
|
if (GetRawInputDeviceList(NULL, &uiNumDevices, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
|
|
SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: failed to get the number of devices."));
|
|
goto _DIRAWGKT_EXIT;
|
|
}
|
|
|
|
if( uiNumDevices ) {
|
|
pList = malloc(sizeof(RAWINPUTDEVICELIST) * uiNumDevices);
|
|
if( !pList ) {
|
|
SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: malloc failed."));
|
|
goto _DIRAWGKT_EXIT;
|
|
}
|
|
|
|
if (GetRawInputDeviceList(pList, &uiNumDevices, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
|
|
SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: failed to get device list."));
|
|
goto _DIRAWGKT_EXIT;
|
|
} else {
|
|
UINT i;
|
|
UINT uiLen;
|
|
UINT cbSize;
|
|
RID_DEVICE_INFO info;
|
|
|
|
info.cbSize = sizeof(RID_DEVICE_INFO);
|
|
|
|
for (i = 0; i<uiNumDevices; ++i)
|
|
{
|
|
if (pList[i].dwType == RIM_TYPEKEYBOARD)
|
|
{
|
|
uiLen = 0;
|
|
|
|
// Get device name
|
|
if (GetRawInputDeviceInfo(pList[i].hDevice, RIDI_DEVICENAME, NULL, &uiLen)) {
|
|
continue;
|
|
}
|
|
|
|
// Get device type info.
|
|
cbSize = sizeof(RID_DEVICE_INFO);
|
|
if (GetRawInputDeviceInfo(pList[i].hDevice, RIDI_DEVICEINFO, &info, &cbSize) == (UINT)-1) {
|
|
continue;
|
|
}
|
|
|
|
if( nTypeFlag == 0 || nTypeFlag == 1) //keyboard type or subtype
|
|
{
|
|
dwType = info.keyboard.dwType;
|
|
if( dwType == 4 || dwType == 7 || dwType == 8 ) {
|
|
nResult = (nTypeFlag==0) ? info.keyboard.dwType : info.keyboard.dwSubType;
|
|
break;
|
|
}
|
|
} else
|
|
{
|
|
RPF("DIRaw_GetKeyboardType: wrong argument, %d is not supported.", nTypeFlag);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_DIRAWGKT_EXIT:
|
|
if( pList ) {
|
|
free(pList);
|
|
}
|
|
|
|
if( !nResult ) {
|
|
nResult = GetKeyboardType(nTypeFlag);
|
|
}
|
|
|
|
SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: %s: %d"),
|
|
nTypeFlag==0 ? TEXT("type"):TEXT("sybtype"), nResult);
|
|
|
|
return nResult;
|
|
}
|
|
|
|
#endif
|