ReactOS 0.4.15-dev-8064-gdaf8068
joystick_linuxinput.c
Go to the documentation of this file.
1/* DirectInput Joystick device
2 *
3 * Copyright 1998,2000 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2005 Daniel Remenak
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23#include "config.h"
24#include "wine/port.h"
25
26#include <assert.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <string.h>
30#include <time.h>
31#ifdef HAVE_UNISTD_H
32# include <unistd.h>
33#endif
34#ifdef HAVE_SYS_TIME_H
35# include <sys/time.h>
36#endif
37#include <fcntl.h>
38#ifdef HAVE_SYS_IOCTL_H
39# include <sys/ioctl.h>
40#endif
41#include <errno.h>
42#ifdef HAVE_LINUX_INPUT_H
43# include <linux/input.h>
44# undef SW_MAX
45# if defined(EVIOCGBIT) && defined(EV_ABS) && defined(BTN_PINKIE)
46# define HAS_PROPER_HEADER
47# endif
48#endif
49#ifdef HAVE_SYS_POLL_H
50# include <sys/poll.h>
51#endif
52
53#include "wine/debug.h"
54#include "wine/unicode.h"
55#include "wine/list.h"
56#include "windef.h"
57#include "winbase.h"
58#include "winerror.h"
59#include "winreg.h"
60#include "devguid.h"
61#include "dinput.h"
62
63#include "dinput_private.h"
64#include "device_private.h"
65#include "joystick_private.h"
66
67#ifdef HAS_PROPER_HEADER
68
70
71#define EVDEVPREFIX "/dev/input/event"
72#define EVDEVDRIVER " (event)"
73
74/* Wine joystick driver object instances */
75#define WINE_JOYSTICK_MAX_AXES 8
76#define WINE_JOYSTICK_MAX_POVS 4
77#define WINE_JOYSTICK_MAX_BUTTONS 128
78
79struct wine_input_absinfo {
80 LONG value;
81 LONG minimum;
82 LONG maximum;
83 LONG fuzz;
84 LONG flat;
85};
86
87enum wine_joystick_linuxinput_fd_state {
88 WINE_FD_STATE_CLOSED = 0, /* No device has been opened yet */
89 WINE_FD_STATE_OK, /* File descriptor is open and ready for reading */
90 WINE_FD_STATE_DISCONNECTED, /* Read error occurred; might be able to reopen later */
91 WINE_FD_STATE_INVALID, /* Device is no longer available at original pathname */
92};
93
94/* implemented in effect_linuxinput.c */
95HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff);
96HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
97HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
98
99static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags);
100
101typedef struct JoystickImpl JoystickImpl;
102static const IDirectInputDevice8AVtbl JoystickAvt;
103static const IDirectInputDevice8WVtbl JoystickWvt;
104
105struct JoyDev {
106 char *device;
107 char *name;
108 GUID guid;
109 GUID guid_product;
110
111 BOOL has_ff, is_joystick;
112 int num_effects;
113
114 /* data returned by EVIOCGBIT for caps, EV_ABS, EV_KEY, and EV_FF */
115 BYTE evbits[(EV_MAX+7)/8];
116 BYTE absbits[(ABS_MAX+7)/8];
117 BYTE keybits[(KEY_MAX+7)/8];
118 BYTE ffbits[(FF_MAX+7)/8];
119
120 /* data returned by the EVIOCGABS() ioctl */
121 struct wine_input_absinfo axes[ABS_MAX];
122
123 WORD vendor_id, product_id, bus_type;
124};
125
126struct JoystickImpl
127{
129 struct JoyDev *joydev;
130
131 /* joystick private */
132 int joyfd;
133 enum wine_joystick_linuxinput_fd_state joyfd_state;
134
135 int dev_axes_to_di[ABS_MAX];
136 POINTL povs[4];
137
138 /* LUT for KEY_ to offset in rgbButtons */
139 BYTE buttons[KEY_MAX];
140
141 /* Force feedback variables */
142 struct list ff_effects;
143 int ff_state;
144 int ff_autocenter;
145 int ff_gain;
146};
147
148static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
149{
150 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
151 JoystickGenericImpl, base), JoystickImpl, generic);
152}
153static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
154{
155 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
156 JoystickGenericImpl, base), JoystickImpl, generic);
157}
158
159static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
160{
161 return &This->generic.base.IDirectInputDevice8W_iface;
162}
163
164static void fake_current_js_state(JoystickImpl *ji);
165static void find_joydevs(void);
166static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
167
168/* This GUID is slightly different from the linux joystick one. Take note. */
169static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a-23903fb6bdf7 */
170 0x9e573eda,
171 0x7734,
172 0x11d2,
173 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
174};
175
176#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
177
178#define MAX_JOYDEV 64
179
180static int have_joydevs = -1;
181static struct JoyDev *joydevs = NULL;
182
183static void find_joydevs(void)
184{
185 int i;
186
187 if (InterlockedCompareExchange(&have_joydevs, 0, -1) != -1)
188 /* Someone beat us to it */
189 return;
190
191 for (i = 0; i < MAX_JOYDEV; i++)
192 {
193 char buf[MAX_PATH];
194 struct JoyDev joydev = {0};
195 int fd;
196 BOOL no_ff_check = FALSE;
197 int j;
198 struct JoyDev *new_joydevs;
199 struct input_id device_id = {0};
200
201 snprintf(buf, sizeof(buf), EVDEVPREFIX"%d", i);
202
203 if ((fd = open(buf, O_RDWR)) == -1)
204 {
205 fd = open(buf, O_RDONLY);
206 no_ff_check = TRUE;
207 }
208
209 if (fd == -1)
210 continue;
211
212 if (ioctl(fd, EVIOCGBIT(0, sizeof(joydev.evbits)), joydev.evbits) == -1)
213 {
214 WARN("ioctl(EVIOCGBIT, 0) failed: %d %s\n", errno, strerror(errno));
215 close(fd);
216 continue;
217 }
218 if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(joydev.absbits)), joydev.absbits) == -1)
219 {
220 WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno, strerror(errno));
221 close(fd);
222 continue;
223 }
224 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(joydev.keybits)), joydev.keybits) == -1)
225 {
226 WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno, strerror(errno));
227 close(fd);
228 continue;
229 }
230
231 /* A true joystick has at least axis X and Y, and at least 1
232 * button. copied from linux/drivers/input/joydev.c */
233 if (((!test_bit(joydev.absbits, ABS_X) || !test_bit(joydev.absbits, ABS_Y)) &&
234 !test_bit(joydev.absbits, ABS_WHEEL) &&
235 !test_bit(joydev.absbits, ABS_GAS) &&
236 !test_bit(joydev.absbits, ABS_BRAKE)) ||
237 !(test_bit(joydev.keybits, BTN_TRIGGER) ||
238 test_bit(joydev.keybits, BTN_A) ||
239 test_bit(joydev.keybits, BTN_1) ||
240 test_bit(joydev.keybits, BTN_BASE) ||
241 test_bit(joydev.keybits, BTN_GEAR_UP) ||
242 test_bit(joydev.keybits, BTN_GEAR_DOWN)))
243 {
244 close(fd);
245 continue;
246 }
247
248 /* in lieu of properly reporting HID usage, detect presence of
249 * "joystick buttons" and report those devices as joysticks instead of
250 * gamepads */
251 joydev.is_joystick =
252 test_bit(joydev.keybits, BTN_TRIGGER) ||
253 test_bit(joydev.keybits, BTN_THUMB) ||
254 test_bit(joydev.keybits, BTN_THUMB2) ||
255 test_bit(joydev.keybits, BTN_TOP) ||
256 test_bit(joydev.keybits, BTN_TOP2) ||
257 test_bit(joydev.keybits, BTN_PINKIE) ||
258 test_bit(joydev.keybits, BTN_BASE) ||
259 test_bit(joydev.keybits, BTN_BASE2) ||
260 test_bit(joydev.keybits, BTN_BASE3) ||
261 test_bit(joydev.keybits, BTN_BASE4) ||
262 test_bit(joydev.keybits, BTN_BASE5) ||
263 test_bit(joydev.keybits, BTN_BASE6) ||
264 test_bit(joydev.keybits, BTN_GEAR_UP) ||
265 test_bit(joydev.keybits, BTN_GEAR_DOWN) ||
266 test_bit(joydev.keybits, BTN_DEAD);
267
268 if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1)))
269 {
270 close(fd);
271 continue;
272 }
273 strcpy(joydev.device, buf);
274
275 buf[MAX_PATH - 1] = 0;
276 if (ioctl(fd, EVIOCGNAME(MAX_PATH - 1), buf) != -1 &&
277 (joydev.name = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + strlen(EVDEVDRIVER) + 1)))
278 {
279 strcpy(joydev.name, buf);
280 /* Append driver name */
281 strcat(joydev.name, EVDEVDRIVER);
282 }
283 else
284 joydev.name = joydev.device;
285
286 if (device_disabled_registry(joydev.name)) {
287 close(fd);
288 HeapFree(GetProcessHeap(), 0, joydev.name);
289 if (joydev.name != joydev.device)
290 HeapFree(GetProcessHeap(), 0, joydev.device);
291 continue;
292 }
293
294 joydev.guid = DInput_Wine_Joystick_Base_GUID;
295 joydev.guid.Data3 += have_joydevs;
296
297 TRACE("Found a joystick on %s: %s (%s)\n",
298 joydev.device, joydev.name,
299 debugstr_guid(&joydev.guid)
300 );
301
302#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
303 if (!no_ff_check &&
304 test_bit(joydev.evbits, EV_FF) &&
305 ioctl(fd, EVIOCGBIT(EV_FF, sizeof(joydev.ffbits)), joydev.ffbits) != -1 &&
306 ioctl(fd, EVIOCGEFFECTS, &joydev.num_effects) != -1 &&
307 joydev.num_effects > 0)
308 {
309 TRACE(" ... with force feedback\n");
310 joydev.has_ff = TRUE;
311 }
312#endif
313
314 for (j = 0; j < ABS_MAX;j ++)
315 {
316 if (!test_bit(joydev.absbits, j)) continue;
317 if (ioctl(fd, EVIOCGABS(j), &(joydev.axes[j])) != -1)
318 {
319 TRACE(" ... with axis %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n",
320 j,
321 joydev.axes[j].value,
322 joydev.axes[j].minimum,
323 joydev.axes[j].maximum,
324 joydev.axes[j].fuzz,
325 joydev.axes[j].flat
326 );
327 }
328 }
329
330 if (ioctl(fd, EVIOCGID, &device_id) == -1)
331 {
332 WARN("ioctl(EVIOCGID) failed: %d %s\n", errno, strerror(errno));
333 joydev.guid_product = DInput_Wine_Joystick_Base_GUID;
334 }
335 else
336 {
337 joydev.vendor_id = device_id.vendor;
338 joydev.product_id = device_id.product;
339 joydev.bus_type = device_id.bustype;
340
341 /* Concatenate product_id with vendor_id to mimic Windows behaviour */
342 joydev.guid_product = DInput_PIDVID_Product_GUID;
343 joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id);
344 }
345
346 if (!have_joydevs)
347 new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev));
348 else
349 new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joydevs, (1 + have_joydevs) * sizeof(struct JoyDev));
350
351 if (!new_joydevs)
352 {
353 close(fd);
354 continue;
355 }
356 joydevs = new_joydevs;
357 joydevs[have_joydevs] = joydev;
358 have_joydevs++;
359
360 close(fd);
361 }
362}
363
364static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
365{
366 DWORD dwSize = lpddi->dwSize;
367
368 TRACE("%d %p\n", dwSize, lpddi);
369 memset(lpddi, 0, dwSize);
370
371 lpddi->dwSize = dwSize;
372 lpddi->guidInstance = joydevs[id].guid;
373 lpddi->guidProduct = joydevs[id].guid_product;
374 lpddi->guidFFDriver = GUID_NULL;
375 lpddi->dwDevType = get_device_type(version, joydevs[id].is_joystick);
376
377 /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */
378 if (joydevs[id].bus_type == BUS_USB &&
379 joydevs[id].vendor_id && joydevs[id].product_id)
380 {
381 lpddi->dwDevType |= DIDEVTYPE_HID;
382 lpddi->wUsagePage = 0x01; /* Desktop */
383 if (joydevs[id].is_joystick)
384 lpddi->wUsage = 0x04; /* Joystick */
385 else
386 lpddi->wUsage = 0x05; /* Game Pad */
387 }
388
389 MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
390 MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszProductName, MAX_PATH);
391}
392
393static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
394{
395 DIDEVICEINSTANCEW lpddiW;
396 DWORD dwSize = lpddi->dwSize;
397
398 lpddiW.dwSize = sizeof(lpddiW);
399 fill_joystick_dideviceinstanceW(&lpddiW, version, id);
400
401 TRACE("%d %p\n", dwSize, lpddi);
402 memset(lpddi, 0, dwSize);
403
404 /* Convert W->A */
405 lpddi->dwSize = dwSize;
406 lpddi->guidInstance = lpddiW.guidInstance;
407 lpddi->guidProduct = lpddiW.guidProduct;
408 lpddi->dwDevType = lpddiW.dwDevType;
409 lstrcpynA(lpddi->tszInstanceName, joydevs[id].name, MAX_PATH);
410 lstrcpynA(lpddi->tszProductName, joydevs[id].name, MAX_PATH);
411 lpddi->guidFFDriver = lpddiW.guidFFDriver;
412 lpddi->wUsagePage = lpddiW.wUsagePage;
413 lpddi->wUsage = lpddiW.wUsage;
414}
415
416static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
417{
418 find_joydevs();
419
420 if (id >= have_joydevs) {
421 return E_FAIL;
422 }
423
424 if (!((dwDevType == 0) ||
425 ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
426 (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
427 return S_FALSE;
428
429#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
431 return S_FALSE;
432#endif
433
434 if (!(dwFlags & DIEDFL_FORCEFEEDBACK) || joydevs[id].has_ff) {
435 fill_joystick_dideviceinstanceA(lpddi, version, id);
436 return S_OK;
437 }
438 return S_FALSE;
439}
440
441static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
442{
443 find_joydevs();
444
445 if (id >= have_joydevs) {
446 return E_FAIL;
447 }
448
449 if (!((dwDevType == 0) ||
450 ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
451 (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
452 return S_FALSE;
453
454#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
456 return S_FALSE;
457#endif
458
459 if (!(dwFlags & DIEDFL_FORCEFEEDBACK) || joydevs[id].has_ff) {
460 fill_joystick_dideviceinstanceW(lpddi, version, id);
461 return S_OK;
462 }
463 return S_FALSE;
464}
465
466static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsigned short index)
467{
468 JoystickImpl* newDevice;
469 LPDIDATAFORMAT df = NULL;
470 int i, idx = 0;
471 int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2];
473
474 newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl));
475 if (!newDevice) return NULL;
476
477 newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
478 newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
479 newDevice->generic.base.ref = 1;
480 newDevice->generic.base.guid = *rguid;
481 newDevice->generic.base.dinput = dinput;
482 newDevice->generic.joy_polldev = joy_polldev;
483 newDevice->joyfd = -1;
484 newDevice->joyfd_state = WINE_FD_STATE_CLOSED;
485 newDevice->joydev = &joydevs[index];
486 newDevice->generic.name = newDevice->joydev->name;
487 list_init(&newDevice->ff_effects);
488#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
489 newDevice->ff_state = FF_STATUS_STOPPED;
490#endif
491 /* There is no way in linux to query force feedback autocenter status.
492 Instead, track it with ff_autocenter, and assume it's initially
493 enabled. */
494 newDevice->ff_autocenter = 1;
495 newDevice->ff_gain = 0xFFFF;
496 InitializeCriticalSection(&newDevice->generic.base.crit);
497 newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
498
499 /* Count number of available axes - supported Axis & POVs */
500 for (i = 0; i < ABS_MAX; i++)
501 {
502 if (idx < WINE_JOYSTICK_MAX_AXES &&
503 i < ABS_HAT0X &&
504 test_bit(newDevice->joydev->absbits, i))
505 {
506 newDevice->generic.device_axis_count++;
507 newDevice->dev_axes_to_di[i] = idx;
508 newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum;
509 newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum;
510 if (i >= 8 && i <= 10) /* If it's a wheel axis... */
511 default_axis_map[idx] = i - 8; /* ... remap to X/Y/Z */
512 else
513 default_axis_map[idx] = i;
514 idx++;
515 }
516 else
517 newDevice->dev_axes_to_di[i] = -1;
518 }
519
520 for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
521 {
522 if (test_bit(newDevice->joydev->absbits, ABS_HAT0X + i * 2) &&
523 test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2))
524 {
525 newDevice->generic.device_axis_count += 2;
526 newDevice->generic.props[idx ].lDevMin = newDevice->joydev->axes[ABS_HAT0X + i * 2].minimum;
527 newDevice->generic.props[idx ].lDevMax = newDevice->joydev->axes[ABS_HAT0X + i * 2].maximum;
528 newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = idx;
529 newDevice->generic.props[idx+1].lDevMin = newDevice->joydev->axes[ABS_HAT0Y + i * 2].minimum;
530 newDevice->generic.props[idx+1].lDevMax = newDevice->joydev->axes[ABS_HAT0Y + i * 2].maximum;
531 newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = idx + 1;
532
533 default_axis_map[idx] = default_axis_map[idx + 1] = WINE_JOYSTICK_MAX_AXES + i;
534 idx += 2;
535 }
536 else
537 newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
538 }
539
540 /* do any user specified configuration */
541 if (setup_dinput_options(&newDevice->generic, default_axis_map) != DI_OK) goto failed;
542
543 /* Create copy of default data format */
544 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
546 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
547
548
549 /* Construct internal data format */
550
551 /* Supported Axis & POVs */
552 for (i = 0, idx = 0; i < newDevice->generic.device_axis_count; i++)
553 {
554 int wine_obj = newDevice->generic.axis_map[i];
555
556 if (wine_obj < 0) continue;
557
558 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
559 if (wine_obj < 8)
561 else
562 {
563 df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
564 i++; /* POV takes 2 axes */
565 }
566
567 newDevice->generic.props[idx].lMin = 0;
568 newDevice->generic.props[idx].lMax = 0xffff;
569 newDevice->generic.props[idx].lSaturation = 0;
570 newDevice->generic.props[idx].lDeadZone = newDevice->generic.deadzone;
571
572 /* Linux supports force-feedback on X & Y axes only */
573 if (newDevice->joydev->has_ff && (i == 0 || i == 1))
575
576 idx++;
577 }
578
579 /* Buttons can be anywhere, so check all */
580 for (i = 0; i < KEY_MAX && newDevice->generic.devcaps.dwButtons < WINE_JOYSTICK_MAX_BUTTONS; i++)
581 {
582 if (!test_bit(newDevice->joydev->keybits, i)) continue;
583
584 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[newDevice->generic.devcaps.dwButtons + 12], df->dwObjSize);
585 newDevice->buttons[i] = 0x80 | newDevice->generic.devcaps.dwButtons;
586 df->rgodf[idx ].pguid = &GUID_Button;
587 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(newDevice->generic.devcaps.dwButtons++) | DIDFT_PSHBUTTON;
588 }
589 df->dwNumObjs = idx;
590 newDevice->generic.base.data_format.wine_df = df;
591
592 fake_current_js_state(newDevice);
593
594 /* Fill the caps */
595 newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
596 newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
597
598 ddi.dwSize = sizeof(ddi);
599 fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index);
600 newDevice->generic.devcaps.dwDevType = ddi.dwDevType;
601
602 if (newDevice->joydev->has_ff)
603 newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
604
605 IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
606
607 EnterCriticalSection(&dinput->crit);
608 list_add_tail(&dinput->devices_list, &newDevice->generic.base.entry);
609 LeaveCriticalSection(&dinput->crit);
610
611 return newDevice;
612
613failed:
614 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
615 HeapFree(GetProcessHeap(), 0, df);
616 HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map);
617 HeapFree(GetProcessHeap(), 0, newDevice);
618 return NULL;
619}
620
621/******************************************************************************
622 * get_joystick_index : Get the joystick index from a given GUID
623 */
624static unsigned short get_joystick_index(REFGUID guid)
625{
626 GUID wine_joystick = DInput_Wine_Joystick_Base_GUID;
627 GUID dev_guid = *guid;
628
629 wine_joystick.Data3 = 0;
630 dev_guid.Data3 = 0;
631
632 /* for the standard joystick GUID use index 0 */
633 if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
634
635 /* for the wine joystick GUIDs use the index stored in Data3 */
636 if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3 - DInput_Wine_Joystick_Base_GUID.Data3;
637
638 return MAX_JOYDEV;
639}
640
641static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
642{
643 unsigned short index;
644
645 TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
646 find_joydevs();
647 *pdev = NULL;
648
649 if ((index = get_joystick_index(rguid)) < MAX_JOYDEV &&
650 have_joydevs && index < have_joydevs)
651 {
652 JoystickImpl *This;
653
654 if (riid == NULL)
655 ;/* nothing */
656 else if (IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
657 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
658 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
659 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
660 {
661 unicode = 0;
662 }
663 else if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) ||
664 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
665 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
666 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
667 {
668 unicode = 1;
669 }
670 else
671 {
672 WARN("no interface\n");
673 return DIERR_NOINTERFACE;
674 }
675
676 This = alloc_device(rguid, dinput, index);
677 TRACE("Created a Joystick device (%p)\n", This);
678
679 if (!This) return DIERR_OUTOFMEMORY;
680
681 if (unicode)
682 *pdev = &This->generic.base.IDirectInputDevice8W_iface;
683 else
684 *pdev = &This->generic.base.IDirectInputDevice8A_iface;
685
686 return DI_OK;
687 }
688
689 return DIERR_DEVICENOTREG;
690}
691
692static int joydev_open_evdev(JoystickImpl *This)
693{
694 int fd;
695
696 if ((fd = open(This->joydev->device, O_RDWR)) == -1)
697 {
698 if ((fd = open(This->joydev->device, O_RDONLY)) == -1)
699 {
700 /* Couldn't open the device at all */
701 }
702 else
703 {
704 /* Couldn't open in r/w but opened in read-only. */
705 WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device);
706 }
707 }
708 else
709 {
710 struct input_event event;
711
712 event.type = EV_FF;
713 event.code = FF_GAIN;
714 event.value = This->ff_gain;
715 if (write(fd, &event, sizeof(event)) == -1)
716 ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno));
717 if (!This->ff_autocenter)
718 {
719 /* Disable autocenter. */
720 event.code = FF_AUTOCENTER;
721 event.value = 0;
722 if (write(fd, &event, sizeof(event)) == -1)
723 ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno));
724 }
725 }
726
727 return fd;
728}
729
730
732 "Wine Linux-input joystick driver",
733 joydev_enum_deviceA,
734 joydev_enum_deviceW,
735 joydev_create_device
736};
737
738/******************************************************************************
739 * Acquire : gets exclusive control of the joystick
740 */
741static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
742{
743 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
744 HRESULT res;
745
746 TRACE("(this=%p)\n",This);
747
749 {
750 WARN("Failed to acquire: %x\n", res);
751 return res;
752 }
753
754 if ((This->joyfd = joydev_open_evdev(This)) == -1)
755 {
756 ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno));
758 return DIERR_NOTFOUND;
759 }
760
761 This->joyfd_state = WINE_FD_STATE_OK;
762 return DI_OK;
763}
764
765static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
766{
767 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
768 return JoystickWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
769}
770
771/******************************************************************************
772 * Unacquire : frees the joystick
773 */
774static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
775{
776 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
777 HRESULT res;
778
779 TRACE("(this=%p)\n",This);
781 if (res==DI_OK && This->joyfd!=-1) {
782 struct input_event event;
783
784 /* Stop and unload all effects */
785 JoystickWImpl_SendForceFeedbackCommand(iface, DISFFC_RESET);
786
787 /* Enable autocenter. */
788 event.type = EV_FF;
789 event.code = FF_AUTOCENTER;
790 /* TODO: Read autocenter strength before disabling it, and use it here
791 * instead of 0xFFFF (maximum strength).
792 */
793 event.value = 0xFFFF;
794 if (write(This->joyfd, &event, sizeof(event)) == -1)
795 ERR("Failed to set autocenter to %04x: %d %s\n", event.value, errno, strerror(errno));
796
797 close(This->joyfd);
798 This->joyfd = -1;
799 This->joyfd_state = WINE_FD_STATE_CLOSED;
800 }
801 return res;
802}
803
804static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
805{
806 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
807 return JoystickWImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
808}
809
810/*
811 * set the current state of the js device as it would be with the middle
812 * values on the axes
813 */
814#define CENTER_AXIS(a) \
815 (ji->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis( &ji->generic.props[ji->dev_axes_to_di[a]], \
816 ji->joydev->axes[a].value ))
817static void fake_current_js_state(JoystickImpl *ji)
818{
819 int i;
820
821 /* center the axes */
822 ji->generic.js.lX = CENTER_AXIS(ABS_X);
823 ji->generic.js.lY = CENTER_AXIS(ABS_Y);
824 ji->generic.js.lZ = CENTER_AXIS(ABS_Z);
825 ji->generic.js.lRx = CENTER_AXIS(ABS_RX);
826 ji->generic.js.lRy = CENTER_AXIS(ABS_RY);
827 ji->generic.js.lRz = CENTER_AXIS(ABS_RZ);
828 ji->generic.js.rglSlider[0] = CENTER_AXIS(ABS_THROTTLE);
829 ji->generic.js.rglSlider[1] = CENTER_AXIS(ABS_RUDDER);
830
831 /* POV center is -1 */
832 for (i = 0; i < 4; i++)
833 ji->generic.js.rgdwPOV[i] = -1;
834}
835#undef CENTER_AXIS
836
837/* convert wine format offset to user format object index */
838static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
839{
840 struct pollfd plfd;
841 struct input_event ie;
842 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
843
844 if (This->joyfd == -1)
845 {
846 int fd;
847 char namebuf[MAX_PATH + 8]; /* 8 == strlen(EVDEVDRIVER) */
848
849 if (This->joyfd_state != WINE_FD_STATE_DISCONNECTED)
850 return;
851 /* Try to reconnect to the device. */
852 fd = joydev_open_evdev(This);
853 if (fd == -1)
854 return;
855 namebuf[sizeof(namebuf) - strlen(EVDEVDRIVER) - 1] = 0;
856 if (ioctl(fd, EVIOCGNAME(sizeof(namebuf) - strlen(EVDEVDRIVER) - 1), namebuf) == -1)
857 {
858 /* Couldn't get the name; assume it's a different device. */
859 ERR("EVIOCGNAME(%s) failed: %d %s", This->joydev->device, errno, strerror(errno));
860 This->joyfd_state = WINE_FD_STATE_INVALID;
861 return;
862 }
863 strcat(namebuf, EVDEVDRIVER); /* Guaranteed to be safe. */
864 if (strcmp(namebuf, This->joydev->name) != 0)
865 {
866 ERR("Device %s changed from \"%s\" to \"%s\"! Can't reconnect.\n", This->joydev->device, This->joydev->name, namebuf);
867 This->joyfd_state = WINE_FD_STATE_INVALID;
868 return;
869 }
870 if (InterlockedCompareExchange(&This->joyfd, fd, -1) == -1)
871 {
872 This->joyfd_state = WINE_FD_STATE_OK;
873 TRACE("Reconnected to \"%s\" on %s", This->joydev->name, This->joydev->device);
874 }
875 else
876 {
877 /* Somebody beat us to it! Throw away our fd and use theirs. */
878 close(fd);
879 }
880 }
881
882 while (1)
883 {
884 LONG value = 0;
885 int inst_id = -1;
886 int result;
887
888 plfd.fd = This->joyfd;
889 plfd.events = POLLIN;
890
891 result = poll(&plfd,1,0);
892 if (result != 1)
893 {
894 if (result == -1)
895 {
896 ERR("poll failed: %d %s\n", errno, strerror(errno));
897 close(This->joyfd);
898 This->joyfd = -1;
899 This->joyfd_state = WINE_FD_STATE_DISCONNECTED;
900 }
901 return;
902 }
903
904 /* we have one event, so we can read */
905 result = read(This->joyfd,&ie,sizeof(ie));
906 if (result != sizeof(ie))
907 {
908 if (result == -1)
909 {
910 ERR("read failed: %d %s\n", errno, strerror(errno));
911 close(This->joyfd);
912 This->joyfd = -1;
913 This->joyfd_state = WINE_FD_STATE_DISCONNECTED;
914 }
915 return;
916 }
917
918 TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value);
919 switch (ie.type) {
920 case EV_KEY: /* button */
921 {
922 int btn = This->buttons[ie.code];
923
924 TRACE("(%p) %d -> %d\n", This, ie.code, btn);
925 if (btn & 0x80)
926 {
927 btn &= 0x7F;
928 btn = This->generic.button_map[btn];
929
930 inst_id = DIDFT_MAKEINSTANCE(btn) | DIDFT_PSHBUTTON;
931 This->generic.js.rgbButtons[btn] = value = ie.value ? 0x80 : 0x00;
932 }
933 break;
934 }
935 case EV_ABS:
936 {
937 int axis = This->dev_axes_to_di[ie.code];
938
939 /* User axis remapping */
940 if (axis < 0) break;
941 axis = This->generic.axis_map[axis];
942 if (axis < 0) break;
943
944 inst_id = axis < 8 ? DIDFT_MAKEINSTANCE(axis) | DIDFT_ABSAXIS :
945 DIDFT_MAKEINSTANCE(axis - 8) | DIDFT_POV;
946 value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], ie.value);
947
948 switch (axis) {
949 case 0: This->generic.js.lX = value; break;
950 case 1: This->generic.js.lY = value; break;
951 case 2: This->generic.js.lZ = value; break;
952 case 3: This->generic.js.lRx = value; break;
953 case 4: This->generic.js.lRy = value; break;
954 case 5: This->generic.js.lRz = value; break;
955 case 6: This->generic.js.rglSlider[0] = value; break;
956 case 7: This->generic.js.rglSlider[1] = value; break;
957 case 8: case 9: case 10: case 11:
958 {
959 int idx = axis - 8;
960
961 if (ie.code % 2)
962 This->povs[idx].y = ie.value;
963 else
964 This->povs[idx].x = ie.value;
965
966 This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
967 break;
968 }
969 default:
970 FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
971 }
972 break;
973 }
974#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
975 case EV_FF_STATUS:
976 This->ff_state = ie.value;
977 break;
978#endif
979#ifdef EV_SYN
980 case EV_SYN:
981 /* there is nothing to do */
982 break;
983#endif
984#ifdef EV_MSC
985 case EV_MSC:
986 /* Ignore */
987 break;
988#endif
989 default:
990 TRACE("skipping event\n");
991 break;
992 }
993 if (inst_id >= 0)
994 queue_event(iface, inst_id,
995 value, GetCurrentTime(), This->generic.base.dinput->evsequence++);
996 }
997}
998
999/******************************************************************************
1000 * SetProperty : change input device properties
1001 */
1002static HRESULT WINAPI JoystickWImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph)
1003{
1004 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
1005
1006 if (!ph) {
1007 WARN("invalid argument\n");
1008 return DIERR_INVALIDPARAM;
1009 }
1010
1011 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1012 TRACE("ph.dwSize = %d, ph.dwHeaderSize =%d, ph.dwObj = %d, ph.dwHow= %d\n",
1013 ph->dwSize, ph->dwHeaderSize, ph->dwObj, ph->dwHow);
1014
1015 if (IS_DIPROP(rguid)) {
1016 switch (LOWORD(rguid)) {
1019
1020 TRACE("autocenter(%d)\n", pd->dwData);
1021 This->ff_autocenter = pd->dwData == DIPROPAUTOCENTER_ON;
1022
1023 break;
1024 }
1025 case (DWORD_PTR)DIPROP_FFGAIN: {
1027
1028 TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData);
1029 This->ff_gain = MulDiv(pd->dwData, 0xFFFF, 10000);
1030 if (This->generic.base.acquired) {
1031 /* Update immediately. */
1032 struct input_event event;
1033
1034 event.type = EV_FF;
1035 event.code = FF_GAIN;
1036 event.value = This->ff_gain;
1037 if (write(This->joyfd, &event, sizeof(event)) == -1)
1038 ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno));
1039 }
1040 break;
1041 }
1042 default:
1043 return JoystickWGenericImpl_SetProperty(iface, rguid, ph);
1044 }
1045 }
1046 return DI_OK;
1047}
1048
1049static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER ph)
1050{
1051 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1052 return JoystickWImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, ph);
1053}
1054
1055/******************************************************************************
1056 * GetProperty : get input device properties
1057 */
1058static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
1059{
1060 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
1061
1062 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
1063 _dump_DIPROPHEADER(pdiph);
1064
1065 if (!IS_DIPROP(rguid)) return DI_OK;
1066
1067 switch (LOWORD(rguid)) {
1069 {
1070 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1071
1072 pd->dwData = This->ff_autocenter ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF;
1073 TRACE("autocenter(%d)\n", pd->dwData);
1074 break;
1075 }
1076 case (DWORD_PTR) DIPROP_FFGAIN:
1077 {
1078 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1079
1080 pd->dwData = MulDiv(This->ff_gain, 10000, 0xFFFF);
1081 TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData);
1082 break;
1083 }
1084
1085 case (DWORD_PTR) DIPROP_VIDPID:
1086 {
1087 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1088
1089 if (!This->joydev->product_id || !This->joydev->vendor_id)
1090 return DIERR_UNSUPPORTED;
1091 pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id);
1092 TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData);
1093 break;
1094 }
1095
1097 {
1098 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1099
1100 pd->dwData = get_joystick_index(&This->generic.base.guid);
1101 TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
1102 break;
1103 }
1104
1106 {
1107 static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
1108 'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0};
1109 static const WCHAR miW[] = {'m','i',0};
1110 static const WCHAR igW[] = {'i','g',0};
1111
1112 BOOL is_gamepad;
1114 WORD vid = This->joydev->vendor_id;
1115 WORD pid = This->joydev->product_id;
1116
1117 if (!pid || !vid)
1118 return DIERR_UNSUPPORTED;
1119
1120 is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
1121 pd->guidClass = GUID_DEVCLASS_HIDCLASS;
1122 sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid));
1123
1124 TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
1125 break;
1126 }
1127
1128 default:
1129 return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
1130 }
1131
1132 return DI_OK;
1133}
1134
1135static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
1136{
1137 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1138 return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
1139}
1140
1141/******************************************************************************
1142 * CreateEffect - Create a new FF effect with the specified params
1143 */
1144static HRESULT WINAPI JoystickWImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid,
1145 LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef,
1146 LPUNKNOWN pUnkOuter)
1147{
1148#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1149 effect_list_item* new_effect = NULL;
1150 HRESULT retval = DI_OK;
1151#endif
1152
1153 JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
1154 TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
1155
1156 *ppdef = NULL;
1157 if (!This->joydev->has_ff)
1158 {
1159 TRACE("No force feedback support\n");
1160 return DIERR_UNSUPPORTED;
1161 }
1162
1163#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
1164 TRACE("not available (compiled w/o force feedback support)\n");
1165 return DIERR_UNSUPPORTED;
1166#else
1167
1168 if (!(new_effect = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_effect))))
1169 return DIERR_OUTOFMEMORY;
1170
1171 retval = linuxinput_create_effect(&This->joyfd, rguid, &new_effect->entry, &new_effect->ref);
1172 if (retval != DI_OK)
1173 {
1174 HeapFree(GetProcessHeap(), 0, new_effect);
1175 return retval;
1176 }
1177
1178 if (lpeff != NULL)
1179 {
1180 retval = IDirectInputEffect_SetParameters(new_effect->ref, lpeff, 0);
1181
1182 if (retval != DI_OK && retval != DI_DOWNLOADSKIPPED)
1183 {
1184 HeapFree(GetProcessHeap(), 0, new_effect);
1185 return retval;
1186 }
1187 }
1188
1189 list_add_tail(&This->ff_effects, &new_effect->entry);
1190 *ppdef = new_effect->ref;
1191
1192 if (pUnkOuter != NULL)
1193 FIXME("Interface aggregation not implemented.\n");
1194
1195 return DI_OK;
1196
1197#endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */
1198}
1199
1200static HRESULT WINAPI JoystickAImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid,
1201 LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef,
1202 LPUNKNOWN pUnkOuter)
1203{
1204 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1205 return JoystickWImpl_CreateEffect(IDirectInputDevice8W_from_impl(This), rguid, lpeff, ppdef, pUnkOuter);
1206}
1207
1208/*******************************************************************************
1209 * EnumEffects - Enumerate available FF effects
1210 */
1211static HRESULT WINAPI JoystickAImpl_EnumEffects(LPDIRECTINPUTDEVICE8A iface,
1212 LPDIENUMEFFECTSCALLBACKA lpCallback,
1213 LPVOID pvRef,
1214 DWORD dwEffType)
1215{
1216#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1217 DIEFFECTINFOA dei; /* feif */
1218 DWORD type = DIEFT_GETTYPE(dwEffType);
1219 JoystickImpl* This = impl_from_IDirectInputDevice8A(iface);
1220
1221 TRACE("(this=%p,%p,%d) type=%d\n", This, pvRef, dwEffType, type);
1222
1223 dei.dwSize = sizeof(DIEFFECTINFOA);
1224
1225 if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
1226 && test_bit(This->joydev->ffbits, FF_CONSTANT)) {
1227 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce);
1228 (*lpCallback)(&dei, pvRef);
1229 }
1230
1231 if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)
1232 && test_bit(This->joydev->ffbits, FF_PERIODIC)) {
1233 if (test_bit(This->joydev->ffbits, FF_SQUARE)) {
1234 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square);
1235 (*lpCallback)(&dei, pvRef);
1236 }
1237 if (test_bit(This->joydev->ffbits, FF_SINE)) {
1238 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine);
1239 (*lpCallback)(&dei, pvRef);
1240 }
1241 if (test_bit(This->joydev->ffbits, FF_TRIANGLE)) {
1242 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle);
1243 (*lpCallback)(&dei, pvRef);
1244 }
1245 if (test_bit(This->joydev->ffbits, FF_SAW_UP)) {
1246 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp);
1247 (*lpCallback)(&dei, pvRef);
1248 }
1249 if (test_bit(This->joydev->ffbits, FF_SAW_DOWN)) {
1250 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown);
1251 (*lpCallback)(&dei, pvRef);
1252 }
1253 }
1254
1255 if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
1256 && test_bit(This->joydev->ffbits, FF_RAMP)) {
1257 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce);
1258 (*lpCallback)(&dei, pvRef);
1259 }
1260
1261 if (type == DIEFT_ALL || type == DIEFT_CONDITION) {
1262 if (test_bit(This->joydev->ffbits, FF_SPRING)) {
1263 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring);
1264 (*lpCallback)(&dei, pvRef);
1265 }
1266 if (test_bit(This->joydev->ffbits, FF_DAMPER)) {
1267 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper);
1268 (*lpCallback)(&dei, pvRef);
1269 }
1270 if (test_bit(This->joydev->ffbits, FF_INERTIA)) {
1271 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia);
1272 (*lpCallback)(&dei, pvRef);
1273 }
1274 if (test_bit(This->joydev->ffbits, FF_FRICTION)) {
1275 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction);
1276 (*lpCallback)(&dei, pvRef);
1277 }
1278 }
1279
1280#endif
1281
1282 return DI_OK;
1283}
1284
1285static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface,
1286 LPDIENUMEFFECTSCALLBACKW lpCallback,
1287 LPVOID pvRef,
1288 DWORD dwEffType)
1289{
1290#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1291 /* seems silly to duplicate all this code but all the structures and functions
1292 * are actually different (A/W) */
1293 DIEFFECTINFOW dei; /* feif */
1294 DWORD type = DIEFT_GETTYPE(dwEffType);
1295 JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
1296 int xfd = This->joyfd;
1297
1298 TRACE("(this=%p,%p,%d) type=%d fd=%d\n", This, pvRef, dwEffType, type, xfd);
1299
1300 dei.dwSize = sizeof(DIEFFECTINFOW);
1301
1302 if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
1303 && test_bit(This->joydev->ffbits, FF_CONSTANT)) {
1304 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce);
1305 (*lpCallback)(&dei, pvRef);
1306 }
1307
1308 if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)
1309 && test_bit(This->joydev->ffbits, FF_PERIODIC)) {
1310 if (test_bit(This->joydev->ffbits, FF_SQUARE)) {
1311 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square);
1312 (*lpCallback)(&dei, pvRef);
1313 }
1314 if (test_bit(This->joydev->ffbits, FF_SINE)) {
1315 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine);
1316 (*lpCallback)(&dei, pvRef);
1317 }
1318 if (test_bit(This->joydev->ffbits, FF_TRIANGLE)) {
1319 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle);
1320 (*lpCallback)(&dei, pvRef);
1321 }
1322 if (test_bit(This->joydev->ffbits, FF_SAW_UP)) {
1323 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp);
1324 (*lpCallback)(&dei, pvRef);
1325 }
1326 if (test_bit(This->joydev->ffbits, FF_SAW_DOWN)) {
1327 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown);
1328 (*lpCallback)(&dei, pvRef);
1329 }
1330 }
1331
1332 if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
1333 && test_bit(This->joydev->ffbits, FF_RAMP)) {
1334 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce);
1335 (*lpCallback)(&dei, pvRef);
1336 }
1337
1338 if (type == DIEFT_ALL || type == DIEFT_CONDITION) {
1339 if (test_bit(This->joydev->ffbits, FF_SPRING)) {
1340 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring);
1341 (*lpCallback)(&dei, pvRef);
1342 }
1343 if (test_bit(This->joydev->ffbits, FF_DAMPER)) {
1344 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper);
1345 (*lpCallback)(&dei, pvRef);
1346 }
1347 if (test_bit(This->joydev->ffbits, FF_INERTIA)) {
1348 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia);
1349 (*lpCallback)(&dei, pvRef);
1350 }
1351 if (test_bit(This->joydev->ffbits, FF_FRICTION)) {
1352 IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction);
1353 (*lpCallback)(&dei, pvRef);
1354 }
1355 }
1356
1357 /* return to unacquired state if that's where it was */
1358 if (xfd == -1)
1360#endif
1361
1362 return DI_OK;
1363}
1364
1365/*******************************************************************************
1366 * GetEffectInfo - Get information about a particular effect
1367 */
1368static HRESULT WINAPI JoystickAImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8A iface,
1369 LPDIEFFECTINFOA pdei,
1370 REFGUID guid)
1371{
1372 JoystickImpl* This = impl_from_IDirectInputDevice8A(iface);
1373
1374 TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid));
1375
1376#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1377 return linuxinput_get_info_A(This->joyfd, guid, pdei);
1378#else
1379 return DI_OK;
1380#endif
1381}
1382
1383static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface,
1384 LPDIEFFECTINFOW pdei,
1385 REFGUID guid)
1386{
1387 JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
1388
1389 TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid));
1390
1391#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1392 return linuxinput_get_info_W(This->joyfd, guid, pdei);
1393#else
1394 return DI_OK;
1395#endif
1396}
1397
1398/*******************************************************************************
1399 * GetForceFeedbackState - Get information about the device's FF state
1400 */
1401static HRESULT WINAPI JoystickWImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
1402{
1403 JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
1404
1405 TRACE("(this=%p,%p)\n", This, pdwOut);
1406
1407 (*pdwOut) = 0;
1408
1409#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1410 /* DIGFFS_STOPPED is the only mandatory flag to report */
1411 if (This->ff_state == FF_STATUS_STOPPED)
1412 (*pdwOut) |= DIGFFS_STOPPED;
1413#endif
1414
1415 return DI_OK;
1416}
1417
1418static HRESULT WINAPI JoystickAImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut)
1419{
1420 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1421 return JoystickWImpl_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), pdwOut);
1422}
1423
1424/*******************************************************************************
1425 * SendForceFeedbackCommand - Send a command to the device's FF system
1426 */
1427static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
1428{
1429 JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
1430 TRACE("(this=%p,%d)\n", This, dwFlags);
1431
1432#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
1433 switch (dwFlags)
1434 {
1435 case DISFFC_STOPALL:
1436 {
1437 effect_list_item *itr;
1438
1439 /* Stop all effects */
1440 LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
1442 break;
1443 }
1444
1445 case DISFFC_RESET:
1446 {
1447 effect_list_item *itr;
1448
1449 /* Stop and unload all effects. It is not true that effects are released */
1450 LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
1451 {
1454 }
1455 break;
1456 }
1457 case DISFFC_PAUSE:
1458 case DISFFC_CONTINUE:
1459 FIXME("No support for Pause or Continue in linux\n");
1460 break;
1461
1464 FIXME("No direct actuator control in linux\n");
1465 break;
1466
1467 default:
1468 WARN("Unknown Force Feedback Command %u!\n", dwFlags);
1469 return DIERR_INVALIDPARAM;
1470 }
1471 return DI_OK;
1472#else
1473 return DIERR_UNSUPPORTED;
1474#endif
1475}
1476
1477static HRESULT WINAPI JoystickAImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags)
1478{
1479 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1480 return JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), dwFlags);
1481}
1482
1483/*******************************************************************************
1484 * EnumCreatedEffectObjects - Enumerate all the effects that have been
1485 * created for this device.
1486 */
1487static HRESULT WINAPI JoystickWImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
1489 LPVOID pvRef, DWORD dwFlags)
1490{
1491 /* this function is safe to call on non-ff-enabled builds */
1492 JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
1493 effect_list_item *itr, *ptr;
1494
1495 TRACE("(this=%p,%p,%p,%d)\n", This, lpCallback, pvRef, dwFlags);
1496
1497 if (!lpCallback)
1498 return DIERR_INVALIDPARAM;
1499
1500 if (dwFlags != 0)
1501 FIXME("Flags specified, but no flags exist yet (DX9)!\n");
1502
1504 (*lpCallback)(itr->ref, pvRef);
1505
1506 return DI_OK;
1507}
1508
1509static HRESULT WINAPI JoystickAImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,
1511 LPVOID pvRef, DWORD dwFlags)
1512{
1513 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1514 return JoystickWImpl_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), lpCallback, pvRef, dwFlags);
1515}
1516
1517/******************************************************************************
1518 * GetDeviceInfo : get information about a device's identity
1519 */
1520static HRESULT WINAPI JoystickAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A iface,
1521 LPDIDEVICEINSTANCEA pdidi)
1522{
1523 JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
1524
1525 TRACE("(%p) %p\n", This, pdidi);
1526
1527 if (pdidi == NULL) return E_POINTER;
1528 if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
1529 (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)))
1530 return DIERR_INVALIDPARAM;
1531
1532 fill_joystick_dideviceinstanceA(pdidi, This->generic.base.dinput->dwVersion,
1533 get_joystick_index(&This->generic.base.guid));
1534 return DI_OK;
1535}
1536
1537static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface,
1538 LPDIDEVICEINSTANCEW pdidi)
1539{
1540 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
1541
1542 TRACE("(%p) %p\n", This, pdidi);
1543
1544 if (pdidi == NULL) return E_POINTER;
1545 if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
1546 (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)))
1547 return DIERR_INVALIDPARAM;
1548
1549 fill_joystick_dideviceinstanceW(pdidi, This->generic.base.dinput->dwVersion,
1550 get_joystick_index(&This->generic.base.guid));
1551 return DI_OK;
1552}
1553
1554static const IDirectInputDevice8AVtbl JoystickAvt =
1555{
1561 JoystickAImpl_GetProperty,
1562 JoystickAImpl_SetProperty,
1563 JoystickAImpl_Acquire,
1564 JoystickAImpl_Unacquire,
1571 JoystickAImpl_GetDeviceInfo,
1574 JoystickAImpl_CreateEffect,
1575 JoystickAImpl_EnumEffects,
1576 JoystickAImpl_GetEffectInfo,
1577 JoystickAImpl_GetForceFeedbackState,
1578 JoystickAImpl_SendForceFeedbackCommand,
1579 JoystickAImpl_EnumCreatedEffectObjects,
1588};
1589
1590static const IDirectInputDevice8WVtbl JoystickWvt =
1591{
1597 JoystickWImpl_GetProperty,
1598 JoystickWImpl_SetProperty,
1599 JoystickWImpl_Acquire,
1600 JoystickWImpl_Unacquire,
1607 JoystickWImpl_GetDeviceInfo,
1610 JoystickWImpl_CreateEffect,
1611 JoystickWImpl_EnumEffects,
1612 JoystickWImpl_GetEffectInfo,
1613 JoystickWImpl_GetForceFeedbackState,
1614 JoystickWImpl_SendForceFeedbackCommand,
1615 JoystickWImpl_EnumCreatedEffectObjects,
1624};
1625
1626#else /* HAS_PROPER_HEADER */
1627
1629 "Wine Linux-input joystick driver",
1630 NULL,
1631 NULL,
1632 NULL
1633};
1634
1635#endif /* HAS_PROPER_HEADER */
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define read
Definition: acwin.h:96
#define O_RDONLY
Definition: acwin.h:108
#define open
Definition: acwin.h:95
#define close
Definition: acwin.h:98
#define write
Definition: acwin.h:97
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:113
Definition: list.h:37
const DIDATAFORMAT c_dfDIJoystick2
Definition: data_formats.c:251
#define E_FAIL
Definition: ddrawi.h:102
DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN
Definition: joystick.c:1024
LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN
Definition: joystick.c:985
#define DIPROP_GUIDANDPATH
Definition: dinput.h:908
#define DIDOI_FFACTUATOR
Definition: dinput.h:817
#define IDirectInputDevice8_GetEffectInfo(p, a, b)
Definition: dinput.h:2056
struct DIPROPDWORD * LPDIPROPDWORD
#define DIEFT_CONDITION
Definition: dinput.h:996
#define IDirectInputEffect_Unload(p)
Definition: dinput.h:1519
#define DIDEVTYPE_JOYSTICK
Definition: dinput.h:200
#define DIERR_INVALIDPARAM
Definition: dinput.h:152
#define DIEFT_PERIODIC
Definition: dinput.h:995
#define DIERR_NOINTERFACE
Definition: dinput.h:153
#define DIDFT_POV
Definition: dinput.h:757
#define DIEFT_CONSTANTFORCE
Definition: dinput.h:993
BOOL(CALLBACK * LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID)
Definition: dinput.h:468
struct IDirectInputDevice8A * LPDIRECTINPUTDEVICE8A
Definition: dinput.h:105
#define DIDEVTYPE_HID
Definition: dinput.h:201
BOOL(CALLBACK * LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID)
Definition: dinput.h:1148
#define DIPROP_FFGAIN
Definition: dinput.h:895
#define DIPROP_AUTOCENTER
Definition: dinput.h:897
#define DIPROP_JOYSTICKID
Definition: dinput.h:912
#define DIDC_ATTACHED
Definition: dinput.h:945
#define DISFFC_PAUSE
Definition: dinput.h:972
#define DIDC_FORCEFEEDBACK
Definition: dinput.h:949
#define IDirectInput_AddRef(p)
Definition: dinput.h:2293
#define DIEFT_GETTYPE(n)
Definition: dinput.h:1006
BOOL(CALLBACK * LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID)
Definition: dinput.h:1149
#define DIEFT_RAMPFORCE
Definition: dinput.h:994
#define DIPROPAUTOCENTER_ON
Definition: dinput.h:900
#define DISFFC_RESET
Definition: dinput.h:970
#define DISFFC_SETACTUATORSON
Definition: dinput.h:974
#define IDirectInputEffect_SetParameters(p, a, b)
Definition: dinput.h:1514
#define DIERR_UNSUPPORTED
Definition: dinput.h:156
const DIPROPDWORD * LPCDIPROPDWORD
Definition: dinput.h:846
#define DISFFC_CONTINUE
Definition: dinput.h:973
#define DIERR_DEVICENOTREG
Definition: dinput.h:147
#define DIDFT_PSHBUTTON
Definition: dinput.h:754
#define DIDFT_ABSAXIS
Definition: dinput.h:752
#define IDirectInputEffect_Stop(p)
Definition: dinput.h:1516
#define DIERR_OUTOFMEMORY
Definition: dinput.h:155
#define DI_OK
Definition: dinput.h:128
#define DISFFC_SETACTUATORSOFF
Definition: dinput.h:975
#define DI_DOWNLOADSKIPPED
Definition: dinput.h:134
#define DISFFC_STOPALL
Definition: dinput.h:971
struct DIPROPGUIDANDPATH * LPDIPROPGUIDANDPATH
#define DIEDFL_FORCEFEEDBACK
Definition: dinput.h:192
#define DIEFT_ALL
Definition: dinput.h:991
struct IDirectInputEffect * LPDIRECTINPUTEFFECT
Definition: dinput.h:107
#define DIDFT_MAKEINSTANCE(n)
Definition: dinput.h:762
#define DIPROP_VIDPID
Definition: dinput.h:918
#define DIGFFS_STOPPED
Definition: dinput.h:978
#define DIPROPAUTOCENTER_OFF
Definition: dinput.h:899
#define DI8DEVTYPE_JOYSTICK
Definition: dinput.h:212
#define IDirectInputDevice8_Unacquire(p)
Definition: dinput.h:2043
#define DIERR_NOTFOUND
Definition: dinput.h:148
#define DI8DEVCLASS_GAMECTRL
Definition: dinput.h:207
struct IDirectInputDevice8W * LPDIRECTINPUTDEVICE8W
Definition: dinput.h:106
#define IS_DIPROP(x)
DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN
Definition: joystick.c:107
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
Definition: device.c:1941
HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
Definition: device.c:1950
HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
Definition: device.c:1156
HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1076
HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface, LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1322
HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
Definition: device.c:1203
void _dump_DIPROPHEADER(LPCDIPROPHEADER diph)
Definition: device.c:176
HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df)
Definition: device.c:1135
static IDirectInputDeviceImpl * impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
Definition: device.c:51
HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
Definition: device.c:1857
HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface, HANDLE event)
Definition: device.c:1212
HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
Definition: device.c:1629
HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags)
Definition: device.c:1700
ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1308
HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface, LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags)
Definition: device.c:1876
const char * _dump_dinput_GUID(const GUID *guid)
Definition: device.c:197
ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1231
void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
Definition: device.c:1025
static IDirectInputDeviceImpl * impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
Definition: device.c:47
HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
Definition: device.c:1685
int id_to_object(LPCDIDATAFORMAT df, int id)
Definition: device.c:588
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
Definition: device.c:1316
HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface, HWND hwnd, DWORD dwflags)
Definition: device.c:1167
HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1352
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
Definition: device.c:1267
HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
Definition: device.c:1302
HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc)
Definition: device.c:1835
HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event)
Definition: device.c:1224
HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface, LPCSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags)
Definition: device.c:1900
HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid)
Definition: device.c:1706
HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj)
Definition: device.c:1273
HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid)
Definition: device.c:1714
HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1108
HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
Definition: device.c:1867
HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
Definition: device.c:1692
HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags)
Definition: device.c:1888
HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags)
Definition: device.c:1912
HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
Definition: device.c:1828
static IDirectInputDevice8W * IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
Definition: device.c:60
HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow)
Definition: joystick.c:563
HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map)
Definition: joystick.c:1038
HRESULT WINAPI JoystickAGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:906
BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
Definition: joystick.c:312
BOOL device_disabled_registry(const char *name)
Definition: joystick.c:274
HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps)
Definition: joystick.c:526
HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
Definition: joystick.c:610
HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph)
Definition: joystick.c:398
HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
Definition: joystick.c:779
HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:831
HRESULT WINAPI JoystickAGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr)
Definition: joystick.c:824
HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
Definition: joystick.c:804
HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:936
HRESULT WINAPI JoystickAGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
Definition: joystick.c:586
HRESULT WINAPI JoystickAGenericImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
Definition: joystick.c:794
const GUID DInput_PIDVID_Product_GUID
Definition: joystick.c:61
HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:948
HRESULT WINAPI JoystickAGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps)
Definition: joystick.c:554
static SysKeyboardImpl * alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
Definition: keyboard.c:255
unsigned int idx
Definition: utils.c:41
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define lstrcpynA
Definition: compat.h:751
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static const WCHAR version[]
Definition: asmname.c:66
#define POLLIN
Definition: linux.h:1853
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
struct _cl_event * event
Definition: glext.h:7739
GLuint res
Definition: glext.h:9613
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define O_RDWR
Definition: fcntl.h:36
REFIID riid
Definition: atlbase.h:39
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define S_OK
Definition: intsafe.h:52
uint32_t entry
Definition: isohybrid.c:63
const struct dinput_device joystick_linuxinput_device
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define GUID_NULL
Definition: ks.h:106
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static int test_bit(int nr, volatile const unsigned long *addr)
Definition: module.h:383
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
const char * strerror(int err)
Definition: compat_str.c:23
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
static LPUNKNOWN
Definition: ndr_ole.c:49
_Out_ PDWORD pdwOut
Definition: ntgdi.h:1813
@ generic
Definition: optimize.h:97
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define sprintfW
Definition: unicode.h:64
#define errno
Definition: errno.h:18
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
HWND buttons[5]
Definition: sndrec32.cpp:40
#define TRACE(s)
Definition: solgame.cpp:4
GUID guidProduct
Definition: dinput.h:414
GUID guidFFDriver
Definition: dinput.h:418
GUID guidInstance
Definition: dinput.h:413
CHAR tszInstanceName[MAX_PATH]
Definition: dinput.h:416
CHAR tszProductName[MAX_PATH]
Definition: dinput.h:417
DWORD dwDevType
Definition: dinput.h:415
DWORD dwDevType
Definition: dinput.h:428
WCHAR tszProductName[MAX_PATH]
Definition: dinput.h:430
GUID guidFFDriver
Definition: dinput.h:431
GUID guidProduct
Definition: dinput.h:427
WCHAR tszInstanceName[MAX_PATH]
Definition: dinput.h:429
GUID guidInstance
Definition: dinput.h:426
DWORD dwSize
Definition: dinput.h:1125
DWORD dwSize
Definition: dinput.h:1135
DWORD dwData
Definition: dinput.h:844
WCHAR wszPath[MAX_PATH]
Definition: dinput.h:869
DWORD dwObj
Definition: dinput.h:830
DWORD dwSize
Definition: dinput.h:828
DWORD dwHeaderSize
Definition: dinput.h:829
DWORD dwHow
Definition: dinput.h:831
struct list devices_list
CRITICAL_SECTION crit
LPDIOBJECTDATAFORMAT rgodf
Definition: dinput.h:813
DWORD dwSize
Definition: dinput.h:808
DWORD dwObjSize
Definition: dinput.h:809
DWORD dwNumObjs
Definition: dinput.h:812
const GUID * pguid
Definition: dinput.h:800
Definition: scsiwmi.h:51
char * name
Definition: compiler.c:66
Definition: devices.h:37
struct list entry
LPDIRECTINPUTEFFECT ref
Definition: name.c:39
Definition: linux.h:1867
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint32_t * LPDWORD
Definition: typedefs.h:59
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
Definition: pdh_main.c:94
#define GetCurrentTime
Definition: winbase.h:2108
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_POINTER
Definition: winerror.h:2365
#define ioctl
Definition: wintirpc.h:60
#define poll
Definition: wintirpc.h:59
#define snprintf
Definition: wintirpc.h:48
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193