Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

493 lines
14 KiB

  1. /*****************************************************************************
  2. *
  3. * DIRaw.c
  4. *
  5. * Copyright (c) 2000 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * DirectInput Raw Input Device processor.
  10. *
  11. * Contents:
  12. *
  13. * CDIRaw_RegisterRawInputDevice
  14. * CDIRaw_UnregisterRawInputDevice
  15. * CDIRaw_ProcessInput
  16. * CDIRaw_OnInput
  17. *
  18. *****************************************************************************/
  19. #include "dinputpr.h"
  20. #ifdef USE_WM_INPUT
  21. #include "ntddkbd.h"
  22. #define sqfl sqflRaw
  23. extern DIMOUSESTATE_INT s_msEd; //in diemm.c
  24. extern ED s_edMouse; //in diemm.c
  25. extern ED s_edKbd; //in diemk.c
  26. extern LPBYTE g_pbKbdXlat; //in diemk.c
  27. static RAWMOUSE s_absrm;
  28. static BOOL s_fFirstRaw;
  29. #ifndef RIDEV_INPUTSINK
  30. // RIDEV_INPUTSINK is defined in winuserp.h
  31. #define RIDEV_INPUTSINK 0x00000100
  32. #endif
  33. #ifndef RIDEV_NOHOTKEYS
  34. #define RIDEV_NOHOTKEYS 0x00000200
  35. #endif
  36. RAWINPUTDEVICE ridOn[] = {
  37. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_INPUTSINK },
  38. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE },
  39. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_INPUTSINK },
  40. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_NOLEGACY | RIDEV_NOHOTKEYS },
  41. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_NOHOTKEYS },
  42. };
  43. RAWINPUTDEVICE ridOff[] = {
  44. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, RIDEV_REMOVE },
  45. { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD, RIDEV_REMOVE },
  46. };
  47. /*****************************************************************************
  48. *
  49. * @doc INTERNAL
  50. *
  51. * @func HRESULE | CDIRaw_RegisterRawInputDevice |
  52. *
  53. * register raw input device.
  54. *
  55. * @parm IN UINT | uirim |
  56. *
  57. * the type of device: RIM_TYPEMOUSE or RIM_TYPEKEYBOARD
  58. *
  59. * @parm IN DWORD | dwOrd |
  60. *
  61. * dwOrd determines which item of ridOn will be used for registration.
  62. *
  63. * @parm IN HWND | hwnd |
  64. *
  65. * the window handler used by RegisterRawInputDevices.
  66. *
  67. * @returns
  68. *
  69. * S_OK - successful
  70. * E_FAIL - otherwise
  71. *
  72. *****************************************************************************/
  73. HRESULT CDIRaw_RegisterRawInputDevice( UINT uirim, DWORD dwOrd, HWND hwnd)
  74. {
  75. HRESULT hres;
  76. AssertF( (uirim == RIM_TYPEMOUSE) || (uirim == RIM_TYPEKEYBOARD) );
  77. if( hwnd ) {
  78. ridOn[uirim*2+dwOrd].hwndTarget = hwnd;
  79. }
  80. if( RegisterRawInputDevices &&
  81. RegisterRawInputDevices(&ridOn[uirim*2+dwOrd], 1, sizeof(RAWINPUTDEVICE)) ) {
  82. SquirtSqflPtszV(sqfl, TEXT("RegisterRawInputDevice: %s, mode: %s, hwnd: 0x%08lx"),
  83. uirim==0 ? TEXT("mouse"):TEXT("keyboard"),
  84. dwOrd==0 ? TEXT("NONEXCL") : dwOrd==1 ? TEXT("EXCL") : TEXT("NOWIN"),
  85. hwnd);
  86. hres = S_OK;
  87. } else {
  88. hres = E_FAIL;
  89. }
  90. return hres;
  91. }
  92. /*****************************************************************************
  93. *
  94. * @doc INTERNAL
  95. *
  96. * @func HRESULE | CDIRaw_UnregisterRawInputDevice |
  97. *
  98. * unregister raw input device.
  99. *
  100. * @parm IN UINT | uirim |
  101. *
  102. * the type of device: RIM_TYPEMOUSE or RIM_TYPEKEYBOARD
  103. *
  104. * @parm IN HWND | hwnd |
  105. *
  106. * the window handler used by RegisterRawInputDevices.
  107. *
  108. * @returns
  109. *
  110. * S_OK - successful
  111. * E_FAIL - otherwise
  112. *
  113. *****************************************************************************/
  114. HRESULT CDIRaw_UnregisterRawInputDevice( UINT uirim, HWND hwnd )
  115. {
  116. HRESULT hres;
  117. AssertF( (uirim == RIM_TYPEMOUSE) || (uirim == RIM_TYPEKEYBOARD) );
  118. if( hwnd ) {
  119. ridOn[uirim].hwndTarget = hwnd;
  120. }
  121. if( RegisterRawInputDevices &&
  122. RegisterRawInputDevices(&ridOff[uirim], 1, sizeof(RAWINPUTDEVICE)) ) {
  123. SquirtSqflPtszV(sqfl, TEXT("UnregisterRawInputDevice: %s, hwnd: 0x%08lx"),
  124. uirim==0 ? TEXT("mouse"):TEXT("keyboard"), hwnd);
  125. hres = S_OK;
  126. } else {
  127. hres = E_FAIL;
  128. }
  129. return hres;
  130. }
  131. /*****************************************************************************
  132. *
  133. * @doc INTERNAL
  134. *
  135. * @func void | CDIRaw_ProcessInput |
  136. *
  137. * Process raw input device data.
  138. *
  139. * @parm IN PRAWINPUT | pRawInput |
  140. *
  141. * pointer to RAWINPUT data
  142. *
  143. * @returns
  144. *
  145. * void
  146. *
  147. *****************************************************************************/
  148. void CDIRaw_ProcessInput(PRAWINPUT pRawInput)
  149. {
  150. HANDLE hDevice = pRawInput->header.hDevice;
  151. if ( g_plts ) {
  152. if( g_plts->rglhs[LLTS_MSE].cHook && pRawInput->header.dwType == RIM_TYPEMOUSE )
  153. {
  154. DIMOUSESTATE_INT ms;
  155. RAWMOUSE *prm = &pRawInput->data.mouse;
  156. memcpy(ms.rgbButtons, s_msEd.rgbButtons, cbX(ms.rgbButtons));
  157. if( prm->usFlags & MOUSE_MOVE_ABSOLUTE ) {
  158. if( s_fFirstRaw ) {
  159. memcpy( &s_absrm, prm, sizeof(RAWMOUSE) );
  160. s_fFirstRaw = FALSE;
  161. return;
  162. } else {
  163. RAWMOUSE rm;
  164. memcpy( &rm, prm, sizeof(RAWMOUSE) );
  165. prm->lLastX -= s_absrm.lLastX;
  166. prm->lLastY -= s_absrm.lLastY;
  167. if ( prm->usButtonFlags & RI_MOUSE_WHEEL ) {
  168. prm->usButtonData -= s_absrm.usButtonData;
  169. }
  170. memcpy( &s_absrm, &rm, sizeof(RAWMOUSE) );
  171. }
  172. }
  173. ms.lX = prm->lLastX;
  174. ms.lY = prm->lLastY;
  175. if ( prm->usButtonFlags & RI_MOUSE_WHEEL ) {
  176. ms.lZ = (short)prm->usButtonData;
  177. } else {
  178. ms.lZ = 0;
  179. }
  180. if( prm->usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN ) {
  181. ms.rgbButtons[0] = 0x80;
  182. } else if (prm->usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP ) {
  183. ms.rgbButtons[0] = 0x00;
  184. }
  185. if( prm->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN ) {
  186. ms.rgbButtons[1] = 0x80;
  187. } else if (prm->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) {
  188. ms.rgbButtons[1] = 0x00;
  189. }
  190. if( prm->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN ) {
  191. ms.rgbButtons[2] = 0x80;
  192. } else if( prm->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP ) {
  193. ms.rgbButtons[2] = 0x00;
  194. }
  195. if( prm->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN ) {
  196. ms.rgbButtons[3] = 0x80;
  197. } else if( prm->usButtonFlags & RI_MOUSE_BUTTON_4_UP ) {
  198. ms.rgbButtons[3] = 0x00;
  199. }
  200. if( prm->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN ) {
  201. ms.rgbButtons[4] = 0x80;
  202. } else if ( prm->usButtonFlags & RI_MOUSE_BUTTON_5_UP ) {
  203. ms.rgbButtons[4] = 0x00;
  204. }
  205. #if 0
  206. {
  207. char buf[128];
  208. static DWORD cnt = 0;
  209. 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]);
  210. RPF(buf);
  211. cnt++;
  212. }
  213. #endif
  214. CEm_Mouse_AddState(&ms, GetTickCount());
  215. } else
  216. if ( g_plts->rglhs[LLTS_KBD].cHook && pRawInput->header.dwType == RIM_TYPEKEYBOARD ) {
  217. RAWKEYBOARD *prk = &pRawInput->data.keyboard;
  218. BYTE bAction, bScan;
  219. static BOOL fE1 = FALSE;
  220. bAction = (prk->Flags & KEY_BREAK) ? 0 : 0x80;
  221. bScan = (BYTE)prk->MakeCode;
  222. if( prk->Flags & KEY_E0 ) {
  223. if( bScan == 0x2A ) { //special extra scancode when pressing PrtScn
  224. return;
  225. } else {
  226. bScan |= 0x80;
  227. }
  228. } else if( prk->Flags & KEY_E1 ) { //special key: PAUSE
  229. fE1 = TRUE;
  230. // now, we need to bypass 0x1d key for compitibility with low level hook.
  231. if( bScan == 0x1d ) {
  232. return;
  233. }
  234. }
  235. if( fE1 ) {
  236. // This is the work around for bug 288535.
  237. // But we really don't want to fix it in this way.
  238. //if( !bAction ) {
  239. // Sleep(80);
  240. //}
  241. bScan |= 0x80;
  242. fE1 = FALSE;
  243. }
  244. AssertF(g_pbKbdXlat);
  245. if( bScan != 0x45 && bScan != 0xc5 ) {
  246. bScan = g_pbKbdXlat[bScan];
  247. }
  248. #if 0
  249. {
  250. char buf[128];
  251. static DWORD cnt = 0;
  252. wsprintfA(buf, "%d: bAction: 0x%lx, bScan: 0x%lx, Flags: 0x%lx, Make: 0x%lx", cnt, bAction, bScan, prk->Flags,prk->MakeCode);
  253. RPF(buf);
  254. cnt++;
  255. }
  256. #endif
  257. CEm_AddEvent(&s_edKbd, bAction, bScan, GetTickCount());
  258. }
  259. }
  260. return;
  261. }
  262. /*****************************************************************************
  263. *
  264. * @doc INTERNAL
  265. *
  266. * @func void | CDIRaw_OnInput |
  267. *
  268. * WM_INPUT message handler used by CEm_LL_ThreadProc (in diem.c).
  269. *
  270. * @parm IN MSG * | pmsg |
  271. *
  272. * pointer to MSG
  273. *
  274. * @returns
  275. *
  276. * TRUE = Successful
  277. * FALSE = otherwise
  278. *
  279. *****************************************************************************/
  280. BOOL CDIRaw_OnInput(MSG *pmsg)
  281. {
  282. BOOL fRtn = FALSE;
  283. HRAWINPUT hRawInput = (HRAWINPUT)pmsg->lParam;
  284. PRAWINPUT pRawInput;
  285. UINT cbSize;
  286. BYTE pbBuf[512];
  287. BOOL fMalloc;
  288. UINT uiRtn;
  289. //
  290. // Firstly, get the size of this Raw Input.
  291. //
  292. if ( (uiRtn = GetRawInputData(hRawInput, RID_INPUT, NULL, &cbSize, sizeof(RAWINPUTHEADER))) != 0) {
  293. return FALSE;
  294. }
  295. //
  296. // Allocate required memory.
  297. //
  298. if( cbSize < cbX(pbBuf) ) {
  299. pRawInput = (PRAWINPUT)pbBuf;
  300. fMalloc = FALSE;
  301. } else {
  302. pRawInput = (PRAWINPUT)malloc(cbSize);
  303. if (pRawInput == NULL) {
  304. RPF("Failed to allocate pRawInput\n");
  305. return FALSE;
  306. }
  307. fMalloc = TRUE;
  308. }
  309. //
  310. // Receive the content of the Raw Input.
  311. //
  312. if (GetRawInputData(hRawInput, RID_INPUT, pRawInput, &cbSize, sizeof(RAWINPUTHEADER)) > 0) {
  313. //
  314. // Call the handler of ours, to start/continue/stop drawing.
  315. //
  316. CDIRaw_ProcessInput(pRawInput);
  317. }
  318. // no longer needed.
  319. if( fMalloc ) {
  320. free(pRawInput);
  321. pRawInput = NULL;
  322. }
  323. return fRtn;
  324. }
  325. /*****************************************************************************
  326. *
  327. * @doc INTERNAL
  328. *
  329. * @func HRESULT | CDIRaw_Mouse_InitButtons |
  330. *
  331. * Initialize the mouse state in preparation for acquisition.
  332. *
  333. *****************************************************************************/
  334. HRESULT INTERNAL
  335. CDIRaw_Mouse_InitButtons(void)
  336. {
  337. if (s_edMouse.cAcquire < 0) {
  338. s_fFirstRaw = TRUE;
  339. }
  340. return S_OK;
  341. }
  342. /*****************************************************************************
  343. *
  344. * @doc EXTERNAL
  345. *
  346. * @func int | DIRaw_GetKeyboardType |
  347. *
  348. * Return keyboard type (nTypeFlag==0) or subtype (nTypeFlag==1).
  349. *
  350. *****************************************************************************/
  351. int EXTERNAL
  352. DIRaw_GetKeyboardType(int nTypeFlag)
  353. {
  354. PRAWINPUTDEVICELIST pList = NULL;
  355. UINT uiNumDevices = 0;
  356. DWORD dwType;
  357. int nResult = 0;
  358. if (GetRawInputDeviceList(NULL, &uiNumDevices, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
  359. SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: failed to get the number of devices."));
  360. goto _DIRAWGKT_EXIT;
  361. }
  362. if( uiNumDevices ) {
  363. pList = malloc(sizeof(RAWINPUTDEVICELIST) * uiNumDevices);
  364. if( !pList ) {
  365. SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: malloc failed."));
  366. goto _DIRAWGKT_EXIT;
  367. }
  368. if (GetRawInputDeviceList(pList, &uiNumDevices, sizeof(RAWINPUTDEVICELIST)) == (UINT)-1) {
  369. SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: failed to get device list."));
  370. goto _DIRAWGKT_EXIT;
  371. } else {
  372. UINT i;
  373. UINT uiLen;
  374. UINT cbSize;
  375. RID_DEVICE_INFO info;
  376. info.cbSize = sizeof(RID_DEVICE_INFO);
  377. for (i = 0; i<uiNumDevices; ++i)
  378. {
  379. if (pList[i].dwType == RIM_TYPEKEYBOARD)
  380. {
  381. uiLen = 0;
  382. // Get device name
  383. if (GetRawInputDeviceInfo(pList[i].hDevice, RIDI_DEVICENAME, NULL, &uiLen)) {
  384. continue;
  385. }
  386. // Get device type info.
  387. cbSize = sizeof(RID_DEVICE_INFO);
  388. if (GetRawInputDeviceInfo(pList[i].hDevice, RIDI_DEVICEINFO, &info, &cbSize) == (UINT)-1) {
  389. continue;
  390. }
  391. if( nTypeFlag == 0 || nTypeFlag == 1) //keyboard type or subtype
  392. {
  393. dwType = info.keyboard.dwType;
  394. if( dwType == 4 || dwType == 7 || dwType == 8 ) {
  395. nResult = (nTypeFlag==0) ? info.keyboard.dwType : info.keyboard.dwSubType;
  396. break;
  397. }
  398. } else
  399. {
  400. RPF("DIRaw_GetKeyboardType: wrong argument, %d is not supported.", nTypeFlag);
  401. }
  402. }
  403. }
  404. }
  405. }
  406. _DIRAWGKT_EXIT:
  407. if( pList ) {
  408. free(pList);
  409. }
  410. if( !nResult ) {
  411. nResult = GetKeyboardType(nTypeFlag);
  412. }
  413. SquirtSqflPtszV(sqfl, TEXT("DIRaw_GetKeyboardType: %s: %d"),
  414. nTypeFlag==0 ? TEXT("type"):TEXT("sybtype"), nResult);
  415. return nResult;
  416. }
  417. #endif