ReactOS  0.4.15-dev-1384-g878186b
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 
79 struct wine_input_absinfo {
80  LONG value;
81  LONG minimum;
82  LONG maximum;
83  LONG fuzz;
84  LONG flat;
85 };
86 
87 enum 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 */
95 HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff);
96 HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
97 HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
98 
99 static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags);
100 
101 typedef struct JoystickImpl JoystickImpl;
102 static const IDirectInputDevice8AVtbl JoystickAvt;
103 static const IDirectInputDevice8WVtbl JoystickWvt;
104 
105 struct 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 
126 struct 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 
148 static 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 }
153 static 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 
159 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
160 {
161  return &This->generic.base.IDirectInputDevice8W_iface;
162 }
163 
164 static void fake_current_js_state(JoystickImpl *ji);
165 static void find_joydevs(void);
166 static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
167 
168 /* This GUID is slightly different from the linux joystick one. Take note. */
169 static 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 
180 static int have_joydevs = -1;
181 static struct JoyDev *joydevs = NULL;
182 
183 static 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 
364 static 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 
393 static 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 
416 static 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 
441 static 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 
466 static 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];
472  DIDEVICEINSTANCEW ddi;
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)
560  df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
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 
613 failed:
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  */
624 static 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 
641 static 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 
692 static 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  */
741 static 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 
748  if ((res = IDirectInputDevice2WImpl_Acquire(iface)) != DI_OK)
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 
765 static 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  */
774 static 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 
804 static 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 ))
817 static 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 */
838 static 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  */
1002 static 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)) {
1017  case (DWORD_PTR)DIPROP_AUTOCENTER: {
1018  LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
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: {
1026  LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
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 
1049 static 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  */
1058 static 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 
1135 static 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  */
1144 static 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 
1200 static 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  */
1211 static 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 
1285 static 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  */
1368 static 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 
1383 static 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  */
1401 static 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 
1418 static 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  */
1427 static 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 
1463  case DISFFC_SETACTUATORSON:
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 
1477 static 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  */
1487 static 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 
1509 static 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  */
1520 static 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 
1537 static 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 
1554 static 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 
1590 static 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 */
HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
Definition: device.c:1950
HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1352
GUID guidInstance
Definition: dinput.h:413
#define IDirectInput_AddRef(p)
Definition: dinput.h:2293
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3835
HRESULT WINAPI JoystickAGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps)
Definition: joystick.c:554
HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
Definition: device.c:1685
#define DIEFT_CONDITION
Definition: dinput.h:996
#define REFIID
Definition: guiddef.h:118
HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
Definition: device.c:1867
DWORD dwSize
Definition: dinput.h:828
DWORD dwDevType
Definition: dinput.h:428
DWORD dwSize
Definition: dinput.h:808
static IDirectInputDevice8W * IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
Definition: device.c:60
#define DWORD_PTR
Definition: treelist.c:76
GLuint64EXT * result
Definition: glext.h:11304
Definition: scsiwmi.h:51
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
BOOL(CALLBACK * LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID)
Definition: dinput.h:468
HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
Definition: joystick.c:610
const char * _dump_dinput_GUID(const GUID *guid)
Definition: device.c:197
HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface, LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1322
#define open
Definition: acwin.h:95
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define DIDFT_PSHBUTTON
Definition: dinput.h:754
#define TRUE
Definition: types.h:120
REFIID riid
Definition: precomp.h:44
#define CP_ACP
Definition: compat.h:109
#define DIEFT_PERIODIC
Definition: dinput.h:995
DWORD dwNumObjs
Definition: dinput.h:812
HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1076
#define WARN(fmt,...)
Definition: debug.h:112
BOOL(CALLBACK * LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID)
Definition: dinput.h:1148
#define DIDFT_MAKEINSTANCE(n)
Definition: dinput.h:762
#define DIDC_ATTACHED
Definition: dinput.h:945
BOOL(CALLBACK * LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID)
Definition: dinput.h:1149
DWORD dwObjSize
Definition: dinput.h:809
#define snprintf
Definition: wintirpc.h:48
#define InterlockedCompareExchange
Definition: interlocked.h:104
HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags)
Definition: device.c:1700
static int fd
Definition: io.c:51
struct list devices_list
#define DIEDFL_FORCEFEEDBACK
Definition: dinput.h:192
struct DIEFFECTINFOW DIEFFECTINFOW
GUID guidFFDriver
Definition: dinput.h:431
int errno
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
Definition: joystick.c:779
HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags)
Definition: device.c:1912
DWORD dwHow
Definition: dinput.h:831
HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow)
Definition: joystick.c:563
#define E_FAIL
Definition: ddrawi.h:102
const char * strerror(int err)
Definition: compat_str.c:23
ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1308
BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
Definition: joystick.c:312
static IDirectInputDeviceImpl * impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
Definition: device.c:47
#define DIDFT_ABSAXIS
Definition: dinput.h:752
DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN
Definition: joystick.c:1024
#define DIERR_NOTFOUND
Definition: dinput.h:148
HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map)
Definition: joystick.c:1038
#define DIERR_UNSUPPORTED
Definition: dinput.h:156
FxDevice * device
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define write
Definition: acwin.h:97
const DIPROPDWORD * LPCDIPROPDWORD
Definition: dinput.h:846
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define IDirectInputEffect_SetParameters(p, a, b)
Definition: dinput.h:1514
const GUID * guid
WCHAR wszPath[MAX_PATH]
Definition: dinput.h:869
#define GetCurrentTime
Definition: winbase.h:2062
DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN
Definition: joystick.c:107
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
Definition: device.c:1857
#define DIEFT_GETTYPE(n)
Definition: dinput.h:1006
static LPUNKNOWN
Definition: ndr_ole.c:49
HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:948
#define ioctl
Definition: wintirpc.h:60
HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph)
Definition: joystick.c:398
#define debugstr_w
Definition: kernel32.h:32
LPDIRECTINPUTEFFECT ref
#define FIXME(fmt,...)
Definition: debug.h:111
DWORD dwDevType
Definition: dinput.h:415
static PVOID ptr
Definition: dispmode.c:27
DWORD dwSize
Definition: dinput.h:1125
unsigned int idx
Definition: utils.c:41
#define S_FALSE
Definition: winerror.h:2357
#define DIDOI_FFACTUATOR
Definition: dinput.h:817
HRESULT WINAPI JoystickAGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr)
Definition: joystick.c:824
struct DIPROPGUIDANDPATH * LPDIPROPGUIDANDPATH
GUID guidProduct
Definition: dinput.h:414
#define MAKELONG(a, b)
Definition: typedefs.h:249
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
static const WCHAR version[]
Definition: asmname.c:66
HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc)
Definition: device.c:1835
GLuint index
Definition: glext.h:6031
static int test_bit(int nr, volatile const unsigned long *addr)
Definition: module.h:381
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define DISFFC_RESET
Definition: dinput.h:970
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
const GUID DInput_PIDVID_Product_GUID
Definition: joystick.c:61
HRESULT WINAPI JoystickAGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
Definition: joystick.c:586
#define DISFFC_SETACTUATORSOFF
Definition: dinput.h:975
#define DIERR_INVALIDPARAM
Definition: dinput.h:152
HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface, LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags)
Definition: device.c:1876
HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
Definition: device.c:1941
static SysKeyboardImpl * alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
Definition: keyboard.c:255
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface, HANDLE event)
Definition: device.c:1212
HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
Definition: device.c:1692
static IDirectInputDeviceImpl * impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
Definition: device.c:51
void _dump_DIPROPHEADER(LPCDIPROPHEADER diph)
Definition: device.c:176
#define GetProcessHeap()
Definition: compat.h:595
HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface, LPCSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags)
Definition: device.c:1900
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define DIEFT_CONSTANTFORCE
Definition: dinput.h:993
HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df)
Definition: device.c:1135
#define DIERR_OUTOFMEMORY
Definition: dinput.h:155
#define IDirectInputEffect_Stop(p)
Definition: dinput.h:1516
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:79
struct list entry
int poll(struct pollfd *ufds, int nfds, int timeout)
Definition: adnstest.c:68
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
unsigned short WORD
Definition: ntddk_ex.h:93
#define DIERR_DEVICENOTREG
Definition: dinput.h:147
unsigned long DWORD
Definition: ntddk_ex.h:95
#define POLLIN
Definition: linux.h:1853
#define DIPROP_FFGAIN
Definition: dinput.h:895
Definition: linux.h:1867
#define DIDEVTYPE_JOYSTICK
Definition: dinput.h:200
HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid)
Definition: device.c:1706
#define DISFFC_PAUSE
Definition: dinput.h:972
struct IDirectInputEffect * LPDIRECTINPUTEFFECT
Definition: dinput.h:107
HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
Definition: device.c:1629
HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
Definition: device.c:1828
WCHAR tszProductName[MAX_PATH]
Definition: dinput.h:430
struct DIEFFECTINFOA DIEFFECTINFOA
#define index(s, c)
Definition: various.h:29
HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj)
Definition: device.c:1273
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
Definition: device.c:1267
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define IDirectInputDevice8_Unacquire(p)
Definition: dinput.h:2043
uint32_t entry
Definition: isohybrid.c:63
DWORD dwData
Definition: dinput.h:844
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
CHAR tszInstanceName[MAX_PATH]
Definition: dinput.h:416
#define DIPROP_JOYSTICKID
Definition: dinput.h:912
#define GUID_NULL
Definition: ks.h:106
Definition: _list.h:228
GLsizei const GLfloat * value
Definition: glext.h:6069
LPDIOBJECTDATAFORMAT rgodf
Definition: dinput.h:813
#define close
Definition: acwin.h:98
HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
Definition: device.c:1302
#define DIPROP_GUIDANDPATH
Definition: dinput.h:908
struct _cl_event * event
Definition: glext.h:7739
uint32_t DWORD_PTR
Definition: typedefs.h:65
WCHAR tszInstanceName[MAX_PATH]
Definition: dinput.h:429
#define IDirectInputDevice8_GetEffectInfo(p, a, b)
Definition: dinput.h:2056
unsigned char BYTE
Definition: xxhash.c:193
const DIDATAFORMAT c_dfDIJoystick2
Definition: data_formats.c:251
#define DI8DEVTYPE_JOYSTICK
Definition: dinput.h:212
BOOL device_disabled_registry(const char *name)
Definition: joystick.c:274
HRESULT WINAPI JoystickAGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:906
DWORD dwSize
Definition: dinput.h:1135
#define ERR(fmt,...)
Definition: debug.h:110
#define DIPROP_AUTOCENTER
Definition: dinput.h:897
const struct dinput_device joystick_linuxinput_device
#define S_OK
Definition: intsafe.h:51
HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
Definition: device.c:1203
CRITICAL_SECTION crit
struct IDirectInputDevice8W * LPDIRECTINPUTDEVICE8W
Definition: dinput.h:106
#define DIPROPAUTOCENTER_ON
Definition: dinput.h:900
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
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
const GUID * pguid
Definition: dinput.h:800
HWND buttons[5]
Definition: sndrec32.cpp:40
#define DIERR_NOINTERFACE
Definition: dinput.h:153
HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface, HWND hwnd, DWORD dwflags)
Definition: device.c:1167
HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:831
HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface, LPCWSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags)
Definition: device.c:1888
HRESULT WINAPI JoystickAGenericImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
Definition: joystick.c:794
#define DIPROPAUTOCENTER_OFF
Definition: dinput.h:899
#define DIDEVTYPE_HID
Definition: dinput.h:201
#define O_RDWR
Definition: fcntl.h:36
#define DIDFT_POV
Definition: dinput.h:757
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
Definition: device.c:1316
#define HeapReAlloc
Definition: compat.h:593
#define sprintfW
Definition: unicode.h:58
GUID guidFFDriver
Definition: dinput.h:418
LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN
Definition: joystick.c:985
HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps)
Definition: joystick.c:526
DWORD dwObj
Definition: dinput.h:830
#define NULL
Definition: types.h:112
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
Definition: joystick.c:804
#define lstrcpynA
Definition: compat.h:610
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
GUID guidInstance
Definition: dinput.h:426
HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
Definition: device.c:1156
#define MultiByteToWideChar
Definition: compat.h:110
#define DISFFC_STOPALL
Definition: dinput.h:971
CHAR tszProductName[MAX_PATH]
Definition: dinput.h:417
void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
Definition: device.c:1025
struct IDirectInputDevice8A * LPDIRECTINPUTDEVICE8A
Definition: dinput.h:105
Definition: name.c:38
#define DI_DOWNLOADSKIPPED
Definition: dinput.h:134
GLuint res
Definition: glext.h:9613
#define DI_OK
Definition: dinput.h:128
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
uint32_t * LPDWORD
Definition: typedefs.h:59
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define DIEFT_RAMPFORCE
Definition: dinput.h:994
DWORD dwHeaderSize
Definition: dinput.h:829
#define DISFFC_CONTINUE
Definition: dinput.h:973
HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1108
GLenum GLuint id
Definition: glext.h:5579
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define IDirectInputEffect_Unload(p)
Definition: dinput.h:1519
#define DIEFT_ALL
Definition: dinput.h:991
_Out_ PDWORD pdwOut
Definition: ntgdi.h:1813
#define IS_DIPROP(x)
int id_to_object(LPCDIDATAFORMAT df, int id)
Definition: device.c:588
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define DI8DEVCLASS_GAMECTRL
Definition: dinput.h:207
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define E_POINTER
Definition: winerror.h:2365
#define DISFFC_SETACTUATORSON
Definition: dinput.h:974
#define memset(x, y, z)
Definition: compat.h:39
#define DIPROP_VIDPID
Definition: dinput.h:918
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define DIDC_FORCEFEEDBACK
Definition: dinput.h:949
HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:936
#define DIGFFS_STOPPED
Definition: dinput.h:978
struct DIPROPDWORD * LPDIPROPDWORD
#define LOWORD(l)
Definition: pedump.c:82
#define HeapFree(x, y, z)
Definition: compat.h:594
HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event)
Definition: device.c:1224
#define MulDiv(x, y, z)
Definition: gdifloat.h:86
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1231
GUID guidProduct
Definition: dinput.h:427
#define O_RDONLY
Definition: acwin.h:108
HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion, REFGUID rguid)
Definition: device.c:1714
GLuint const GLchar * name
Definition: glext.h:6031