ReactOS  0.4.15-dev-4853-g3a72a52
effect_linuxinput.c
Go to the documentation of this file.
1 /* DirectInput Linux Event Device Effect
2  *
3  * Copyright 2005 Daniel Remenak
4  *
5  * Thanks to Google's Summer of Code Program (2005)
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 #include "config.h"
23 
24 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
25 
26 #include <stdarg.h>
27 #include <string.h>
28 #ifdef HAVE_LINUX_INPUT_H
29 # include <linux/input.h>
30 # undef SW_MAX
31 #endif
32 #include <limits.h>
33 #include <errno.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include <math.h>
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
40 #include "windef.h"
41 #include "winbase.h"
42 #include "winerror.h"
43 #include "dinput.h"
44 
45 #include "device_private.h"
46 #include "joystick_private.h"
47 
49 
50 static const IDirectInputEffectVtbl LinuxInputEffectVtbl;
51 typedef struct LinuxInputEffectImpl LinuxInputEffectImpl;
52 struct LinuxInputEffectImpl
53 {
54  IDirectInputEffect IDirectInputEffect_iface;
55  LONG ref;
56  GUID guid;
57 
58  struct ff_effect effect; /* Effect data */
59  int gain; /* Effect gain */
60  BOOL first_axis_is_x;
61  int* fd; /* Parent device */
62  struct list *entry; /* Entry into the parent's list of effects */
63 };
64 
65 static inline LinuxInputEffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
66 {
67  return CONTAINING_RECORD(iface, LinuxInputEffectImpl, IDirectInputEffect_iface);
68 }
69 
70 static double ff_effect_direction_to_rad(unsigned int dir)
71 {
72  return (dir & 0xffff) * M_PI / 0x8000;
73 }
74 
75 static void ff_dump_effect(struct ff_effect *effect)
76 {
77  const char *type = "(Unknown)", *length = "INFINITE";
78  struct ff_envelope *env = NULL;
79  double angle;
80 #define FE(x) case x: type = #x; break
81  switch (effect->type)
82  {
83  FE(FF_RUMBLE);
84  FE(FF_PERIODIC);
85  FE(FF_CONSTANT);
86  FE(FF_SPRING);
87  FE(FF_FRICTION);
88  FE(FF_DAMPER);
89  FE(FF_INERTIA);
90  FE(FF_RAMP);
91  }
92 #undef FE
93 
94  /* rotate so 0 points right */
95  angle = 360 - ff_effect_direction_to_rad(effect->direction + 0xc000) * 180 / M_PI;
96 
97  if (effect->replay.length)
98  length = wine_dbg_sprintf("%u ms", effect->replay.length);
99 
100  TRACE("type 0x%x %s, id %d, direction 0x%x (source angle %.2f), time length %s, start delay %u ms\n",
101  effect->type, type, effect->id, effect->direction, angle, length, effect->replay.delay);
102  if (effect->trigger.button || effect->trigger.interval)
103  TRACE(" -> trigger button %u, re-trigger interval %u ms\n",
104  effect->trigger.button, effect->trigger.interval);
105 
106  if (effect->type == FF_PERIODIC)
107  {
108  struct ff_periodic_effect *per = &effect->u.periodic;
109  const char *wave = "(Unknown)";
110 #define FE(x) case x: wave = #x; break
111  switch (per->waveform)
112  {
113  FE(FF_SQUARE);
114  FE(FF_TRIANGLE);
115  FE(FF_SINE);
116  FE(FF_SAW_UP);
117  FE(FF_SAW_DOWN);
118  FE(FF_CUSTOM);
119  }
120 #undef FE
121  angle = ff_effect_direction_to_rad(per->phase) * 180 / M_PI;
122  TRACE(" -> waveform 0x%x %s, period %u ms, magnitude %d, offset %d, phase 0x%x (angle %.2f), custom len %d\n",
123  per->waveform, wave, per->period, per->magnitude, per->offset, per->phase, angle, per->custom_len);
124  env = &per->envelope;
125  }
126  else if (effect->type == FF_CONSTANT)
127  {
128  struct ff_constant_effect *cons = &effect->u.constant;
129  TRACE(" -> level %d\n", cons->level);
130  env = &cons->envelope;
131  }
132  else if (effect->type == FF_RAMP)
133  {
134  struct ff_ramp_effect *ramp = &effect->u.ramp;
135  TRACE(" -> start/end level %d/%d\n", ramp->start_level, ramp->end_level);
136  env = &ramp->envelope;
137  }
138  else if (effect->type == FF_RUMBLE)
139  {
140  struct ff_rumble_effect *rumble = &effect->u.rumble;
141  TRACE(" -> strong/weak magnitude %u/%u\n", rumble->strong_magnitude, rumble->weak_magnitude);
142  }
143  else if (effect->type == FF_SPRING || effect->type == FF_FRICTION ||
144  effect->type == FF_DAMPER || effect->type == FF_INERTIA)
145  {
146  struct ff_condition_effect *cond = effect->u.condition;
147  int i;
148  for (i = 0; i < 2; i++)
149  {
150  /* format numbers here to make them align correctly */
151  TRACE(" -> [%d] right/left saturation %5u/%5u, right/left coefficient %5d/%5d,"
152  " deadband %5u, center %5d\n", i, cond[i].right_saturation, cond[i].left_saturation,
153  cond[i].right_coeff, cond[i].left_coeff, cond[i].deadband, cond[i].center);
154  }
155  }
156 
157  if (env)
158  TRACE(" -> envelope attack length(ms)/level %u/%u, fade length(ms)/level %u/%u\n",
159  env->attack_length, env->attack_level, env->fade_length, env->fade_level);
160 }
161 
162 /******************************************************************************
163  * LinuxInputEffectImpl
164  */
165 
166 static ULONG WINAPI LinuxInputEffectImpl_AddRef(
167  LPDIRECTINPUTEFFECT iface)
168 {
169  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
171  TRACE( "(%p) ref %d\n", This, ref );
172  return ref;
173 }
174 
175 static HRESULT WINAPI LinuxInputEffectImpl_Download(
176  LPDIRECTINPUTEFFECT iface)
177 {
178  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
179  int ret, old_effect_id;
180 
181  TRACE("(this=%p)\n", This);
182  ff_dump_effect(&This->effect);
183 
184  old_effect_id = This->effect.id;
185  if (ioctl(*(This->fd), EVIOCSFF, &This->effect) != -1)
186  return DI_OK;
187 
188  /* Linux kernel < 3.14 has a bug that incorrectly assigns an effect ID even
189  * on error, restore it here if that is the case. */
190  This->effect.id = old_effect_id;
191 
192  switch (errno)
193  {
194  case EINVAL:
196  break;
197  case ENOSPC:
199  break;
200  case ENOMEM:
202  break;
203  default:
205  break;
206  }
207  TRACE("Could not upload effect to fd %d, errno %d \"%s\", returning 0x%x.\n",
208  *This->fd, errno, strerror(errno), ret);
209  return ret;
210 }
211 
212 static HRESULT WINAPI LinuxInputEffectImpl_Escape(
213  LPDIRECTINPUTEFFECT iface,
214  LPDIEFFESCAPE pesc)
215 {
216  WARN("(this=%p,%p): invalid: no hardware-specific escape codes in this"
217  " driver!\n", iface, pesc);
218 
219  return DI_OK;
220 }
221 
222 static HRESULT WINAPI LinuxInputEffectImpl_GetEffectGuid(
223  LPDIRECTINPUTEFFECT iface,
224  LPGUID pguid)
225 {
226  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
227 
228  TRACE("(this=%p,%p)\n", This, pguid);
229 
230  *pguid = This->guid;
231 
232  return DI_OK;
233 }
234 
235 static HRESULT WINAPI LinuxInputEffectImpl_GetEffectStatus(
236  LPDIRECTINPUTEFFECT iface,
237  LPDWORD pdwFlags)
238 {
239  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
240 
241  TRACE("(this=%p,%p)\n", This, pdwFlags);
242 
243  if (!pdwFlags)
244  return E_POINTER;
245 
246  if (This->effect.id == -1)
247  return DIERR_NOTDOWNLOADED;
248 
249  /* linux sends the effect status through an event.
250  * that event is trapped by our parent joystick driver
251  * and there is no clean way to pass it back to us. */
252  FIXME("Not enough information to provide a status.\n");
253 
254  (*pdwFlags) = 0;
255 
256  return DI_OK;
257 }
258 
259 static HRESULT WINAPI LinuxInputEffectImpl_GetParameters(
260  LPDIRECTINPUTEFFECT iface,
261  LPDIEFFECT peff,
262  DWORD dwFlags)
263 {
264  HRESULT diErr = DI_OK;
265  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
266  TRACE("(this=%p,%p,%d)\n", This, peff, dwFlags);
267 
268  /* Major conversion factors are:
269  * times: millisecond (linux) -> microsecond (windows) (x * 1000)
270  * forces: scale 0x7FFF (linux) -> scale 10000 (windows) approx ((x / 33) * 10)
271  * angles: scale 0x7FFF (linux) -> scale 35999 (windows) approx ((x / 33) * 36)
272  * angle bases: 0 -> -y (down) (linux) -> 0 -> +x (right) (windows)
273  */
274 
275  if (dwFlags & DIEP_AXES) {
276  if (peff->cAxes < 2 /* linuxinput effects always use 2 axes, x and y */)
277  diErr = DIERR_MOREDATA;
278  peff->cAxes = 2;
279  if (diErr)
280  return diErr;
281  else {
282  peff->rgdwAxes[0] = DIJOFS_X;
283  peff->rgdwAxes[1] = DIJOFS_Y;
284  }
285  }
286 
287  if (dwFlags & DIEP_DIRECTION) {
288  if (peff->cAxes < 2)
289  diErr = DIERR_MOREDATA;
290  peff->cAxes = 2;
291  if (diErr)
292  return diErr;
293  else {
294  if (peff->dwFlags & DIEFF_CARTESIAN) {
295  /* rotate so 0 points right */
296  double angle = ff_effect_direction_to_rad(This->effect.direction + 0xc000);
297  peff->rglDirection[0] = sin(angle) * 1000;
298  peff->rglDirection[1] = -cos(angle) * 1000;
299  } else {
300  /* Polar and spherical coordinates are the same for two or less
301  * axes.
302  * Note that we also use this case if NO flags are marked.
303  * According to MSDN, we should return the direction in the
304  * format that it was specified in, if no flags are marked.
305  */
306  peff->rglDirection[0] = (This->effect.direction / 33) * 36 + 9000;
307  if (peff->rglDirection[0] > 35999)
308  peff->rglDirection[0] -= 35999;
309  }
310  }
311  }
312 
313  if (dwFlags & DIEP_DURATION)
314  {
315  if (!This->effect.replay.length) /* infinite for the linux driver */
316  peff->dwDuration = INFINITE;
317  else
318  peff->dwDuration = (DWORD)This->effect.replay.length * 1000;
319  }
320 
321  if (dwFlags & DIEP_ENVELOPE) {
322  struct ff_envelope* env;
323  if (This->effect.type == FF_CONSTANT) env = &This->effect.u.constant.envelope;
324  else if (This->effect.type == FF_PERIODIC) env = &This->effect.u.periodic.envelope;
325  else if (This->effect.type == FF_RAMP) env = &This->effect.u.ramp.envelope;
326  else env = NULL;
327  if (env == NULL) {
328  peff->lpEnvelope = NULL;
329  } else if (peff->lpEnvelope == NULL) {
330  return DIERR_INVALIDPARAM;
331  } else {
332  peff->lpEnvelope->dwAttackLevel = (env->attack_level / 33) * 10;
333  peff->lpEnvelope->dwAttackTime = env->attack_length * 1000;
334  peff->lpEnvelope->dwFadeLevel = (env->fade_level / 33) * 10;
335  peff->lpEnvelope->dwFadeTime = env->fade_length * 1000;
336  }
337  }
338 
339  if (dwFlags & DIEP_GAIN) {
340  peff->dwGain = This->gain * 10000 / 0xFFFF;
341  }
342 
343  if (dwFlags & DIEP_SAMPLEPERIOD) {
344  /* the linux input ff driver has no support for setting
345  * the playback sample period. 0 means default. */
346  peff->dwSamplePeriod = 0;
347  }
348 
349  if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5))
350  peff->dwStartDelay = This->effect.replay.delay * 1000;
351 
352  if (dwFlags & DIEP_TRIGGERBUTTON) {
353  FIXME("LinuxInput button mapping needs redoing; for now, assuming we're using an actual joystick.\n");
354  peff->dwTriggerButton = DIJOFS_BUTTON(This->effect.trigger.button - BTN_JOYSTICK);
355  }
356 
358  peff->dwTriggerRepeatInterval = This->effect.trigger.interval * 1000;
359  }
360 
362  DWORD expectedsize = 0;
363  if (This->effect.type == FF_PERIODIC) {
364  expectedsize = sizeof(DIPERIODIC);
365  } else if (This->effect.type == FF_CONSTANT) {
366  expectedsize = sizeof(DICONSTANTFORCE);
367  } else if (This->effect.type == FF_SPRING
368  || This->effect.type == FF_FRICTION
369  || This->effect.type == FF_INERTIA
370  || This->effect.type == FF_DAMPER) {
371  expectedsize = sizeof(DICONDITION) * 2;
372  } else if (This->effect.type == FF_RAMP) {
373  expectedsize = sizeof(DIRAMPFORCE);
374  }
375  if (expectedsize > peff->cbTypeSpecificParams)
376  diErr = DIERR_MOREDATA;
377  peff->cbTypeSpecificParams = expectedsize;
378  if (diErr)
379  return diErr;
380  else {
381  if (This->effect.type == FF_PERIODIC) {
383  tsp->dwMagnitude = (This->effect.u.periodic.magnitude / 33) * 10;
384  tsp->lOffset = (This->effect.u.periodic.offset / 33) * 10;
385  tsp->dwPhase = (This->effect.u.periodic.phase / 33) * 36;
386  tsp->dwPeriod = (This->effect.u.periodic.period * 1000);
387  } else if (This->effect.type == FF_CONSTANT) {
389  tsp->lMagnitude = (This->effect.u.constant.level / 33) * 10;
390  } else if (This->effect.type == FF_SPRING
391  || This->effect.type == FF_FRICTION
392  || This->effect.type == FF_INERTIA
393  || This->effect.type == FF_DAMPER) {
395  int i;
396  for (i = 0; i < 2; ++i) {
397  tsp[i].lOffset = (This->effect.u.condition[i].center / 33) * 10;
398  tsp[i].lPositiveCoefficient = (This->effect.u.condition[i].right_coeff / 33) * 10;
399  tsp[i].lNegativeCoefficient = (This->effect.u.condition[i].left_coeff / 33) * 10;
400  tsp[i].dwPositiveSaturation = (This->effect.u.condition[i].right_saturation / 33) * 10;
401  tsp[i].dwNegativeSaturation = (This->effect.u.condition[i].left_saturation / 33) * 10;
402  tsp[i].lDeadBand = (This->effect.u.condition[i].deadband / 33) * 10;
403  }
404  } else if (This->effect.type == FF_RAMP) {
406  tsp->lStart = (This->effect.u.ramp.start_level / 33) * 10;
407  tsp->lEnd = (This->effect.u.ramp.end_level / 33) * 10;
408  }
409  }
410  }
411 
412  return diErr;
413 }
414 
415 static HRESULT WINAPI LinuxInputEffectImpl_Initialize(
416  LPDIRECTINPUTEFFECT iface,
418  DWORD dwVersion,
419  REFGUID rguid)
420 {
421  FIXME("(this=%p,%p,%d,%s): stub!\n",
422  iface, hinst, dwVersion, debugstr_guid(rguid));
423 
424  return DI_OK;
425 }
426 
427 static HRESULT WINAPI LinuxInputEffectImpl_QueryInterface(
428  LPDIRECTINPUTEFFECT iface,
429  REFIID riid,
430  void **ppvObject)
431 {
432  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
433 
434  TRACE("(this=%p,%s,%p)\n", This, debugstr_guid(riid), ppvObject);
435 
436  if (IsEqualGUID(&IID_IUnknown, riid) ||
437  IsEqualGUID(&IID_IDirectInputEffect, riid)) {
438  LinuxInputEffectImpl_AddRef(iface);
439  *ppvObject = This;
440  return 0;
441  }
442 
443  TRACE("Unsupported interface!\n");
444  return E_FAIL;
445 }
446 
447 static HRESULT WINAPI LinuxInputEffectImpl_Start(
448  LPDIRECTINPUTEFFECT iface,
449  DWORD dwIterations,
450  DWORD dwFlags)
451 {
452  struct input_event event;
453  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
454 
455  TRACE("(this=%p,%d,%d)\n", This, dwIterations, dwFlags);
456 
457  if (!(dwFlags & DIES_NODOWNLOAD)) {
458  /* Download the effect if necessary */
459  if (This->effect.id == -1) {
460  HRESULT res = LinuxInputEffectImpl_Download(iface);
461  if (res != DI_OK)
462  return res;
463  }
464  }
465 
466  if (dwFlags & DIES_SOLO) {
467  FIXME("Solo mode requested: should be stopping all effects here!\n");
468  }
469 
470  event.type = EV_FF;
471  event.code = This->effect.id;
472  event.value = min( dwIterations, INT_MAX );
473  if (write(*(This->fd), &event, sizeof(event)) == -1) {
474  FIXME("Unable to write event. Assuming device disconnected.\n");
475  return DIERR_INPUTLOST;
476  }
477 
478  return DI_OK;
479 }
480 
481 static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
482  LPDIRECTINPUTEFFECT iface,
483  LPCDIEFFECT peff,
484  DWORD dwFlags)
485 {
486  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
487  DWORD type = typeFromGUID(&This->guid);
488  HRESULT retval = DI_OK;
489 
490  TRACE("(this=%p,%p,%d)\n", This, peff, dwFlags);
491 
492  dump_DIEFFECT(peff, &This->guid, dwFlags);
493 
494  if ((dwFlags & ~DIEP_NORESTART & ~DIEP_NODOWNLOAD & ~DIEP_START) == 0) {
495  /* set everything */
499  }
500 
501  if (dwFlags & DIEP_AXES) {
502  /* the linux input effect system only supports one or two axes */
503  if (peff->cAxes > 2)
504  return DIERR_INVALIDPARAM;
505  else if (peff->cAxes < 1)
506  return DIERR_INCOMPLETEEFFECT;
507  This->first_axis_is_x = peff->rgdwAxes[0] == DIJOFS_X;
508  }
509 
510  /* some of this may look funky, but it's 'cause the linux driver and directx have
511  * different opinions about which way direction "0" is. directx has 0 along the x
512  * axis (left), linux has it along the y axis (down). */
513  if (dwFlags & DIEP_DIRECTION) {
514  if (peff->cAxes == 1) {
515  if (peff->dwFlags & DIEFF_CARTESIAN) {
516  if (dwFlags & DIEP_AXES) {
517  if (peff->rgdwAxes[0] == DIJOFS_X && peff->rglDirection[0] >= 0)
518  This->effect.direction = 0x4000;
519  else if (peff->rgdwAxes[0] == DIJOFS_X && peff->rglDirection[0] < 0)
520  This->effect.direction = 0xC000;
521  else if (peff->rgdwAxes[0] == DIJOFS_Y && peff->rglDirection[0] >= 0)
522  This->effect.direction = 0;
523  else if (peff->rgdwAxes[0] == DIJOFS_Y && peff->rglDirection[0] < 0)
524  This->effect.direction = 0x8000;
525  }
526  } else {
527  /* one-axis effects must use cartesian coords */
528  return DIERR_INVALIDPARAM;
529  }
530  }
531  /* two axes */
532  else
533  {
534  if (peff->dwFlags & DIEFF_CARTESIAN)
535  {
536  LONG x, y;
537  if (This->first_axis_is_x)
538  {
539  x = peff->rglDirection[0];
540  y = peff->rglDirection[1];
541  }
542  else
543  {
544  x = peff->rglDirection[1];
545  y = peff->rglDirection[0];
546  }
547  This->effect.direction = (unsigned int)((M_PI / 2 + atan2(y, x)) * 0x8000 / M_PI);
548  }
549  else
550  {
551  /* Polar and spherical are the same for 2 axes */
552  /* Precision is important here, so we do double math with exact constants */
553  This->effect.direction = (unsigned int)(((double)peff->rglDirection[0] / 18000) * 0x8000);
554  }
555  }
556  }
557 
558  if (dwFlags & DIEP_DURATION)
559  {
560  if (peff->dwDuration == INFINITE)
561  This->effect.replay.length = 0; /* infinite for the linux driver */
562  else if(peff->dwDuration > 1000)
563  This->effect.replay.length = peff->dwDuration / 1000;
564  else
565  This->effect.replay.length = 1;
566  }
567 
568  if (dwFlags & DIEP_ENVELOPE)
569  {
570  struct ff_envelope* env;
571  if (This->effect.type == FF_CONSTANT)
572  env = &This->effect.u.constant.envelope;
573  else if (This->effect.type == FF_PERIODIC)
574  env = &This->effect.u.periodic.envelope;
575  else if (This->effect.type == FF_RAMP)
576  env = &This->effect.u.ramp.envelope;
577  else
578  env = NULL;
579 
580  /* copy the envelope if it is present and the linux effect supports it */
581  if (peff->lpEnvelope && env)
582  {
583  env->attack_length = peff->lpEnvelope->dwAttackTime / 1000;
584  env->attack_level = (peff->lpEnvelope->dwAttackLevel / 10) * 32;
585  env->fade_length = peff->lpEnvelope->dwFadeTime / 1000;
586  env->fade_level = (peff->lpEnvelope->dwFadeLevel / 10) * 32;
587  }
588  /* if the dinput envelope is NULL we will clear the linux envelope */
589  else if (env)
590  {
591  env->attack_length = 0;
592  env->attack_level = 0;
593  env->fade_length = 0;
594  env->fade_level = 0;
595  }
596  else if(peff->lpEnvelope)
597  {
598  if(peff->lpEnvelope->dwAttackTime || peff->lpEnvelope->dwAttackLevel ||
599  peff->lpEnvelope->dwFadeTime || peff->lpEnvelope->dwFadeLevel)
600  WARN("Ignoring dinput envelope not supported in the linux effect\n");
601  }
602  }
603 
604  /* Gain and Sample Period settings are not supported by the linux
605  * event system */
606  if (dwFlags & DIEP_GAIN) {
607  This->gain = 0xFFFF * peff->dwGain / 10000;
608  TRACE("Effect gain requested but no effect gain functionality present.\n");
609  }
610 
612  TRACE("Sample period requested but no sample period functionality present.\n");
613 
614  if (dwFlags & DIEP_STARTDELAY)
615  if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5))
616  This->effect.replay.delay = peff->dwStartDelay / 1000;
617 
618  if (dwFlags & DIEP_TRIGGERBUTTON) {
619  if (peff->dwTriggerButton != -1) {
620  FIXME("Linuxinput button mapping needs redoing, assuming we're using a joystick.\n");
621  FIXME("Trigger button translation not yet implemented!\n");
622  }
623  This->effect.trigger.button = 0;
624  }
625 
627  This->effect.trigger.interval = peff->dwTriggerRepeatInterval / 1000;
628 
630  {
631  if (!(peff->lpvTypeSpecificParams))
632  return DIERR_INCOMPLETEEFFECT;
633 
634  if (type == DIEFT_PERIODIC)
635  {
636  DIPERIODIC *tsp;
637  if (peff->cbTypeSpecificParams != sizeof(DIPERIODIC))
638  return DIERR_INVALIDPARAM;
639  tsp = peff->lpvTypeSpecificParams;
640 
641  This->effect.u.periodic.magnitude = (tsp->dwMagnitude / 10) * 32;
642  This->effect.u.periodic.offset = (tsp->lOffset / 10) * 32;
643  /* phase ranges from 0 - 35999 in dinput and 0 - 65535 on Linux */
644  This->effect.u.periodic.phase = (tsp->dwPhase / 36) * 65;
645  /* dinput uses microseconds, Linux uses milliseconds */
646  if (tsp->dwPeriod <= 1000)
647  This->effect.u.periodic.period = 1;
648  else
649  This->effect.u.periodic.period = tsp->dwPeriod / 1000;
650  }
651  else if (type == DIEFT_CONSTANTFORCE)
652  {
653  LPCDICONSTANTFORCE tsp;
654  if (peff->cbTypeSpecificParams != sizeof(DICONSTANTFORCE))
655  return DIERR_INVALIDPARAM;
656  tsp = peff->lpvTypeSpecificParams;
657  This->effect.u.constant.level = (max(min(tsp->lMagnitude, 10000), -10000) / 10) * 32;
658  } else if (type == DIEFT_RAMPFORCE) {
659  LPCDIRAMPFORCE tsp;
660  if (peff->cbTypeSpecificParams != sizeof(DIRAMPFORCE))
661  return DIERR_INVALIDPARAM;
662  tsp = peff->lpvTypeSpecificParams;
663  This->effect.u.ramp.start_level = (tsp->lStart / 10) * 32;
664  This->effect.u.ramp.end_level = (tsp->lEnd / 10) * 32;
665  }
666  else if (type == DIEFT_CONDITION)
667  {
668  DICONDITION *tsp = peff->lpvTypeSpecificParams;
669  struct ff_condition_effect *cond = This->effect.u.condition;
670  int i, j, sources;
671  double factor[2];
672 
673  if (peff->cbTypeSpecificParams == sizeof(DICONDITION))
674  {
675  /* One condition block. This needs to be rotated to direction,
676  * and expanded to separate x and y conditions. Ensures 0 points right */
677  double angle = ff_effect_direction_to_rad(This->effect.direction + 0xc000);
678  factor[0] = sin(angle);
679  factor[1] = -cos(angle);
680  sources = 1;
681  }
682  else if (peff->cbTypeSpecificParams == 2 * sizeof(DICONDITION))
683  {
684  /* Direct parameter copy without changes */
685  factor[0] = factor[1] = 1;
686  sources = 2;
687  }
688  else
689  return DIERR_INVALIDPARAM;
690 
691  for (i = j = 0; i < 2; ++i)
692  {
693  cond[i].center = (int)(factor[i] * (tsp[j].lOffset / 10) * 32);
694  cond[i].right_coeff = (int)(factor[i] * (tsp[j].lPositiveCoefficient / 10) * 32);
695  cond[i].left_coeff = (int)(factor[i] * (tsp[j].lNegativeCoefficient / 10) * 32);
696  cond[i].right_saturation = (int)(factor[i] * (tsp[j].dwPositiveSaturation / 10) * 65);
697  cond[i].left_saturation = (int)(factor[i] * (tsp[j].dwNegativeSaturation / 10) * 65);
698  cond[i].deadband = (int)(factor[i] * (tsp[j].lDeadBand / 10) * 32);
699  if (sources == 2)
700  j++;
701  }
702  }
703  else
704  {
705  FIXME("Custom force types are not supported\n");
706  return DIERR_INVALIDPARAM;
707  }
708  }
709 
710  if (!(dwFlags & DIEP_NODOWNLOAD))
711  retval = LinuxInputEffectImpl_Download(iface);
712  if (retval != DI_OK)
713  return DI_DOWNLOADSKIPPED;
714 
715  if (dwFlags & DIEP_NORESTART)
716  TRACE("DIEP_NORESTART: not handled (we have no control of that).\n");
717 
718  if (dwFlags & DIEP_START)
719  retval = LinuxInputEffectImpl_Start(iface, 1, 0);
720  if (retval != DI_OK)
721  return retval;
722 
723  return DI_OK;
724 }
725 
726 static HRESULT WINAPI LinuxInputEffectImpl_Stop(
727  LPDIRECTINPUTEFFECT iface)
728 {
729  struct input_event event;
730  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
731 
732  TRACE("(this=%p)\n", This);
733 
734  event.type = EV_FF;
735  event.code = This->effect.id;
736  event.value = 0;
737  /* we don't care about the success or failure of this call */
738  write(*(This->fd), &event, sizeof(event));
739 
740  return DI_OK;
741 }
742 
743 static HRESULT WINAPI LinuxInputEffectImpl_Unload(
744  LPDIRECTINPUTEFFECT iface)
745 {
746  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
747  TRACE("(this=%p)\n", This);
748 
749  /* Erase the downloaded effect */
750  if (ioctl(*(This->fd), EVIOCRMFF, This->effect.id) == -1)
751  return DIERR_INVALIDPARAM;
752 
753  /* Mark the effect as deallocated */
754  This->effect.id = -1;
755 
756  return DI_OK;
757 }
758 
759 static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface)
760 {
761  LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
762  ULONG ref = InterlockedDecrement(&(This->ref));
763 
764  TRACE( "(%p) ref %d\n", This, ref );
765 
766  if (ref == 0)
767  {
768  LinuxInputEffectImpl_Stop(iface);
769  LinuxInputEffectImpl_Unload(iface);
770  list_remove(This->entry);
773  }
774  return ref;
775 }
776 
777 /******************************************************************************
778  * LinuxInputEffect
779  */
780 
781 DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(
782  int* fd,
783  REFGUID rguid,
784  struct list *parent_list_entry,
785  LPDIRECTINPUTEFFECT* peff)
786 {
787  LinuxInputEffectImpl* newEffect = HeapAlloc(GetProcessHeap(),
788  HEAP_ZERO_MEMORY, sizeof(LinuxInputEffectImpl));
789  DWORD type = typeFromGUID(rguid);
790 
791  newEffect->IDirectInputEffect_iface.lpVtbl = &LinuxInputEffectVtbl;
792  newEffect->ref = 1;
793  newEffect->guid = *rguid;
794  newEffect->fd = fd;
795  newEffect->gain = 0xFFFF;
796 
797  /* set the type. this cannot be changed over the effect's life. */
798  switch (type) {
799  case DIEFT_PERIODIC:
800  newEffect->effect.type = FF_PERIODIC;
801  if (IsEqualGUID(rguid, &GUID_Sine)) {
802  newEffect->effect.u.periodic.waveform = FF_SINE;
803  } else if (IsEqualGUID(rguid, &GUID_Triangle)) {
804  newEffect->effect.u.periodic.waveform = FF_TRIANGLE;
805  } else if (IsEqualGUID(rguid, &GUID_Square)) {
806  newEffect->effect.u.periodic.waveform = FF_SQUARE;
807  } else if (IsEqualGUID(rguid, &GUID_SawtoothUp)) {
808  newEffect->effect.u.periodic.waveform = FF_SAW_UP;
809  } else if (IsEqualGUID(rguid, &GUID_SawtoothDown)) {
810  newEffect->effect.u.periodic.waveform = FF_SAW_DOWN;
811  }
812  break;
813  case DIEFT_CONSTANTFORCE:
814  newEffect->effect.type = FF_CONSTANT;
815  break;
816  case DIEFT_RAMPFORCE:
817  newEffect->effect.type = FF_RAMP;
818  break;
819  case DIEFT_CONDITION:
820  if (IsEqualGUID(rguid, &GUID_Spring)) {
821  newEffect->effect.type = FF_SPRING;
822  } else if (IsEqualGUID(rguid, &GUID_Friction)) {
823  newEffect->effect.type = FF_FRICTION;
824  } else if (IsEqualGUID(rguid, &GUID_Inertia)) {
825  newEffect->effect.type = FF_INERTIA;
826  } else if (IsEqualGUID(rguid, &GUID_Damper)) {
827  newEffect->effect.type = FF_DAMPER;
828  }
829  break;
830  case DIEFT_CUSTOMFORCE:
831  FIXME("Custom forces are not supported.\n");
832  HeapFree(GetProcessHeap(), 0, newEffect);
833  return DIERR_INVALIDPARAM;
834  default:
835  FIXME("Unknown force type 0x%x.\n", type);
836  HeapFree(GetProcessHeap(), 0, newEffect);
837  return DIERR_INVALIDPARAM;
838  }
839 
840  /* mark as non-uploaded */
841  newEffect->effect.id = -1;
842 
843  newEffect->entry = parent_list_entry;
844 
845  *peff = &newEffect->IDirectInputEffect_iface;
846 
847  TRACE("Creating linux input system effect (%p) with guid %s\n",
848  *peff, _dump_dinput_GUID(rguid));
849 
850  return DI_OK;
851 }
852 
853 DECLSPEC_HIDDEN HRESULT linuxinput_get_info_A(
854  int fd,
855  REFGUID rguid,
857 {
858  DWORD type = typeFromGUID(rguid);
859 
860  TRACE("(%d, %s, %p) type=%d\n", fd, _dump_dinput_GUID(rguid), info, type);
861 
862  if (!info) return E_POINTER;
863 
864  if (info->dwSize != sizeof(DIEFFECTINFOA)) return DIERR_INVALIDPARAM;
865 
866  info->guid = *rguid;
867 
868  info->dwEffType = type;
869  /* the event device API does not support querying for all these things
870  * therefore we assume that we have support for them
871  * that's not as dangerous as it sounds, since drivers are allowed to
872  * ignore parameters they claim to support anyway */
876 
877  /* again, assume we have support for everything */
878  info->dwStaticParams = DIEP_ALLPARAMS;
879  info->dwDynamicParams = info->dwStaticParams;
880 
881  /* yes, this is windows behavior (print the GUID_Name for name) */
882  strcpy(info->tszName, _dump_dinput_GUID(rguid));
883 
884  return DI_OK;
885 }
886 
887 DECLSPEC_HIDDEN HRESULT linuxinput_get_info_W(
888  int fd,
889  REFGUID rguid,
891 {
892  DWORD type = typeFromGUID(rguid);
893 
894  TRACE("(%d, %s, %p) type=%d\n", fd, _dump_dinput_GUID(rguid), info, type);
895 
896  if (!info) return E_POINTER;
897 
898  if (info->dwSize != sizeof(DIEFFECTINFOW)) return DIERR_INVALIDPARAM;
899 
900  info->guid = *rguid;
901 
902  info->dwEffType = type;
903  /* the event device API does not support querying for all these things
904  * therefore we assume that we have support for them
905  * that's not as dangerous as it sounds, since drivers are allowed to
906  * ignore parameters they claim to support anyway */
910 
911  /* again, assume we have support for everything */
912  info->dwStaticParams = DIEP_ALLPARAMS;
913  info->dwDynamicParams = info->dwStaticParams;
914 
915  /* yes, this is windows behavior (print the GUID_Name for name) */
917  info->tszName, MAX_PATH);
918 
919  return DI_OK;
920 }
921 
922 static const IDirectInputEffectVtbl LinuxInputEffectVtbl = {
923  LinuxInputEffectImpl_QueryInterface,
924  LinuxInputEffectImpl_AddRef,
925  LinuxInputEffectImpl_Release,
926  LinuxInputEffectImpl_Initialize,
927  LinuxInputEffectImpl_GetEffectGuid,
928  LinuxInputEffectImpl_GetParameters,
929  LinuxInputEffectImpl_SetParameters,
930  LinuxInputEffectImpl_Start,
931  LinuxInputEffectImpl_Stop,
932  LinuxInputEffectImpl_GetEffectStatus,
933  LinuxInputEffectImpl_Download,
934  LinuxInputEffectImpl_Unload,
935  LinuxInputEffectImpl_Escape
936 };
937 
938 #endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */
DWORD cAxes
Definition: dinput.h:1112
#define DIEP_AXES
Definition: dinput.h:1019
DWORD dwTriggerRepeatInterval
Definition: dinput.h:1111
DWORD dwDuration
Definition: dinput.h:1107
#define max(a, b)
Definition: svc.c:63
#define DIEFT_CONDITION
Definition: dinput.h:996
#define REFIID
Definition: guiddef.h:118
valarray< _Tp > atan2(const valarray< _Tp > &__x, const valarray< _Tp > &__y)
Definition: _valarray.h:928
LONG lMagnitude
Definition: dinput.h:1042
DWORD dwFadeTime
Definition: dinput.h:1083
LPDIENVELOPE lpEnvelope
Definition: dinput.h:1115
#define INT_MAX
Definition: limits.h:40
Definition: scsiwmi.h:51
#define DIEFT_DEADBAND
Definition: dinput.h:1004
const char * _dump_dinput_GUID(const GUID *guid)
Definition: device.c:197
DWORD dwFadeLevel
Definition: dinput.h:1082
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 factor
Definition: glfuncs.h:178
REFIID riid
Definition: precomp.h:44
#define CP_ACP
Definition: compat.h:109
Definition: arc.h:39
#define DIEFT_PERIODIC
Definition: dinput.h:995
DWORD dwPositiveSaturation
Definition: dinput.h:1064
#define WARN(fmt,...)
Definition: debug.h:112
#define DIEP_GAIN
Definition: dinput.h:1016
#define DIJOFS_BUTTON(n)
Definition: dinput.h:1215
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
static int fd
Definition: io.c:51
DWORD dwGain
Definition: dinput.h:1109
#define DIEFT_STARTDELAY
Definition: dinput.h:1005
LPVOID lpvTypeSpecificParams
Definition: dinput.h:1117
#define DIES_SOLO
Definition: dinput.h:1031
int errno
GLfloat angle
Definition: glext.h:10853
static const BYTE ramp[17]
Definition: dib.c:2709
unsigned char wave[]
Definition: in.h:3
struct DICONDITION DICONDITION
#define E_FAIL
Definition: ddrawi.h:102
DWORD typeFromGUID(REFGUID guid)
Definition: joystick.c:82
const char * strerror(int err)
Definition: compat_str.c:23
#define DIEFT_FFFADE
Definition: dinput.h:1000
#define DWORD
Definition: nt_native.h:44
Definition: send.c:48
Definition: arc.h:48
DWORD dwStartDelay
Definition: dinput.h:1118
#define DIJOFS_X
Definition: dinput.h:1205
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define write
Definition: acwin.h:97
#define DIEP_TYPESPECIFICPARAMS
Definition: dinput.h:1022
const GUID * guid
#define DIEFT_FFATTACK
Definition: dinput.h:999
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
DWORD dwPhase
Definition: dinput.h:1055
struct DIRAMPFORCE DIRAMPFORCE
#define DIEFT_CUSTOMFORCE
Definition: dinput.h:997
#define ioctl
Definition: wintirpc.h:60
GLenum GLint ref
Definition: glext.h:6028
#define DIEFT_POSNEGCOEFFICIENTS
Definition: dinput.h:1002
#define FIXME(fmt,...)
Definition: debug.h:111
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
DWORD dwSize
Definition: dinput.h:1105
Definition: arc.h:49
_STLP_DECLSPEC complex< float > _STLP_CALL cos(const complex< float > &)
#define DIEP_DIRECTION
Definition: dinput.h:1020
GLsizei GLenum * sources
Definition: glext.h:7753
#define DIEFT_POSNEGSATURATION
Definition: dinput.h:1003
#define DIEP_TRIGGERBUTTON
Definition: dinput.h:1017
unsigned int dir
Definition: maze.c:112
#define debugstr_guid
Definition: kernel32.h:35
#define DIEP_TRIGGERREPEATINTERVAL
Definition: dinput.h:1018
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
struct DIPERIODIC DIPERIODIC
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
DWORD dwAttackTime
Definition: dinput.h:1081
#define DIJOFS_Y
Definition: dinput.h:1206
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
#define DIERR_INVALIDPARAM
Definition: dinput.h:152
LONG lStart
Definition: dinput.h:1047
LPDWORD rgdwAxes
Definition: dinput.h:1113
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define DIEP_ENVELOPE
Definition: dinput.h:1021
#define DIEFT_CONSTANTFORCE
Definition: dinput.h:993
DWORD cbTypeSpecificParams
Definition: dinput.h:1116
#define DIERR_OUTOFMEMORY
Definition: dinput.h:155
struct DICONSTANTFORCE DICONSTANTFORCE
LONG HRESULT
Definition: typedefs.h:79
const GUID IID_IUnknown
struct DIEFFECT_DX5 DIEFFECT_DX5
#define MAX_PATH
Definition: compat.h:34
#define DIES_NODOWNLOAD
Definition: dinput.h:1032
#define WINAPI
Definition: msvc.h:6
#define DIERR_DEVICEFULL
Definition: dinput.h:175
pair cons(caddr_t car, pair cdr)
Definition: tree.c:57
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DIERR_NOTDOWNLOADED
Definition: dinput.h:177
#define FE(x)
#define DIEP_NODOWNLOAD
Definition: dinput.h:1028
struct IDirectInputEffect * LPDIRECTINPUTEFFECT
Definition: dinput.h:107
#define DIEP_START
Definition: dinput.h:1026
#define DIEP_SAMPLEPERIOD
Definition: dinput.h:1015
#define DIEFF_CARTESIAN
Definition: dinput.h:1010
#define DIEP_ALLPARAMS
Definition: dinput.h:1025
int ret
#define M_PI
Definition: dib.cpp:249
#define InterlockedDecrement
Definition: armddk.h:52
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
uint32_t entry
Definition: isohybrid.c:63
void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags)
Definition: joystick.c:190
Definition: _list.h:228
REFIID LPVOID * ppvObject
Definition: precomp.h:44
DWORD dwSamplePeriod
Definition: dinput.h:1108
#define DIERR_MOREDATA
Definition: dinput.h:176
struct _cl_event * event
Definition: glext.h:7739
LPLONG rglDirection
Definition: dinput.h:1114
#define DIERR_INCOMPLETEEFFECT
Definition: dinput.h:180
LONG lDeadBand
Definition: dinput.h:1066
#define DIEP_DURATION
Definition: dinput.h:1014
#define InterlockedIncrement
Definition: armddk.h:53
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
DWORD dwMagnitude
Definition: dinput.h:1053
LONG lOffset
Definition: dinput.h:1061
DWORD dwNegativeSaturation
Definition: dinput.h:1065
#define min(a, b)
Definition: monoChain.cc:55
DWORD dwTriggerButton
Definition: dinput.h:1110
#define NULL
Definition: types.h:112
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define DIEFT_SATURATION
Definition: dinput.h:1001
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
#define MultiByteToWideChar
Definition: compat.h:110
DWORD dwAttackLevel
Definition: dinput.h:1080
LONG lNegativeCoefficient
Definition: dinput.h:1063
#define DI_DOWNLOADSKIPPED
Definition: dinput.h:134
GLuint res
Definition: glext.h:9613
#define DI_OK
Definition: dinput.h:128
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
#define DIEP_NORESTART
Definition: dinput.h:1027
unsigned int ULONG
Definition: retypes.h:1
static HINSTANCE hinst
Definition: edit.c:551
LONG lOffset
Definition: dinput.h:1054
DWORD dwFlags
Definition: dinput.h:1106
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define DIEP_STARTDELAY
Definition: dinput.h:1023
#define LIST_ENTRY(type)
Definition: queue.h:175
#define E_POINTER
Definition: winerror.h:2365
#define INFINITE
Definition: serial.h:102
LONG lPositiveCoefficient
Definition: dinput.h:1062
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define DIERR_INPUTLOST
Definition: dinput.h:163
#define HeapFree(x, y, z)
Definition: compat.h:594
LONG lEnd
Definition: dinput.h:1048
DWORD dwPeriod
Definition: dinput.h:1056
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31