Implemented DirectInput Joystick support (tested with WC:Prophecy).
[wine/dcerpc.git] / windows / dinput.c
blob8e1b2ae6bbaae985a7d3acad6158d504fd9e3df2
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) || (errno!=ENODEV)) {
246 /* Return joystick */
247 devInstance.guidInstance = GUID_Joystick;
248 devInstance.guidProduct = DInput_Wine_Joystick_GUID;
249 /* we only support traditional joysticks for now */
250 devInstance.dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
251 strcpy(devInstance.tszInstanceName, "Joystick");
252 /* ioctl JSIOCGNAME(len) */
253 strcpy(devInstance.tszProductName, "Wine Joystick");
255 ret = lpCallback(&devInstance,pvRef);
256 TRACE("Joystick registered\n");
257 if (ret == DIENUM_STOP)
258 return 0;
260 #endif
262 return 0;
265 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
267 ICOM_THIS(IDirectInputAImpl,iface);
268 return ++(This->ref);
271 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
273 ICOM_THIS(IDirectInputAImpl,iface);
274 if (!(--This->ref)) {
275 HeapFree(GetProcessHeap(),0,This);
276 return 0;
278 return This->ref;
281 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
282 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
283 LPUNKNOWN punk
285 ICOM_THIS(IDirectInputAImpl,iface);
286 char xbuf[50];
288 WINE_StringFromCLSID(rguid,xbuf);
289 FIXME("(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
290 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
291 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
292 SysKeyboardAImpl* newDevice;
293 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
294 newDevice->ref = 1;
295 newDevice->lpvtbl = &SysKeyboardAvt;
296 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
297 memset(newDevice->keystate,0,256);
298 *pdev=(IDirectInputDeviceA*)newDevice;
299 return DI_OK;
301 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
302 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
303 SysMouseAImpl* newDevice;
304 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
305 newDevice->ref = 1;
306 newDevice->lpvtbl = &SysMouseAvt;
307 InitializeCriticalSection(&(newDevice->crit));
308 MakeCriticalSectionGlobal(&(newDevice->crit));
309 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
310 *pdev=(IDirectInputDeviceA*)newDevice;
311 return DI_OK;
313 #ifdef HAVE_LINUX_22_JOYSTICK_API
314 if ((!memcmp(&GUID_Joystick,rguid,sizeof(GUID_Joystick))) ||
315 (!memcmp(&DInput_Wine_Joystick_GUID,rguid,sizeof(GUID_Joystick)))) {
316 JoystickAImpl* newDevice;
317 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
318 newDevice->ref = 1;
319 newDevice->lpvtbl = &JoystickAvt;
320 newDevice->joyfd = -1;
321 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
322 *pdev=(IDirectInputDeviceA*)newDevice;
323 return DI_OK;
325 #endif
326 return E_FAIL;
329 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
330 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
332 ICOM_THIS(IDirectInputAImpl,iface);
333 char xbuf[50];
335 WINE_StringFromCLSID(riid,xbuf);
336 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
337 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
338 IDirectInputA_AddRef(iface);
339 *ppobj = This;
340 return 0;
342 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
343 IDirectInputA_AddRef(iface);
344 *ppobj = This;
345 return 0;
347 return E_FAIL;
350 static HRESULT WINAPI IDirectInputAImpl_Initialize(
351 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
353 return DIERR_ALREADYINITIALIZED;
356 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
357 REFGUID rguid) {
358 ICOM_THIS(IDirectInputAImpl,iface);
359 char xbuf[50];
361 WINE_StringFromCLSID(rguid,xbuf);
362 FIXME("(%p)->(%s): stub\n",This,xbuf);
364 return DI_OK;
367 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
368 HWND hwndOwner,
369 DWORD dwFlags) {
370 ICOM_THIS(IDirectInputAImpl,iface);
371 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
373 return DI_OK;
376 static ICOM_VTABLE(IDirectInputA) ddiavt =
378 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
379 IDirectInputAImpl_QueryInterface,
380 IDirectInputAImpl_AddRef,
381 IDirectInputAImpl_Release,
382 IDirectInputAImpl_CreateDevice,
383 IDirectInputAImpl_EnumDevices,
384 IDirectInputAImpl_GetDeviceStatus,
385 IDirectInputAImpl_RunControlPanel,
386 IDirectInputAImpl_Initialize
389 /******************************************************************************
390 * IDirectInputDeviceA
393 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
394 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
397 int i;
398 TRACE(dinput,"(this=%p,%p)\n",This,df);
400 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
401 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
402 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
403 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
404 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
406 for (i=0;i<df->dwNumObjs;i++) {
407 char xbuf[50];
409 if (df->rgodf[i].pguid)
410 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
411 else
412 strcpy(xbuf,"<no guid>");
413 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
414 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
415 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
416 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
419 return 0;
422 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
423 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
425 ICOM_THIS(IDirectInputDevice2AImpl,iface);
426 FIXME("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
427 if (TRACE_ON(dinput))
428 _dump_cooperativelevel(dwflags);
429 return 0;
432 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
433 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
435 ICOM_THIS(IDirectInputDevice2AImpl,iface);
436 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
437 return 0;
440 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
442 ICOM_THIS(IDirectInputDevice2AImpl,iface);
443 This->ref--;
444 if (This->ref)
445 return This->ref;
446 HeapFree(GetProcessHeap(),0,This);
447 return 0;
450 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
451 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
454 ICOM_THIS(SysKeyboardAImpl,iface);
455 char xbuf[50];
457 if (HIWORD(rguid))
458 WINE_StringFromCLSID(rguid,xbuf);
459 else
460 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
461 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
462 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
463 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
464 if (!HIWORD(rguid)) {
465 switch ((DWORD)rguid) {
466 case (DWORD) DIPROP_BUFFERSIZE: {
467 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
469 TRACE("(buffersize=%ld)\n",pd->dwData);
470 break;
472 default:
473 WARN("Unknown type %ld\n",(DWORD)rguid);
474 break;
477 return 0;
480 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
481 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
484 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
487 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
488 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
489 LPDWORD entries,DWORD flags
492 ICOM_THIS(SysKeyboardAImpl,iface);
493 HRESULT ret;
494 int i;
496 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
497 This,dodsize,dod,entries,entries?*entries:0,flags);
499 ret=KEYBOARD_Driver->pGetDIData(
500 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
501 for (i=0;i<*entries;i++) {
502 dod[i].dwTimeStamp = time(NULL);
503 dod[i].dwSequence = evsequence++;
505 return ret;
508 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
510 ICOM_THIS(SysKeyboardAImpl,iface);
511 TRACE("(this=%p): stub\n",This);
512 return 0;
515 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
517 ICOM_THIS(SysKeyboardAImpl,iface);
518 TRACE("(this=%p): stub\n",This);
519 return 0;
522 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
523 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
526 ICOM_THIS(IDirectInputDevice2AImpl,iface);
527 char xbuf[50];
529 WINE_StringFromCLSID(riid,xbuf);
530 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
531 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
532 IDirectInputDevice2_AddRef(iface);
533 *ppobj = This;
534 return 0;
536 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
537 IDirectInputDevice2_AddRef(iface);
538 *ppobj = This;
539 return 0;
541 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
542 IDirectInputDevice2_AddRef(iface);
543 *ppobj = This;
544 return 0;
546 return E_FAIL;
549 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
550 LPDIRECTINPUTDEVICE2A iface)
552 ICOM_THIS(IDirectInputDevice2AImpl,iface);
553 return ++This->ref;
556 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
557 LPDIRECTINPUTDEVICE2A iface,
558 LPDIDEVCAPS lpDIDevCaps)
560 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
561 FIXME("stub!\n");
562 return DI_OK;
565 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
566 LPDIRECTINPUTDEVICE2A iface,
567 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
568 LPVOID lpvRef,
569 DWORD dwFlags)
571 FIXME("stub!\n");
572 #if 0
573 if (lpCallback)
574 lpCallback(NULL, lpvRef);
575 #endif
576 return DI_OK;
579 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
580 LPDIRECTINPUTDEVICE2A iface,
581 REFGUID rguid,
582 LPDIPROPHEADER pdiph)
584 FIXME("stub!\n");
585 return DI_OK;
588 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
589 LPDIRECTINPUTDEVICE2A iface,
590 LPDIDEVICEOBJECTINSTANCEA pdidoi,
591 DWORD dwObj,
592 DWORD dwHow)
594 FIXME("stub!\n");
595 return DI_OK;
598 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
599 LPDIRECTINPUTDEVICE2A iface,
600 LPDIDEVICEINSTANCEA pdidi)
602 FIXME("stub!\n");
603 return DI_OK;
606 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
607 LPDIRECTINPUTDEVICE2A iface,
608 HWND hwndOwner,
609 DWORD dwFlags)
611 FIXME("stub!\n");
612 return DI_OK;
615 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
616 LPDIRECTINPUTDEVICE2A iface,
617 HINSTANCE hinst,
618 DWORD dwVersion,
619 REFGUID rguid)
621 FIXME("stub!\n");
622 return DI_OK;
625 /******************************************************************************
626 * IDirectInputDevice2A
629 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
630 LPDIRECTINPUTDEVICE2A iface,
631 REFGUID rguid,
632 LPCDIEFFECT lpeff,
633 LPDIRECTINPUTEFFECT *ppdef,
634 LPUNKNOWN pUnkOuter)
636 FIXME("stub!\n");
637 return DI_OK;
640 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
641 LPDIRECTINPUTDEVICE2A iface,
642 LPDIENUMEFFECTSCALLBACKA lpCallback,
643 LPVOID lpvRef,
644 DWORD dwFlags)
646 FIXME("stub!\n");
647 if (lpCallback)
648 lpCallback(NULL, lpvRef);
649 return DI_OK;
652 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
653 LPDIRECTINPUTDEVICE2A iface,
654 LPDIEFFECTINFOA lpdei,
655 REFGUID rguid)
657 FIXME("stub!\n");
658 return DI_OK;
661 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
662 LPDIRECTINPUTDEVICE2A iface,
663 LPDWORD pdwOut)
665 FIXME("stub!\n");
666 return DI_OK;
669 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
670 LPDIRECTINPUTDEVICE2A iface,
671 DWORD dwFlags)
673 FIXME("stub!\n");
674 return DI_OK;
677 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
678 LPDIRECTINPUTDEVICE2A iface,
679 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
680 LPVOID lpvRef,
681 DWORD dwFlags)
683 FIXME("stub!\n");
684 if (lpCallback)
685 lpCallback(NULL, lpvRef);
686 return DI_OK;
689 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
690 LPDIRECTINPUTDEVICE2A iface,
691 LPDIEFFESCAPE lpDIEEsc)
693 FIXME("stub!\n");
694 return DI_OK;
697 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
698 LPDIRECTINPUTDEVICE2A iface)
700 FIXME("stub!\n");
701 return DI_OK;
704 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
705 LPDIRECTINPUTDEVICE2A iface,
706 DWORD cbObjectData,
707 LPDIDEVICEOBJECTDATA rgdod,
708 LPDWORD pdwInOut,
709 DWORD dwFlags)
711 FIXME("stub!\n");
712 return DI_OK;
715 /******************************************************************************
716 * SysMouseA (DInput Mouse support)
719 /******************************************************************************
720 * Release : release the mouse buffer.
722 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
724 ICOM_THIS(SysMouseAImpl,iface);
726 This->ref--;
727 if (This->ref)
728 return This->ref;
730 /* Free the data queue */
731 if (This->data_queue != NULL)
732 HeapFree(GetProcessHeap(),0,This->data_queue);
734 /* Install the previous event handler (in case of releasing an aquired
735 mouse device) */
736 if (This->prev_handler != NULL)
737 MOUSE_Enable(This->prev_handler);
738 DeleteCriticalSection(&(This->crit));
740 HeapFree(GetProcessHeap(),0,This);
741 return 0;
745 /******************************************************************************
746 * SetCooperativeLevel : store the window in which we will do our
747 * grabbing.
749 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
750 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
753 ICOM_THIS(SysMouseAImpl,iface);
755 TRACE("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
757 if (TRACE_ON(dinput))
758 _dump_cooperativelevel(dwflags);
760 /* Store the window which asks for the mouse */
761 This->win = hwnd;
763 return 0;
767 /******************************************************************************
768 * SetDataFormat : the application can choose the format of the data
769 * the device driver sends back with GetDeviceState.
771 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
772 * in absolute and relative mode.
774 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
775 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
778 ICOM_THIS(SysMouseAImpl,iface);
779 int i;
781 TRACE("(this=%p,%p)\n",This,df);
783 TRACE("(df.dwSize=%ld)\n",df->dwSize);
784 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
785 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
786 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
787 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
789 for (i=0;i<df->dwNumObjs;i++) {
790 char xbuf[50];
792 if (df->rgodf[i].pguid)
793 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
794 else
795 strcpy(xbuf,"<no guid>");
796 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
797 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
798 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
799 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
802 /* Check size of data format to prevent crashes if the applications
803 sends a smaller buffer */
804 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
805 FIXME("non-standard mouse configuration not supported yet.");
806 return DIERR_INVALIDPARAM;
809 /* For the moment, ignore these fields and return always as if
810 c_dfDIMouse was passed as format... */
812 /* Check if the mouse is in absolute or relative mode */
813 if (df->dwFlags == DIDF_ABSAXIS)
814 This->absolute = 1;
815 else if (df->dwFlags == DIDF_RELAXIS)
816 This->absolute = 0;
817 else
818 ERR("Neither absolute nor relative flag set.");
820 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
821 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
822 return 0;
825 #define GEN_EVENT(offset,data,xtime,seq) \
827 if (This->queue_pos < This->queue_len) { \
828 This->data_queue[This->queue_pos].dwOfs = offset; \
829 This->data_queue[This->queue_pos].dwData = data; \
830 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
831 This->data_queue[This->queue_pos].dwSequence = seq; \
832 This->queue_pos++; \
837 /* Our private mouse event handler */
838 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
839 DWORD cButtons, DWORD dwExtraInfo )
841 DWORD posX, posY, keyState, xtime, extra;
842 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
844 EnterCriticalSection(&(This->crit));
845 /* Mouse moved -> send event if asked */
846 if (This->hEvent)
847 SetEvent(This->hEvent);
849 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
850 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
851 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
852 keyState = wme->keyState;
853 xtime = wme->time;
854 extra = (DWORD)wme->hWnd;
856 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
857 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
858 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
859 } else {
860 ERR("Mouse event not supported...\n");
861 LeaveCriticalSection(&(This->crit));
862 return ;
865 TRACE(" %ld %ld ", posX, posY);
867 if ( dwFlags & MOUSEEVENTF_MOVE ) {
868 if (This->absolute) {
869 if (posX != This->prevX)
870 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
871 if (posY != This->prevY)
872 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
873 } else {
874 /* Relative mouse input : the real fun starts here... */
875 if (This->need_warp) {
876 if (posX != This->prevX)
877 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
878 if (posY != This->prevY)
879 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
880 } else {
881 /* This is the first time the event handler has been called after a
882 GetData of GetState. */
883 if (posX != This->win_centerX) {
884 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
885 This->need_warp = 1;
888 if (posY != This->win_centerY) {
889 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
890 This->need_warp = 1;
895 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
896 if (TRACE_ON(dinput))
897 DPRINTF(" LD ");
899 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
901 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
902 if (TRACE_ON(dinput))
903 DPRINTF(" LU ");
905 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
907 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
908 if (TRACE_ON(dinput))
909 DPRINTF(" RD ");
911 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
913 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
914 if (TRACE_ON(dinput))
915 DPRINTF(" RU ");
917 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
919 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
920 if (TRACE_ON(dinput))
921 DPRINTF(" MD ");
923 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
925 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
926 if (TRACE_ON(dinput))
927 DPRINTF(" MU ");
929 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
931 if (TRACE_ON(dinput))
932 DPRINTF("\n");
934 This->prevX = posX;
935 This->prevY = posY;
936 LeaveCriticalSection(&(This->crit));
940 /******************************************************************************
941 * Acquire : gets exclusive control of the mouse
943 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
945 ICOM_THIS(SysMouseAImpl,iface);
946 RECT rect;
948 TRACE("(this=%p)\n",This);
950 if (This->acquired == 0) {
951 POINT point;
953 /* This stores the current mouse handler. */
954 This->prev_handler = mouse_event;
956 /* Store (in a global variable) the current lock */
957 current_lock = (IDirectInputDevice2A*)This;
959 /* Install our own mouse event handler */
960 MOUSE_Enable(dinput_mouse_event);
962 /* Get the window dimension and find the center */
963 GetWindowRect(This->win, &rect);
964 This->win_centerX = (rect.right - rect.left) / 2;
965 This->win_centerY = (rect.bottom - rect.top ) / 2;
967 /* Warp the mouse to the center of the window */
968 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
969 point.x = This->win_centerX;
970 point.y = This->win_centerY;
971 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
972 DISPLAY_MoveCursor(point.x, point.y);
974 This->acquired = 1;
976 return 0;
979 /******************************************************************************
980 * Unacquire : frees the mouse
982 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
984 ICOM_THIS(SysMouseAImpl,iface);
986 TRACE("(this=%p)\n",This);
988 /* Reinstall previous mouse event handler */
989 MOUSE_Enable(This->prev_handler);
990 This->prev_handler = NULL;
992 /* No more locks */
993 current_lock = NULL;
995 /* Unacquire device */
996 This->acquired = 0;
998 return 0;
1001 /******************************************************************************
1002 * GetDeviceState : returns the "state" of the mouse.
1004 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1005 * supported.
1007 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1008 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1010 ICOM_THIS(SysMouseAImpl,iface);
1011 DWORD rx, ry, state;
1012 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
1014 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1016 /* Check if the buffer is big enough */
1017 if (len < sizeof(struct DIMOUSESTATE)) {
1018 FIXME("unsupported state structure.");
1019 return DIERR_INVALIDPARAM;
1022 /* Get the mouse position */
1023 EVENT_QueryPointer(&rx, &ry, &state);
1024 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
1026 /* Fill the mouse state structure */
1027 if (This->absolute) {
1028 mstate->lX = rx;
1029 mstate->lY = ry;
1030 } else {
1031 mstate->lX = rx - This->win_centerX;
1032 mstate->lY = ry - This->win_centerY;
1034 if ((mstate->lX != 0) || (mstate->lY != 0))
1035 This->need_warp = 1;
1037 mstate->lZ = 0;
1038 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
1039 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
1040 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
1041 mstate->rgbButtons[3] = 0x00;
1043 /* Check if we need to do a mouse warping */
1044 if (This->need_warp) {
1045 POINT point;
1047 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1048 point.x = This->win_centerX;
1049 point.y = This->win_centerY;
1050 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1051 DISPLAY_MoveCursor(point.x, point.y);
1053 This->need_warp = 0;
1056 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1057 mstate->lX, mstate->lY,
1058 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1060 return 0;
1063 /******************************************************************************
1064 * GetDeviceState : gets buffered input data.
1066 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1067 DWORD dodsize,
1068 LPDIDEVICEOBJECTDATA dod,
1069 LPDWORD entries,
1070 DWORD flags
1072 ICOM_THIS(SysMouseAImpl,iface);
1074 EnterCriticalSection(&(This->crit));
1075 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1077 if (flags & DIGDD_PEEK)
1078 FIXME("DIGDD_PEEK\n");
1080 if (dod == NULL) {
1081 *entries = This->queue_pos;
1082 This->queue_pos = 0;
1083 } else {
1084 /* Check for buffer overflow */
1085 if (This->queue_pos > *entries) {
1086 WARN("Buffer overflow not handled properly yet...\n");
1087 This->queue_pos = *entries;
1089 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1090 ERR("Wrong structure size !\n");
1091 LeaveCriticalSection(&(This->crit));
1092 return DIERR_INVALIDPARAM;
1095 if (This->queue_pos)
1096 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1098 /* Copy the buffered data into the application queue */
1099 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1100 *entries = This->queue_pos;
1102 /* Reset the event queue */
1103 This->queue_pos = 0;
1105 LeaveCriticalSection(&(This->crit));
1107 #if 0 /* FIXME: seems to create motion events, which fire back at us. */
1108 /* Check if we need to do a mouse warping */
1109 if (This->need_warp) {
1110 POINT point;
1112 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1113 point.x = This->win_centerX;
1114 point.y = This->win_centerY;
1115 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1117 DISPLAY_MoveCursor(point.x, point.y);
1119 This->need_warp = 0;
1121 #endif
1122 return 0;
1125 /******************************************************************************
1126 * SetProperty : change input device properties
1128 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1129 REFGUID rguid,
1130 LPCDIPROPHEADER ph)
1132 ICOM_THIS(SysMouseAImpl,iface);
1133 char xbuf[50];
1135 if (HIWORD(rguid))
1136 WINE_StringFromCLSID(rguid,xbuf);
1137 else
1138 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1140 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1142 if (!HIWORD(rguid)) {
1143 switch ((DWORD)rguid) {
1144 case (DWORD) DIPROP_BUFFERSIZE: {
1145 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1147 TRACE("buffersize = %ld\n",pd->dwData);
1149 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1150 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1151 This->queue_pos = 0;
1152 This->queue_len = pd->dwData;
1153 break;
1155 default:
1156 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1157 break;
1161 return 0;
1164 /******************************************************************************
1165 * SetEventNotification : specifies event to be sent on state change
1167 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1168 HANDLE hnd) {
1169 ICOM_THIS(SysMouseAImpl,iface);
1171 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1173 This->hEvent = hnd;
1175 return DI_OK;
1178 #ifdef HAVE_LINUX_22_JOYSTICK_API
1179 /******************************************************************************
1180 * Joystick
1182 static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1184 ICOM_THIS(JoystickAImpl,iface);
1186 This->ref--;
1187 if (This->ref)
1188 return This->ref;
1189 HeapFree(GetProcessHeap(),0,This);
1190 return 0;
1193 /******************************************************************************
1194 * SetDataFormat : the application can choose the format of the data
1195 * the device driver sends back with GetDeviceState.
1197 static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1198 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1201 ICOM_THIS(JoystickAImpl,iface);
1202 int i;
1204 TRACE("(this=%p,%p)\n",This,df);
1206 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1207 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1208 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1209 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1210 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1212 for (i=0;i<df->dwNumObjs;i++) {
1213 char xbuf[50];
1215 if (df->rgodf[i].pguid)
1216 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1217 else
1218 strcpy(xbuf,"<no guid>");
1219 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1220 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1221 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1222 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1224 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1225 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1226 return 0;
1229 /******************************************************************************
1230 * Acquire : gets exclusive control of the joystick
1232 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1234 ICOM_THIS(JoystickAImpl,iface);
1236 TRACE("(this=%p)\n",This);
1237 if (This->joyfd!=-1)
1238 return 0;
1239 This->joyfd=open(JOYDEV,O_RDONLY);
1240 if (This->joyfd==-1)
1241 return DIERR_NOTFOUND;
1242 return 0;
1245 /******************************************************************************
1246 * Unacquire : frees the joystick
1248 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1250 ICOM_THIS(JoystickAImpl,iface);
1252 TRACE("(this=%p)\n",This);
1253 if (This->joyfd!=-1) {
1254 close(This->joyfd);
1255 This->joyfd = -1;
1257 return 0;
1260 #define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1262 static void joy_polldev(JoystickAImpl *This) {
1263 struct timeval tv;
1264 fd_set readfds;
1265 struct js_event jse;
1267 if (This->joyfd==-1)
1268 return;
1269 while (1) {
1270 memset(&tv,0,sizeof(tv));
1271 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1272 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1273 return;
1274 /* we have one event, so we can read */
1275 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1276 return;
1278 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1279 if (jse.type & JS_EVENT_BUTTON) {
1280 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1281 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1283 if (jse.type & JS_EVENT_AXIS) {
1284 switch (jse.number) {
1285 case 0:
1286 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1287 This->js.lX = map_axis(jse.value);
1288 break;
1289 case 1:
1290 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1291 This->js.lY = map_axis(jse.value);
1292 break;
1293 case 2:
1294 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1295 This->js.lZ = map_axis(jse.value);
1296 break;
1297 default:
1298 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1299 break;
1305 /******************************************************************************
1306 * GetDeviceState : returns the "state" of the joystick.
1309 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1310 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1312 ICOM_THIS(JoystickAImpl,iface);
1314 joy_polldev(This);
1315 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1316 if (len != sizeof(DIJOYSTATE)) {
1317 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1319 memcpy(ptr,&(This->js),len);
1320 This->queue_pos = 0;
1321 return 0;
1324 /******************************************************************************
1325 * GetDeviceState : gets buffered input data.
1327 static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1328 DWORD dodsize,
1329 LPDIDEVICEOBJECTDATA dod,
1330 LPDWORD entries,
1331 DWORD flags
1333 ICOM_THIS(JoystickAImpl,iface);
1335 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1337 joy_polldev(This);
1338 if (flags & DIGDD_PEEK)
1339 FIXME("DIGDD_PEEK\n");
1341 if (dod == NULL) {
1342 } else {
1344 return 0;
1347 /******************************************************************************
1348 * SetProperty : change input device properties
1350 static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1351 REFGUID rguid,
1352 LPCDIPROPHEADER ph)
1354 ICOM_THIS(JoystickAImpl,iface);
1355 char xbuf[50];
1357 if (HIWORD(rguid))
1358 WINE_StringFromCLSID(rguid,xbuf);
1359 else
1360 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1362 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1363 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1365 if (!HIWORD(rguid)) {
1366 switch ((DWORD)rguid) {
1367 case (DWORD) DIPROP_BUFFERSIZE: {
1368 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1370 FIXME("buffersize = %ld\n",pd->dwData);
1371 break;
1373 case (DWORD)DIPROP_RANGE: {
1374 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1376 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1377 This->lMin = pr->lMin;
1378 This->lMax = pr->lMax;
1379 break;
1381 case (DWORD)DIPROP_DEADZONE: {
1382 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1384 FIXME("deadzone(%ld)\n",pd->dwData);
1385 This->deadzone = pd->dwData;
1386 break;
1388 default:
1389 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1390 break;
1393 return 0;
1396 /******************************************************************************
1397 * SetEventNotification : specifies event to be sent on state change
1399 static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1400 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1402 ICOM_THIS(JoystickAImpl,iface);
1404 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1405 This->hEvent = hnd;
1406 return DI_OK;
1409 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1410 LPDIRECTINPUTDEVICE2A iface,
1411 LPDIDEVCAPS lpDIDevCaps)
1413 ICOM_THIS(JoystickAImpl,iface);
1414 BYTE axes,buttons;
1415 int xfd = This->joyfd;
1417 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1418 if (xfd==-1)
1419 xfd = open(JOYDEV,O_RDONLY);
1420 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1421 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1422 #ifdef JSIOCGAXES
1423 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1424 axes = 2;
1425 lpDIDevCaps->dwAxes = axes;
1426 #endif
1427 #ifdef JSIOCGBUTTONS
1428 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1429 buttons = 2;
1430 lpDIDevCaps->dwButtons = buttons;
1431 #endif
1432 if (xfd!=This->joyfd)
1433 close(xfd);
1434 return DI_OK;
1436 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1437 ICOM_THIS(JoystickAImpl,iface);
1438 TRACE("(),stub!\n");
1440 joy_polldev(This);
1441 return DI_OK;
1443 #endif
1445 /****************************************************************************/
1446 /****************************************************************************/
1448 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1450 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1451 IDirectInputDevice2AImpl_QueryInterface,
1452 IDirectInputDevice2AImpl_AddRef,
1453 IDirectInputDevice2AImpl_Release,
1454 IDirectInputDevice2AImpl_GetCapabilities,
1455 IDirectInputDevice2AImpl_EnumObjects,
1456 IDirectInputDevice2AImpl_GetProperty,
1457 SysKeyboardAImpl_SetProperty,
1458 SysKeyboardAImpl_Acquire,
1459 SysKeyboardAImpl_Unacquire,
1460 SysKeyboardAImpl_GetDeviceState,
1461 SysKeyboardAImpl_GetDeviceData,
1462 IDirectInputDevice2AImpl_SetDataFormat,
1463 IDirectInputDevice2AImpl_SetEventNotification,
1464 IDirectInputDevice2AImpl_SetCooperativeLevel,
1465 IDirectInputDevice2AImpl_GetObjectInfo,
1466 IDirectInputDevice2AImpl_GetDeviceInfo,
1467 IDirectInputDevice2AImpl_RunControlPanel,
1468 IDirectInputDevice2AImpl_Initialize,
1469 IDirectInputDevice2AImpl_CreateEffect,
1470 IDirectInputDevice2AImpl_EnumEffects,
1471 IDirectInputDevice2AImpl_GetEffectInfo,
1472 IDirectInputDevice2AImpl_GetForceFeedbackState,
1473 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1474 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1475 IDirectInputDevice2AImpl_Escape,
1476 IDirectInputDevice2AImpl_Poll,
1477 IDirectInputDevice2AImpl_SendDeviceData,
1480 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1482 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1483 IDirectInputDevice2AImpl_QueryInterface,
1484 IDirectInputDevice2AImpl_AddRef,
1485 SysMouseAImpl_Release,
1486 IDirectInputDevice2AImpl_GetCapabilities,
1487 IDirectInputDevice2AImpl_EnumObjects,
1488 IDirectInputDevice2AImpl_GetProperty,
1489 SysMouseAImpl_SetProperty,
1490 SysMouseAImpl_Acquire,
1491 SysMouseAImpl_Unacquire,
1492 SysMouseAImpl_GetDeviceState,
1493 SysMouseAImpl_GetDeviceData,
1494 SysMouseAImpl_SetDataFormat,
1495 SysMouseAImpl_SetEventNotification,
1496 SysMouseAImpl_SetCooperativeLevel,
1497 IDirectInputDevice2AImpl_GetObjectInfo,
1498 IDirectInputDevice2AImpl_GetDeviceInfo,
1499 IDirectInputDevice2AImpl_RunControlPanel,
1500 IDirectInputDevice2AImpl_Initialize,
1501 IDirectInputDevice2AImpl_CreateEffect,
1502 IDirectInputDevice2AImpl_EnumEffects,
1503 IDirectInputDevice2AImpl_GetEffectInfo,
1504 IDirectInputDevice2AImpl_GetForceFeedbackState,
1505 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1506 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1507 IDirectInputDevice2AImpl_Escape,
1508 IDirectInputDevice2AImpl_Poll,
1509 IDirectInputDevice2AImpl_SendDeviceData,
1512 #ifdef HAVE_LINUX_22_JOYSTICK_API
1513 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1515 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1516 IDirectInputDevice2AImpl_QueryInterface,
1517 IDirectInputDevice2AImpl_AddRef,
1518 JoystickAImpl_Release,
1519 JoystickAImpl_GetCapabilities,
1520 IDirectInputDevice2AImpl_EnumObjects,
1521 IDirectInputDevice2AImpl_GetProperty,
1522 JoystickAImpl_SetProperty,
1523 JoystickAImpl_Acquire,
1524 JoystickAImpl_Unacquire,
1525 JoystickAImpl_GetDeviceState,
1526 JoystickAImpl_GetDeviceData,
1527 JoystickAImpl_SetDataFormat,
1528 JoystickAImpl_SetEventNotification,
1529 IDirectInputDevice2AImpl_SetCooperativeLevel,
1530 IDirectInputDevice2AImpl_GetObjectInfo,
1531 IDirectInputDevice2AImpl_GetDeviceInfo,
1532 IDirectInputDevice2AImpl_RunControlPanel,
1533 IDirectInputDevice2AImpl_Initialize,
1534 IDirectInputDevice2AImpl_CreateEffect,
1535 IDirectInputDevice2AImpl_EnumEffects,
1536 IDirectInputDevice2AImpl_GetEffectInfo,
1537 IDirectInputDevice2AImpl_GetForceFeedbackState,
1538 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1539 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1540 IDirectInputDevice2AImpl_Escape,
1541 JoystickAImpl_Poll,
1542 IDirectInputDevice2AImpl_SendDeviceData,
1544 #endif