source: trunk/src/dinput/dinput.cpp@ 1633

Last change on this file since 1633 was 1633, checked in by sandervl, 26 years ago

Creation of initial Wine Port (991031)

File size: 44.3 KB
Line 
1/* DirectInput
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 *
6 */
7/* Status:
8 *
9 * - Tomb Raider 2 Demo:
10 * Playable using keyboard only.
11 * - WingCommander Prophecy Demo:
12 * Doesn't get Input Focus.
13 *
14 * - Fallout : works great in X and DGA mode
15 *
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.)
19 */
20#ifdef __WIN32OS2__
21#include <odin.h>
22#include <os2win.h>
23
24#define ICOM_CINTERFACE 1
25#define CINTERFACE
26#endif
27
28#include "config.h"
29#include <string.h>
30#include <time.h>
31//#include <unistd.h>
32#include <assert.h>
33#ifdef HAVE_SYS_SIGNAL_H
34# include <sys/signal.h>
35#endif
36//#include <sys/time.h>
37//#include <sys/fcntl.h>
38//#include <sys/ioctl.h>
39#include <errno.h>
40#ifdef HAVE_SYS_ERRNO_H
41# include <sys/errno.h>
42#endif
43#ifdef HAVE_LINUX_JOYSTICK_H
44# include <linux/joystick.h>
45# define JOYDEV "/dev/js0"
46#endif
47#include "wine/obj_base.h"
48#include "debugtools.h"
49#include "dinput.h"
50#include "display.h"
51//#include "keyboard.h"
52//#include "message.h"
53#include "mouse.h"
54#include "sysmetrics.h"
55#include "winbase.h"
56#include "winerror.h"
57#include "winuser.h"
58
59#ifdef __WIN32OS2__
60#include <heapstring.h>
61#include <misc.h>
62#include "oslibinput.h"
63#endif
64
65DEFAULT_DEBUG_CHANNEL(dinput)
66
67
68extern BYTE InputKeyStateTable[256];
69extern int min_keycode, max_keycode;
70extern WORD keyc2vkey[256];
71
72extern ICOM_VTABLE(IDirectInputA) ddiavt;
73extern ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
74extern ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
75
76typedef struct IDirectInputAImpl IDirectInputAImpl;
77typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
78typedef struct SysKeyboardAImpl SysKeyboardAImpl;
79typedef struct SysMouseAImpl SysMouseAImpl;
80
81struct IDirectInputDevice2AImpl
82{
83 ICOM_VFIELD(IDirectInputDevice2A);
84 DWORD ref;
85 GUID guid;
86};
87
88struct SysKeyboardAImpl
89{
90 /* IDirectInputDevice2AImpl */
91 ICOM_VFIELD(IDirectInputDevice2A);
92 DWORD ref;
93 GUID guid;
94 /* SysKeyboardAImpl */
95 BYTE keystate[256];
96};
97
98#ifdef HAVE_LINUX_22_JOYSTICK_API
99typedef struct JoystickAImpl JoystickAImpl;
100ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt;
101struct JoystickAImpl
102{
103 /* IDirectInputDevice2AImpl */
104 ICOM_VFIELD(IDirectInputDevice2A);
105 DWORD ref;
106 GUID guid;
107
108 /* joystick private */
109 int joyfd;
110 LPDIDATAFORMAT df;
111 HANDLE hEvent;
112 LONG lMin,lMax,deadzone;
113 LPDIDEVICEOBJECTDATA data_queue;
114 int queue_pos, queue_len;
115 DIJOYSTATE js;
116};
117#endif
118
119struct SysMouseAImpl
120{
121 /* IDirectInputDevice2AImpl */
122 ICOM_VFIELD(IDirectInputDevice2A);
123 DWORD ref;
124 GUID guid;
125
126 LPDIDATAFORMAT df;
127 /* SysMouseAImpl */
128 BYTE absolute;
129 /* Previous position for relative moves */
130 LONG prevX, prevY;
131 LPMOUSE_EVENT_PROC prev_handler;
132 HWND win;
133 DWORD win_centerX, win_centerY;
134 LPDIDEVICEOBJECTDATA data_queue;
135 int queue_pos, queue_len;
136 int need_warp;
137 int acquired;
138 HANDLE hEvent;
139 CRITICAL_SECTION crit;
140};
141
142static int evsequence=0;
143
144
145/* UIDs for Wine "drivers".
146 When enumerating each device supporting DInput, they have two UIDs :
147 - the 'windows' UID
148 - a vendor UID */
149#ifdef HAVE_LINUX_22_JOYSTICK_API
150static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
151 0x9e573ed9,
152 0x7734,
153 0x11d2,
154 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
155};
156#endif
157static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
158 0x9e573ed8,
159 0x7734,
160 0x11d2,
161 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
162};
163static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
164 0x0ab8648a,
165 0x7735,
166 0x11d2,
167 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
168};
169
170/* FIXME: This is ugly and not thread safe :/ */
171static IDirectInputDevice2A* current_lock = NULL;
172
173/******************************************************************************
174 * Various debugging tools
175 */
176static void _dump_cooperativelevel(DWORD dwFlags) {
177 int i;
178 const struct {
179 DWORD mask;
180 char *name;
181 } flags[] = {
182#define FE(x) { x, #x},
183 FE(DISCL_BACKGROUND)
184 FE(DISCL_EXCLUSIVE)
185 FE(DISCL_FOREGROUND)
186 FE(DISCL_NONEXCLUSIVE)
187 };
188 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
189 if (flags[i].mask & dwFlags)
190 DPRINTF("%s ",flags[i].name);
191 DPRINTF("\n");
192}
193
194struct IDirectInputAImpl
195{
196 ICOM_VFIELD(IDirectInputA);
197 DWORD ref;
198};
199
200/******************************************************************************
201 * DirectInputCreate32A
202 */
203HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
204{
205 IDirectInputAImpl* This;
206 TRACE("(0x%08lx,%04lx,%p,%p)\n",
207 (DWORD)hinst,dwVersion,ppDI,punkOuter
208 );
209 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
210 This->ref = 1;
211 ICOM_VTBL(This) = &ddiavt;
212 *ppDI=(IDirectInputA*)This;
213 return 0;
214}
215/******************************************************************************
216 * IDirectInputA_EnumDevices
217 */
218static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
219 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
220 LPVOID pvRef, DWORD dwFlags
221)
222{
223 ICOM_THIS(IDirectInputAImpl,iface);
224 DIDEVICEINSTANCEA devInstance;
225 int ret;
226
227 TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
228
229 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
230 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
231 /* Return keyboard */
232 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
233 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
234 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
235 strcpy(devInstance.tszInstanceName, "Keyboard");
236 strcpy(devInstance.tszProductName, "Wine Keyboard");
237
238 ret = lpCallback(&devInstance, pvRef);
239 TRACE("Keyboard registered\n");
240 if (ret == DIENUM_STOP)
241 return 0;
242 }
243
244 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
245 /* Return mouse */
246 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
247 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
248 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
249 strcpy(devInstance.tszInstanceName, "Mouse");
250 strcpy(devInstance.tszProductName, "Wine Mouse");
251
252 ret = lpCallback(&devInstance, pvRef);
253 TRACE("Mouse registered\n");
254 if (ret == DIENUM_STOP)
255 return 0;
256 }
257 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) {
258 /* check whether we have a joystick */
259#ifdef HAVE_LINUX_22_JOYSTICK_API
260 if ( (access(JOYDEV,O_RDONLY)!=-1) ||
261 (errno!=ENODEV && errno!=ENOENT)
262 ) {
263 /* Return joystick */
264 devInstance.guidInstance = GUID_Joystick;
265 devInstance.guidProduct = DInput_Wine_Joystick_GUID;
266 /* we only support traditional joysticks for now */
267 devInstance.dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
268 strcpy(devInstance.tszInstanceName, "Joystick");
269 /* ioctl JSIOCGNAME(len) */
270 strcpy(devInstance.tszProductName, "Wine Joystick");
271
272 ret = lpCallback(&devInstance,pvRef);
273 TRACE("Joystick registered\n");
274 if (ret == DIENUM_STOP)
275 return 0;
276 }
277#endif
278 }
279 return 0;
280}
281
282static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
283{
284 ICOM_THIS(IDirectInputAImpl,iface);
285 return ++(This->ref);
286}
287
288static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
289{
290 ICOM_THIS(IDirectInputAImpl,iface);
291 if (!(--This->ref)) {
292 HeapFree(GetProcessHeap(),0,This);
293 return 0;
294 }
295 return This->ref;
296}
297
298static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
299 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
300 LPUNKNOWN punk
301) {
302 ICOM_THIS(IDirectInputAImpl,iface);
303 char xbuf[50];
304
305 WINE_StringFromCLSID(rguid,xbuf);
306 FIXME("(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
307 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
308 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
309 SysKeyboardAImpl* newDevice;
310 newDevice = (SysKeyboardAImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
311 newDevice->ref = 1;
312 ICOM_VTBL(newDevice) = &SysKeyboardAvt;
313 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
314 memset(newDevice->keystate,0,256);
315 *pdev=(IDirectInputDeviceA*)newDevice;
316 return DI_OK;
317 }
318 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
319 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
320 SysMouseAImpl* newDevice;
321 newDevice = (SysMouseAImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
322 newDevice->ref = 1;
323 ICOM_VTBL(newDevice) = &SysMouseAvt;
324 InitializeCriticalSection(&(newDevice->crit));
325 MakeCriticalSectionGlobal(&(newDevice->crit));
326 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
327 *pdev=(IDirectInputDeviceA*)newDevice;
328 return DI_OK;
329 }
330#ifdef HAVE_LINUX_22_JOYSTICK_API
331 if ((!memcmp(&GUID_Joystick,rguid,sizeof(GUID_Joystick))) ||
332 (!memcmp(&DInput_Wine_Joystick_GUID,rguid,sizeof(GUID_Joystick)))) {
333 JoystickAImpl* newDevice;
334 newDevice = (JoystickAImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
335 newDevice->ref = 1;
336 ICOM_VTBL(newDevice) = &JoystickAvt;
337 newDevice->joyfd = -1;
338 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
339 *pdev=(IDirectInputDeviceA*)newDevice;
340 return DI_OK;
341 }
342#endif
343 return E_FAIL;
344}
345
346static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
347 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
348) {
349 ICOM_THIS(IDirectInputAImpl,iface);
350 char xbuf[50];
351
352 WINE_StringFromCLSID(riid,xbuf);
353 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
354 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
355 IDirectInputA_AddRef(iface);
356 *ppobj = This;
357 return 0;
358 }
359 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
360 IDirectInputA_AddRef(iface);
361 *ppobj = This;
362 return 0;
363 }
364 return E_FAIL;
365}
366
367static HRESULT WINAPI IDirectInputAImpl_Initialize(
368 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
369) {
370 return DIERR_ALREADYINITIALIZED;
371}
372
373static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
374 REFGUID rguid) {
375 ICOM_THIS(IDirectInputAImpl,iface);
376 char xbuf[50];
377
378 WINE_StringFromCLSID(rguid,xbuf);
379 FIXME("(%p)->(%s): stub\n",This,xbuf);
380
381 return DI_OK;
382}
383
384static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
385 HWND hwndOwner,
386 DWORD dwFlags) {
387 ICOM_THIS(IDirectInputAImpl,iface);
388 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
389
390 return DI_OK;
391}
392
393ICOM_VTABLE(IDirectInputA) ddiavt =
394{
395 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
396 IDirectInputAImpl_QueryInterface,
397 IDirectInputAImpl_AddRef,
398 IDirectInputAImpl_Release,
399 IDirectInputAImpl_CreateDevice,
400 IDirectInputAImpl_EnumDevices,
401 IDirectInputAImpl_GetDeviceStatus,
402 IDirectInputAImpl_RunControlPanel,
403 IDirectInputAImpl_Initialize
404};
405
406/******************************************************************************
407 * IDirectInputDeviceA
408 */
409
410static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
411 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
412) {
413 /*
414 int i;
415 TRACE(dinput,"(this=%p,%p)\n",This,df);
416
417 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
418 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
419 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
420 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
421 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
422
423 for (i=0;i<df->dwNumObjs;i++) {
424 char xbuf[50];
425
426 if (df->rgodf[i].pguid)
427 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
428 else
429 strcpy(xbuf,"<no guid>");
430 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
431 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
432 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
433 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
434 }
435 */
436 return 0;
437}
438
439static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
440 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
441) {
442 ICOM_THIS(IDirectInputDevice2AImpl,iface);
443 FIXME("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
444// if (TRACE_ON(dinput))
445// _dump_cooperativelevel(dwflags);
446 return 0;
447}
448
449static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
450 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
451) {
452 ICOM_THIS(IDirectInputDevice2AImpl,iface);
453 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
454 return 0;
455}
456
457static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
458{
459 ICOM_THIS(IDirectInputDevice2AImpl,iface);
460 This->ref--;
461 if (This->ref)
462 return This->ref;
463 HeapFree(GetProcessHeap(),0,This);
464 return 0;
465}
466
467static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
468 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
469)
470{
471 ICOM_THIS(SysKeyboardAImpl,iface);
472 char xbuf[50];
473
474 if (HIWORD(rguid))
475 WINE_StringFromCLSID(rguid,xbuf);
476 else
477 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
478 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
479 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
480 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
481 if (!HIWORD(rguid)) {
482#ifdef __WIN32OS2__
483 if(rguid == DIPROP_BUFFERSIZE) {
484 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
485
486 TRACE("(buffersize=%ld)\n",pd->dwData);
487 }
488 else WARN("Unknown type %ld\n",(DWORD)rguid);
489
490#else
491 switch ((DWORD)rguid) {
492 case (DWORD) DIPROP_BUFFERSIZE: {
493 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
494
495 TRACE("(buffersize=%ld)\n",pd->dwData);
496 break;
497 }
498 default:
499 WARN("Unknown type %ld\n",(DWORD)rguid);
500 break;
501 }
502#endif
503 }
504 return 0;
505}
506
507static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
508 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
509)
510{
511#ifdef __WIN32OS2__
512 return OSLibGetDIState(len, ptr) ? DI_OK : E_FAIL;
513#else
514 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
515#endif
516}
517
518static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
519 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
520 LPDWORD entries,DWORD flags
521)
522{
523 ICOM_THIS(SysKeyboardAImpl,iface);
524 HRESULT ret;
525 int i;
526
527 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
528 This,dodsize,dod,entries,entries?*entries:0,flags);
529
530#ifdef __WIN32OS2__
531//Copied this from the X11 keyboard driver (991031)
532{
533 int keyc,n,xentries;
534 BYTE win32keys[256];
535
536 OSLibGetDIState(256, &win32keys);
537 /* FIXME !!! */
538
539 if (entries)
540 xentries = *entries;
541 else
542 xentries = 1;
543
544 n = 0;
545
546 for (int i=0;i<256 && (n<*entries);i++)
547 {
548 if (This->keystate[i] == (win32keys[i]&0x80))
549 continue;
550 if (dod) {
551 /* add an entry */
552 dod[n].dwOfs = i; /* scancode */
553 dod[n].dwData = win32keys[i]&0x80;
554 dod[i].dwTimeStamp = time(NULL);
555 dod[i].dwSequence = evsequence++;
556 n++;
557 }
558 if (!(flags & DIGDD_PEEK))
559 This->keystate[i] = win32keys[i]&0x80;
560
561 }
562
563 *entries = n;
564 ret = DI_OK;
565}
566#else
567 ret=KEYBOARD_Driver->pGetDIData(
568 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
569
570 for (i=0;i<*entries;i++) {
571 dod[i].dwTimeStamp = time(NULL);
572 dod[i].dwSequence = evsequence++;
573 }
574#endif
575 return ret;
576}
577
578static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
579{
580 ICOM_THIS(SysKeyboardAImpl,iface);
581 TRACE("(this=%p): stub\n",This);
582 return 0;
583}
584
585static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
586{
587 ICOM_THIS(SysKeyboardAImpl,iface);
588 TRACE("(this=%p): stub\n",This);
589 return 0;
590}
591
592static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
593 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
594)
595{
596 ICOM_THIS(IDirectInputDevice2AImpl,iface);
597 char xbuf[50];
598
599 WINE_StringFromCLSID(riid,xbuf);
600 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
601 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
602 IDirectInputDevice2_AddRef(iface);
603 *ppobj = This;
604 return 0;
605 }
606 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
607 IDirectInputDevice2_AddRef(iface);
608 *ppobj = This;
609 return 0;
610 }
611 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
612 IDirectInputDevice2_AddRef(iface);
613 *ppobj = This;
614 return 0;
615 }
616 return E_FAIL;
617}
618
619static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
620 LPDIRECTINPUTDEVICE2A iface)
621{
622 ICOM_THIS(IDirectInputDevice2AImpl,iface);
623 return ++This->ref;
624}
625
626static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
627 LPDIRECTINPUTDEVICE2A iface,
628 LPDIDEVCAPS lpDIDevCaps)
629{
630 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
631 FIXME("stub!\n");
632 return DI_OK;
633}
634
635static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
636 LPDIRECTINPUTDEVICE2A iface,
637 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
638 LPVOID lpvRef,
639 DWORD dwFlags)
640{
641 FIXME("stub!\n");
642#if 0
643 if (lpCallback)
644 lpCallback(NULL, lpvRef);
645#endif
646 return DI_OK;
647}
648
649static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
650 LPDIRECTINPUTDEVICE2A iface,
651 REFGUID rguid,
652 LPDIPROPHEADER pdiph)
653{
654 FIXME("stub!\n");
655 return DI_OK;
656}
657
658static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
659 LPDIRECTINPUTDEVICE2A iface,
660 LPDIDEVICEOBJECTINSTANCEA pdidoi,
661 DWORD dwObj,
662 DWORD dwHow)
663{
664 FIXME("stub!\n");
665 return DI_OK;
666}
667
668static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
669 LPDIRECTINPUTDEVICE2A iface,
670 LPDIDEVICEINSTANCEA pdidi)
671{
672 FIXME("stub!\n");
673 return DI_OK;
674}
675
676static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
677 LPDIRECTINPUTDEVICE2A iface,
678 HWND hwndOwner,
679 DWORD dwFlags)
680{
681 FIXME("stub!\n");
682 return DI_OK;
683}
684
685static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
686 LPDIRECTINPUTDEVICE2A iface,
687 HINSTANCE hinst,
688 DWORD dwVersion,
689 REFGUID rguid)
690{
691 FIXME("stub!\n");
692 return DI_OK;
693}
694
695/******************************************************************************
696 * IDirectInputDevice2A
697 */
698
699static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
700 LPDIRECTINPUTDEVICE2A iface,
701 REFGUID rguid,
702 LPCDIEFFECT lpeff,
703 LPDIRECTINPUTEFFECT *ppdef,
704 LPUNKNOWN pUnkOuter)
705{
706 FIXME("stub!\n");
707 return DI_OK;
708}
709
710static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
711 LPDIRECTINPUTDEVICE2A iface,
712 LPDIENUMEFFECTSCALLBACKA lpCallback,
713 LPVOID lpvRef,
714 DWORD dwFlags)
715{
716 FIXME("stub!\n");
717 if (lpCallback)
718 lpCallback(NULL, lpvRef);
719 return DI_OK;
720}
721
722static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
723 LPDIRECTINPUTDEVICE2A iface,
724 LPDIEFFECTINFOA lpdei,
725 REFGUID rguid)
726{
727 FIXME("stub!\n");
728 return DI_OK;
729}
730
731static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
732 LPDIRECTINPUTDEVICE2A iface,
733 LPDWORD pdwOut)
734{
735 FIXME("stub!\n");
736 return DI_OK;
737}
738
739static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
740 LPDIRECTINPUTDEVICE2A iface,
741 DWORD dwFlags)
742{
743 FIXME("stub!\n");
744 return DI_OK;
745}
746
747static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
748 LPDIRECTINPUTDEVICE2A iface,
749 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
750 LPVOID lpvRef,
751 DWORD dwFlags)
752{
753 FIXME("stub!\n");
754 if (lpCallback)
755 lpCallback(NULL, lpvRef);
756 return DI_OK;
757}
758
759static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
760 LPDIRECTINPUTDEVICE2A iface,
761 LPDIEFFESCAPE lpDIEEsc)
762{
763 FIXME("stub!\n");
764 return DI_OK;
765}
766
767static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
768 LPDIRECTINPUTDEVICE2A iface)
769{
770 FIXME("stub!\n");
771 return DI_OK;
772}
773
774static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
775 LPDIRECTINPUTDEVICE2A iface,
776 DWORD cbObjectData,
777 LPDIDEVICEOBJECTDATA rgdod,
778 LPDWORD pdwInOut,
779 DWORD dwFlags)
780{
781 FIXME("stub!\n");
782 return DI_OK;
783}
784
785/******************************************************************************
786 * SysMouseA (DInput Mouse support)
787 */
788
789/******************************************************************************
790 * Release : release the mouse buffer.
791 */
792static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
793{
794 ICOM_THIS(SysMouseAImpl,iface);
795
796 This->ref--;
797 if (This->ref)
798 return This->ref;
799
800 /* Free the data queue */
801 if (This->data_queue != NULL)
802 HeapFree(GetProcessHeap(),0,This->data_queue);
803
804 /* Install the previous event handler (in case of releasing an aquired
805 mouse device) */
806 if (This->prev_handler != NULL)
807 MOUSE_Enable(This->prev_handler);
808 DeleteCriticalSection(&(This->crit));
809
810 HeapFree(GetProcessHeap(),0,This);
811 return 0;
812}
813
814
815/******************************************************************************
816 * SetCooperativeLevel : store the window in which we will do our
817 * grabbing.
818 */
819static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
820 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
821)
822{
823 ICOM_THIS(SysMouseAImpl,iface);
824
825 TRACE("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
826
827// if (TRACE_ON(dinput))
828// _dump_cooperativelevel(dwflags);
829
830 /* Store the window which asks for the mouse */
831 This->win = hwnd;
832
833 return 0;
834}
835
836
837/******************************************************************************
838 * SetDataFormat : the application can choose the format of the data
839 * the device driver sends back with GetDeviceState.
840 *
841 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
842 * in absolute and relative mode.
843 */
844static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
845 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
846)
847{
848 ICOM_THIS(SysMouseAImpl,iface);
849 int i;
850
851 TRACE("(this=%p,%p)\n",This,df);
852
853 TRACE("(df.dwSize=%ld)\n",df->dwSize);
854 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
855 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
856 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
857 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
858
859 for (i=0;i<df->dwNumObjs;i++) {
860 char xbuf[50];
861
862 if (df->rgodf[i].pguid)
863 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
864 else
865 strcpy(xbuf,"<no guid>");
866 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
867 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
868 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
869 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
870 }
871
872 /* Check size of data format to prevent crashes if the applications
873 sends a smaller buffer */
874 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
875 FIXME("non-standard mouse configuration not supported yet.");
876 return DIERR_INVALIDPARAM;
877 }
878
879 /* For the moment, ignore these fields and return always as if
880 c_dfDIMouse was passed as format... */
881
882 /* Check if the mouse is in absolute or relative mode */
883 if (df->dwFlags == DIDF_ABSAXIS)
884 This->absolute = 1;
885 else if (df->dwFlags == DIDF_RELAXIS)
886 This->absolute = 0;
887 else
888 ERR("Neither absolute nor relative flag set.");
889
890 This->df = (LPCDIDATAFORMAT)HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
891 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
892 return 0;
893}
894
895#define GEN_EVENT(offset,data,xtime,seq) \
896{ \
897 if (This->queue_pos < This->queue_len) { \
898 This->data_queue[This->queue_pos].dwOfs = offset; \
899 This->data_queue[This->queue_pos].dwData = data; \
900 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
901 This->data_queue[This->queue_pos].dwSequence = seq; \
902 This->queue_pos++; \
903 } \
904}
905
906
907/* Our private mouse event handler */
908static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
909 DWORD cButtons, DWORD dwExtraInfo )
910{
911 DWORD posX, posY, keyState, xtime, extra;
912 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
913
914 EnterCriticalSection(&(This->crit));
915 /* Mouse moved -> send event if asked */
916 if (This->hEvent)
917 SetEvent(This->hEvent);
918
919 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
920 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
921 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
922 keyState = wme->keyState;
923 xtime = wme->time;
924 extra = (DWORD)wme->hWnd;
925
926 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
927 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
928 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
929 } else {
930 ERR("Mouse event not supported...\n");
931 LeaveCriticalSection(&(This->crit));
932 return ;
933 }
934
935 TRACE(" %ld %ld ", posX, posY);
936
937 if ( dwFlags & MOUSEEVENTF_MOVE ) {
938 if (This->absolute) {
939 if (posX != This->prevX)
940 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
941 if (posY != This->prevY)
942 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
943 } else {
944 /* Relative mouse input : the real fun starts here... */
945 if (This->need_warp) {
946 if (posX != This->prevX)
947 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
948 if (posY != This->prevY)
949 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
950 } else {
951 /* This is the first time the event handler has been called after a
952 GetData of GetState. */
953 if (posX != This->win_centerX) {
954 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
955 This->need_warp = 1;
956 }
957
958 if (posY != This->win_centerY) {
959 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
960 This->need_warp = 1;
961 }
962 }
963 }
964 }
965 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
966// if (TRACE_ON(dinput))
967// DPRINTF(" LD ");
968
969 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
970 }
971 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
972// if (TRACE_ON(dinput))
973// DPRINTF(" LU ");
974
975 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
976 }
977 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
978// if (TRACE_ON(dinput))
979// DPRINTF(" RD ");
980
981 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
982 }
983 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
984// if (TRACE_ON(dinput))
985// DPRINTF(" RU ");
986
987 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
988 }
989 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
990// if (TRACE_ON(dinput))
991// DPRINTF(" MD ");
992
993 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
994 }
995 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
996// if (TRACE_ON(dinput))
997// DPRINTF(" MU ");
998
999 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
1000 }
1001// if (TRACE_ON(dinput))
1002// DPRINTF("\n");
1003
1004 This->prevX = posX;
1005 This->prevY = posY;
1006 LeaveCriticalSection(&(This->crit));
1007}
1008
1009
1010/******************************************************************************
1011 * Acquire : gets exclusive control of the mouse
1012 */
1013static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1014{
1015 ICOM_THIS(SysMouseAImpl,iface);
1016 RECT rect;
1017
1018 TRACE("(this=%p)\n",This);
1019
1020 if (This->acquired == 0) {
1021 POINT point;
1022
1023 /* This stores the current mouse handler. */
1024#ifdef __WIN32OS2__
1025 This->prev_handler = (LPMOUSE_EVENT_PROC)-1;
1026#else
1027 This->prev_handler = mouse_event;
1028#endif
1029
1030 /* Store (in a global variable) the current lock */
1031 current_lock = (IDirectInputDevice2A*)This;
1032
1033 /* Install our own mouse event handler */
1034 MOUSE_Enable(dinput_mouse_event);
1035
1036 /* Get the window dimension and find the center */
1037 GetWindowRect(This->win, &rect);
1038 This->win_centerX = (rect.right - rect.left) / 2;
1039 This->win_centerY = (rect.bottom - rect.top ) / 2;
1040
1041 /* Warp the mouse to the center of the window */
1042 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1043 point.x = This->win_centerX;
1044 point.y = This->win_centerY;
1045 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1046#ifdef __WIN32OS2__
1047 OSLibMoveCursor(point.x, point.y);
1048#else
1049 DISPLAY_MoveCursor(point.x, point.y);
1050#endif
1051
1052 This->acquired = 1;
1053 }
1054 return 0;
1055}
1056
1057/******************************************************************************
1058 * Unacquire : frees the mouse
1059 */
1060static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1061{
1062 ICOM_THIS(SysMouseAImpl,iface);
1063
1064 TRACE("(this=%p)\n",This);
1065
1066 /* Reinstall previous mouse event handler */
1067 MOUSE_Enable(This->prev_handler);
1068 This->prev_handler = NULL;
1069
1070 /* No more locks */
1071 current_lock = NULL;
1072
1073 /* Unacquire device */
1074 This->acquired = 0;
1075
1076 return 0;
1077}
1078
1079/******************************************************************************
1080 * GetDeviceState : returns the "state" of the mouse.
1081 *
1082 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1083 * supported.
1084 */
1085static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1086 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1087) {
1088 ICOM_THIS(SysMouseAImpl,iface);
1089 DWORD rx, ry, state;
1090 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
1091
1092 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1093
1094 /* Check if the buffer is big enough */
1095 if (len < sizeof(struct DIMOUSESTATE)) {
1096 FIXME("unsupported state structure.");
1097 return DIERR_INVALIDPARAM;
1098 }
1099
1100 /* Get the mouse position */
1101#ifdef __WIN32OS2__
1102 OSLibQueryMousePos(&rx, &ry, &state);
1103#else
1104 EVENT_QueryPointer(&rx, &ry, &state);
1105#endif
1106 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
1107
1108 /* Fill the mouse state structure */
1109 if (This->absolute) {
1110 mstate->lX = rx;
1111 mstate->lY = ry;
1112 } else {
1113 mstate->lX = rx - This->win_centerX;
1114 mstate->lY = ry - This->win_centerY;
1115
1116 if ((mstate->lX != 0) || (mstate->lY != 0))
1117 This->need_warp = 1;
1118 }
1119 mstate->lZ = 0;
1120 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
1121 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
1122 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
1123 mstate->rgbButtons[3] = 0x00;
1124
1125 /* Check if we need to do a mouse warping */
1126 if (This->need_warp) {
1127 POINT point;
1128
1129 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1130 point.x = This->win_centerX;
1131 point.y = This->win_centerY;
1132 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1133#ifdef __WIN32OS2__
1134 OSLibMoveCursor(point.x, point.y);
1135#else
1136 DISPLAY_MoveCursor(point.x, point.y);
1137#endif
1138 This->need_warp = 0;
1139 }
1140
1141 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1142 mstate->lX, mstate->lY,
1143 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1144
1145 return 0;
1146}
1147
1148/******************************************************************************
1149 * GetDeviceState : gets buffered input data.
1150 */
1151static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1152 DWORD dodsize,
1153 LPDIDEVICEOBJECTDATA dod,
1154 LPDWORD entries,
1155 DWORD flags
1156) {
1157 ICOM_THIS(SysMouseAImpl,iface);
1158
1159 EnterCriticalSection(&(This->crit));
1160 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1161
1162 if (flags & DIGDD_PEEK)
1163 FIXME("DIGDD_PEEK\n");
1164
1165 if (dod == NULL) {
1166 *entries = This->queue_pos;
1167 This->queue_pos = 0;
1168 } else {
1169 /* Check for buffer overflow */
1170 if (This->queue_pos > *entries) {
1171 WARN("Buffer overflow not handled properly yet...\n");
1172 This->queue_pos = *entries;
1173 }
1174 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1175 ERR("Wrong structure size !\n");
1176 LeaveCriticalSection(&(This->crit));
1177 return DIERR_INVALIDPARAM;
1178 }
1179
1180 if (This->queue_pos)
1181 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1182
1183 /* Copy the buffered data into the application queue */
1184 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1185 *entries = This->queue_pos;
1186
1187 /* Reset the event queue */
1188 This->queue_pos = 0;
1189 }
1190 LeaveCriticalSection(&(This->crit));
1191
1192#if 0 /* FIXME: seems to create motion events, which fire back at us. */
1193 /* Check if we need to do a mouse warping */
1194 if (This->need_warp) {
1195 POINT point;
1196
1197 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1198 point.x = This->win_centerX;
1199 point.y = This->win_centerY;
1200 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1201
1202#ifdef __WIN32OS2__
1203 OSLibMoveCursor(point.x, point.y);
1204#else
1205 DISPLAY_MoveCursor(point.x, point.y);
1206#endif
1207
1208 This->need_warp = 0;
1209 }
1210#endif
1211 return 0;
1212}
1213
1214/******************************************************************************
1215 * SetProperty : change input device properties
1216 */
1217static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1218 REFGUID rguid,
1219 LPCDIPROPHEADER ph)
1220{
1221 ICOM_THIS(SysMouseAImpl,iface);
1222 char xbuf[50];
1223
1224 if (HIWORD(rguid))
1225 WINE_StringFromCLSID(rguid,xbuf);
1226 else
1227 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1228
1229 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1230
1231 if (!HIWORD(rguid)) {
1232#ifdef __WIN32OS2__
1233 if(rguid == DIPROP_BUFFERSIZE) {
1234 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1235
1236 TRACE("buffersize = %ld\n",pd->dwData);
1237
1238 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1239 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1240 This->queue_pos = 0;
1241 This->queue_len = pd->dwData;
1242 }
1243 else {
1244 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1245 }
1246#else
1247 switch ((DWORD)rguid) {
1248 case (DWORD) DIPROP_BUFFERSIZE: {
1249 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1250
1251 TRACE("buffersize = %ld\n",pd->dwData);
1252
1253 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1254 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1255 This->queue_pos = 0;
1256 This->queue_len = pd->dwData;
1257 break;
1258 }
1259 default:
1260 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1261 break;
1262 }
1263#endif
1264 }
1265
1266 return 0;
1267}
1268
1269/******************************************************************************
1270 * SetEventNotification : specifies event to be sent on state change
1271 */
1272static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1273 HANDLE hnd) {
1274 ICOM_THIS(SysMouseAImpl,iface);
1275
1276 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1277
1278 This->hEvent = hnd;
1279
1280 return DI_OK;
1281}
1282
1283#ifdef HAVE_LINUX_22_JOYSTICK_API
1284/******************************************************************************
1285 * Joystick
1286 */
1287static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1288{
1289 ICOM_THIS(JoystickAImpl,iface);
1290
1291 This->ref--;
1292 if (This->ref)
1293 return This->ref;
1294 HeapFree(GetProcessHeap(),0,This);
1295 return 0;
1296}
1297
1298/******************************************************************************
1299 * SetDataFormat : the application can choose the format of the data
1300 * the device driver sends back with GetDeviceState.
1301 */
1302static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1303 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1304)
1305{
1306 ICOM_THIS(JoystickAImpl,iface);
1307 int i;
1308
1309 TRACE("(this=%p,%p)\n",This,df);
1310
1311 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1312 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1313 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1314 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1315 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1316
1317 for (i=0;i<df->dwNumObjs;i++) {
1318 char xbuf[50];
1319
1320 if (df->rgodf[i].pguid)
1321 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1322 else
1323 strcpy(xbuf,"<no guid>");
1324 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1325 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1326 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1327 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1328 }
1329 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1330 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1331 return 0;
1332}
1333
1334/******************************************************************************
1335 * Acquire : gets exclusive control of the joystick
1336 */
1337static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1338{
1339 ICOM_THIS(JoystickAImpl,iface);
1340
1341 TRACE("(this=%p)\n",This);
1342 if (This->joyfd!=-1)
1343 return 0;
1344 This->joyfd=open(JOYDEV,O_RDONLY);
1345 if (This->joyfd==-1)
1346 return DIERR_NOTFOUND;
1347 return 0;
1348}
1349
1350/******************************************************************************
1351 * Unacquire : frees the joystick
1352 */
1353static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1354{
1355 ICOM_THIS(JoystickAImpl,iface);
1356
1357 TRACE("(this=%p)\n",This);
1358 if (This->joyfd!=-1) {
1359 close(This->joyfd);
1360 This->joyfd = -1;
1361 }
1362 return 0;
1363}
1364
1365#define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1366
1367static void joy_polldev(JoystickAImpl *This) {
1368 struct timeval tv;
1369 fd_set readfds;
1370 struct js_event jse;
1371
1372 if (This->joyfd==-1)
1373 return;
1374 while (1) {
1375 memset(&tv,0,sizeof(tv));
1376 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1377 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1378 return;
1379 /* we have one event, so we can read */
1380 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1381 return;
1382 }
1383 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1384 if (jse.type & JS_EVENT_BUTTON) {
1385 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1386 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1387 }
1388 if (jse.type & JS_EVENT_AXIS) {
1389 switch (jse.number) {
1390 case 0:
1391 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1392 This->js.lX = map_axis(jse.value);
1393 break;
1394 case 1:
1395 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1396 This->js.lY = map_axis(jse.value);
1397 break;
1398 case 2:
1399 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1400 This->js.lZ = map_axis(jse.value);
1401 break;
1402 default:
1403 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1404 break;
1405 }
1406 }
1407 }
1408}
1409
1410/******************************************************************************
1411 * GetDeviceState : returns the "state" of the joystick.
1412 *
1413 */
1414static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1415 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1416) {
1417 ICOM_THIS(JoystickAImpl,iface);
1418
1419 joy_polldev(This);
1420 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1421 if (len != sizeof(DIJOYSTATE)) {
1422 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1423 }
1424 memcpy(ptr,&(This->js),len);
1425 This->queue_pos = 0;
1426 return 0;
1427}
1428
1429/******************************************************************************
1430 * GetDeviceState : gets buffered input data.
1431 */
1432static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1433 DWORD dodsize,
1434 LPDIDEVICEOBJECTDATA dod,
1435 LPDWORD entries,
1436 DWORD flags
1437) {
1438 ICOM_THIS(JoystickAImpl,iface);
1439
1440 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1441
1442 joy_polldev(This);
1443 if (flags & DIGDD_PEEK)
1444 FIXME("DIGDD_PEEK\n");
1445
1446 if (dod == NULL) {
1447 } else {
1448 }
1449 return 0;
1450}
1451
1452/******************************************************************************
1453 * SetProperty : change input device properties
1454 */
1455static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1456 REFGUID rguid,
1457 LPCDIPROPHEADER ph)
1458{
1459 ICOM_THIS(JoystickAImpl,iface);
1460 char xbuf[50];
1461
1462 if (HIWORD(rguid))
1463 WINE_StringFromCLSID(rguid,xbuf);
1464 else
1465 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1466
1467 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1468 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1469
1470 if (!HIWORD(rguid)) {
1471 switch ((DWORD)rguid) {
1472 case (DWORD) DIPROP_BUFFERSIZE: {
1473 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1474
1475 FIXME("buffersize = %ld\n",pd->dwData);
1476 break;
1477 }
1478 case (DWORD)DIPROP_RANGE: {
1479 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1480
1481 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1482 This->lMin = pr->lMin;
1483 This->lMax = pr->lMax;
1484 break;
1485 }
1486 case (DWORD)DIPROP_DEADZONE: {
1487 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1488
1489 FIXME("deadzone(%ld)\n",pd->dwData);
1490 This->deadzone = pd->dwData;
1491 break;
1492 }
1493 default:
1494 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1495 break;
1496 }
1497 }
1498 return 0;
1499}
1500
1501/******************************************************************************
1502 * SetEventNotification : specifies event to be sent on state change
1503 */
1504static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1505 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1506) {
1507 ICOM_THIS(JoystickAImpl,iface);
1508
1509 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1510 This->hEvent = hnd;
1511 return DI_OK;
1512}
1513
1514static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1515 LPDIRECTINPUTDEVICE2A iface,
1516 LPDIDEVCAPS lpDIDevCaps)
1517{
1518 ICOM_THIS(JoystickAImpl,iface);
1519 BYTE axes,buttons;
1520 int xfd = This->joyfd;
1521
1522 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1523 if (xfd==-1)
1524 xfd = open(JOYDEV,O_RDONLY);
1525 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1526 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1527#ifdef JSIOCGAXES
1528 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1529 axes = 2;
1530 lpDIDevCaps->dwAxes = axes;
1531#endif
1532#ifdef JSIOCGBUTTONS
1533 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1534 buttons = 2;
1535 lpDIDevCaps->dwButtons = buttons;
1536#endif
1537 if (xfd!=This->joyfd)
1538 close(xfd);
1539 return DI_OK;
1540}
1541static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1542 ICOM_THIS(JoystickAImpl,iface);
1543 TRACE("(),stub!\n");
1544
1545 joy_polldev(This);
1546 return DI_OK;
1547}
1548#endif
1549
1550/****************************************************************************/
1551/****************************************************************************/
1552
1553ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1554{
1555 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1556 IDirectInputDevice2AImpl_QueryInterface,
1557 IDirectInputDevice2AImpl_AddRef,
1558 IDirectInputDevice2AImpl_Release,
1559 IDirectInputDevice2AImpl_GetCapabilities,
1560 IDirectInputDevice2AImpl_EnumObjects,
1561 IDirectInputDevice2AImpl_GetProperty,
1562 SysKeyboardAImpl_SetProperty,
1563 SysKeyboardAImpl_Acquire,
1564 SysKeyboardAImpl_Unacquire,
1565 SysKeyboardAImpl_GetDeviceState,
1566 SysKeyboardAImpl_GetDeviceData,
1567 IDirectInputDevice2AImpl_SetDataFormat,
1568 IDirectInputDevice2AImpl_SetEventNotification,
1569 IDirectInputDevice2AImpl_SetCooperativeLevel,
1570 IDirectInputDevice2AImpl_GetObjectInfo,
1571 IDirectInputDevice2AImpl_GetDeviceInfo,
1572 IDirectInputDevice2AImpl_RunControlPanel,
1573 IDirectInputDevice2AImpl_Initialize,
1574 IDirectInputDevice2AImpl_CreateEffect,
1575 IDirectInputDevice2AImpl_EnumEffects,
1576 IDirectInputDevice2AImpl_GetEffectInfo,
1577 IDirectInputDevice2AImpl_GetForceFeedbackState,
1578 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1579 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1580 IDirectInputDevice2AImpl_Escape,
1581 IDirectInputDevice2AImpl_Poll,
1582 IDirectInputDevice2AImpl_SendDeviceData,
1583};
1584
1585ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1586{
1587 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1588 IDirectInputDevice2AImpl_QueryInterface,
1589 IDirectInputDevice2AImpl_AddRef,
1590 SysMouseAImpl_Release,
1591 IDirectInputDevice2AImpl_GetCapabilities,
1592 IDirectInputDevice2AImpl_EnumObjects,
1593 IDirectInputDevice2AImpl_GetProperty,
1594 SysMouseAImpl_SetProperty,
1595 SysMouseAImpl_Acquire,
1596 SysMouseAImpl_Unacquire,
1597 SysMouseAImpl_GetDeviceState,
1598 SysMouseAImpl_GetDeviceData,
1599 SysMouseAImpl_SetDataFormat,
1600 SysMouseAImpl_SetEventNotification,
1601 SysMouseAImpl_SetCooperativeLevel,
1602 IDirectInputDevice2AImpl_GetObjectInfo,
1603 IDirectInputDevice2AImpl_GetDeviceInfo,
1604 IDirectInputDevice2AImpl_RunControlPanel,
1605 IDirectInputDevice2AImpl_Initialize,
1606 IDirectInputDevice2AImpl_CreateEffect,
1607 IDirectInputDevice2AImpl_EnumEffects,
1608 IDirectInputDevice2AImpl_GetEffectInfo,
1609 IDirectInputDevice2AImpl_GetForceFeedbackState,
1610 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1611 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1612 IDirectInputDevice2AImpl_Escape,
1613 IDirectInputDevice2AImpl_Poll,
1614 IDirectInputDevice2AImpl_SendDeviceData,
1615};
1616
1617#ifdef HAVE_LINUX_22_JOYSTICK_API
1618ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1619{
1620 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1621 IDirectInputDevice2AImpl_QueryInterface,
1622 IDirectInputDevice2AImpl_AddRef,
1623 JoystickAImpl_Release,
1624 JoystickAImpl_GetCapabilities,
1625 IDirectInputDevice2AImpl_EnumObjects,
1626 IDirectInputDevice2AImpl_GetProperty,
1627 JoystickAImpl_SetProperty,
1628 JoystickAImpl_Acquire,
1629 JoystickAImpl_Unacquire,
1630 JoystickAImpl_GetDeviceState,
1631 JoystickAImpl_GetDeviceData,
1632 JoystickAImpl_SetDataFormat,
1633 JoystickAImpl_SetEventNotification,
1634 IDirectInputDevice2AImpl_SetCooperativeLevel,
1635 IDirectInputDevice2AImpl_GetObjectInfo,
1636 IDirectInputDevice2AImpl_GetDeviceInfo,
1637 IDirectInputDevice2AImpl_RunControlPanel,
1638 IDirectInputDevice2AImpl_Initialize,
1639 IDirectInputDevice2AImpl_CreateEffect,
1640 IDirectInputDevice2AImpl_EnumEffects,
1641 IDirectInputDevice2AImpl_GetEffectInfo,
1642 IDirectInputDevice2AImpl_GetForceFeedbackState,
1643 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1644 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1645 IDirectInputDevice2AImpl_Escape,
1646 JoystickAImpl_Poll,
1647 IDirectInputDevice2AImpl_SendDeviceData,
1648};
1649#endif
Note: See TracBrowser for help on using the repository browser.