If the joydevice is not present, do not create a DirectInputDevice.
[wine/wine-kai.git] / windows / dinput.c
blob0b2c0cd52a80af44f70f31b3ce743523df7f44c9
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 #include <sys/errno.h>
34 #ifdef HAVE_LINUX_JOYSTICK_H
35 # include <linux/joystick.h>
36 # define JOYDEV "/dev/js0"
37 #endif
38 #include "wine/obj_base.h"
39 #include "debugtools.h"
40 #include "dinput.h"
41 #include "display.h"
42 #include "keyboard.h"
43 #include "message.h"
44 #include "mouse.h"
45 #include "sysmetrics.h"
46 #include "winbase.h"
47 #include "winerror.h"
48 #include "winuser.h"
50 DEFAULT_DEBUG_CHANNEL(dinput)
53 extern BYTE InputKeyStateTable[256];
54 extern int min_keycode, max_keycode;
55 extern WORD keyc2vkey[256];
57 static ICOM_VTABLE(IDirectInputA) ddiavt;
58 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
59 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
61 typedef struct IDirectInputAImpl IDirectInputAImpl;
62 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
63 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
64 typedef struct SysMouseAImpl SysMouseAImpl;
66 struct IDirectInputDevice2AImpl
68 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
69 DWORD ref;
70 GUID guid;
73 struct SysKeyboardAImpl
75 /* IDirectInputDevice2AImpl */
76 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
77 DWORD ref;
78 GUID guid;
79 /* SysKeyboardAImpl */
80 BYTE keystate[256];
83 #ifdef HAVE_LINUX_22_JOYSTICK_API
84 typedef struct JoystickAImpl JoystickAImpl;
85 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt;
86 struct JoystickAImpl
88 /* IDirectInputDevice2AImpl */
89 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
90 DWORD ref;
91 GUID guid;
93 /* joystick private */
94 int joyfd;
95 LPDIDATAFORMAT df;
96 HANDLE hEvent;
97 LONG lMin,lMax,deadzone;
98 LPDIDEVICEOBJECTDATA data_queue;
99 int queue_pos, queue_len;
100 DIJOYSTATE js;
102 #endif
104 struct SysMouseAImpl
106 /* IDirectInputDevice2AImpl */
107 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
108 DWORD ref;
109 GUID guid;
111 LPDIDATAFORMAT df;
112 /* SysMouseAImpl */
113 BYTE absolute;
114 /* Previous position for relative moves */
115 LONG prevX, prevY;
116 LPMOUSE_EVENT_PROC prev_handler;
117 HWND win;
118 DWORD win_centerX, win_centerY;
119 LPDIDEVICEOBJECTDATA data_queue;
120 int queue_pos, queue_len;
121 int need_warp;
122 int acquired;
123 HANDLE hEvent;
124 CRITICAL_SECTION crit;
127 static int evsequence=0;
130 /* UIDs for Wine "drivers".
131 When enumerating each device supporting DInput, they have two UIDs :
132 - the 'windows' UID
133 - a vendor UID */
134 #ifdef HAVE_LINUX_22_JOYSTICK_API
135 static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
136 0x9e573ed9,
137 0x7734,
138 0x11d2,
139 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
141 #endif
142 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
143 0x9e573ed8,
144 0x7734,
145 0x11d2,
146 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
148 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
149 0x0ab8648a,
150 0x7735,
151 0x11d2,
152 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
155 /* FIXME: This is ugly and not thread safe :/ */
156 static IDirectInputDevice2A* current_lock = NULL;
158 /******************************************************************************
159 * Various debugging tools
161 static void _dump_cooperativelevel(DWORD dwFlags) {
162 int i;
163 const struct {
164 DWORD mask;
165 char *name;
166 } flags[] = {
167 #define FE(x) { x, #x},
168 FE(DISCL_BACKGROUND)
169 FE(DISCL_EXCLUSIVE)
170 FE(DISCL_FOREGROUND)
171 FE(DISCL_NONEXCLUSIVE)
173 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
174 if (flags[i].mask & dwFlags)
175 DPRINTF("%s ",flags[i].name);
176 DPRINTF("\n");
179 struct IDirectInputAImpl
181 ICOM_VTABLE(IDirectInputA)* lpvtbl;
182 DWORD ref;
185 /******************************************************************************
186 * DirectInputCreate32A
188 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
190 IDirectInputAImpl* This;
191 TRACE("(0x%08lx,%04lx,%p,%p)\n",
192 (DWORD)hinst,dwVersion,ppDI,punkOuter
194 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
195 This->ref = 1;
196 This->lpvtbl = &ddiavt;
197 *ppDI=(IDirectInputA*)This;
198 return 0;
200 /******************************************************************************
201 * IDirectInputA_EnumDevices
203 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
204 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
205 LPVOID pvRef, DWORD dwFlags
208 ICOM_THIS(IDirectInputAImpl,iface);
209 DIDEVICEINSTANCEA devInstance;
210 int ret;
212 TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
214 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
215 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
216 /* Return keyboard */
217 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
218 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
219 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
220 strcpy(devInstance.tszInstanceName, "Keyboard");
221 strcpy(devInstance.tszProductName, "Wine Keyboard");
223 ret = lpCallback(&devInstance, pvRef);
224 TRACE("Keyboard registered\n");
225 if (ret == DIENUM_STOP)
226 return 0;
229 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
230 /* Return mouse */
231 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
232 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
233 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
234 strcpy(devInstance.tszInstanceName, "Mouse");
235 strcpy(devInstance.tszProductName, "Wine Mouse");
237 ret = lpCallback(&devInstance, pvRef);
238 TRACE("Mouse registered\n");
239 if (ret == DIENUM_STOP)
240 return 0;
242 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) {
243 /* check whether we have a joystick */
244 #ifdef HAVE_LINUX_22_JOYSTICK_API
245 if ( (access(JOYDEV,O_RDONLY)!=-1) ||
246 (errno!=ENODEV && errno!=ENOENT)
248 /* Return joystick */
249 devInstance.guidInstance = GUID_Joystick;
250 devInstance.guidProduct = DInput_Wine_Joystick_GUID;
251 /* we only support traditional joysticks for now */
252 devInstance.dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
253 strcpy(devInstance.tszInstanceName, "Joystick");
254 /* ioctl JSIOCGNAME(len) */
255 strcpy(devInstance.tszProductName, "Wine Joystick");
257 ret = lpCallback(&devInstance,pvRef);
258 TRACE("Joystick registered\n");
259 if (ret == DIENUM_STOP)
260 return 0;
262 #endif
264 return 0;
267 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
269 ICOM_THIS(IDirectInputAImpl,iface);
270 return ++(This->ref);
273 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
275 ICOM_THIS(IDirectInputAImpl,iface);
276 if (!(--This->ref)) {
277 HeapFree(GetProcessHeap(),0,This);
278 return 0;
280 return This->ref;
283 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
284 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
285 LPUNKNOWN punk
287 ICOM_THIS(IDirectInputAImpl,iface);
288 char xbuf[50];
290 WINE_StringFromCLSID(rguid,xbuf);
291 FIXME("(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
292 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
293 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
294 SysKeyboardAImpl* newDevice;
295 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
296 newDevice->ref = 1;
297 newDevice->lpvtbl = &SysKeyboardAvt;
298 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
299 memset(newDevice->keystate,0,256);
300 *pdev=(IDirectInputDeviceA*)newDevice;
301 return DI_OK;
303 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
304 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
305 SysMouseAImpl* newDevice;
306 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
307 newDevice->ref = 1;
308 newDevice->lpvtbl = &SysMouseAvt;
309 InitializeCriticalSection(&(newDevice->crit));
310 MakeCriticalSectionGlobal(&(newDevice->crit));
311 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
312 *pdev=(IDirectInputDeviceA*)newDevice;
313 return DI_OK;
315 #ifdef HAVE_LINUX_22_JOYSTICK_API
316 if ((!memcmp(&GUID_Joystick,rguid,sizeof(GUID_Joystick))) ||
317 (!memcmp(&DInput_Wine_Joystick_GUID,rguid,sizeof(GUID_Joystick)))) {
318 JoystickAImpl* newDevice;
319 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
320 newDevice->ref = 1;
321 newDevice->lpvtbl = &JoystickAvt;
322 newDevice->joyfd = -1;
323 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
324 *pdev=(IDirectInputDeviceA*)newDevice;
325 return DI_OK;
327 #endif
328 return E_FAIL;
331 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
332 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
334 ICOM_THIS(IDirectInputAImpl,iface);
335 char xbuf[50];
337 WINE_StringFromCLSID(riid,xbuf);
338 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
339 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
340 IDirectInputA_AddRef(iface);
341 *ppobj = This;
342 return 0;
344 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
345 IDirectInputA_AddRef(iface);
346 *ppobj = This;
347 return 0;
349 return E_FAIL;
352 static HRESULT WINAPI IDirectInputAImpl_Initialize(
353 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
355 return DIERR_ALREADYINITIALIZED;
358 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
359 REFGUID rguid) {
360 ICOM_THIS(IDirectInputAImpl,iface);
361 char xbuf[50];
363 WINE_StringFromCLSID(rguid,xbuf);
364 FIXME("(%p)->(%s): stub\n",This,xbuf);
366 return DI_OK;
369 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
370 HWND hwndOwner,
371 DWORD dwFlags) {
372 ICOM_THIS(IDirectInputAImpl,iface);
373 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
375 return DI_OK;
378 static ICOM_VTABLE(IDirectInputA) ddiavt =
380 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
381 IDirectInputAImpl_QueryInterface,
382 IDirectInputAImpl_AddRef,
383 IDirectInputAImpl_Release,
384 IDirectInputAImpl_CreateDevice,
385 IDirectInputAImpl_EnumDevices,
386 IDirectInputAImpl_GetDeviceStatus,
387 IDirectInputAImpl_RunControlPanel,
388 IDirectInputAImpl_Initialize
391 /******************************************************************************
392 * IDirectInputDeviceA
395 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
396 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
399 int i;
400 TRACE(dinput,"(this=%p,%p)\n",This,df);
402 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
403 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
404 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
405 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
406 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
408 for (i=0;i<df->dwNumObjs;i++) {
409 char xbuf[50];
411 if (df->rgodf[i].pguid)
412 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
413 else
414 strcpy(xbuf,"<no guid>");
415 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
416 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
417 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
418 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
421 return 0;
424 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
425 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
427 ICOM_THIS(IDirectInputDevice2AImpl,iface);
428 FIXME("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
429 if (TRACE_ON(dinput))
430 _dump_cooperativelevel(dwflags);
431 return 0;
434 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
435 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
437 ICOM_THIS(IDirectInputDevice2AImpl,iface);
438 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
439 return 0;
442 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
444 ICOM_THIS(IDirectInputDevice2AImpl,iface);
445 This->ref--;
446 if (This->ref)
447 return This->ref;
448 HeapFree(GetProcessHeap(),0,This);
449 return 0;
452 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
453 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
456 ICOM_THIS(SysKeyboardAImpl,iface);
457 char xbuf[50];
459 if (HIWORD(rguid))
460 WINE_StringFromCLSID(rguid,xbuf);
461 else
462 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
463 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
464 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
465 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
466 if (!HIWORD(rguid)) {
467 switch ((DWORD)rguid) {
468 case (DWORD) DIPROP_BUFFERSIZE: {
469 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
471 TRACE("(buffersize=%ld)\n",pd->dwData);
472 break;
474 default:
475 WARN("Unknown type %ld\n",(DWORD)rguid);
476 break;
479 return 0;
482 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
483 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
486 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
489 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
490 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
491 LPDWORD entries,DWORD flags
494 ICOM_THIS(SysKeyboardAImpl,iface);
495 HRESULT ret;
496 int i;
498 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
499 This,dodsize,dod,entries,entries?*entries:0,flags);
501 ret=KEYBOARD_Driver->pGetDIData(
502 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
503 for (i=0;i<*entries;i++) {
504 dod[i].dwTimeStamp = time(NULL);
505 dod[i].dwSequence = evsequence++;
507 return ret;
510 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
512 ICOM_THIS(SysKeyboardAImpl,iface);
513 TRACE("(this=%p): stub\n",This);
514 return 0;
517 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
519 ICOM_THIS(SysKeyboardAImpl,iface);
520 TRACE("(this=%p): stub\n",This);
521 return 0;
524 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
525 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
528 ICOM_THIS(IDirectInputDevice2AImpl,iface);
529 char xbuf[50];
531 WINE_StringFromCLSID(riid,xbuf);
532 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
533 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
534 IDirectInputDevice2_AddRef(iface);
535 *ppobj = This;
536 return 0;
538 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
539 IDirectInputDevice2_AddRef(iface);
540 *ppobj = This;
541 return 0;
543 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
544 IDirectInputDevice2_AddRef(iface);
545 *ppobj = This;
546 return 0;
548 return E_FAIL;
551 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
552 LPDIRECTINPUTDEVICE2A iface)
554 ICOM_THIS(IDirectInputDevice2AImpl,iface);
555 return ++This->ref;
558 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
559 LPDIRECTINPUTDEVICE2A iface,
560 LPDIDEVCAPS lpDIDevCaps)
562 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
563 FIXME("stub!\n");
564 return DI_OK;
567 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
568 LPDIRECTINPUTDEVICE2A iface,
569 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
570 LPVOID lpvRef,
571 DWORD dwFlags)
573 FIXME("stub!\n");
574 #if 0
575 if (lpCallback)
576 lpCallback(NULL, lpvRef);
577 #endif
578 return DI_OK;
581 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
582 LPDIRECTINPUTDEVICE2A iface,
583 REFGUID rguid,
584 LPDIPROPHEADER pdiph)
586 FIXME("stub!\n");
587 return DI_OK;
590 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
591 LPDIRECTINPUTDEVICE2A iface,
592 LPDIDEVICEOBJECTINSTANCEA pdidoi,
593 DWORD dwObj,
594 DWORD dwHow)
596 FIXME("stub!\n");
597 return DI_OK;
600 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
601 LPDIRECTINPUTDEVICE2A iface,
602 LPDIDEVICEINSTANCEA pdidi)
604 FIXME("stub!\n");
605 return DI_OK;
608 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
609 LPDIRECTINPUTDEVICE2A iface,
610 HWND hwndOwner,
611 DWORD dwFlags)
613 FIXME("stub!\n");
614 return DI_OK;
617 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
618 LPDIRECTINPUTDEVICE2A iface,
619 HINSTANCE hinst,
620 DWORD dwVersion,
621 REFGUID rguid)
623 FIXME("stub!\n");
624 return DI_OK;
627 /******************************************************************************
628 * IDirectInputDevice2A
631 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
632 LPDIRECTINPUTDEVICE2A iface,
633 REFGUID rguid,
634 LPCDIEFFECT lpeff,
635 LPDIRECTINPUTEFFECT *ppdef,
636 LPUNKNOWN pUnkOuter)
638 FIXME("stub!\n");
639 return DI_OK;
642 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
643 LPDIRECTINPUTDEVICE2A iface,
644 LPDIENUMEFFECTSCALLBACKA lpCallback,
645 LPVOID lpvRef,
646 DWORD dwFlags)
648 FIXME("stub!\n");
649 if (lpCallback)
650 lpCallback(NULL, lpvRef);
651 return DI_OK;
654 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
655 LPDIRECTINPUTDEVICE2A iface,
656 LPDIEFFECTINFOA lpdei,
657 REFGUID rguid)
659 FIXME("stub!\n");
660 return DI_OK;
663 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
664 LPDIRECTINPUTDEVICE2A iface,
665 LPDWORD pdwOut)
667 FIXME("stub!\n");
668 return DI_OK;
671 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
672 LPDIRECTINPUTDEVICE2A iface,
673 DWORD dwFlags)
675 FIXME("stub!\n");
676 return DI_OK;
679 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
680 LPDIRECTINPUTDEVICE2A iface,
681 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
682 LPVOID lpvRef,
683 DWORD dwFlags)
685 FIXME("stub!\n");
686 if (lpCallback)
687 lpCallback(NULL, lpvRef);
688 return DI_OK;
691 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
692 LPDIRECTINPUTDEVICE2A iface,
693 LPDIEFFESCAPE lpDIEEsc)
695 FIXME("stub!\n");
696 return DI_OK;
699 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
700 LPDIRECTINPUTDEVICE2A iface)
702 FIXME("stub!\n");
703 return DI_OK;
706 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
707 LPDIRECTINPUTDEVICE2A iface,
708 DWORD cbObjectData,
709 LPDIDEVICEOBJECTDATA rgdod,
710 LPDWORD pdwInOut,
711 DWORD dwFlags)
713 FIXME("stub!\n");
714 return DI_OK;
717 /******************************************************************************
718 * SysMouseA (DInput Mouse support)
721 /******************************************************************************
722 * Release : release the mouse buffer.
724 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
726 ICOM_THIS(SysMouseAImpl,iface);
728 This->ref--;
729 if (This->ref)
730 return This->ref;
732 /* Free the data queue */
733 if (This->data_queue != NULL)
734 HeapFree(GetProcessHeap(),0,This->data_queue);
736 /* Install the previous event handler (in case of releasing an aquired
737 mouse device) */
738 if (This->prev_handler != NULL)
739 MOUSE_Enable(This->prev_handler);
740 DeleteCriticalSection(&(This->crit));
742 HeapFree(GetProcessHeap(),0,This);
743 return 0;
747 /******************************************************************************
748 * SetCooperativeLevel : store the window in which we will do our
749 * grabbing.
751 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
752 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
755 ICOM_THIS(SysMouseAImpl,iface);
757 TRACE("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
759 if (TRACE_ON(dinput))
760 _dump_cooperativelevel(dwflags);
762 /* Store the window which asks for the mouse */
763 This->win = hwnd;
765 return 0;
769 /******************************************************************************
770 * SetDataFormat : the application can choose the format of the data
771 * the device driver sends back with GetDeviceState.
773 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
774 * in absolute and relative mode.
776 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
777 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
780 ICOM_THIS(SysMouseAImpl,iface);
781 int i;
783 TRACE("(this=%p,%p)\n",This,df);
785 TRACE("(df.dwSize=%ld)\n",df->dwSize);
786 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
787 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
788 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
789 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
791 for (i=0;i<df->dwNumObjs;i++) {
792 char xbuf[50];
794 if (df->rgodf[i].pguid)
795 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
796 else
797 strcpy(xbuf,"<no guid>");
798 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
799 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
800 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
801 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
804 /* Check size of data format to prevent crashes if the applications
805 sends a smaller buffer */
806 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
807 FIXME("non-standard mouse configuration not supported yet.");
808 return DIERR_INVALIDPARAM;
811 /* For the moment, ignore these fields and return always as if
812 c_dfDIMouse was passed as format... */
814 /* Check if the mouse is in absolute or relative mode */
815 if (df->dwFlags == DIDF_ABSAXIS)
816 This->absolute = 1;
817 else if (df->dwFlags == DIDF_RELAXIS)
818 This->absolute = 0;
819 else
820 ERR("Neither absolute nor relative flag set.");
822 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
823 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
824 return 0;
827 #define GEN_EVENT(offset,data,xtime,seq) \
829 if (This->queue_pos < This->queue_len) { \
830 This->data_queue[This->queue_pos].dwOfs = offset; \
831 This->data_queue[This->queue_pos].dwData = data; \
832 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
833 This->data_queue[This->queue_pos].dwSequence = seq; \
834 This->queue_pos++; \
839 /* Our private mouse event handler */
840 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
841 DWORD cButtons, DWORD dwExtraInfo )
843 DWORD posX, posY, keyState, xtime, extra;
844 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
846 EnterCriticalSection(&(This->crit));
847 /* Mouse moved -> send event if asked */
848 if (This->hEvent)
849 SetEvent(This->hEvent);
851 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
852 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
853 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
854 keyState = wme->keyState;
855 xtime = wme->time;
856 extra = (DWORD)wme->hWnd;
858 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
859 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
860 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
861 } else {
862 ERR("Mouse event not supported...\n");
863 LeaveCriticalSection(&(This->crit));
864 return ;
867 TRACE(" %ld %ld ", posX, posY);
869 if ( dwFlags & MOUSEEVENTF_MOVE ) {
870 if (This->absolute) {
871 if (posX != This->prevX)
872 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
873 if (posY != This->prevY)
874 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
875 } else {
876 /* Relative mouse input : the real fun starts here... */
877 if (This->need_warp) {
878 if (posX != This->prevX)
879 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
880 if (posY != This->prevY)
881 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
882 } else {
883 /* This is the first time the event handler has been called after a
884 GetData of GetState. */
885 if (posX != This->win_centerX) {
886 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
887 This->need_warp = 1;
890 if (posY != This->win_centerY) {
891 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
892 This->need_warp = 1;
897 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
898 if (TRACE_ON(dinput))
899 DPRINTF(" LD ");
901 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
903 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
904 if (TRACE_ON(dinput))
905 DPRINTF(" LU ");
907 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
909 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
910 if (TRACE_ON(dinput))
911 DPRINTF(" RD ");
913 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
915 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
916 if (TRACE_ON(dinput))
917 DPRINTF(" RU ");
919 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
921 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
922 if (TRACE_ON(dinput))
923 DPRINTF(" MD ");
925 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
927 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
928 if (TRACE_ON(dinput))
929 DPRINTF(" MU ");
931 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
933 if (TRACE_ON(dinput))
934 DPRINTF("\n");
936 This->prevX = posX;
937 This->prevY = posY;
938 LeaveCriticalSection(&(This->crit));
942 /******************************************************************************
943 * Acquire : gets exclusive control of the mouse
945 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
947 ICOM_THIS(SysMouseAImpl,iface);
948 RECT rect;
950 TRACE("(this=%p)\n",This);
952 if (This->acquired == 0) {
953 POINT point;
955 /* This stores the current mouse handler. */
956 This->prev_handler = mouse_event;
958 /* Store (in a global variable) the current lock */
959 current_lock = (IDirectInputDevice2A*)This;
961 /* Install our own mouse event handler */
962 MOUSE_Enable(dinput_mouse_event);
964 /* Get the window dimension and find the center */
965 GetWindowRect(This->win, &rect);
966 This->win_centerX = (rect.right - rect.left) / 2;
967 This->win_centerY = (rect.bottom - rect.top ) / 2;
969 /* Warp the mouse to the center of the window */
970 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
971 point.x = This->win_centerX;
972 point.y = This->win_centerY;
973 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
974 DISPLAY_MoveCursor(point.x, point.y);
976 This->acquired = 1;
978 return 0;
981 /******************************************************************************
982 * Unacquire : frees the mouse
984 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
986 ICOM_THIS(SysMouseAImpl,iface);
988 TRACE("(this=%p)\n",This);
990 /* Reinstall previous mouse event handler */
991 MOUSE_Enable(This->prev_handler);
992 This->prev_handler = NULL;
994 /* No more locks */
995 current_lock = NULL;
997 /* Unacquire device */
998 This->acquired = 0;
1000 return 0;
1003 /******************************************************************************
1004 * GetDeviceState : returns the "state" of the mouse.
1006 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1007 * supported.
1009 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1010 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1012 ICOM_THIS(SysMouseAImpl,iface);
1013 DWORD rx, ry, state;
1014 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
1016 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1018 /* Check if the buffer is big enough */
1019 if (len < sizeof(struct DIMOUSESTATE)) {
1020 FIXME("unsupported state structure.");
1021 return DIERR_INVALIDPARAM;
1024 /* Get the mouse position */
1025 EVENT_QueryPointer(&rx, &ry, &state);
1026 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
1028 /* Fill the mouse state structure */
1029 if (This->absolute) {
1030 mstate->lX = rx;
1031 mstate->lY = ry;
1032 } else {
1033 mstate->lX = rx - This->win_centerX;
1034 mstate->lY = ry - This->win_centerY;
1036 if ((mstate->lX != 0) || (mstate->lY != 0))
1037 This->need_warp = 1;
1039 mstate->lZ = 0;
1040 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
1041 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
1042 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
1043 mstate->rgbButtons[3] = 0x00;
1045 /* Check if we need to do a mouse warping */
1046 if (This->need_warp) {
1047 POINT point;
1049 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1050 point.x = This->win_centerX;
1051 point.y = This->win_centerY;
1052 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1053 DISPLAY_MoveCursor(point.x, point.y);
1055 This->need_warp = 0;
1058 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1059 mstate->lX, mstate->lY,
1060 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1062 return 0;
1065 /******************************************************************************
1066 * GetDeviceState : gets buffered input data.
1068 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1069 DWORD dodsize,
1070 LPDIDEVICEOBJECTDATA dod,
1071 LPDWORD entries,
1072 DWORD flags
1074 ICOM_THIS(SysMouseAImpl,iface);
1076 EnterCriticalSection(&(This->crit));
1077 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1079 if (flags & DIGDD_PEEK)
1080 FIXME("DIGDD_PEEK\n");
1082 if (dod == NULL) {
1083 *entries = This->queue_pos;
1084 This->queue_pos = 0;
1085 } else {
1086 /* Check for buffer overflow */
1087 if (This->queue_pos > *entries) {
1088 WARN("Buffer overflow not handled properly yet...\n");
1089 This->queue_pos = *entries;
1091 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1092 ERR("Wrong structure size !\n");
1093 LeaveCriticalSection(&(This->crit));
1094 return DIERR_INVALIDPARAM;
1097 if (This->queue_pos)
1098 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1100 /* Copy the buffered data into the application queue */
1101 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1102 *entries = This->queue_pos;
1104 /* Reset the event queue */
1105 This->queue_pos = 0;
1107 LeaveCriticalSection(&(This->crit));
1109 #if 0 /* FIXME: seems to create motion events, which fire back at us. */
1110 /* Check if we need to do a mouse warping */
1111 if (This->need_warp) {
1112 POINT point;
1114 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1115 point.x = This->win_centerX;
1116 point.y = This->win_centerY;
1117 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1119 DISPLAY_MoveCursor(point.x, point.y);
1121 This->need_warp = 0;
1123 #endif
1124 return 0;
1127 /******************************************************************************
1128 * SetProperty : change input device properties
1130 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1131 REFGUID rguid,
1132 LPCDIPROPHEADER ph)
1134 ICOM_THIS(SysMouseAImpl,iface);
1135 char xbuf[50];
1137 if (HIWORD(rguid))
1138 WINE_StringFromCLSID(rguid,xbuf);
1139 else
1140 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1142 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1144 if (!HIWORD(rguid)) {
1145 switch ((DWORD)rguid) {
1146 case (DWORD) DIPROP_BUFFERSIZE: {
1147 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1149 TRACE("buffersize = %ld\n",pd->dwData);
1151 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1152 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1153 This->queue_pos = 0;
1154 This->queue_len = pd->dwData;
1155 break;
1157 default:
1158 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1159 break;
1163 return 0;
1166 /******************************************************************************
1167 * SetEventNotification : specifies event to be sent on state change
1169 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1170 HANDLE hnd) {
1171 ICOM_THIS(SysMouseAImpl,iface);
1173 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1175 This->hEvent = hnd;
1177 return DI_OK;
1180 #ifdef HAVE_LINUX_22_JOYSTICK_API
1181 /******************************************************************************
1182 * Joystick
1184 static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1186 ICOM_THIS(JoystickAImpl,iface);
1188 This->ref--;
1189 if (This->ref)
1190 return This->ref;
1191 HeapFree(GetProcessHeap(),0,This);
1192 return 0;
1195 /******************************************************************************
1196 * SetDataFormat : the application can choose the format of the data
1197 * the device driver sends back with GetDeviceState.
1199 static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1200 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1203 ICOM_THIS(JoystickAImpl,iface);
1204 int i;
1206 TRACE("(this=%p,%p)\n",This,df);
1208 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1209 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1210 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1211 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1212 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1214 for (i=0;i<df->dwNumObjs;i++) {
1215 char xbuf[50];
1217 if (df->rgodf[i].pguid)
1218 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1219 else
1220 strcpy(xbuf,"<no guid>");
1221 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1222 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1223 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1224 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1226 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1227 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1228 return 0;
1231 /******************************************************************************
1232 * Acquire : gets exclusive control of the joystick
1234 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1236 ICOM_THIS(JoystickAImpl,iface);
1238 TRACE("(this=%p)\n",This);
1239 if (This->joyfd!=-1)
1240 return 0;
1241 This->joyfd=open(JOYDEV,O_RDONLY);
1242 if (This->joyfd==-1)
1243 return DIERR_NOTFOUND;
1244 return 0;
1247 /******************************************************************************
1248 * Unacquire : frees the joystick
1250 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1252 ICOM_THIS(JoystickAImpl,iface);
1254 TRACE("(this=%p)\n",This);
1255 if (This->joyfd!=-1) {
1256 close(This->joyfd);
1257 This->joyfd = -1;
1259 return 0;
1262 #define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1264 static void joy_polldev(JoystickAImpl *This) {
1265 struct timeval tv;
1266 fd_set readfds;
1267 struct js_event jse;
1269 if (This->joyfd==-1)
1270 return;
1271 while (1) {
1272 memset(&tv,0,sizeof(tv));
1273 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1274 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1275 return;
1276 /* we have one event, so we can read */
1277 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1278 return;
1280 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1281 if (jse.type & JS_EVENT_BUTTON) {
1282 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1283 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1285 if (jse.type & JS_EVENT_AXIS) {
1286 switch (jse.number) {
1287 case 0:
1288 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1289 This->js.lX = map_axis(jse.value);
1290 break;
1291 case 1:
1292 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1293 This->js.lY = map_axis(jse.value);
1294 break;
1295 case 2:
1296 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1297 This->js.lZ = map_axis(jse.value);
1298 break;
1299 default:
1300 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1301 break;
1307 /******************************************************************************
1308 * GetDeviceState : returns the "state" of the joystick.
1311 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1312 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1314 ICOM_THIS(JoystickAImpl,iface);
1316 joy_polldev(This);
1317 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1318 if (len != sizeof(DIJOYSTATE)) {
1319 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1321 memcpy(ptr,&(This->js),len);
1322 This->queue_pos = 0;
1323 return 0;
1326 /******************************************************************************
1327 * GetDeviceState : gets buffered input data.
1329 static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1330 DWORD dodsize,
1331 LPDIDEVICEOBJECTDATA dod,
1332 LPDWORD entries,
1333 DWORD flags
1335 ICOM_THIS(JoystickAImpl,iface);
1337 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1339 joy_polldev(This);
1340 if (flags & DIGDD_PEEK)
1341 FIXME("DIGDD_PEEK\n");
1343 if (dod == NULL) {
1344 } else {
1346 return 0;
1349 /******************************************************************************
1350 * SetProperty : change input device properties
1352 static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1353 REFGUID rguid,
1354 LPCDIPROPHEADER ph)
1356 ICOM_THIS(JoystickAImpl,iface);
1357 char xbuf[50];
1359 if (HIWORD(rguid))
1360 WINE_StringFromCLSID(rguid,xbuf);
1361 else
1362 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1364 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1365 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1367 if (!HIWORD(rguid)) {
1368 switch ((DWORD)rguid) {
1369 case (DWORD) DIPROP_BUFFERSIZE: {
1370 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1372 FIXME("buffersize = %ld\n",pd->dwData);
1373 break;
1375 case (DWORD)DIPROP_RANGE: {
1376 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1378 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1379 This->lMin = pr->lMin;
1380 This->lMax = pr->lMax;
1381 break;
1383 case (DWORD)DIPROP_DEADZONE: {
1384 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1386 FIXME("deadzone(%ld)\n",pd->dwData);
1387 This->deadzone = pd->dwData;
1388 break;
1390 default:
1391 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1392 break;
1395 return 0;
1398 /******************************************************************************
1399 * SetEventNotification : specifies event to be sent on state change
1401 static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1402 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1404 ICOM_THIS(JoystickAImpl,iface);
1406 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1407 This->hEvent = hnd;
1408 return DI_OK;
1411 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1412 LPDIRECTINPUTDEVICE2A iface,
1413 LPDIDEVCAPS lpDIDevCaps)
1415 ICOM_THIS(JoystickAImpl,iface);
1416 BYTE axes,buttons;
1417 int xfd = This->joyfd;
1419 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1420 if (xfd==-1)
1421 xfd = open(JOYDEV,O_RDONLY);
1422 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1423 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1424 #ifdef JSIOCGAXES
1425 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1426 axes = 2;
1427 lpDIDevCaps->dwAxes = axes;
1428 #endif
1429 #ifdef JSIOCGBUTTONS
1430 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1431 buttons = 2;
1432 lpDIDevCaps->dwButtons = buttons;
1433 #endif
1434 if (xfd!=This->joyfd)
1435 close(xfd);
1436 return DI_OK;
1438 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1439 ICOM_THIS(JoystickAImpl,iface);
1440 TRACE("(),stub!\n");
1442 joy_polldev(This);
1443 return DI_OK;
1445 #endif
1447 /****************************************************************************/
1448 /****************************************************************************/
1450 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1452 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1453 IDirectInputDevice2AImpl_QueryInterface,
1454 IDirectInputDevice2AImpl_AddRef,
1455 IDirectInputDevice2AImpl_Release,
1456 IDirectInputDevice2AImpl_GetCapabilities,
1457 IDirectInputDevice2AImpl_EnumObjects,
1458 IDirectInputDevice2AImpl_GetProperty,
1459 SysKeyboardAImpl_SetProperty,
1460 SysKeyboardAImpl_Acquire,
1461 SysKeyboardAImpl_Unacquire,
1462 SysKeyboardAImpl_GetDeviceState,
1463 SysKeyboardAImpl_GetDeviceData,
1464 IDirectInputDevice2AImpl_SetDataFormat,
1465 IDirectInputDevice2AImpl_SetEventNotification,
1466 IDirectInputDevice2AImpl_SetCooperativeLevel,
1467 IDirectInputDevice2AImpl_GetObjectInfo,
1468 IDirectInputDevice2AImpl_GetDeviceInfo,
1469 IDirectInputDevice2AImpl_RunControlPanel,
1470 IDirectInputDevice2AImpl_Initialize,
1471 IDirectInputDevice2AImpl_CreateEffect,
1472 IDirectInputDevice2AImpl_EnumEffects,
1473 IDirectInputDevice2AImpl_GetEffectInfo,
1474 IDirectInputDevice2AImpl_GetForceFeedbackState,
1475 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1476 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1477 IDirectInputDevice2AImpl_Escape,
1478 IDirectInputDevice2AImpl_Poll,
1479 IDirectInputDevice2AImpl_SendDeviceData,
1482 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1484 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1485 IDirectInputDevice2AImpl_QueryInterface,
1486 IDirectInputDevice2AImpl_AddRef,
1487 SysMouseAImpl_Release,
1488 IDirectInputDevice2AImpl_GetCapabilities,
1489 IDirectInputDevice2AImpl_EnumObjects,
1490 IDirectInputDevice2AImpl_GetProperty,
1491 SysMouseAImpl_SetProperty,
1492 SysMouseAImpl_Acquire,
1493 SysMouseAImpl_Unacquire,
1494 SysMouseAImpl_GetDeviceState,
1495 SysMouseAImpl_GetDeviceData,
1496 SysMouseAImpl_SetDataFormat,
1497 SysMouseAImpl_SetEventNotification,
1498 SysMouseAImpl_SetCooperativeLevel,
1499 IDirectInputDevice2AImpl_GetObjectInfo,
1500 IDirectInputDevice2AImpl_GetDeviceInfo,
1501 IDirectInputDevice2AImpl_RunControlPanel,
1502 IDirectInputDevice2AImpl_Initialize,
1503 IDirectInputDevice2AImpl_CreateEffect,
1504 IDirectInputDevice2AImpl_EnumEffects,
1505 IDirectInputDevice2AImpl_GetEffectInfo,
1506 IDirectInputDevice2AImpl_GetForceFeedbackState,
1507 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1508 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1509 IDirectInputDevice2AImpl_Escape,
1510 IDirectInputDevice2AImpl_Poll,
1511 IDirectInputDevice2AImpl_SendDeviceData,
1514 #ifdef HAVE_LINUX_22_JOYSTICK_API
1515 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1517 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1518 IDirectInputDevice2AImpl_QueryInterface,
1519 IDirectInputDevice2AImpl_AddRef,
1520 JoystickAImpl_Release,
1521 JoystickAImpl_GetCapabilities,
1522 IDirectInputDevice2AImpl_EnumObjects,
1523 IDirectInputDevice2AImpl_GetProperty,
1524 JoystickAImpl_SetProperty,
1525 JoystickAImpl_Acquire,
1526 JoystickAImpl_Unacquire,
1527 JoystickAImpl_GetDeviceState,
1528 JoystickAImpl_GetDeviceData,
1529 JoystickAImpl_SetDataFormat,
1530 JoystickAImpl_SetEventNotification,
1531 IDirectInputDevice2AImpl_SetCooperativeLevel,
1532 IDirectInputDevice2AImpl_GetObjectInfo,
1533 IDirectInputDevice2AImpl_GetDeviceInfo,
1534 IDirectInputDevice2AImpl_RunControlPanel,
1535 IDirectInputDevice2AImpl_Initialize,
1536 IDirectInputDevice2AImpl_CreateEffect,
1537 IDirectInputDevice2AImpl_EnumEffects,
1538 IDirectInputDevice2AImpl_GetEffectInfo,
1539 IDirectInputDevice2AImpl_GetForceFeedbackState,
1540 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1541 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1542 IDirectInputDevice2AImpl_Escape,
1543 JoystickAImpl_Poll,
1544 IDirectInputDevice2AImpl_SendDeviceData,
1546 #endif