Removed resource.h.
[wine.git] / windows / dinput.c
blob696e533fee943f26ff67957018e0f64b6965bf6c
1 /* DirectInput
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
6 */
7 /* Status:
9 * - Tomb Raider 2 Demo:
10 * Playable using keyboard only.
11 * - WingCommander Prophecy Demo:
12 * Doesn't get Input Focus.
14 * - Fallout : works great in X and DGA mode
16 * FIXME: The keyboard handling needs to (and will) be merged into keyboard.c
17 * (The current implementation is currently only a proof of concept and
18 * an utter mess.)
21 #include "config.h"
22 #include <string.h>
23 #include <time.h>
24 #include <unistd.h>
25 #include <assert.h>
26 #ifdef HAVE_SYS_SIGNAL_H
27 # include <sys/signal.h>
28 #endif
29 #include <sys/time.h>
30 #include <sys/fcntl.h>
31 #include <sys/ioctl.h>
32 #include <errno.h>
33 #ifdef HAVE_SYS_ERRNO_H
34 # include <sys/errno.h>
35 #endif
36 #ifdef HAVE_LINUX_JOYSTICK_H
37 # include <linux/joystick.h>
38 # define JOYDEV "/dev/js0"
39 #endif
40 #include "wine/obj_base.h"
41 #include "debugtools.h"
42 #include "dinput.h"
43 #include "display.h"
44 #include "input.h"
45 #include "keyboard.h"
46 #include "message.h"
47 #include "mouse.h"
48 #include "sysmetrics.h"
49 #include "winbase.h"
50 #include "winerror.h"
51 #include "winuser.h"
53 DEFAULT_DEBUG_CHANNEL(dinput)
56 extern BYTE InputKeyStateTable[256];
57 extern int min_keycode, max_keycode;
58 extern WORD keyc2vkey[256];
60 static ICOM_VTABLE(IDirectInputA) ddiavt;
61 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
62 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
64 typedef struct IDirectInputAImpl IDirectInputAImpl;
65 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
66 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
67 typedef struct SysMouseAImpl SysMouseAImpl;
69 struct IDirectInputDevice2AImpl
71 ICOM_VFIELD(IDirectInputDevice2A);
72 DWORD ref;
73 GUID guid;
76 struct SysKeyboardAImpl
78 /* IDirectInputDevice2AImpl */
79 ICOM_VFIELD(IDirectInputDevice2A);
80 DWORD ref;
81 GUID guid;
82 /* SysKeyboardAImpl */
83 BYTE keystate[256];
84 KEYBOARD_CONFIG initial_config;
85 int acquired;
88 #ifdef HAVE_LINUX_22_JOYSTICK_API
89 typedef struct JoystickAImpl JoystickAImpl;
90 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt;
91 struct JoystickAImpl
93 /* IDirectInputDevice2AImpl */
94 ICOM_VFIELD(IDirectInputDevice2A);
95 DWORD ref;
96 GUID guid;
98 /* joystick private */
99 int joyfd;
100 LPDIDATAFORMAT df;
101 HANDLE hEvent;
102 LONG lMin,lMax,deadzone;
103 LPDIDEVICEOBJECTDATA data_queue;
104 int queue_pos, queue_len;
105 DIJOYSTATE js;
107 #endif
109 struct SysMouseAImpl
111 /* IDirectInputDevice2AImpl */
112 ICOM_VFIELD(IDirectInputDevice2A);
113 DWORD ref;
114 GUID guid;
116 LPDIDATAFORMAT df;
117 /* SysMouseAImpl */
118 BYTE absolute;
119 /* Previous position for relative moves */
120 LONG prevX, prevY;
121 LPMOUSE_EVENT_PROC prev_handler;
122 HWND win;
123 DWORD win_centerX, win_centerY;
124 LPDIDEVICEOBJECTDATA data_queue;
125 int queue_pos, queue_len;
126 int need_warp;
127 int acquired;
128 HANDLE hEvent;
129 CRITICAL_SECTION crit;
131 /* This is for mouse reporting. */
132 struct DIMOUSESTATE2 m_state;
135 static int evsequence=0;
138 /* UIDs for Wine "drivers".
139 When enumerating each device supporting DInput, they have two UIDs :
140 - the 'windows' UID
141 - a vendor UID */
142 #ifdef HAVE_LINUX_22_JOYSTICK_API
143 static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
144 0x9e573ed9,
145 0x7734,
146 0x11d2,
147 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
149 #endif
150 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
151 0x9e573ed8,
152 0x7734,
153 0x11d2,
154 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
156 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
157 0x0ab8648a,
158 0x7735,
159 0x11d2,
160 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
163 /* FIXME: This is ugly and not thread safe :/ */
164 static IDirectInputDevice2A* current_lock = NULL;
166 /******************************************************************************
167 * Various debugging tools
169 static void _dump_cooperativelevel(DWORD dwFlags) {
170 int i;
171 const struct {
172 DWORD mask;
173 char *name;
174 } flags[] = {
175 #define FE(x) { x, #x},
176 FE(DISCL_BACKGROUND)
177 FE(DISCL_EXCLUSIVE)
178 FE(DISCL_FOREGROUND)
179 FE(DISCL_NONEXCLUSIVE)
181 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
182 if (flags[i].mask & dwFlags)
183 DPRINTF("%s ",flags[i].name);
184 DPRINTF("\n");
187 struct IDirectInputAImpl
189 ICOM_VFIELD(IDirectInputA);
190 DWORD ref;
193 /******************************************************************************
194 * DirectInputCreate32A
196 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
198 IDirectInputAImpl* This;
199 TRACE("(0x%08lx,%04lx,%p,%p)\n",
200 (DWORD)hinst,dwVersion,ppDI,punkOuter
202 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
203 This->ref = 1;
204 ICOM_VTBL(This) = &ddiavt;
205 *ppDI=(IDirectInputA*)This;
206 return 0;
208 /******************************************************************************
209 * IDirectInputA_EnumDevices
211 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
212 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
213 LPVOID pvRef, DWORD dwFlags
216 ICOM_THIS(IDirectInputAImpl,iface);
217 DIDEVICEINSTANCEA devInstance;
218 int ret;
220 TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
222 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
223 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
224 /* Return keyboard */
225 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
226 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
227 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
228 strcpy(devInstance.tszInstanceName, "Keyboard");
229 strcpy(devInstance.tszProductName, "Wine Keyboard");
231 ret = lpCallback(&devInstance, pvRef);
232 TRACE("Keyboard registered\n");
233 if (ret == DIENUM_STOP)
234 return 0;
237 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
238 /* Return mouse */
239 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
240 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
241 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
242 strcpy(devInstance.tszInstanceName, "Mouse");
243 strcpy(devInstance.tszProductName, "Wine Mouse");
245 ret = lpCallback(&devInstance, pvRef);
246 TRACE("Mouse registered\n");
247 if (ret == DIENUM_STOP)
248 return 0;
250 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) {
251 /* check whether we have a joystick */
252 #ifdef HAVE_LINUX_22_JOYSTICK_API
253 if ( (access(JOYDEV,O_RDONLY)!=-1) ||
254 (errno!=ENODEV && errno!=ENOENT)
256 /* Return joystick */
257 devInstance.guidInstance = GUID_Joystick;
258 devInstance.guidProduct = DInput_Wine_Joystick_GUID;
259 /* we only support traditional joysticks for now */
260 devInstance.dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
261 strcpy(devInstance.tszInstanceName, "Joystick");
262 /* ioctl JSIOCGNAME(len) */
263 strcpy(devInstance.tszProductName, "Wine Joystick");
265 ret = lpCallback(&devInstance,pvRef);
266 TRACE("Joystick registered\n");
267 if (ret == DIENUM_STOP)
268 return 0;
270 #endif
272 return 0;
275 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
277 ICOM_THIS(IDirectInputAImpl,iface);
278 return ++(This->ref);
281 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
283 ICOM_THIS(IDirectInputAImpl,iface);
284 if (!(--This->ref)) {
285 HeapFree(GetProcessHeap(),0,This);
286 return 0;
288 return This->ref;
291 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
292 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
293 LPUNKNOWN punk
295 ICOM_THIS(IDirectInputAImpl,iface);
297 TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
298 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
299 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
300 SysKeyboardAImpl* newDevice;
301 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
302 newDevice->ref = 1;
303 ICOM_VTBL(newDevice) = &SysKeyboardAvt;
304 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
305 memset(newDevice->keystate,0,256);
306 *pdev=(IDirectInputDeviceA*)newDevice;
307 return DI_OK;
309 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
310 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
311 SysMouseAImpl* newDevice;
312 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
313 newDevice->ref = 1;
314 ICOM_VTBL(newDevice) = &SysMouseAvt;
315 InitializeCriticalSection(&(newDevice->crit));
316 MakeCriticalSectionGlobal(&(newDevice->crit));
317 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
318 *pdev=(IDirectInputDeviceA*)newDevice;
319 return DI_OK;
321 #ifdef HAVE_LINUX_22_JOYSTICK_API
322 if ((!memcmp(&GUID_Joystick,rguid,sizeof(GUID_Joystick))) ||
323 (!memcmp(&DInput_Wine_Joystick_GUID,rguid,sizeof(GUID_Joystick)))) {
324 JoystickAImpl* newDevice;
325 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
326 newDevice->ref = 1;
327 ICOM_VTBL(newDevice) = &JoystickAvt;
328 newDevice->joyfd = -1;
329 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
330 *pdev=(IDirectInputDeviceA*)newDevice;
331 return DI_OK;
333 #endif
334 return E_FAIL;
337 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
338 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
340 ICOM_THIS(IDirectInputAImpl,iface);
342 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
343 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
344 IDirectInputA_AddRef(iface);
345 *ppobj = This;
346 return 0;
348 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
349 IDirectInputA_AddRef(iface);
350 *ppobj = This;
351 return 0;
353 return E_FAIL;
356 static HRESULT WINAPI IDirectInputAImpl_Initialize(
357 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
359 return DIERR_ALREADYINITIALIZED;
362 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
363 REFGUID rguid) {
364 ICOM_THIS(IDirectInputAImpl,iface);
366 FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
368 return DI_OK;
371 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
372 HWND hwndOwner,
373 DWORD dwFlags) {
374 ICOM_THIS(IDirectInputAImpl,iface);
375 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
377 return DI_OK;
380 static ICOM_VTABLE(IDirectInputA) ddiavt =
382 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
383 IDirectInputAImpl_QueryInterface,
384 IDirectInputAImpl_AddRef,
385 IDirectInputAImpl_Release,
386 IDirectInputAImpl_CreateDevice,
387 IDirectInputAImpl_EnumDevices,
388 IDirectInputAImpl_GetDeviceStatus,
389 IDirectInputAImpl_RunControlPanel,
390 IDirectInputAImpl_Initialize
393 /******************************************************************************
394 * IDirectInputDeviceA
397 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
398 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
401 int i;
402 TRACE(dinput,"(this=%p,%p)\n",This,df);
404 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
405 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
406 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
407 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
408 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
410 for (i=0;i<df->dwNumObjs;i++) {
411 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,debugstr_guid(df->rgodf[i].pguid));
412 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
413 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
414 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
417 return 0;
420 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
421 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
423 ICOM_THIS(IDirectInputDevice2AImpl,iface);
424 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
425 if (TRACE_ON(dinput))
426 _dump_cooperativelevel(dwflags);
427 return 0;
430 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
431 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
433 ICOM_THIS(IDirectInputDevice2AImpl,iface);
434 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
435 return 0;
438 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
440 ICOM_THIS(IDirectInputDevice2AImpl,iface);
441 This->ref--;
442 if (This->ref)
443 return This->ref;
444 HeapFree(GetProcessHeap(),0,This);
445 return 0;
448 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
449 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
452 ICOM_THIS(SysKeyboardAImpl,iface);
454 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
455 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
456 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
457 if (!HIWORD(rguid)) {
458 switch ((DWORD)rguid) {
459 case (DWORD) DIPROP_BUFFERSIZE: {
460 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
462 TRACE("(buffersize=%ld)\n",pd->dwData);
463 break;
465 default:
466 WARN("Unknown type %ld\n",(DWORD)rguid);
467 break;
470 return 0;
473 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
474 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
477 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
480 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
481 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
482 LPDWORD entries,DWORD flags
485 ICOM_THIS(SysKeyboardAImpl,iface);
486 HRESULT ret;
487 int i;
489 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
490 This,dodsize,dod,entries,entries?*entries:0,flags);
492 ret=KEYBOARD_Driver->pGetDIData(
493 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
494 for (i=0;i<*entries;i++) {
495 dod[i].dwTimeStamp = GetTickCount();
496 dod[i].dwSequence = evsequence++;
498 return ret;
501 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
503 ICOM_THIS(SysKeyboardAImpl,iface);
505 TRACE("(this=%p)\n",This);
507 if (This->acquired == 0) {
508 KEYBOARD_CONFIG no_auto;
510 /* Save the original config */
511 KEYBOARD_Driver->pGetKeyboardConfig(&(This->initial_config));
513 /* Now, remove auto-repeat */
514 no_auto.auto_repeat = FALSE;
515 KEYBOARD_Driver->pSetKeyboardConfig(&no_auto, WINE_KEYBOARD_CONFIG_AUTO_REPEAT);
517 This->acquired = 1;
520 return DI_OK;
523 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
525 ICOM_THIS(SysKeyboardAImpl,iface);
526 TRACE("(this=%p)\n",This);
528 if (This->acquired == 1) {
529 /* Restore the original configuration */
530 KEYBOARD_Driver->pSetKeyboardConfig(&(This->initial_config), 0xFFFFFFFF);
531 This->acquired = 0;
532 } else {
533 ERR("Unacquiring a not-acquired device !!!\n");
536 return DI_OK;
539 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
540 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
543 ICOM_THIS(IDirectInputDevice2AImpl,iface);
545 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
546 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
547 IDirectInputDevice2_AddRef(iface);
548 *ppobj = This;
549 return 0;
551 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
552 IDirectInputDevice2_AddRef(iface);
553 *ppobj = This;
554 return 0;
556 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
557 IDirectInputDevice2_AddRef(iface);
558 *ppobj = This;
559 return 0;
561 return E_FAIL;
564 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
565 LPDIRECTINPUTDEVICE2A iface)
567 ICOM_THIS(IDirectInputDevice2AImpl,iface);
568 return ++This->ref;
571 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
572 LPDIRECTINPUTDEVICE2A iface,
573 LPDIDEVCAPS lpDIDevCaps)
575 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
576 FIXME("stub!\n");
577 return DI_OK;
580 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
581 LPDIRECTINPUTDEVICE2A iface,
582 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
583 LPVOID lpvRef,
584 DWORD dwFlags)
586 FIXME("stub!\n");
587 #if 0
588 if (lpCallback)
589 lpCallback(NULL, lpvRef);
590 #endif
591 return DI_OK;
594 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
595 LPDIRECTINPUTDEVICE2A iface,
596 REFGUID rguid,
597 LPDIPROPHEADER pdiph)
599 FIXME("stub!\n");
600 return DI_OK;
603 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
604 LPDIRECTINPUTDEVICE2A iface,
605 LPDIDEVICEOBJECTINSTANCEA pdidoi,
606 DWORD dwObj,
607 DWORD dwHow)
609 FIXME("stub!\n");
610 return DI_OK;
613 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
614 LPDIRECTINPUTDEVICE2A iface,
615 LPDIDEVICEINSTANCEA pdidi)
617 FIXME("stub!\n");
618 return DI_OK;
621 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
622 LPDIRECTINPUTDEVICE2A iface,
623 HWND hwndOwner,
624 DWORD dwFlags)
626 FIXME("stub!\n");
627 return DI_OK;
630 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
631 LPDIRECTINPUTDEVICE2A iface,
632 HINSTANCE hinst,
633 DWORD dwVersion,
634 REFGUID rguid)
636 FIXME("stub!\n");
637 return DI_OK;
640 /******************************************************************************
641 * IDirectInputDevice2A
644 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
645 LPDIRECTINPUTDEVICE2A iface,
646 REFGUID rguid,
647 LPCDIEFFECT lpeff,
648 LPDIRECTINPUTEFFECT *ppdef,
649 LPUNKNOWN pUnkOuter)
651 FIXME("stub!\n");
652 return DI_OK;
655 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
656 LPDIRECTINPUTDEVICE2A iface,
657 LPDIENUMEFFECTSCALLBACKA lpCallback,
658 LPVOID lpvRef,
659 DWORD dwFlags)
661 FIXME("stub!\n");
662 if (lpCallback)
663 lpCallback(NULL, lpvRef);
664 return DI_OK;
667 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
668 LPDIRECTINPUTDEVICE2A iface,
669 LPDIEFFECTINFOA lpdei,
670 REFGUID rguid)
672 FIXME("stub!\n");
673 return DI_OK;
676 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
677 LPDIRECTINPUTDEVICE2A iface,
678 LPDWORD pdwOut)
680 FIXME("stub!\n");
681 return DI_OK;
684 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
685 LPDIRECTINPUTDEVICE2A iface,
686 DWORD dwFlags)
688 FIXME("stub!\n");
689 return DI_OK;
692 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
693 LPDIRECTINPUTDEVICE2A iface,
694 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
695 LPVOID lpvRef,
696 DWORD dwFlags)
698 FIXME("stub!\n");
699 if (lpCallback)
700 lpCallback(NULL, lpvRef);
701 return DI_OK;
704 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
705 LPDIRECTINPUTDEVICE2A iface,
706 LPDIEFFESCAPE lpDIEEsc)
708 FIXME("stub!\n");
709 return DI_OK;
712 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
713 LPDIRECTINPUTDEVICE2A iface)
715 FIXME("stub!\n");
716 return DI_OK;
719 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
720 LPDIRECTINPUTDEVICE2A iface,
721 DWORD cbObjectData,
722 LPDIDEVICEOBJECTDATA rgdod,
723 LPDWORD pdwInOut,
724 DWORD dwFlags)
726 FIXME("stub!\n");
727 return DI_OK;
730 /******************************************************************************
731 * SysMouseA (DInput Mouse support)
734 /******************************************************************************
735 * Release : release the mouse buffer.
737 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
739 ICOM_THIS(SysMouseAImpl,iface);
741 This->ref--;
742 if (This->ref)
743 return This->ref;
745 /* Free the data queue */
746 if (This->data_queue != NULL)
747 HeapFree(GetProcessHeap(),0,This->data_queue);
749 /* Install the previous event handler (in case of releasing an aquired
750 mouse device) */
751 if (This->prev_handler != NULL)
752 MOUSE_Enable(This->prev_handler);
753 DeleteCriticalSection(&(This->crit));
755 HeapFree(GetProcessHeap(),0,This);
756 return 0;
760 /******************************************************************************
761 * SetCooperativeLevel : store the window in which we will do our
762 * grabbing.
764 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
765 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
768 ICOM_THIS(SysMouseAImpl,iface);
770 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
772 if (TRACE_ON(dinput))
773 _dump_cooperativelevel(dwflags);
775 /* Store the window which asks for the mouse */
776 This->win = hwnd;
778 return 0;
782 /******************************************************************************
783 * SetDataFormat : the application can choose the format of the data
784 * the device driver sends back with GetDeviceState.
786 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
787 * in absolute and relative mode.
789 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
790 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
793 ICOM_THIS(SysMouseAImpl,iface);
794 int i;
796 TRACE("(this=%p,%p)\n",This,df);
798 TRACE("(df.dwSize=%ld)\n",df->dwSize);
799 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
800 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
801 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
802 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
804 for (i=0;i<df->dwNumObjs;i++) {
806 TRACE("df.rgodf[%d].guid %s (%p)\n",i, debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid);
807 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
808 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
809 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
812 /* Check size of data format to prevent crashes if the applications
813 sends a smaller buffer */
814 if ((df->dwDataSize != sizeof(struct DIMOUSESTATE)) &&
815 (df->dwDataSize != sizeof(struct DIMOUSESTATE2))) {
816 FIXME("non-standard mouse configuration not supported yet.");
817 return DIERR_INVALIDPARAM;
820 /* For the moment, ignore these fields and return always as if
821 c_dfDIMouse was passed as format... */
823 /* Check if the mouse is in absolute or relative mode */
824 if (df->dwFlags == DIDF_ABSAXIS)
825 This->absolute = 1;
826 else if (df->dwFlags == DIDF_RELAXIS)
827 This->absolute = 0;
828 else
829 ERR("Neither absolute nor relative flag set.");
831 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
832 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
833 return 0;
836 #define GEN_EVENT(offset,data,xtime,seq) \
838 if (This->queue_pos < This->queue_len) { \
839 This->data_queue[This->queue_pos].dwOfs = offset; \
840 This->data_queue[This->queue_pos].dwData = data; \
841 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
842 This->data_queue[This->queue_pos].dwSequence = seq; \
843 This->queue_pos++; \
848 /* Our private mouse event handler */
849 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
850 DWORD cButtons, DWORD dwExtraInfo )
852 DWORD posX, posY, keyState, xtime, extra;
853 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
855 EnterCriticalSection(&(This->crit));
856 /* Mouse moved -> send event if asked */
857 if (This->hEvent)
858 SetEvent(This->hEvent);
860 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
861 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
862 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
863 keyState = wme->keyState;
864 xtime = wme->time;
865 extra = (DWORD)wme->hWnd;
867 if ((dwFlags & MOUSEEVENTF_MOVE) &&
868 (dwFlags & MOUSEEVENTF_ABSOLUTE)) {
869 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
870 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
871 } else {
872 posX = This->prevX;
873 posY = This->prevY;
875 } else {
876 ERR("Mouse event not supported...\n");
877 LeaveCriticalSection(&(This->crit));
878 return ;
881 TRACE(" %ld %ld ", posX, posY);
883 if ( dwFlags & MOUSEEVENTF_MOVE ) {
884 if (This->absolute) {
885 if (posX != This->prevX)
886 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
887 if (posY != This->prevY)
888 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
889 } else {
890 /* Relative mouse input : the real fun starts here... */
891 if (This->need_warp) {
892 if (posX != This->prevX)
893 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
894 if (posY != This->prevY)
895 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
896 } else {
897 /* This is the first time the event handler has been called after a
898 GetData of GetState. */
899 if (posX != This->win_centerX) {
900 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
901 This->need_warp = 1;
904 if (posY != This->win_centerY) {
905 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
906 This->need_warp = 1;
911 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
912 if (TRACE_ON(dinput))
913 DPRINTF(" LD ");
915 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
916 This->m_state.rgbButtons[0] = 0xFF;
918 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
919 if (TRACE_ON(dinput))
920 DPRINTF(" LU ");
922 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
923 This->m_state.rgbButtons[0] = 0x00;
925 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
926 if (TRACE_ON(dinput))
927 DPRINTF(" RD ");
929 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
930 This->m_state.rgbButtons[1] = 0xFF;
932 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
933 if (TRACE_ON(dinput))
934 DPRINTF(" RU ");
936 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
937 This->m_state.rgbButtons[1] = 0x00;
939 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
940 if (TRACE_ON(dinput))
941 DPRINTF(" MD ");
943 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
944 This->m_state.rgbButtons[2] = 0xFF;
946 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
947 if (TRACE_ON(dinput))
948 DPRINTF(" MU ");
950 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
951 This->m_state.rgbButtons[2] = 0x00;
953 if (TRACE_ON(dinput))
954 DPRINTF("\n");
956 This->prevX = posX;
957 This->prevY = posY;
959 if (This->absolute) {
960 This->m_state.lX = posX;
961 This->m_state.lY = posY;
962 } else {
963 This->m_state.lX = posX - This->win_centerX;
964 This->m_state.lY = posY - This->win_centerY;
967 LeaveCriticalSection(&(This->crit));
972 /******************************************************************************
973 * Acquire : gets exclusive control of the mouse
975 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
977 ICOM_THIS(SysMouseAImpl,iface);
978 RECT rect;
980 TRACE("(this=%p)\n",This);
982 if (This->acquired == 0) {
983 POINT point;
984 int i;
986 /* This stores the current mouse handler. */
987 This->prev_handler = mouse_event;
989 /* Store (in a global variable) the current lock */
990 current_lock = (IDirectInputDevice2A*)This;
992 /* Init the mouse state */
993 This->m_state.lX = PosX;
994 This->m_state.lY = PosY;
995 This->m_state.lZ = 0;
996 This->m_state.rgbButtons[0] = (MouseButtonsStates[0] ? 0xFF : 0x00);
997 This->m_state.rgbButtons[1] = (MouseButtonsStates[1] ? 0xFF : 0x00);
998 This->m_state.rgbButtons[2] = (MouseButtonsStates[2] ? 0xFF : 0x00);
999 for (i = 0; i < 8; i++)
1000 This->m_state.rgbButtons[i] = 0x00;
1002 /* Install our own mouse event handler */
1003 MOUSE_Enable(dinput_mouse_event);
1005 /* Get the window dimension and find the center */
1006 GetWindowRect(This->win, &rect);
1007 This->win_centerX = (rect.right - rect.left) / 2;
1008 This->win_centerY = (rect.bottom - rect.top ) / 2;
1010 /* Warp the mouse to the center of the window */
1011 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1012 point.x = This->win_centerX;
1013 point.y = This->win_centerY;
1014 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1015 DISPLAY_MoveCursor(point.x, point.y);
1017 This->acquired = 1;
1019 return 0;
1022 /******************************************************************************
1023 * Unacquire : frees the mouse
1025 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1027 ICOM_THIS(SysMouseAImpl,iface);
1029 TRACE("(this=%p)\n",This);
1031 /* Reinstall previous mouse event handler */
1032 MOUSE_Enable(This->prev_handler);
1033 This->prev_handler = NULL;
1035 /* No more locks */
1036 current_lock = NULL;
1038 /* Unacquire device */
1039 This->acquired = 0;
1041 return 0;
1044 /******************************************************************************
1045 * GetDeviceState : returns the "state" of the mouse.
1047 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1048 * supported.
1050 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1051 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1053 ICOM_THIS(SysMouseAImpl,iface);
1055 EnterCriticalSection(&(This->crit));
1056 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1058 /* Check if the buffer is big enough */
1059 if ((len != sizeof(struct DIMOUSESTATE)) &&
1060 (len != sizeof(struct DIMOUSESTATE2))) {
1061 FIXME("unsupported state structure.");
1062 LeaveCriticalSection(&(This->crit));
1063 return DIERR_INVALIDPARAM;
1066 /* Copy the current mouse state */
1067 memcpy(ptr, &(This->m_state), len);
1069 /* Check if we need to do a mouse warping */
1070 if (This->need_warp) {
1071 POINT point;
1073 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1074 point.x = This->win_centerX;
1075 point.y = This->win_centerY;
1076 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1077 DISPLAY_MoveCursor(point.x, point.y);
1079 This->need_warp = 0;
1082 LeaveCriticalSection(&(This->crit));
1084 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1085 This->m_state.lX, This->m_state.lY,
1086 This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
1088 return 0;
1091 /******************************************************************************
1092 * GetDeviceState : gets buffered input data.
1094 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1095 DWORD dodsize,
1096 LPDIDEVICEOBJECTDATA dod,
1097 LPDWORD entries,
1098 DWORD flags
1100 ICOM_THIS(SysMouseAImpl,iface);
1102 EnterCriticalSection(&(This->crit));
1103 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1105 if (flags & DIGDD_PEEK)
1106 FIXME("DIGDD_PEEK\n");
1108 if (dod == NULL) {
1109 *entries = This->queue_pos;
1110 This->queue_pos = 0;
1111 } else {
1112 /* Check for buffer overflow */
1113 if (This->queue_pos > *entries) {
1114 WARN("Buffer overflow not handled properly yet...\n");
1115 This->queue_pos = *entries;
1117 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1118 ERR("Wrong structure size !\n");
1119 LeaveCriticalSection(&(This->crit));
1120 return DIERR_INVALIDPARAM;
1123 if (This->queue_pos)
1124 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1126 /* Copy the buffered data into the application queue */
1127 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1128 *entries = This->queue_pos;
1130 /* Reset the event queue */
1131 This->queue_pos = 0;
1133 LeaveCriticalSection(&(This->crit));
1135 #if 0 /* FIXME: seems to create motion events, which fire back at us. */
1136 /* Check if we need to do a mouse warping */
1137 if (This->need_warp) {
1138 POINT point;
1140 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1141 point.x = This->win_centerX;
1142 point.y = This->win_centerY;
1143 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1145 DISPLAY_MoveCursor(point.x, point.y);
1147 This->need_warp = 0;
1149 #endif
1150 return 0;
1153 /******************************************************************************
1154 * SetProperty : change input device properties
1156 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1157 REFGUID rguid,
1158 LPCDIPROPHEADER ph)
1160 ICOM_THIS(SysMouseAImpl,iface);
1162 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1164 if (!HIWORD(rguid)) {
1165 switch ((DWORD)rguid) {
1166 case (DWORD) DIPROP_BUFFERSIZE: {
1167 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1169 TRACE("buffersize = %ld\n",pd->dwData);
1171 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1172 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1173 This->queue_pos = 0;
1174 This->queue_len = pd->dwData;
1175 break;
1177 default:
1178 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1179 break;
1183 return 0;
1186 /******************************************************************************
1187 * SetEventNotification : specifies event to be sent on state change
1189 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1190 HANDLE hnd) {
1191 ICOM_THIS(SysMouseAImpl,iface);
1193 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1195 This->hEvent = hnd;
1197 return DI_OK;
1200 #ifdef HAVE_LINUX_22_JOYSTICK_API
1201 /******************************************************************************
1202 * Joystick
1204 static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1206 ICOM_THIS(JoystickAImpl,iface);
1208 This->ref--;
1209 if (This->ref)
1210 return This->ref;
1211 HeapFree(GetProcessHeap(),0,This);
1212 return 0;
1215 /******************************************************************************
1216 * SetDataFormat : the application can choose the format of the data
1217 * the device driver sends back with GetDeviceState.
1219 static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1220 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1223 ICOM_THIS(JoystickAImpl,iface);
1224 int i;
1226 TRACE("(this=%p,%p)\n",This,df);
1228 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1229 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1230 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1231 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1232 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1234 for (i=0;i<df->dwNumObjs;i++) {
1235 TRACE("df.rgodf[%d].guid %s (%p)\n",i,debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid);
1236 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1237 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1238 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1240 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1241 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1242 return 0;
1245 /******************************************************************************
1246 * Acquire : gets exclusive control of the joystick
1248 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1250 ICOM_THIS(JoystickAImpl,iface);
1252 TRACE("(this=%p)\n",This);
1253 if (This->joyfd!=-1)
1254 return 0;
1255 This->joyfd=open(JOYDEV,O_RDONLY);
1256 if (This->joyfd==-1)
1257 return DIERR_NOTFOUND;
1258 return 0;
1261 /******************************************************************************
1262 * Unacquire : frees the joystick
1264 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1266 ICOM_THIS(JoystickAImpl,iface);
1268 TRACE("(this=%p)\n",This);
1269 if (This->joyfd!=-1) {
1270 close(This->joyfd);
1271 This->joyfd = -1;
1273 return 0;
1276 #define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1278 static void joy_polldev(JoystickAImpl *This) {
1279 struct timeval tv;
1280 fd_set readfds;
1281 struct js_event jse;
1283 if (This->joyfd==-1)
1284 return;
1285 while (1) {
1286 memset(&tv,0,sizeof(tv));
1287 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1288 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1289 return;
1290 /* we have one event, so we can read */
1291 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1292 return;
1294 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1295 if (jse.type & JS_EVENT_BUTTON) {
1296 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1297 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1299 if (jse.type & JS_EVENT_AXIS) {
1300 switch (jse.number) {
1301 case 0:
1302 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1303 This->js.lX = map_axis(jse.value);
1304 break;
1305 case 1:
1306 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1307 This->js.lY = map_axis(jse.value);
1308 break;
1309 case 2:
1310 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1311 This->js.lZ = map_axis(jse.value);
1312 break;
1313 default:
1314 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1315 break;
1321 /******************************************************************************
1322 * GetDeviceState : returns the "state" of the joystick.
1325 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1326 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1328 ICOM_THIS(JoystickAImpl,iface);
1330 joy_polldev(This);
1331 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1332 if (len != sizeof(DIJOYSTATE)) {
1333 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1335 memcpy(ptr,&(This->js),len);
1336 This->queue_pos = 0;
1337 return 0;
1340 /******************************************************************************
1341 * GetDeviceState : gets buffered input data.
1343 static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1344 DWORD dodsize,
1345 LPDIDEVICEOBJECTDATA dod,
1346 LPDWORD entries,
1347 DWORD flags
1349 ICOM_THIS(JoystickAImpl,iface);
1351 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1353 joy_polldev(This);
1354 if (flags & DIGDD_PEEK)
1355 FIXME("DIGDD_PEEK\n");
1357 if (dod == NULL) {
1358 } else {
1360 return 0;
1363 /******************************************************************************
1364 * SetProperty : change input device properties
1366 static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1367 REFGUID rguid,
1368 LPCDIPROPHEADER ph)
1370 ICOM_THIS(JoystickAImpl,iface);
1372 FIXME("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1373 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1375 if (!HIWORD(rguid)) {
1376 switch ((DWORD)rguid) {
1377 case (DWORD) DIPROP_BUFFERSIZE: {
1378 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1380 FIXME("buffersize = %ld\n",pd->dwData);
1381 break;
1383 case (DWORD)DIPROP_RANGE: {
1384 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1386 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1387 This->lMin = pr->lMin;
1388 This->lMax = pr->lMax;
1389 break;
1391 case (DWORD)DIPROP_DEADZONE: {
1392 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1394 FIXME("deadzone(%ld)\n",pd->dwData);
1395 This->deadzone = pd->dwData;
1396 break;
1398 default:
1399 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1400 break;
1403 return 0;
1406 /******************************************************************************
1407 * SetEventNotification : specifies event to be sent on state change
1409 static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1410 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1412 ICOM_THIS(JoystickAImpl,iface);
1414 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1415 This->hEvent = hnd;
1416 return DI_OK;
1419 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1420 LPDIRECTINPUTDEVICE2A iface,
1421 LPDIDEVCAPS lpDIDevCaps)
1423 ICOM_THIS(JoystickAImpl,iface);
1424 BYTE axes,buttons;
1425 int xfd = This->joyfd;
1427 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1428 if (xfd==-1)
1429 xfd = open(JOYDEV,O_RDONLY);
1430 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1431 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1432 #ifdef JSIOCGAXES
1433 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1434 axes = 2;
1435 lpDIDevCaps->dwAxes = axes;
1436 #endif
1437 #ifdef JSIOCGBUTTONS
1438 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1439 buttons = 2;
1440 lpDIDevCaps->dwButtons = buttons;
1441 #endif
1442 if (xfd!=This->joyfd)
1443 close(xfd);
1444 return DI_OK;
1446 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1447 ICOM_THIS(JoystickAImpl,iface);
1448 TRACE("(),stub!\n");
1450 joy_polldev(This);
1451 return DI_OK;
1453 #endif
1455 /****************************************************************************/
1456 /****************************************************************************/
1458 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1460 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1461 IDirectInputDevice2AImpl_QueryInterface,
1462 IDirectInputDevice2AImpl_AddRef,
1463 IDirectInputDevice2AImpl_Release,
1464 IDirectInputDevice2AImpl_GetCapabilities,
1465 IDirectInputDevice2AImpl_EnumObjects,
1466 IDirectInputDevice2AImpl_GetProperty,
1467 SysKeyboardAImpl_SetProperty,
1468 SysKeyboardAImpl_Acquire,
1469 SysKeyboardAImpl_Unacquire,
1470 SysKeyboardAImpl_GetDeviceState,
1471 SysKeyboardAImpl_GetDeviceData,
1472 IDirectInputDevice2AImpl_SetDataFormat,
1473 IDirectInputDevice2AImpl_SetEventNotification,
1474 IDirectInputDevice2AImpl_SetCooperativeLevel,
1475 IDirectInputDevice2AImpl_GetObjectInfo,
1476 IDirectInputDevice2AImpl_GetDeviceInfo,
1477 IDirectInputDevice2AImpl_RunControlPanel,
1478 IDirectInputDevice2AImpl_Initialize,
1479 IDirectInputDevice2AImpl_CreateEffect,
1480 IDirectInputDevice2AImpl_EnumEffects,
1481 IDirectInputDevice2AImpl_GetEffectInfo,
1482 IDirectInputDevice2AImpl_GetForceFeedbackState,
1483 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1484 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1485 IDirectInputDevice2AImpl_Escape,
1486 IDirectInputDevice2AImpl_Poll,
1487 IDirectInputDevice2AImpl_SendDeviceData,
1490 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1492 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1493 IDirectInputDevice2AImpl_QueryInterface,
1494 IDirectInputDevice2AImpl_AddRef,
1495 SysMouseAImpl_Release,
1496 IDirectInputDevice2AImpl_GetCapabilities,
1497 IDirectInputDevice2AImpl_EnumObjects,
1498 IDirectInputDevice2AImpl_GetProperty,
1499 SysMouseAImpl_SetProperty,
1500 SysMouseAImpl_Acquire,
1501 SysMouseAImpl_Unacquire,
1502 SysMouseAImpl_GetDeviceState,
1503 SysMouseAImpl_GetDeviceData,
1504 SysMouseAImpl_SetDataFormat,
1505 SysMouseAImpl_SetEventNotification,
1506 SysMouseAImpl_SetCooperativeLevel,
1507 IDirectInputDevice2AImpl_GetObjectInfo,
1508 IDirectInputDevice2AImpl_GetDeviceInfo,
1509 IDirectInputDevice2AImpl_RunControlPanel,
1510 IDirectInputDevice2AImpl_Initialize,
1511 IDirectInputDevice2AImpl_CreateEffect,
1512 IDirectInputDevice2AImpl_EnumEffects,
1513 IDirectInputDevice2AImpl_GetEffectInfo,
1514 IDirectInputDevice2AImpl_GetForceFeedbackState,
1515 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1516 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1517 IDirectInputDevice2AImpl_Escape,
1518 IDirectInputDevice2AImpl_Poll,
1519 IDirectInputDevice2AImpl_SendDeviceData,
1522 #ifdef HAVE_LINUX_22_JOYSTICK_API
1523 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1525 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1526 IDirectInputDevice2AImpl_QueryInterface,
1527 IDirectInputDevice2AImpl_AddRef,
1528 JoystickAImpl_Release,
1529 JoystickAImpl_GetCapabilities,
1530 IDirectInputDevice2AImpl_EnumObjects,
1531 IDirectInputDevice2AImpl_GetProperty,
1532 JoystickAImpl_SetProperty,
1533 JoystickAImpl_Acquire,
1534 JoystickAImpl_Unacquire,
1535 JoystickAImpl_GetDeviceState,
1536 JoystickAImpl_GetDeviceData,
1537 JoystickAImpl_SetDataFormat,
1538 JoystickAImpl_SetEventNotification,
1539 IDirectInputDevice2AImpl_SetCooperativeLevel,
1540 IDirectInputDevice2AImpl_GetObjectInfo,
1541 IDirectInputDevice2AImpl_GetDeviceInfo,
1542 IDirectInputDevice2AImpl_RunControlPanel,
1543 IDirectInputDevice2AImpl_Initialize,
1544 IDirectInputDevice2AImpl_CreateEffect,
1545 IDirectInputDevice2AImpl_EnumEffects,
1546 IDirectInputDevice2AImpl_GetEffectInfo,
1547 IDirectInputDevice2AImpl_GetForceFeedbackState,
1548 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1549 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1550 IDirectInputDevice2AImpl_Escape,
1551 JoystickAImpl_Poll,
1552 IDirectInputDevice2AImpl_SendDeviceData,
1554 #endif