Use poll() instead of select() for the server main loop.
[wine/multimedia.git] / windows / dinput.c
blob0a5975ecaa6bf6c273cfe18c5d3bbd07cf5809ec
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);
296 char xbuf[50];
298 WINE_StringFromCLSID(rguid,xbuf);
299 TRACE("(this=%p,%s,%p,%p)\n",This,xbuf,pdev,punk);
300 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
301 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
302 SysKeyboardAImpl* newDevice;
303 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
304 newDevice->ref = 1;
305 ICOM_VTBL(newDevice) = &SysKeyboardAvt;
306 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
307 memset(newDevice->keystate,0,256);
308 *pdev=(IDirectInputDeviceA*)newDevice;
309 return DI_OK;
311 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
312 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
313 SysMouseAImpl* newDevice;
314 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
315 newDevice->ref = 1;
316 ICOM_VTBL(newDevice) = &SysMouseAvt;
317 InitializeCriticalSection(&(newDevice->crit));
318 MakeCriticalSectionGlobal(&(newDevice->crit));
319 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
320 *pdev=(IDirectInputDeviceA*)newDevice;
321 return DI_OK;
323 #ifdef HAVE_LINUX_22_JOYSTICK_API
324 if ((!memcmp(&GUID_Joystick,rguid,sizeof(GUID_Joystick))) ||
325 (!memcmp(&DInput_Wine_Joystick_GUID,rguid,sizeof(GUID_Joystick)))) {
326 JoystickAImpl* newDevice;
327 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
328 newDevice->ref = 1;
329 ICOM_VTBL(newDevice) = &JoystickAvt;
330 newDevice->joyfd = -1;
331 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
332 *pdev=(IDirectInputDeviceA*)newDevice;
333 return DI_OK;
335 #endif
336 return E_FAIL;
339 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
340 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
342 ICOM_THIS(IDirectInputAImpl,iface);
343 char xbuf[50];
345 WINE_StringFromCLSID(riid,xbuf);
346 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
347 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
348 IDirectInputA_AddRef(iface);
349 *ppobj = This;
350 return 0;
352 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
353 IDirectInputA_AddRef(iface);
354 *ppobj = This;
355 return 0;
357 return E_FAIL;
360 static HRESULT WINAPI IDirectInputAImpl_Initialize(
361 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
363 return DIERR_ALREADYINITIALIZED;
366 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
367 REFGUID rguid) {
368 ICOM_THIS(IDirectInputAImpl,iface);
369 char xbuf[50];
371 WINE_StringFromCLSID(rguid,xbuf);
372 FIXME("(%p)->(%s): stub\n",This,xbuf);
374 return DI_OK;
377 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
378 HWND hwndOwner,
379 DWORD dwFlags) {
380 ICOM_THIS(IDirectInputAImpl,iface);
381 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
383 return DI_OK;
386 static ICOM_VTABLE(IDirectInputA) ddiavt =
388 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
389 IDirectInputAImpl_QueryInterface,
390 IDirectInputAImpl_AddRef,
391 IDirectInputAImpl_Release,
392 IDirectInputAImpl_CreateDevice,
393 IDirectInputAImpl_EnumDevices,
394 IDirectInputAImpl_GetDeviceStatus,
395 IDirectInputAImpl_RunControlPanel,
396 IDirectInputAImpl_Initialize
399 /******************************************************************************
400 * IDirectInputDeviceA
403 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
404 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
407 int i;
408 TRACE(dinput,"(this=%p,%p)\n",This,df);
410 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
411 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
412 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
413 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
414 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
416 for (i=0;i<df->dwNumObjs;i++) {
417 char xbuf[50];
419 if (df->rgodf[i].pguid)
420 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
421 else
422 strcpy(xbuf,"<no guid>");
423 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
424 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
425 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
426 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
429 return 0;
432 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
433 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
435 ICOM_THIS(IDirectInputDevice2AImpl,iface);
436 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
437 if (TRACE_ON(dinput))
438 _dump_cooperativelevel(dwflags);
439 return 0;
442 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
443 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
445 ICOM_THIS(IDirectInputDevice2AImpl,iface);
446 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
447 return 0;
450 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
452 ICOM_THIS(IDirectInputDevice2AImpl,iface);
453 This->ref--;
454 if (This->ref)
455 return This->ref;
456 HeapFree(GetProcessHeap(),0,This);
457 return 0;
460 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
461 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
464 ICOM_THIS(SysKeyboardAImpl,iface);
465 char xbuf[50];
467 if (HIWORD(rguid))
468 WINE_StringFromCLSID(rguid,xbuf);
469 else
470 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
471 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
472 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
473 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
474 if (!HIWORD(rguid)) {
475 switch ((DWORD)rguid) {
476 case (DWORD) DIPROP_BUFFERSIZE: {
477 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
479 TRACE("(buffersize=%ld)\n",pd->dwData);
480 break;
482 default:
483 WARN("Unknown type %ld\n",(DWORD)rguid);
484 break;
487 return 0;
490 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
491 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
494 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
497 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
498 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
499 LPDWORD entries,DWORD flags
502 ICOM_THIS(SysKeyboardAImpl,iface);
503 HRESULT ret;
504 int i;
506 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
507 This,dodsize,dod,entries,entries?*entries:0,flags);
509 ret=KEYBOARD_Driver->pGetDIData(
510 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
511 for (i=0;i<*entries;i++) {
512 dod[i].dwTimeStamp = GetTickCount();
513 dod[i].dwSequence = evsequence++;
515 return ret;
518 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
520 ICOM_THIS(SysKeyboardAImpl,iface);
522 TRACE("(this=%p)\n",This);
524 if (This->acquired == 0) {
525 KEYBOARD_CONFIG no_auto;
527 /* Save the original config */
528 KEYBOARD_Driver->pGetKeyboardConfig(&(This->initial_config));
530 /* Now, remove auto-repeat */
531 no_auto.auto_repeat = FALSE;
532 KEYBOARD_Driver->pSetKeyboardConfig(&no_auto, WINE_KEYBOARD_CONFIG_AUTO_REPEAT);
534 This->acquired = 1;
537 return DI_OK;
540 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
542 ICOM_THIS(SysKeyboardAImpl,iface);
543 TRACE("(this=%p)\n",This);
545 if (This->acquired == 1) {
546 /* Restore the original configuration */
547 KEYBOARD_Driver->pSetKeyboardConfig(&(This->initial_config), 0xFFFFFFFF);
548 This->acquired = 0;
549 } else {
550 ERR("Unacquiring a not-acquired device !!!\n");
553 return DI_OK;
556 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
557 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
560 ICOM_THIS(IDirectInputDevice2AImpl,iface);
561 char xbuf[50];
563 WINE_StringFromCLSID(riid,xbuf);
564 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
565 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
566 IDirectInputDevice2_AddRef(iface);
567 *ppobj = This;
568 return 0;
570 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
571 IDirectInputDevice2_AddRef(iface);
572 *ppobj = This;
573 return 0;
575 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
576 IDirectInputDevice2_AddRef(iface);
577 *ppobj = This;
578 return 0;
580 return E_FAIL;
583 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
584 LPDIRECTINPUTDEVICE2A iface)
586 ICOM_THIS(IDirectInputDevice2AImpl,iface);
587 return ++This->ref;
590 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
591 LPDIRECTINPUTDEVICE2A iface,
592 LPDIDEVCAPS lpDIDevCaps)
594 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
595 FIXME("stub!\n");
596 return DI_OK;
599 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
600 LPDIRECTINPUTDEVICE2A iface,
601 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
602 LPVOID lpvRef,
603 DWORD dwFlags)
605 FIXME("stub!\n");
606 #if 0
607 if (lpCallback)
608 lpCallback(NULL, lpvRef);
609 #endif
610 return DI_OK;
613 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
614 LPDIRECTINPUTDEVICE2A iface,
615 REFGUID rguid,
616 LPDIPROPHEADER pdiph)
618 FIXME("stub!\n");
619 return DI_OK;
622 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
623 LPDIRECTINPUTDEVICE2A iface,
624 LPDIDEVICEOBJECTINSTANCEA pdidoi,
625 DWORD dwObj,
626 DWORD dwHow)
628 FIXME("stub!\n");
629 return DI_OK;
632 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
633 LPDIRECTINPUTDEVICE2A iface,
634 LPDIDEVICEINSTANCEA pdidi)
636 FIXME("stub!\n");
637 return DI_OK;
640 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
641 LPDIRECTINPUTDEVICE2A iface,
642 HWND hwndOwner,
643 DWORD dwFlags)
645 FIXME("stub!\n");
646 return DI_OK;
649 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
650 LPDIRECTINPUTDEVICE2A iface,
651 HINSTANCE hinst,
652 DWORD dwVersion,
653 REFGUID rguid)
655 FIXME("stub!\n");
656 return DI_OK;
659 /******************************************************************************
660 * IDirectInputDevice2A
663 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
664 LPDIRECTINPUTDEVICE2A iface,
665 REFGUID rguid,
666 LPCDIEFFECT lpeff,
667 LPDIRECTINPUTEFFECT *ppdef,
668 LPUNKNOWN pUnkOuter)
670 FIXME("stub!\n");
671 return DI_OK;
674 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
675 LPDIRECTINPUTDEVICE2A iface,
676 LPDIENUMEFFECTSCALLBACKA lpCallback,
677 LPVOID lpvRef,
678 DWORD dwFlags)
680 FIXME("stub!\n");
681 if (lpCallback)
682 lpCallback(NULL, lpvRef);
683 return DI_OK;
686 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
687 LPDIRECTINPUTDEVICE2A iface,
688 LPDIEFFECTINFOA lpdei,
689 REFGUID rguid)
691 FIXME("stub!\n");
692 return DI_OK;
695 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
696 LPDIRECTINPUTDEVICE2A iface,
697 LPDWORD pdwOut)
699 FIXME("stub!\n");
700 return DI_OK;
703 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
704 LPDIRECTINPUTDEVICE2A iface,
705 DWORD dwFlags)
707 FIXME("stub!\n");
708 return DI_OK;
711 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
712 LPDIRECTINPUTDEVICE2A iface,
713 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
714 LPVOID lpvRef,
715 DWORD dwFlags)
717 FIXME("stub!\n");
718 if (lpCallback)
719 lpCallback(NULL, lpvRef);
720 return DI_OK;
723 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
724 LPDIRECTINPUTDEVICE2A iface,
725 LPDIEFFESCAPE lpDIEEsc)
727 FIXME("stub!\n");
728 return DI_OK;
731 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
732 LPDIRECTINPUTDEVICE2A iface)
734 FIXME("stub!\n");
735 return DI_OK;
738 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
739 LPDIRECTINPUTDEVICE2A iface,
740 DWORD cbObjectData,
741 LPDIDEVICEOBJECTDATA rgdod,
742 LPDWORD pdwInOut,
743 DWORD dwFlags)
745 FIXME("stub!\n");
746 return DI_OK;
749 /******************************************************************************
750 * SysMouseA (DInput Mouse support)
753 /******************************************************************************
754 * Release : release the mouse buffer.
756 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
758 ICOM_THIS(SysMouseAImpl,iface);
760 This->ref--;
761 if (This->ref)
762 return This->ref;
764 /* Free the data queue */
765 if (This->data_queue != NULL)
766 HeapFree(GetProcessHeap(),0,This->data_queue);
768 /* Install the previous event handler (in case of releasing an aquired
769 mouse device) */
770 if (This->prev_handler != NULL)
771 MOUSE_Enable(This->prev_handler);
772 DeleteCriticalSection(&(This->crit));
774 HeapFree(GetProcessHeap(),0,This);
775 return 0;
779 /******************************************************************************
780 * SetCooperativeLevel : store the window in which we will do our
781 * grabbing.
783 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
784 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
787 ICOM_THIS(SysMouseAImpl,iface);
789 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
791 if (TRACE_ON(dinput))
792 _dump_cooperativelevel(dwflags);
794 /* Store the window which asks for the mouse */
795 This->win = hwnd;
797 return 0;
801 /******************************************************************************
802 * SetDataFormat : the application can choose the format of the data
803 * the device driver sends back with GetDeviceState.
805 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
806 * in absolute and relative mode.
808 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
809 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
812 ICOM_THIS(SysMouseAImpl,iface);
813 int i;
815 TRACE("(this=%p,%p)\n",This,df);
817 TRACE("(df.dwSize=%ld)\n",df->dwSize);
818 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
819 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
820 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
821 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
823 for (i=0;i<df->dwNumObjs;i++) {
824 char xbuf[50];
826 if (df->rgodf[i].pguid)
827 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
828 else
829 strcpy(xbuf,"<no guid>");
830 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
831 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
832 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
833 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
836 /* Check size of data format to prevent crashes if the applications
837 sends a smaller buffer */
838 if ((df->dwDataSize != sizeof(struct DIMOUSESTATE)) &&
839 (df->dwDataSize != sizeof(struct DIMOUSESTATE2))) {
840 FIXME("non-standard mouse configuration not supported yet.");
841 return DIERR_INVALIDPARAM;
844 /* For the moment, ignore these fields and return always as if
845 c_dfDIMouse was passed as format... */
847 /* Check if the mouse is in absolute or relative mode */
848 if (df->dwFlags == DIDF_ABSAXIS)
849 This->absolute = 1;
850 else if (df->dwFlags == DIDF_RELAXIS)
851 This->absolute = 0;
852 else
853 ERR("Neither absolute nor relative flag set.");
855 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
856 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
857 return 0;
860 #define GEN_EVENT(offset,data,xtime,seq) \
862 if (This->queue_pos < This->queue_len) { \
863 This->data_queue[This->queue_pos].dwOfs = offset; \
864 This->data_queue[This->queue_pos].dwData = data; \
865 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
866 This->data_queue[This->queue_pos].dwSequence = seq; \
867 This->queue_pos++; \
872 /* Our private mouse event handler */
873 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
874 DWORD cButtons, DWORD dwExtraInfo )
876 DWORD posX, posY, keyState, xtime, extra;
877 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
879 EnterCriticalSection(&(This->crit));
880 /* Mouse moved -> send event if asked */
881 if (This->hEvent)
882 SetEvent(This->hEvent);
884 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
885 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
886 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
887 keyState = wme->keyState;
888 xtime = wme->time;
889 extra = (DWORD)wme->hWnd;
891 if ((dwFlags & MOUSEEVENTF_MOVE) &&
892 (dwFlags & MOUSEEVENTF_ABSOLUTE)) {
893 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
894 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
895 } else {
896 posX = This->prevX;
897 posY = This->prevY;
899 } else {
900 ERR("Mouse event not supported...\n");
901 LeaveCriticalSection(&(This->crit));
902 return ;
905 TRACE(" %ld %ld ", posX, posY);
907 if ( dwFlags & MOUSEEVENTF_MOVE ) {
908 if (This->absolute) {
909 if (posX != This->prevX)
910 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
911 if (posY != This->prevY)
912 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
913 } else {
914 /* Relative mouse input : the real fun starts here... */
915 if (This->need_warp) {
916 if (posX != This->prevX)
917 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
918 if (posY != This->prevY)
919 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
920 } else {
921 /* This is the first time the event handler has been called after a
922 GetData of GetState. */
923 if (posX != This->win_centerX) {
924 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
925 This->need_warp = 1;
928 if (posY != This->win_centerY) {
929 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
930 This->need_warp = 1;
935 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
936 if (TRACE_ON(dinput))
937 DPRINTF(" LD ");
939 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
940 This->m_state.rgbButtons[0] = 0xFF;
942 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
943 if (TRACE_ON(dinput))
944 DPRINTF(" LU ");
946 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
947 This->m_state.rgbButtons[0] = 0x00;
949 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
950 if (TRACE_ON(dinput))
951 DPRINTF(" RD ");
953 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
954 This->m_state.rgbButtons[1] = 0xFF;
956 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
957 if (TRACE_ON(dinput))
958 DPRINTF(" RU ");
960 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
961 This->m_state.rgbButtons[1] = 0x00;
963 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
964 if (TRACE_ON(dinput))
965 DPRINTF(" MD ");
967 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
968 This->m_state.rgbButtons[2] = 0xFF;
970 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
971 if (TRACE_ON(dinput))
972 DPRINTF(" MU ");
974 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
975 This->m_state.rgbButtons[2] = 0x00;
977 if (TRACE_ON(dinput))
978 DPRINTF("\n");
980 This->prevX = posX;
981 This->prevY = posY;
983 if (This->absolute) {
984 This->m_state.lX = posX;
985 This->m_state.lY = posY;
986 } else {
987 This->m_state.lX = posX - This->win_centerX;
988 This->m_state.lY = posY - This->win_centerY;
991 LeaveCriticalSection(&(This->crit));
996 /******************************************************************************
997 * Acquire : gets exclusive control of the mouse
999 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1001 ICOM_THIS(SysMouseAImpl,iface);
1002 RECT rect;
1004 TRACE("(this=%p)\n",This);
1006 if (This->acquired == 0) {
1007 POINT point;
1008 int i;
1010 /* This stores the current mouse handler. */
1011 This->prev_handler = mouse_event;
1013 /* Store (in a global variable) the current lock */
1014 current_lock = (IDirectInputDevice2A*)This;
1016 /* Init the mouse state */
1017 This->m_state.lX = PosX;
1018 This->m_state.lY = PosY;
1019 This->m_state.lZ = 0;
1020 This->m_state.rgbButtons[0] = (MouseButtonsStates[0] ? 0xFF : 0x00);
1021 This->m_state.rgbButtons[1] = (MouseButtonsStates[1] ? 0xFF : 0x00);
1022 This->m_state.rgbButtons[2] = (MouseButtonsStates[2] ? 0xFF : 0x00);
1023 for (i = 0; i < 8; i++)
1024 This->m_state.rgbButtons[i] = 0x00;
1026 /* Install our own mouse event handler */
1027 MOUSE_Enable(dinput_mouse_event);
1029 /* Get the window dimension and find the center */
1030 GetWindowRect(This->win, &rect);
1031 This->win_centerX = (rect.right - rect.left) / 2;
1032 This->win_centerY = (rect.bottom - rect.top ) / 2;
1034 /* Warp the mouse to the center of the window */
1035 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1036 point.x = This->win_centerX;
1037 point.y = This->win_centerY;
1038 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1039 DISPLAY_MoveCursor(point.x, point.y);
1041 This->acquired = 1;
1043 return 0;
1046 /******************************************************************************
1047 * Unacquire : frees the mouse
1049 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1051 ICOM_THIS(SysMouseAImpl,iface);
1053 TRACE("(this=%p)\n",This);
1055 /* Reinstall previous mouse event handler */
1056 MOUSE_Enable(This->prev_handler);
1057 This->prev_handler = NULL;
1059 /* No more locks */
1060 current_lock = NULL;
1062 /* Unacquire device */
1063 This->acquired = 0;
1065 return 0;
1068 /******************************************************************************
1069 * GetDeviceState : returns the "state" of the mouse.
1071 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1072 * supported.
1074 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1075 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1077 ICOM_THIS(SysMouseAImpl,iface);
1079 EnterCriticalSection(&(This->crit));
1080 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1082 /* Check if the buffer is big enough */
1083 if ((len != sizeof(struct DIMOUSESTATE)) &&
1084 (len != sizeof(struct DIMOUSESTATE2))) {
1085 FIXME("unsupported state structure.");
1086 LeaveCriticalSection(&(This->crit));
1087 return DIERR_INVALIDPARAM;
1090 /* Copy the current mouse state */
1091 memcpy(ptr, &(This->m_state), len);
1093 /* Check if we need to do a mouse warping */
1094 if (This->need_warp) {
1095 POINT point;
1097 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1098 point.x = This->win_centerX;
1099 point.y = This->win_centerY;
1100 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1101 DISPLAY_MoveCursor(point.x, point.y);
1103 This->need_warp = 0;
1106 LeaveCriticalSection(&(This->crit));
1108 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1109 This->m_state.lX, This->m_state.lY,
1110 This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
1112 return 0;
1115 /******************************************************************************
1116 * GetDeviceState : gets buffered input data.
1118 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1119 DWORD dodsize,
1120 LPDIDEVICEOBJECTDATA dod,
1121 LPDWORD entries,
1122 DWORD flags
1124 ICOM_THIS(SysMouseAImpl,iface);
1126 EnterCriticalSection(&(This->crit));
1127 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1129 if (flags & DIGDD_PEEK)
1130 FIXME("DIGDD_PEEK\n");
1132 if (dod == NULL) {
1133 *entries = This->queue_pos;
1134 This->queue_pos = 0;
1135 } else {
1136 /* Check for buffer overflow */
1137 if (This->queue_pos > *entries) {
1138 WARN("Buffer overflow not handled properly yet...\n");
1139 This->queue_pos = *entries;
1141 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1142 ERR("Wrong structure size !\n");
1143 LeaveCriticalSection(&(This->crit));
1144 return DIERR_INVALIDPARAM;
1147 if (This->queue_pos)
1148 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1150 /* Copy the buffered data into the application queue */
1151 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1152 *entries = This->queue_pos;
1154 /* Reset the event queue */
1155 This->queue_pos = 0;
1157 LeaveCriticalSection(&(This->crit));
1159 #if 0 /* FIXME: seems to create motion events, which fire back at us. */
1160 /* Check if we need to do a mouse warping */
1161 if (This->need_warp) {
1162 POINT point;
1164 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1165 point.x = This->win_centerX;
1166 point.y = This->win_centerY;
1167 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1169 DISPLAY_MoveCursor(point.x, point.y);
1171 This->need_warp = 0;
1173 #endif
1174 return 0;
1177 /******************************************************************************
1178 * SetProperty : change input device properties
1180 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1181 REFGUID rguid,
1182 LPCDIPROPHEADER ph)
1184 ICOM_THIS(SysMouseAImpl,iface);
1185 char xbuf[50];
1187 if (HIWORD(rguid))
1188 WINE_StringFromCLSID(rguid,xbuf);
1189 else
1190 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1192 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1194 if (!HIWORD(rguid)) {
1195 switch ((DWORD)rguid) {
1196 case (DWORD) DIPROP_BUFFERSIZE: {
1197 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1199 TRACE("buffersize = %ld\n",pd->dwData);
1201 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1202 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1203 This->queue_pos = 0;
1204 This->queue_len = pd->dwData;
1205 break;
1207 default:
1208 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1209 break;
1213 return 0;
1216 /******************************************************************************
1217 * SetEventNotification : specifies event to be sent on state change
1219 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1220 HANDLE hnd) {
1221 ICOM_THIS(SysMouseAImpl,iface);
1223 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1225 This->hEvent = hnd;
1227 return DI_OK;
1230 #ifdef HAVE_LINUX_22_JOYSTICK_API
1231 /******************************************************************************
1232 * Joystick
1234 static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1236 ICOM_THIS(JoystickAImpl,iface);
1238 This->ref--;
1239 if (This->ref)
1240 return This->ref;
1241 HeapFree(GetProcessHeap(),0,This);
1242 return 0;
1245 /******************************************************************************
1246 * SetDataFormat : the application can choose the format of the data
1247 * the device driver sends back with GetDeviceState.
1249 static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1250 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1253 ICOM_THIS(JoystickAImpl,iface);
1254 int i;
1256 TRACE("(this=%p,%p)\n",This,df);
1258 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1259 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1260 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1261 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1262 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1264 for (i=0;i<df->dwNumObjs;i++) {
1265 char xbuf[50];
1267 if (df->rgodf[i].pguid)
1268 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1269 else
1270 strcpy(xbuf,"<no guid>");
1271 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1272 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1273 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1274 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1276 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1277 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1278 return 0;
1281 /******************************************************************************
1282 * Acquire : gets exclusive control of the joystick
1284 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1286 ICOM_THIS(JoystickAImpl,iface);
1288 TRACE("(this=%p)\n",This);
1289 if (This->joyfd!=-1)
1290 return 0;
1291 This->joyfd=open(JOYDEV,O_RDONLY);
1292 if (This->joyfd==-1)
1293 return DIERR_NOTFOUND;
1294 return 0;
1297 /******************************************************************************
1298 * Unacquire : frees the joystick
1300 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1302 ICOM_THIS(JoystickAImpl,iface);
1304 TRACE("(this=%p)\n",This);
1305 if (This->joyfd!=-1) {
1306 close(This->joyfd);
1307 This->joyfd = -1;
1309 return 0;
1312 #define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1314 static void joy_polldev(JoystickAImpl *This) {
1315 struct timeval tv;
1316 fd_set readfds;
1317 struct js_event jse;
1319 if (This->joyfd==-1)
1320 return;
1321 while (1) {
1322 memset(&tv,0,sizeof(tv));
1323 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1324 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1325 return;
1326 /* we have one event, so we can read */
1327 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1328 return;
1330 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1331 if (jse.type & JS_EVENT_BUTTON) {
1332 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1333 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1335 if (jse.type & JS_EVENT_AXIS) {
1336 switch (jse.number) {
1337 case 0:
1338 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1339 This->js.lX = map_axis(jse.value);
1340 break;
1341 case 1:
1342 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1343 This->js.lY = map_axis(jse.value);
1344 break;
1345 case 2:
1346 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1347 This->js.lZ = map_axis(jse.value);
1348 break;
1349 default:
1350 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1351 break;
1357 /******************************************************************************
1358 * GetDeviceState : returns the "state" of the joystick.
1361 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1362 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1364 ICOM_THIS(JoystickAImpl,iface);
1366 joy_polldev(This);
1367 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1368 if (len != sizeof(DIJOYSTATE)) {
1369 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1371 memcpy(ptr,&(This->js),len);
1372 This->queue_pos = 0;
1373 return 0;
1376 /******************************************************************************
1377 * GetDeviceState : gets buffered input data.
1379 static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1380 DWORD dodsize,
1381 LPDIDEVICEOBJECTDATA dod,
1382 LPDWORD entries,
1383 DWORD flags
1385 ICOM_THIS(JoystickAImpl,iface);
1387 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1389 joy_polldev(This);
1390 if (flags & DIGDD_PEEK)
1391 FIXME("DIGDD_PEEK\n");
1393 if (dod == NULL) {
1394 } else {
1396 return 0;
1399 /******************************************************************************
1400 * SetProperty : change input device properties
1402 static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1403 REFGUID rguid,
1404 LPCDIPROPHEADER ph)
1406 ICOM_THIS(JoystickAImpl,iface);
1407 char xbuf[50];
1409 if (HIWORD(rguid))
1410 WINE_StringFromCLSID(rguid,xbuf);
1411 else
1412 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1414 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1415 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1417 if (!HIWORD(rguid)) {
1418 switch ((DWORD)rguid) {
1419 case (DWORD) DIPROP_BUFFERSIZE: {
1420 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1422 FIXME("buffersize = %ld\n",pd->dwData);
1423 break;
1425 case (DWORD)DIPROP_RANGE: {
1426 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1428 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1429 This->lMin = pr->lMin;
1430 This->lMax = pr->lMax;
1431 break;
1433 case (DWORD)DIPROP_DEADZONE: {
1434 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1436 FIXME("deadzone(%ld)\n",pd->dwData);
1437 This->deadzone = pd->dwData;
1438 break;
1440 default:
1441 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1442 break;
1445 return 0;
1448 /******************************************************************************
1449 * SetEventNotification : specifies event to be sent on state change
1451 static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1452 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1454 ICOM_THIS(JoystickAImpl,iface);
1456 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1457 This->hEvent = hnd;
1458 return DI_OK;
1461 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1462 LPDIRECTINPUTDEVICE2A iface,
1463 LPDIDEVCAPS lpDIDevCaps)
1465 ICOM_THIS(JoystickAImpl,iface);
1466 BYTE axes,buttons;
1467 int xfd = This->joyfd;
1469 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1470 if (xfd==-1)
1471 xfd = open(JOYDEV,O_RDONLY);
1472 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1473 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1474 #ifdef JSIOCGAXES
1475 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1476 axes = 2;
1477 lpDIDevCaps->dwAxes = axes;
1478 #endif
1479 #ifdef JSIOCGBUTTONS
1480 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1481 buttons = 2;
1482 lpDIDevCaps->dwButtons = buttons;
1483 #endif
1484 if (xfd!=This->joyfd)
1485 close(xfd);
1486 return DI_OK;
1488 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1489 ICOM_THIS(JoystickAImpl,iface);
1490 TRACE("(),stub!\n");
1492 joy_polldev(This);
1493 return DI_OK;
1495 #endif
1497 /****************************************************************************/
1498 /****************************************************************************/
1500 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1502 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1503 IDirectInputDevice2AImpl_QueryInterface,
1504 IDirectInputDevice2AImpl_AddRef,
1505 IDirectInputDevice2AImpl_Release,
1506 IDirectInputDevice2AImpl_GetCapabilities,
1507 IDirectInputDevice2AImpl_EnumObjects,
1508 IDirectInputDevice2AImpl_GetProperty,
1509 SysKeyboardAImpl_SetProperty,
1510 SysKeyboardAImpl_Acquire,
1511 SysKeyboardAImpl_Unacquire,
1512 SysKeyboardAImpl_GetDeviceState,
1513 SysKeyboardAImpl_GetDeviceData,
1514 IDirectInputDevice2AImpl_SetDataFormat,
1515 IDirectInputDevice2AImpl_SetEventNotification,
1516 IDirectInputDevice2AImpl_SetCooperativeLevel,
1517 IDirectInputDevice2AImpl_GetObjectInfo,
1518 IDirectInputDevice2AImpl_GetDeviceInfo,
1519 IDirectInputDevice2AImpl_RunControlPanel,
1520 IDirectInputDevice2AImpl_Initialize,
1521 IDirectInputDevice2AImpl_CreateEffect,
1522 IDirectInputDevice2AImpl_EnumEffects,
1523 IDirectInputDevice2AImpl_GetEffectInfo,
1524 IDirectInputDevice2AImpl_GetForceFeedbackState,
1525 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1526 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1527 IDirectInputDevice2AImpl_Escape,
1528 IDirectInputDevice2AImpl_Poll,
1529 IDirectInputDevice2AImpl_SendDeviceData,
1532 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1534 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1535 IDirectInputDevice2AImpl_QueryInterface,
1536 IDirectInputDevice2AImpl_AddRef,
1537 SysMouseAImpl_Release,
1538 IDirectInputDevice2AImpl_GetCapabilities,
1539 IDirectInputDevice2AImpl_EnumObjects,
1540 IDirectInputDevice2AImpl_GetProperty,
1541 SysMouseAImpl_SetProperty,
1542 SysMouseAImpl_Acquire,
1543 SysMouseAImpl_Unacquire,
1544 SysMouseAImpl_GetDeviceState,
1545 SysMouseAImpl_GetDeviceData,
1546 SysMouseAImpl_SetDataFormat,
1547 SysMouseAImpl_SetEventNotification,
1548 SysMouseAImpl_SetCooperativeLevel,
1549 IDirectInputDevice2AImpl_GetObjectInfo,
1550 IDirectInputDevice2AImpl_GetDeviceInfo,
1551 IDirectInputDevice2AImpl_RunControlPanel,
1552 IDirectInputDevice2AImpl_Initialize,
1553 IDirectInputDevice2AImpl_CreateEffect,
1554 IDirectInputDevice2AImpl_EnumEffects,
1555 IDirectInputDevice2AImpl_GetEffectInfo,
1556 IDirectInputDevice2AImpl_GetForceFeedbackState,
1557 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1558 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1559 IDirectInputDevice2AImpl_Escape,
1560 IDirectInputDevice2AImpl_Poll,
1561 IDirectInputDevice2AImpl_SendDeviceData,
1564 #ifdef HAVE_LINUX_22_JOYSTICK_API
1565 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1567 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1568 IDirectInputDevice2AImpl_QueryInterface,
1569 IDirectInputDevice2AImpl_AddRef,
1570 JoystickAImpl_Release,
1571 JoystickAImpl_GetCapabilities,
1572 IDirectInputDevice2AImpl_EnumObjects,
1573 IDirectInputDevice2AImpl_GetProperty,
1574 JoystickAImpl_SetProperty,
1575 JoystickAImpl_Acquire,
1576 JoystickAImpl_Unacquire,
1577 JoystickAImpl_GetDeviceState,
1578 JoystickAImpl_GetDeviceData,
1579 JoystickAImpl_SetDataFormat,
1580 JoystickAImpl_SetEventNotification,
1581 IDirectInputDevice2AImpl_SetCooperativeLevel,
1582 IDirectInputDevice2AImpl_GetObjectInfo,
1583 IDirectInputDevice2AImpl_GetDeviceInfo,
1584 IDirectInputDevice2AImpl_RunControlPanel,
1585 IDirectInputDevice2AImpl_Initialize,
1586 IDirectInputDevice2AImpl_CreateEffect,
1587 IDirectInputDevice2AImpl_EnumEffects,
1588 IDirectInputDevice2AImpl_GetEffectInfo,
1589 IDirectInputDevice2AImpl_GetForceFeedbackState,
1590 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1591 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1592 IDirectInputDevice2AImpl_Escape,
1593 JoystickAImpl_Poll,
1594 IDirectInputDevice2AImpl_SendDeviceData,
1596 #endif