1 /* DirectInput Joystick device
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/port.h"
38 #ifdef HAVE_SYS_TIME_H
39 # include <sys/time.h>
42 #ifdef HAVE_SYS_IOCTL_H
43 # include <sys/ioctl.h>
46 #ifdef HAVE_LINUX_IOCTL_H
47 # include <linux/ioctl.h>
49 #ifdef HAVE_LINUX_JOYSTICK_H
50 # include <linux/joystick.h>
53 #ifdef HAVE_SYS_POLL_H
54 # include <sys/poll.h>
57 #include "wine/debug.h"
58 #include "wine/unicode.h"
64 #include "dinput_private.h"
65 #include "device_private.h"
66 #include "joystick_private.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
70 #ifdef HAVE_LINUX_22_JOYSTICK_API
72 #define JOYDEV_NEW "/dev/input/js"
73 #define JOYDEV_OLD "/dev/js"
74 #define JOYDEVDRIVER " (js)"
78 char device[MAX_PATH];
86 typedef struct JoystickImpl JoystickImpl;
87 static const IDirectInputDevice8AVtbl JoystickAvt;
88 static const IDirectInputDevice8WVtbl JoystickWvt;
91 struct JoystickGenericImpl generic;
93 struct JoyDev *joydev;
95 /* joystick private */
100 static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
102 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
103 JoystickGenericImpl, base), JoystickImpl, generic);
105 static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
107 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
108 JoystickGenericImpl, base), JoystickImpl, generic);
110 static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(JoystickImpl *This)
112 return &This->generic.base.IDirectInputDevice8A_iface;
114 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
116 return &This->generic.base.IDirectInputDevice8W_iface;
119 static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
123 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
126 #define MAX_JOYSTICKS 64
127 static INT joystick_devices_count = -1;
128 static struct JoyDev *joystick_devices;
130 static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
132 static INT find_joystick_devices(void)
136 if (joystick_devices_count != -1) return joystick_devices_count;
138 joystick_devices_count = 0;
139 for (i = 0; i < MAX_JOYSTICKS; i++)
142 struct JoyDev joydev, *new_joydevs;
143 BYTE axes_map[ABS_MAX + 1];
145 snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i);
146 if ((fd = open(joydev.device, O_RDONLY)) < 0)
148 snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_OLD, i);
149 if ((fd = open(joydev.device, O_RDONLY)) < 0) continue;
152 strcpy(joydev.name, "Wine Joystick");
153 #if defined(JSIOCGNAME)
154 if (ioctl(fd, JSIOCGNAME(sizeof(joydev.name) - sizeof(JOYDEVDRIVER)), joydev.name) < 0)
155 WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", joydev.device, strerror(errno));
158 /* Append driver name */
159 strcat(joydev.name, JOYDEVDRIVER);
162 if (ioctl(fd, JSIOCGAXES, &joydev.axis_count) < 0)
164 WARN("ioctl(%s,JSIOCGAXES) failed: %s, defauting to 2\n", joydev.device, strerror(errno));
165 joydev.axis_count = 2;
169 if (ioctl(fd, JSIOCGBUTTONS, &joydev.button_count) < 0)
171 WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defauting to 2\n", joydev.device, strerror(errno));
172 joydev.button_count = 2;
176 if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0)
178 WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", joydev.device, strerror(errno));
179 joydev.dev_axes_map = NULL;
182 if ((joydev.dev_axes_map = HeapAlloc(GetProcessHeap(), 0, joydev.axis_count * sizeof(int))))
186 /* Remap to DI numbers */
187 for (j = 0; j < joydev.axis_count; j++)
189 /* Axis match 1-to-1 */
190 joydev.dev_axes_map[j] = j;
191 else if (axes_map[j] == 16 ||
194 joydev.dev_axes_map[j] = 8;
196 joydev.dev_axes_map[j] = -1;
201 if (!joystick_devices_count)
202 new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev));
204 new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joystick_devices,
205 (joystick_devices_count + 1) * sizeof(struct JoyDev));
206 if (!new_joydevs) continue;
208 TRACE("Found a joystick on %s: %s\n with %d axes and %d buttons\n", joydev.device,
209 joydev.name, joydev.axis_count, joydev.button_count);
211 joystick_devices = new_joydevs;
212 joystick_devices[joystick_devices_count++] = joydev;
215 return joystick_devices_count;
218 static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
222 if (id >= find_joystick_devices()) return FALSE;
224 if (dwFlags & DIEDFL_FORCEFEEDBACK) {
225 WARN("force feedback not supported\n");
229 if ((dwDevType == 0) ||
230 ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
231 (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
232 /* check whether we have a joystick */
233 if ((fd = open(joystick_devices[id].device, O_RDONLY)) < 0)
235 WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].name, strerror(errno));
239 /* Return joystick */
240 lpddi->guidInstance = DInput_Wine_Joystick_GUID;
241 lpddi->guidInstance.Data3 = id;
242 lpddi->guidProduct = DInput_Wine_Joystick_GUID;
243 /* we only support traditional joysticks for now */
244 if (version >= 0x0800)
245 lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
247 lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
249 strcpy(lpddi->tszInstanceName, joystick_devices[id].name);
250 strcpy(lpddi->tszProductName, joystick_devices[id].name);
252 lpddi->guidFFDriver = GUID_NULL;
254 TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, lpddi->tszProductName);
261 static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
265 if (id >= find_joystick_devices()) return FALSE;
267 if (dwFlags & DIEDFL_FORCEFEEDBACK) {
268 WARN("force feedback not supported\n");
272 if ((dwDevType == 0) ||
273 ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
274 (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
275 /* check whether we have a joystick */
276 if ((fd = open(joystick_devices[id].device, O_RDONLY)) < 0)
278 WARN("open(%s,O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno));
282 /* Return joystick */
283 lpddi->guidInstance = DInput_Wine_Joystick_GUID;
284 lpddi->guidInstance.Data3 = id;
285 lpddi->guidProduct = DInput_Wine_Joystick_GUID;
286 /* we only support traditional joysticks for now */
287 if (version >= 0x0800)
288 lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
290 lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
292 MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
293 MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszProductName, MAX_PATH);
294 lpddi->guidFFDriver = GUID_NULL;
296 TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, joystick_devices[id].name);
303 static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
304 JoystickImpl **pdev, unsigned short index)
307 JoystickImpl* newDevice;
309 LPDIDATAFORMAT df = NULL;
312 TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
314 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
315 if (newDevice == 0) {
316 WARN("out of memory\n");
318 return DIERR_OUTOFMEMORY;
321 newDevice->joydev = &joystick_devices[index];
322 newDevice->joyfd = -1;
323 newDevice->generic.guidInstance = DInput_Wine_Joystick_GUID;
324 newDevice->generic.guidInstance.Data3 = index;
325 newDevice->generic.guidProduct = DInput_Wine_Joystick_GUID;
326 newDevice->generic.joy_polldev = joy_polldev;
327 newDevice->generic.name = newDevice->joydev->name;
328 newDevice->generic.device_axis_count = newDevice->joydev->axis_count;
329 newDevice->generic.devcaps.dwButtons = newDevice->joydev->button_count;
331 if (newDevice->generic.devcaps.dwButtons > 128)
333 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
334 newDevice->generic.devcaps.dwButtons = 128;
337 newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
338 newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
339 newDevice->generic.base.ref = 1;
340 newDevice->generic.base.dinput = dinput;
341 newDevice->generic.base.guid = *rguid;
342 InitializeCriticalSection(&newDevice->generic.base.crit);
343 newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
345 /* setup_dinput_options may change these */
346 newDevice->generic.deadzone = 0;
348 /* do any user specified configuration */
349 hr = setup_dinput_options(&newDevice->generic, newDevice->joydev->dev_axes_map);
353 /* Create copy of default data format */
354 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
355 memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
357 df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
358 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
360 for (i = 0; i < newDevice->generic.device_axis_count; i++)
362 int wine_obj = newDevice->generic.axis_map[i];
364 if (wine_obj < 0) continue;
366 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
368 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
371 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
372 i++; /* POV takes 2 axes */
375 for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++)
377 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
378 df->rgodf[idx ].pguid = &GUID_Button;
379 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
381 newDevice->generic.base.data_format.wine_df = df;
383 /* initialize default properties */
384 for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
385 newDevice->generic.props[i].lDevMin = -32767;
386 newDevice->generic.props[i].lDevMax = +32767;
387 newDevice->generic.props[i].lMin = 0;
388 newDevice->generic.props[i].lMax = 0xffff;
389 newDevice->generic.props[i].lDeadZone = newDevice->generic.deadzone; /* % * 1000 */
390 newDevice->generic.props[i].lSaturation = 0;
393 IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
395 EnterCriticalSection(&dinput->crit);
396 list_add_tail(&dinput->devices_list, &newDevice->generic.base.entry);
397 LeaveCriticalSection(&dinput->crit);
399 newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
400 newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
401 if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
402 newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
404 newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
405 newDevice->generic.devcaps.dwFFSamplePeriod = 0;
406 newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
407 newDevice->generic.devcaps.dwFirmwareRevision = 0;
408 newDevice->generic.devcaps.dwHardwareRevision = 0;
409 newDevice->generic.devcaps.dwFFDriverVersion = 0;
411 if (TRACE_ON(dinput)) {
412 _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df);
413 for (i = 0; i < (newDevice->generic.device_axis_count); i++)
414 TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]);
415 _dump_DIDEVCAPS(&newDevice->generic.devcaps);
423 hr = DIERR_OUTOFMEMORY;
425 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
426 HeapFree(GetProcessHeap(), 0, df);
427 release_DataFormat(&newDevice->generic.base.data_format);
428 HeapFree(GetProcessHeap(),0,newDevice->generic.axis_map);
429 HeapFree(GetProcessHeap(),0,newDevice);
435 /******************************************************************************
436 * get_joystick_index : Get the joystick index from a given GUID
438 static unsigned short get_joystick_index(REFGUID guid)
440 GUID wine_joystick = DInput_Wine_Joystick_GUID;
441 GUID dev_guid = *guid;
443 wine_joystick.Data3 = 0;
446 /* for the standard joystick GUID use index 0 */
447 if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
449 /* for the wine joystick GUIDs use the index stored in Data3 */
450 if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
452 return MAX_JOYSTICKS;
455 static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
457 unsigned short index;
459 TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
460 find_joystick_devices();
463 if ((index = get_joystick_index(rguid)) < MAX_JOYSTICKS &&
464 joystick_devices_count && index < joystick_devices_count)
471 else if (IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
472 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
473 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
474 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
478 else if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) ||
479 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
480 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
481 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
487 WARN("no interface\n");
488 return DIERR_NOINTERFACE;
491 hr = alloc_device(rguid, dinput, &This, index);
492 if (!This) return hr;
495 *pdev = &This->generic.base.IDirectInputDevice8W_iface;
497 *pdev = &This->generic.base.IDirectInputDevice8A_iface;
502 return DIERR_DEVICENOTREG;
507 const struct dinput_device joystick_linux_device = {
508 "Wine Linux joystick driver",
514 /******************************************************************************
515 * Acquire : gets exclusive control of the joystick
517 static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
519 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
522 TRACE("(%p)\n",This);
524 res = IDirectInputDevice2WImpl_Acquire(iface);
528 /* open the joystick device */
529 if (This->joyfd==-1) {
530 TRACE("opening joystick device %s\n", This->joydev->device);
532 This->joyfd = open(This->joydev->device, O_RDONLY);
533 if (This->joyfd==-1) {
534 ERR("open(%s) failed: %s\n", This->joydev->device, strerror(errno));
535 IDirectInputDevice2WImpl_Unacquire(iface);
536 return DIERR_NOTFOUND;
543 static HRESULT WINAPI JoystickLinuxAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
545 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
546 return JoystickLinuxWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
549 /******************************************************************************
550 * GetProperty : get input device properties
552 static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
554 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
556 TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph);
557 _dump_DIPROPHEADER(pdiph);
559 if (!IS_DIPROP(rguid)) return DI_OK;
561 switch (LOWORD(rguid)) {
563 case (DWORD_PTR) DIPROP_JOYSTICKID:
565 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
567 pd->dwData = get_joystick_index(&This->generic.base.guid);
568 TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
573 return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
579 static HRESULT WINAPI JoystickLinuxAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
581 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
582 return JoystickLinuxWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
585 /******************************************************************************
586 * Unacquire : frees the joystick
588 static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
590 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
593 TRACE("(%p)\n",This);
595 res = IDirectInputDevice2WImpl_Unacquire(iface);
600 if (This->joyfd!=-1) {
601 TRACE("closing joystick device\n");
610 static HRESULT WINAPI JoystickLinuxAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
612 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
613 return JoystickLinuxWImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
616 static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
620 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
622 TRACE("(%p)\n", This);
624 if (This->joyfd==-1) {
633 plfd.fd = This->joyfd;
634 plfd.events = POLLIN;
635 if (poll(&plfd,1,0) != 1)
637 /* we have one event, so we can read */
638 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
641 TRACE("js_event: type 0x%x, number %d, value %d\n",
642 jse.type,jse.number,jse.value);
643 if (jse.type & JS_EVENT_BUTTON)
645 if (jse.number >= This->generic.devcaps.dwButtons) return;
647 inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON;
648 This->generic.js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00;
650 else if (jse.type & JS_EVENT_AXIS)
652 int number = This->generic.axis_map[jse.number]; /* wine format object index */
654 if (number < 0) return;
655 inst_id = number < 8 ? DIDFT_MAKEINSTANCE(number) | DIDFT_ABSAXIS :
656 DIDFT_MAKEINSTANCE(number - 8) | DIDFT_POV;
657 value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], jse.value);
659 TRACE("changing axis %d => %d\n", jse.number, number);
662 case 0: This->generic.js.lX = value; break;
663 case 1: This->generic.js.lY = value; break;
664 case 2: This->generic.js.lZ = value; break;
665 case 3: This->generic.js.lRx = value; break;
666 case 4: This->generic.js.lRy = value; break;
667 case 5: This->generic.js.lRz = value; break;
668 case 6: This->generic.js.rglSlider[0] = value; break;
669 case 7: This->generic.js.rglSlider[1] = value; break;
670 case 8: case 9: case 10: case 11:
672 int idx = number - 8;
675 This->povs[idx].y = jse.value;
677 This->povs[idx].x = jse.value;
679 This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
683 WARN("axis %d not supported\n", number);
687 queue_event(iface, inst_id,
688 value, jse.time, This->generic.base.dinput->evsequence++);
692 static const IDirectInputDevice8AVtbl JoystickAvt =
694 IDirectInputDevice2AImpl_QueryInterface,
695 IDirectInputDevice2AImpl_AddRef,
696 IDirectInputDevice2AImpl_Release,
697 JoystickAGenericImpl_GetCapabilities,
698 IDirectInputDevice2AImpl_EnumObjects,
699 JoystickLinuxAImpl_GetProperty,
700 JoystickAGenericImpl_SetProperty,
701 JoystickLinuxAImpl_Acquire,
702 JoystickLinuxAImpl_Unacquire,
703 JoystickAGenericImpl_GetDeviceState,
704 IDirectInputDevice2AImpl_GetDeviceData,
705 IDirectInputDevice2AImpl_SetDataFormat,
706 IDirectInputDevice2AImpl_SetEventNotification,
707 IDirectInputDevice2AImpl_SetCooperativeLevel,
708 JoystickAGenericImpl_GetObjectInfo,
709 JoystickAGenericImpl_GetDeviceInfo,
710 IDirectInputDevice2AImpl_RunControlPanel,
711 IDirectInputDevice2AImpl_Initialize,
712 IDirectInputDevice2AImpl_CreateEffect,
713 IDirectInputDevice2AImpl_EnumEffects,
714 IDirectInputDevice2AImpl_GetEffectInfo,
715 IDirectInputDevice2AImpl_GetForceFeedbackState,
716 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
717 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
718 IDirectInputDevice2AImpl_Escape,
719 JoystickAGenericImpl_Poll,
720 IDirectInputDevice2AImpl_SendDeviceData,
721 IDirectInputDevice7AImpl_EnumEffectsInFile,
722 IDirectInputDevice7AImpl_WriteEffectToFile,
723 JoystickAGenericImpl_BuildActionMap,
724 JoystickAGenericImpl_SetActionMap,
725 IDirectInputDevice8AImpl_GetImageInfo
728 static const IDirectInputDevice8WVtbl JoystickWvt =
730 IDirectInputDevice2WImpl_QueryInterface,
731 IDirectInputDevice2WImpl_AddRef,
732 IDirectInputDevice2WImpl_Release,
733 JoystickWGenericImpl_GetCapabilities,
734 IDirectInputDevice2WImpl_EnumObjects,
735 JoystickLinuxWImpl_GetProperty,
736 JoystickWGenericImpl_SetProperty,
737 JoystickLinuxWImpl_Acquire,
738 JoystickLinuxWImpl_Unacquire,
739 JoystickWGenericImpl_GetDeviceState,
740 IDirectInputDevice2WImpl_GetDeviceData,
741 IDirectInputDevice2WImpl_SetDataFormat,
742 IDirectInputDevice2WImpl_SetEventNotification,
743 IDirectInputDevice2WImpl_SetCooperativeLevel,
744 JoystickWGenericImpl_GetObjectInfo,
745 JoystickWGenericImpl_GetDeviceInfo,
746 IDirectInputDevice2WImpl_RunControlPanel,
747 IDirectInputDevice2WImpl_Initialize,
748 IDirectInputDevice2WImpl_CreateEffect,
749 IDirectInputDevice2WImpl_EnumEffects,
750 IDirectInputDevice2WImpl_GetEffectInfo,
751 IDirectInputDevice2WImpl_GetForceFeedbackState,
752 IDirectInputDevice2WImpl_SendForceFeedbackCommand,
753 IDirectInputDevice2WImpl_EnumCreatedEffectObjects,
754 IDirectInputDevice2WImpl_Escape,
755 JoystickWGenericImpl_Poll,
756 IDirectInputDevice2WImpl_SendDeviceData,
757 IDirectInputDevice7WImpl_EnumEffectsInFile,
758 IDirectInputDevice7WImpl_WriteEffectToFile,
759 JoystickWGenericImpl_BuildActionMap,
760 JoystickWGenericImpl_SetActionMap,
761 IDirectInputDevice8WImpl_GetImageInfo
764 #else /* HAVE_LINUX_22_JOYSTICK_API */
766 const struct dinput_device joystick_linux_device = {
767 "Wine Linux joystick driver",
773 #endif /* HAVE_LINUX_22_JOYSTICK_API */