ReactOS  0.4.15-dev-1177-g6cb3b62
joystick_linux.c
Go to the documentation of this file.
1 /* DirectInput Joystick device
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  * Copyright 2000-2001 TransGaming Technologies Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 /*
23  * To Do:
24  * dead zone
25  * force feedback
26  */
27 
28 #include "config.h"
29 #include "wine/port.h"
30 
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #ifdef HAVE_SYS_TIME_H
39 # include <sys/time.h>
40 #endif
41 #include <fcntl.h>
42 #ifdef HAVE_SYS_IOCTL_H
43 # include <sys/ioctl.h>
44 #endif
45 #include <errno.h>
46 #ifdef HAVE_LINUX_IOCTL_H
47 # include <linux/ioctl.h>
48 #endif
49 #ifdef HAVE_LINUX_JOYSTICK_H
50 # include <linux/joystick.h>
51 # undef SW_MAX
52 #endif
53 #ifdef HAVE_SYS_POLL_H
54 # include <sys/poll.h>
55 #endif
56 
57 #include "wine/debug.h"
58 #include "wine/unicode.h"
59 #include "windef.h"
60 #include "winbase.h"
61 #include "winerror.h"
62 #include "devguid.h"
63 #include "dinput.h"
64 
65 #include "dinput_private.h"
66 #include "device_private.h"
67 #include "joystick_private.h"
68 
69 #ifdef HAVE_LINUX_22_JOYSTICK_API
70 
72 
73 #define JOYDEV_NEW "/dev/input/js"
74 #define JOYDEV_OLD "/dev/js"
75 #define JOYDEVDRIVER " (js)"
76 
77 struct JoyDev
78 {
79  char device[MAX_PATH];
80  char name[MAX_PATH];
81  GUID guid_product;
82 
83  BYTE axis_count;
84  BYTE button_count;
85  int *dev_axes_map;
86 
87  WORD vendor_id, product_id, bus_type;
88 
89  BOOL is_joystick;
90 };
91 
92 typedef struct JoystickImpl JoystickImpl;
93 static const IDirectInputDevice8AVtbl JoystickAvt;
94 static const IDirectInputDevice8WVtbl JoystickWvt;
95 struct JoystickImpl
96 {
98 
99  struct JoyDev *joydev;
100 
101  /* joystick private */
102  int joyfd;
103  POINTL povs[4];
104 };
105 
106 static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
107 {
108  return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
109  JoystickGenericImpl, base), JoystickImpl, generic);
110 }
111 static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
112 {
113  return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
114  JoystickGenericImpl, base), JoystickImpl, generic);
115 }
116 
117 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
118 {
119  return &This->generic.base.IDirectInputDevice8W_iface;
120 }
121 
122 static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
123  0x9e573ed9,
124  0x7734,
125  0x11d2,
126  {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
127 };
128 
129 #define MAX_JOYSTICKS 64
130 static INT joystick_devices_count = -1;
131 static struct JoyDev *joystick_devices;
132 
133 static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
134 
135 #define SYS_PATH_FORMAT "/sys/class/input/js%d/device/id/%s"
136 static BOOL read_sys_id_variable(int index, const char *property, WORD *value)
137 {
138  char sys_path[sizeof(SYS_PATH_FORMAT) + 16], id_str[5];
139  int sys_fd;
140  BOOL ret = FALSE;
141 
142  sprintf(sys_path, SYS_PATH_FORMAT, index, property);
143  if ((sys_fd = open(sys_path, O_RDONLY)) != -1)
144  {
145  if (read(sys_fd, id_str, 4) == 4)
146  {
147  id_str[4] = '\0';
148  *value = strtol(id_str, NULL, 16);
149  ret = TRUE;
150  }
151 
152  close(sys_fd);
153  }
154  return ret;
155 }
156 #undef SYS_PATH_FORMAT
157 
158 static INT find_joystick_devices(void)
159 {
160  INT i;
161 
162  if (joystick_devices_count != -1) return joystick_devices_count;
163 
164  joystick_devices_count = 0;
165  for (i = 0; i < MAX_JOYSTICKS; i++)
166  {
167  int fd;
168  struct JoyDev joydev, *new_joydevs;
169  BYTE axes_map[ABS_MAX + 1];
170  SHORT btn_map[KEY_MAX - BTN_MISC + 1];
171  BOOL is_stylus = FALSE;
172 
173  snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i);
174  if ((fd = open(joydev.device, O_RDONLY)) == -1)
175  {
176  snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_OLD, i);
177  if ((fd = open(joydev.device, O_RDONLY)) == -1) continue;
178  }
179 
180  strcpy(joydev.name, "Wine Joystick");
181 #if defined(JSIOCGNAME)
182  if (ioctl(fd, JSIOCGNAME(sizeof(joydev.name) - sizeof(JOYDEVDRIVER)), joydev.name) < 0)
183  WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", joydev.device, strerror(errno));
184 #endif
185 
186  /* Append driver name */
187  strcat(joydev.name, JOYDEVDRIVER);
188 
189  if (device_disabled_registry(joydev.name)) {
190  close(fd);
191  continue;
192  }
193 
194 #ifdef JSIOCGAXES
195  if (ioctl(fd, JSIOCGAXES, &joydev.axis_count) < 0)
196  {
197  WARN("ioctl(%s,JSIOCGAXES) failed: %s, defaulting to 2\n", joydev.device, strerror(errno));
198  joydev.axis_count = 2;
199  }
200 #else
201  WARN("reading number of joystick axes unsupported in this platform, defaulting to 2\n");
202  joydev.axis_count = 2;
203 #endif
204 #ifdef JSIOCGBUTTONS
205  if (ioctl(fd, JSIOCGBUTTONS, &joydev.button_count) < 0)
206  {
207  WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defaulting to 2\n", joydev.device, strerror(errno));
208  joydev.button_count = 2;
209  }
210 #else
211  WARN("reading number of joystick buttons unsupported in this platform, defaulting to 2\n");
212  joydev.button_count = 2;
213 #endif
214 
215  joydev.is_joystick = FALSE;
216  if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0)
217  {
218  WARN("ioctl(%s,JSIOCGBTNMAP) failed: %s\n", joydev.device, strerror(errno));
219  }
220  else
221  {
222  INT j;
223  /* in lieu of properly reporting HID usage, detect presence of
224  * "joystick buttons" and report those devices as joysticks instead of
225  * gamepads */
226  for (j = 0; !joydev.is_joystick && j < joydev.button_count; j++)
227  {
228  switch (btn_map[j])
229  {
230  case BTN_TRIGGER:
231  case BTN_THUMB:
232  case BTN_THUMB2:
233  case BTN_TOP:
234  case BTN_TOP2:
235  case BTN_PINKIE:
236  case BTN_BASE:
237  case BTN_BASE2:
238  case BTN_BASE3:
239  case BTN_BASE4:
240  case BTN_BASE5:
241  case BTN_BASE6:
242  case BTN_DEAD:
243  joydev.is_joystick = TRUE;
244  break;
245  case BTN_STYLUS:
246  is_stylus = TRUE;
247  break;
248  default:
249  break;
250  }
251  }
252  }
253 
254  if(is_stylus)
255  {
256  TRACE("Stylus detected. Skipping\n");
257  close(fd);
258  continue;
259  }
260 
261  if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0)
262  {
263  WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno));
264  joydev.dev_axes_map = NULL;
265  }
266  else
267  if ((joydev.dev_axes_map = HeapAlloc(GetProcessHeap(), 0, joydev.axis_count * sizeof(int))))
268  {
269  INT j, found_axes = 0;
270 
271  /* Remap to DI numbers */
272  for (j = 0; j < joydev.axis_count; j++)
273  {
274  if (axes_map[j] < 8)
275  {
276  /* Axis match 1-to-1 */
277  joydev.dev_axes_map[j] = j;
278  found_axes++;
279  }
280  else if (axes_map[j] <= 10)
281  {
282  /* Axes 8 through 10 are Wheel, Gas and Brake,
283  * remap to 0, 1 and 2
284  */
285  joydev.dev_axes_map[j] = axes_map[j] - 8;
286  found_axes++;
287  }
288  else if (axes_map[j] == 16 ||
289  axes_map[j] == 17)
290  {
291  /* POV axis */
292  joydev.dev_axes_map[j] = 8;
293  found_axes++;
294  }
295  else
296  joydev.dev_axes_map[j] = -1;
297  }
298 
299  /* If no axes were configured but there are axes assume a 1-to-1 (wii controller) */
300  if (joydev.axis_count && !found_axes)
301  {
302  int axes_limit = min(joydev.axis_count, 8); /* generic driver limit */
303 
304  ERR("Incoherent joystick data, advertised %d axes, detected 0. Assuming 1-to-1.\n",
305  joydev.axis_count);
306  for (j = 0; j < axes_limit; j++)
307  joydev.dev_axes_map[j] = j;
308 
309  joydev.axis_count = axes_limit;
310  }
311  }
312 
313  /* Find vendor_id and product_id in sysfs */
314  joydev.vendor_id = 0;
315  joydev.product_id = 0;
316 
317  read_sys_id_variable(i, "vendor", &joydev.vendor_id);
318  read_sys_id_variable(i, "product", &joydev.product_id);
319  read_sys_id_variable(i, "bustype", &joydev.bus_type);
320 
321  if (joydev.vendor_id == 0 || joydev.product_id == 0)
322  {
323  joydev.guid_product = DInput_Wine_Joystick_GUID;
324  }
325  else
326  {
327  /* Concatenate product_id with vendor_id to mimic Windows behaviour */
328  joydev.guid_product = DInput_PIDVID_Product_GUID;
329  joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id);
330  }
331 
332  close(fd);
333 
334  if (!joystick_devices_count)
335  new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev));
336  else
337  new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joystick_devices,
338  (joystick_devices_count + 1) * sizeof(struct JoyDev));
339  if (!new_joydevs) continue;
340 
341  TRACE("Found a joystick on %s: %s\n with %d axes and %d buttons\n", joydev.device,
342  joydev.name, joydev.axis_count, joydev.button_count);
343 
344  joystick_devices = new_joydevs;
345  joystick_devices[joystick_devices_count++] = joydev;
346  }
347 
348  return joystick_devices_count;
349 }
350 
351 static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
352 {
353  DWORD dwSize = lpddi->dwSize;
354 
355  TRACE("%d %p\n", dwSize, lpddi);
356  memset(lpddi, 0, dwSize);
357 
358  /* Return joystick */
359  lpddi->dwSize = dwSize;
360  lpddi->guidInstance = DInput_Wine_Joystick_GUID;
361  lpddi->guidInstance.Data3 = id;
362  lpddi->guidProduct = joystick_devices[id].guid_product;
363  lpddi->dwDevType = get_device_type(version, joystick_devices[id].is_joystick);
364 
365  /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */
366  if (joystick_devices[id].bus_type == BUS_USB &&
367  joystick_devices[id].vendor_id && joystick_devices[id].product_id)
368  {
369  lpddi->dwDevType |= DIDEVTYPE_HID;
370  lpddi->wUsagePage = 0x01; /* Desktop */
371  if (joystick_devices[id].is_joystick)
372  lpddi->wUsage = 0x04; /* Joystick */
373  else
374  lpddi->wUsage = 0x05; /* Game Pad */
375  }
376 
377  MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
378  MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszProductName, MAX_PATH);
379  lpddi->guidFFDriver = GUID_NULL;
380 }
381 
382 static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
383 {
384  DIDEVICEINSTANCEW lpddiW;
385  DWORD dwSize = lpddi->dwSize;
386 
387  lpddiW.dwSize = sizeof(lpddiW);
388  fill_joystick_dideviceinstanceW(&lpddiW, version, id);
389 
390  TRACE("%d %p\n", dwSize, lpddi);
391  memset(lpddi, 0, dwSize);
392 
393  /* Convert W->A */
394  lpddi->dwSize = dwSize;
395  lpddi->guidInstance = lpddiW.guidInstance;
396  lpddi->guidProduct = lpddiW.guidProduct;
397  lpddi->dwDevType = lpddiW.dwDevType;
398  strcpy(lpddi->tszInstanceName, joystick_devices[id].name);
399  strcpy(lpddi->tszProductName, joystick_devices[id].name);
400  lpddi->guidFFDriver = lpddiW.guidFFDriver;
401  lpddi->wUsagePage = lpddiW.wUsagePage;
402  lpddi->wUsage = lpddiW.wUsage;
403 }
404 
405 static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
406 {
407  int fd = -1;
408 
409  if (id >= find_joystick_devices()) return E_FAIL;
410 
412  WARN("force feedback not supported\n");
413  return S_FALSE;
414  }
415 
416  if ((dwDevType == 0) ||
417  ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
418  (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
419  /* check whether we have a joystick */
420  if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1)
421  {
422  WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno));
423  return S_FALSE;
424  }
425  fill_joystick_dideviceinstanceA( lpddi, version, id );
426  close(fd);
427  TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, joystick_devices[id].name);
428  return S_OK;
429  }
430 
431  return S_FALSE;
432 }
433 
434 static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
435 {
436  int fd = -1;
437 
438  if (id >= find_joystick_devices()) return E_FAIL;
439 
441  WARN("force feedback not supported\n");
442  return S_FALSE;
443  }
444 
445  if ((dwDevType == 0) ||
446  ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
447  (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
448  /* check whether we have a joystick */
449  if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1)
450  {
451  WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno));
452  return S_FALSE;
453  }
454  fill_joystick_dideviceinstanceW( lpddi, version, id );
455  close(fd);
456  TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, joystick_devices[id].name);
457  return S_OK;
458  }
459 
460  return S_FALSE;
461 }
462 
463 static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
464  JoystickImpl **pdev, unsigned short index)
465 {
466  DWORD i;
467  JoystickImpl* newDevice;
468  HRESULT hr;
469  LPDIDATAFORMAT df = NULL;
470  int idx = 0;
471  DIDEVICEINSTANCEW ddi;
472 
473  TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
474 
475  newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
476  if (newDevice == 0) {
477  WARN("out of memory\n");
478  *pdev = 0;
479  return DIERR_OUTOFMEMORY;
480  }
481 
482  newDevice->joydev = &joystick_devices[index];
483  newDevice->joyfd = -1;
484  newDevice->generic.guidInstance = DInput_Wine_Joystick_GUID;
485  newDevice->generic.guidInstance.Data3 = index;
486  newDevice->generic.guidProduct = DInput_Wine_Joystick_GUID;
487  newDevice->generic.joy_polldev = joy_polldev;
488  newDevice->generic.name = newDevice->joydev->name;
489  newDevice->generic.device_axis_count = newDevice->joydev->axis_count;
490  newDevice->generic.devcaps.dwButtons = newDevice->joydev->button_count;
491 
492  if (newDevice->generic.devcaps.dwButtons > 128)
493  {
494  WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
495  newDevice->generic.devcaps.dwButtons = 128;
496  }
497 
498  newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
499  newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
500  newDevice->generic.base.ref = 1;
501  newDevice->generic.base.dinput = dinput;
502  newDevice->generic.base.guid = *rguid;
503  InitializeCriticalSection(&newDevice->generic.base.crit);
504  newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
505 
506  /* setup_dinput_options may change these */
507  newDevice->generic.deadzone = 0;
508 
509  /* do any user specified configuration */
510  hr = setup_dinput_options(&newDevice->generic, newDevice->joydev->dev_axes_map);
511  if (hr != DI_OK)
512  goto FAILED1;
513 
514  /* Create copy of default data format */
515  if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
517 
518  df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
519  if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
520 
521  for (i = 0; i < newDevice->generic.device_axis_count; i++)
522  {
523  int wine_obj = newDevice->generic.axis_map[i];
524 
525  if (wine_obj < 0) continue;
526 
527  memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
528  if (wine_obj < 8)
529  df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
530  else
531  {
532  df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
533  i++; /* POV takes 2 axes */
534  }
535  }
536  for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++)
537  {
538  memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
539  df->rgodf[idx ].pguid = &GUID_Button;
541  }
542  newDevice->generic.base.data_format.wine_df = df;
543 
544  /* initialize default properties */
545  for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
546  newDevice->generic.props[i].lDevMin = -32767;
547  newDevice->generic.props[i].lDevMax = +32767;
548  newDevice->generic.props[i].lMin = 0;
549  newDevice->generic.props[i].lMax = 0xffff;
550  newDevice->generic.props[i].lDeadZone = newDevice->generic.deadzone; /* % * 1000 */
551  newDevice->generic.props[i].lSaturation = 0;
552  }
553 
554  IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
555 
556  EnterCriticalSection(&dinput->crit);
557  list_add_tail(&dinput->devices_list, &newDevice->generic.base.entry);
558  LeaveCriticalSection(&dinput->crit);
559 
560  newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
561  newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
562 
563  ddi.dwSize = sizeof(ddi);
564  fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index);
565  newDevice->generic.devcaps.dwDevType = ddi.dwDevType;
566 
567  newDevice->generic.devcaps.dwFFSamplePeriod = 0;
568  newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
569  newDevice->generic.devcaps.dwFirmwareRevision = 0;
570  newDevice->generic.devcaps.dwHardwareRevision = 0;
571  newDevice->generic.devcaps.dwFFDriverVersion = 0;
572 
573  if (TRACE_ON(dinput)) {
574  _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df);
575  for (i = 0; i < (newDevice->generic.device_axis_count); i++)
576  TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]);
577  _dump_DIDEVCAPS(&newDevice->generic.devcaps);
578  }
579 
580  *pdev = newDevice;
581 
582  return DI_OK;
583 
584 FAILED:
586 FAILED1:
587  if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
588  HeapFree(GetProcessHeap(), 0, df);
589  release_DataFormat(&newDevice->generic.base.data_format);
590  HeapFree(GetProcessHeap(),0,newDevice->generic.axis_map);
591  HeapFree(GetProcessHeap(),0,newDevice);
592  *pdev = 0;
593 
594  return hr;
595 }
596 
597 /******************************************************************************
598  * get_joystick_index : Get the joystick index from a given GUID
599  */
600 static unsigned short get_joystick_index(REFGUID guid)
601 {
602  GUID wine_joystick = DInput_Wine_Joystick_GUID;
603  GUID dev_guid = *guid;
604 
605  wine_joystick.Data3 = 0;
606  dev_guid.Data3 = 0;
607 
608  /* for the standard joystick GUID use index 0 */
609  if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
610 
611  /* for the wine joystick GUIDs use the index stored in Data3 */
612  if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
613 
614  return MAX_JOYSTICKS;
615 }
616 
617 static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
618 {
619  unsigned short index;
620 
621  TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
622  find_joystick_devices();
623  *pdev = NULL;
624 
625  if ((index = get_joystick_index(rguid)) < MAX_JOYSTICKS &&
626  joystick_devices_count && index < joystick_devices_count)
627  {
628  JoystickImpl *This;
629  HRESULT hr;
630 
631  if (riid == NULL)
632  ;/* nothing */
633  else if (IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
634  IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
635  IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
636  IsEqualGUID(&IID_IDirectInputDevice8A, riid))
637  {
638  unicode = 0;
639  }
640  else if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) ||
641  IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
642  IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
643  IsEqualGUID(&IID_IDirectInputDevice8W, riid))
644  {
645  unicode = 1;
646  }
647  else
648  {
649  WARN("no interface\n");
650  return DIERR_NOINTERFACE;
651  }
652 
653  hr = alloc_device(rguid, dinput, &This, index);
654  if (!This) return hr;
655 
656  if (unicode)
657  *pdev = &This->generic.base.IDirectInputDevice8W_iface;
658  else
659  *pdev = &This->generic.base.IDirectInputDevice8A_iface;
660 
661  return hr;
662  }
663 
664  return DIERR_DEVICENOTREG;
665 }
666 
667 #undef MAX_JOYSTICKS
668 
669 const struct dinput_device joystick_linux_device = {
670  "Wine Linux joystick driver",
671  joydev_enum_deviceA,
672  joydev_enum_deviceW,
673  joydev_create_device
674 };
675 
676 /******************************************************************************
677  * Acquire : gets exclusive control of the joystick
678  */
679 static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
680 {
681  JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
682  HRESULT res;
683 
684  TRACE("(%p)\n",This);
685 
687  if (res != DI_OK)
688  return res;
689 
690  /* open the joystick device */
691  if (This->joyfd==-1) {
692  TRACE("opening joystick device %s\n", This->joydev->device);
693 
694  This->joyfd = open(This->joydev->device, O_RDONLY);
695  if (This->joyfd==-1) {
696  ERR("open(%s) failed: %s\n", This->joydev->device, strerror(errno));
698  return DIERR_NOTFOUND;
699  }
700  }
701 
702  return DI_OK;
703 }
704 
705 static HRESULT WINAPI JoystickLinuxAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
706 {
707  JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
708  return JoystickLinuxWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
709 }
710 
711 /******************************************************************************
712  * GetProperty : get input device properties
713  */
714 static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
715 {
716  JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
717 
718  TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
719  _dump_DIPROPHEADER(pdiph);
720 
721  if (!IS_DIPROP(rguid)) return DI_OK;
722 
723  switch (LOWORD(rguid)) {
724 
725  case (DWORD_PTR) DIPROP_VIDPID:
726  {
727  LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
728 
729  if (!This->joydev->product_id || !This->joydev->vendor_id)
730  return DIERR_UNSUPPORTED;
731  pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id);
732  TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData);
733  break;
734  }
736  {
737  LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
738 
739  pd->dwData = get_joystick_index(&This->generic.base.guid);
740  TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
741  break;
742  }
743 
745  {
746  static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
747  'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0};
748  static const WCHAR miW[] = {'m','i',0};
749  static const WCHAR igW[] = {'i','g',0};
750 
751  BOOL is_gamepad;
753  WORD vid = This->joydev->vendor_id;
754  WORD pid = This->joydev->product_id;
755 
756  if (!pid || !vid)
757  return DIERR_UNSUPPORTED;
758 
759  is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
760  pd->guidClass = GUID_DEVCLASS_HIDCLASS;
761  sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid));
762 
763  TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
764  break;
765  }
766 
767  default:
768  return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
769  }
770 
771  return DI_OK;
772 }
773 
774 static HRESULT WINAPI JoystickLinuxAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
775 {
776  JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
777  return JoystickLinuxWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
778 }
779 
780 /******************************************************************************
781  * GetDeviceInfo : get information about a device's identity
782  */
783 static HRESULT WINAPI JoystickLinuxAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEINSTANCEA ddi)
784 {
785  JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
786 
787  TRACE("(%p) %p\n", This, ddi);
788 
789  if (ddi == NULL) return E_POINTER;
790  if ((ddi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
791  (ddi->dwSize != sizeof(DIDEVICEINSTANCEA)))
792  return DIERR_INVALIDPARAM;
793 
794  fill_joystick_dideviceinstanceA( ddi, This->generic.base.dinput->dwVersion,
795  get_joystick_index(&This->generic.base.guid) );
796  return DI_OK;
797 }
798 
799 static HRESULT WINAPI JoystickLinuxWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW ddi)
800 {
801  JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
802 
803  TRACE("(%p) %p\n", This, ddi);
804 
805  if (ddi == NULL) return E_POINTER;
806  if ((ddi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
807  (ddi->dwSize != sizeof(DIDEVICEINSTANCEW)))
808  return DIERR_INVALIDPARAM;
809 
810  fill_joystick_dideviceinstanceW( ddi, This->generic.base.dinput->dwVersion,
811  get_joystick_index(&This->generic.base.guid) );
812  return DI_OK;
813 }
814 
815 /******************************************************************************
816  * Unacquire : frees the joystick
817  */
818 static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
819 {
820  JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
821  HRESULT res;
822 
823  TRACE("(%p)\n",This);
824 
826 
827  if (res != DI_OK)
828  return res;
829 
830  if (This->joyfd!=-1) {
831  TRACE("closing joystick device\n");
832  close(This->joyfd);
833  This->joyfd = -1;
834  return DI_OK;
835  }
836 
837  return DI_NOEFFECT;
838 }
839 
840 static HRESULT WINAPI JoystickLinuxAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
841 {
842  JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
843  return JoystickLinuxWImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
844 }
845 
846 static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
847 {
848  struct pollfd plfd;
849  struct js_event jse;
850  JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
851 
852  TRACE("(%p)\n", This);
853 
854  if (This->joyfd==-1) {
855  WARN("no device\n");
856  return;
857  }
858  while (1)
859  {
860  LONG value;
861  int inst_id = -1;
862 
863  plfd.fd = This->joyfd;
864  plfd.events = POLLIN;
865  if (poll(&plfd,1,0) != 1)
866  return;
867  /* we have one event, so we can read */
868  if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
869  return;
870  }
871  TRACE("js_event: type 0x%x, number %d, value %d\n",
872  jse.type,jse.number,jse.value);
873  if (jse.type & JS_EVENT_BUTTON)
874  {
875  int button;
876  if (jse.number >= This->generic.devcaps.dwButtons) return;
877 
878  button = This->generic.button_map[jse.number];
879 
881  This->generic.js.rgbButtons[button] = value = jse.value ? 0x80 : 0x00;
882  }
883  else if (jse.type & JS_EVENT_AXIS)
884  {
885  int number = This->generic.axis_map[jse.number]; /* wine format object index */
886 
887  if (number < 0) return;
888  inst_id = number < 8 ? DIDFT_MAKEINSTANCE(number) | DIDFT_ABSAXIS :
890  value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], jse.value);
891 
892  TRACE("changing axis %d => %d\n", jse.number, number);
893  switch (number)
894  {
895  case 0: This->generic.js.lX = value; break;
896  case 1: This->generic.js.lY = value; break;
897  case 2: This->generic.js.lZ = value; break;
898  case 3: This->generic.js.lRx = value; break;
899  case 4: This->generic.js.lRy = value; break;
900  case 5: This->generic.js.lRz = value; break;
901  case 6: This->generic.js.rglSlider[0] = value; break;
902  case 7: This->generic.js.rglSlider[1] = value; break;
903  case 8: case 9: case 10: case 11:
904  {
905  int idx = number - 8;
906 
907  if (jse.number % 2)
908  This->povs[idx].y = jse.value;
909  else
910  This->povs[idx].x = jse.value;
911 
912  This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
913  break;
914  }
915  default:
916  WARN("axis %d not supported\n", number);
917  }
918  }
919  if (inst_id >= 0)
920  queue_event(iface, inst_id, value, GetCurrentTime(), This->generic.base.dinput->evsequence++);
921  }
922 }
923 
924 static const IDirectInputDevice8AVtbl JoystickAvt =
925 {
931  JoystickLinuxAImpl_GetProperty,
933  JoystickLinuxAImpl_Acquire,
934  JoystickLinuxAImpl_Unacquire,
941  JoystickLinuxAImpl_GetDeviceInfo,
958 };
959 
960 static const IDirectInputDevice8WVtbl JoystickWvt =
961 {
967  JoystickLinuxWImpl_GetProperty,
969  JoystickLinuxWImpl_Acquire,
970  JoystickLinuxWImpl_Unacquire,
977  JoystickLinuxWImpl_GetDeviceInfo,
994 };
995 
996 #else /* HAVE_LINUX_22_JOYSTICK_API */
997 
999  "Wine Linux joystick driver",
1000  NULL,
1001  NULL,
1002  NULL
1003 };
1004 
1005 #endif /* HAVE_LINUX_22_JOYSTICK_API */
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
HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
Definition: device.c:1725
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 REFIID
Definition: guiddef.h:118
HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
Definition: device.c:1867
DWORD dwDevType
Definition: dinput.h:428
HRESULT WINAPI JoystickAGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER ph)
Definition: joystick.c:473
HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
Definition: device.c:1800
DWORD dwSize
Definition: dinput.h:808
static IDirectInputDevice8W * IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
Definition: device.c:60
#define DWORD_PTR
Definition: treelist.c:76
HRESULT hr
Definition: shlfolder.c:183
Definition: scsiwmi.h:51
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
Definition: joystick.c:610
HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface, LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1322
#define open
Definition: acwin.h:95
#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
DWORD dwNumObjs
Definition: dinput.h:812
HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1076
#define WARN(fmt,...)
Definition: debug.h:112
DWORD button
Definition: button.c:166
#define DIDFT_MAKEINSTANCE(n)
Definition: dinput.h:762
#define DIDC_ATTACHED
Definition: dinput.h:945
DWORD dwObjSize
Definition: dinput.h:809
#define snprintf
Definition: wintirpc.h:48
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
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
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
int32_t INT
Definition: typedefs.h:58
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
#define sprintf(buf, format,...)
Definition: sprintf.c:55
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
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 * 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
Definition: devices.h:37
HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags)
Definition: device.c:1857
static size_t double number
Definition: printf.c:69
short SHORT
Definition: pedump.c:59
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
DWORD dwDevType
Definition: dinput.h:415
unsigned int idx
Definition: utils.c:41
void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
Definition: joystick.c:480
#define S_FALSE
Definition: winerror.h:2357
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
smooth NULL
Definition: ftsmooth.c:416
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
#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
HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1821
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 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
void _dump_DIDATAFORMAT(const DIDATAFORMAT *df)
Definition: device.c:242
#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:484
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)
HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df)
Definition: device.c:1135
#define DIERR_OUTOFMEMORY
Definition: dinput.h:155
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:79
int poll(struct pollfd *ufds, int nfds, int timeout)
Definition: adnstest.c:68
HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(LPDIRECTINPUTDEVICE8A iface, LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1743
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1755
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
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
HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags)
Definition: device.c:1807
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
HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8A iface, LPDIEFFECTINFOA lpdei, REFGUID rguid)
Definition: device.c:1767
WCHAR tszProductName[MAX_PATH]
Definition: dinput.h:430
int ret
#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
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
#define DI_NOEFFECT
Definition: dinput.h:132
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
uint32_t DWORD_PTR
Definition: typedefs.h:65
WCHAR tszInstanceName[MAX_PATH]
Definition: dinput.h:429
GLsizei const GLfloat * value
Definition: glext.h:6069
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 IDirectInputDevice2WImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIEFFECTINFOW lpdei, REFGUID rguid)
Definition: device.c:1777
HRESULT WINAPI JoystickAGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:906
#define ERR(fmt,...)
Definition: debug.h:110
void release_DataFormat(DataFormat *format)
Definition: device.c:391
#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
HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut)
Definition: device.c:1794
const GUID * pguid
Definition: dinput.h:800
#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 DIDEVTYPE_HID
Definition: dinput.h:201
#define DIDFT_POV
Definition: dinput.h:757
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
Definition: device.c:1316
#define HeapReAlloc
Definition: compat.h:482
#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
#define min(a, b)
Definition: monoChain.cc:55
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 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
HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
Definition: device.c:1736
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
HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
Definition: device.c:1813
Definition: name.c:38
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
GLuint res
Definition: glext.h:9613
#define DI_OK
Definition: dinput.h:128
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
Definition: device.c:1108
GLenum GLuint id
Definition: glext.h:5579
#define IS_DIPROP(x)
int id_to_object(LPCDIDATAFORMAT df, int id)
Definition: device.c:588
#define DI8DEVCLASS_GAMECTRL
Definition: dinput.h:207
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define E_POINTER
Definition: winerror.h:2365
#define memset(x, y, z)
Definition: compat.h:39
#define DIPROP_VIDPID
Definition: dinput.h:918
#define TRACE_ON(x)
Definition: compat.h:75
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags)
Definition: joystick.c:936
struct DIPROPDWORD * LPDIPROPDWORD
#define LOWORD(l)
Definition: pedump.c:82
#define HeapFree(x, y, z)
Definition: compat.h:483
HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event)
Definition: device.c:1224
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
Definition: device.c:1787
_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
const struct dinput_device joystick_linux_device