windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/dx8/dll/diraw.c
2020-09-26 16:20:57 +08:00

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