ReactOS 0.4.15-dev-7924-g5949c20
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
50static const IDirectInputEffectVtbl LinuxInputEffectVtbl;
51typedef struct LinuxInputEffectImpl LinuxInputEffectImpl;
52struct 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
65static inline LinuxInputEffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
66{
67 return CONTAINING_RECORD(iface, LinuxInputEffectImpl, IDirectInputEffect_iface);
68}
69
70static double ff_effect_direction_to_rad(unsigned int dir)
71{
72 return (dir & 0xffff) * M_PI / 0x8000;
73}
74
75static 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
166static ULONG WINAPI LinuxInputEffectImpl_AddRef(
168{
169 LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
171 TRACE( "(%p) ref %d\n", This, ref );
172 return ref;
173}
174
175static HRESULT WINAPI LinuxInputEffectImpl_Download(
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
212static HRESULT WINAPI LinuxInputEffectImpl_Escape(
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
222static HRESULT WINAPI LinuxInputEffectImpl_GetEffectGuid(
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
235static HRESULT WINAPI LinuxInputEffectImpl_GetEffectStatus(
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
259static HRESULT WINAPI LinuxInputEffectImpl_GetParameters(
261 LPDIEFFECT peff,
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
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
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
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
415static HRESULT WINAPI LinuxInputEffectImpl_Initialize(
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
427static HRESULT WINAPI LinuxInputEffectImpl_QueryInterface(
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
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
447static HRESULT WINAPI LinuxInputEffectImpl_Start(
449 DWORD dwIterations,
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
481static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
483 LPCDIEFFECT peff,
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)
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
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
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 ||
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
615 if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5))
616 This->effect.replay.delay = peff->dwStartDelay / 1000;
617
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))
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 {
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 {
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
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
726static HRESULT WINAPI LinuxInputEffectImpl_Stop(
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
743static HRESULT WINAPI LinuxInputEffectImpl_Unload(
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
759static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface)
760{
761 LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
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
781DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(
782 int* fd,
783 REFGUID rguid,
784 struct list *parent_list_entry,
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;
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;
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
853DECLSPEC_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
887DECLSPEC_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
922static 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 */
_STLP_DECLSPEC complex< float > _STLP_CALL cos(const complex< float > &)
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
valarray< _Tp > atan2(const valarray< _Tp > &__x, const valarray< _Tp > &__y)
Definition: _valarray.h:928
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define write
Definition: acwin.h:97
unsigned int dir
Definition: maze.c:112
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
pair cons(caddr_t car, pair cdr)
Definition: tree.c:57
static void list_remove(struct list_entry *entry)
Definition: list.h:90
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
Definition: list.h:37
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
#define FE(x)
#define E_FAIL
Definition: ddrawi.h:102
#define DIEP_TYPESPECIFICPARAMS
Definition: dinput.h:1022
#define DIEFT_DEADBAND
Definition: dinput.h:1004
#define DIEFT_POSNEGSATURATION
Definition: dinput.h:1003
#define DIEFT_CONDITION
Definition: dinput.h:996
#define DIERR_INCOMPLETEEFFECT
Definition: dinput.h:180
#define DIEFT_STARTDELAY
Definition: dinput.h:1005
#define DIEFT_CUSTOMFORCE
Definition: dinput.h:997
#define DIERR_INVALIDPARAM
Definition: dinput.h:152
#define DIEFT_PERIODIC
Definition: dinput.h:995
#define DIEFT_CONSTANTFORCE
Definition: dinput.h:993
#define DIEP_ENVELOPE
Definition: dinput.h:1021
#define DIEFT_FFATTACK
Definition: dinput.h:999
#define DIEP_TRIGGERREPEATINTERVAL
Definition: dinput.h:1018
#define DIERR_NOTDOWNLOADED
Definition: dinput.h:177
#define DIEP_START
Definition: dinput.h:1026
#define DIEP_DURATION
Definition: dinput.h:1014
#define DIEFT_POSNEGCOEFFICIENTS
Definition: dinput.h:1002
#define DIJOFS_X
Definition: dinput.h:1205
#define DIEP_STARTDELAY
Definition: dinput.h:1023
#define DIJOFS_Y
Definition: dinput.h:1206
#define DIEP_ALLPARAMS
Definition: dinput.h:1025
#define DIEFT_RAMPFORCE
Definition: dinput.h:994
#define DIEP_SAMPLEPERIOD
Definition: dinput.h:1015
#define DIEP_NORESTART
Definition: dinput.h:1027
#define DIEP_AXES
Definition: dinput.h:1019
#define DIERR_OUTOFMEMORY
Definition: dinput.h:155
#define DI_OK
Definition: dinput.h:128
#define DI_DOWNLOADSKIPPED
Definition: dinput.h:134
#define DIEFT_SATURATION
Definition: dinput.h:1001
#define DIERR_INPUTLOST
Definition: dinput.h:163
#define DIES_SOLO
Definition: dinput.h:1031
struct IDirectInputEffect * LPDIRECTINPUTEFFECT
Definition: dinput.h:107
#define DIERR_MOREDATA
Definition: dinput.h:176
#define DIEP_GAIN
Definition: dinput.h:1016
#define DIJOFS_BUTTON(n)
Definition: dinput.h:1215
#define DIEP_NODOWNLOAD
Definition: dinput.h:1028
#define DIEFT_FFFADE
Definition: dinput.h:1000
#define DIEFF_CARTESIAN
Definition: dinput.h:1010
#define DIEP_TRIGGERBUTTON
Definition: dinput.h:1017
#define DIERR_DEVICEFULL
Definition: dinput.h:175
#define DIES_NODOWNLOAD
Definition: dinput.h:1032
#define DIEP_DIRECTION
Definition: dinput.h:1020
#define NULL
Definition: types.h:112
const char * _dump_dinput_GUID(const GUID *guid)
Definition: device.c:197
DWORD typeFromGUID(REFGUID guid)
Definition: joystick.c:82
void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags)
Definition: joystick.c:190
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define ENOSPC
Definition: errno.h:34
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
struct _cl_event * event
Definition: glext.h:7739
GLuint res
Definition: glext.h:9613
GLsizei GLenum * sources
Definition: glext.h:7753
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat angle
Definition: glext.h:10853
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
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
unsigned char wave[]
Definition: in.h:3
#define INT_MAX
Definition: limits.h:40
REFIID riid
Definition: atlbase.h:39
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
#define M_PI
Definition: macros.h:263
const GUID * guid
static HINSTANCE hinst
Definition: edit.c:551
static const BYTE ramp[17]
Definition: dib.c:2709
const char * strerror(int err)
Definition: compat_str.c:23
#define min(a, b)
Definition: monoChain.cc:55
#define DWORD
Definition: nt_native.h:44
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define errno
Definition: errno.h:18
static int fd
Definition: io.c:51
#define TRACE(s)
Definition: solgame.cpp:4
LONG lOffset
Definition: dinput.h:1061
DWORD dwPositiveSaturation
Definition: dinput.h:1064
DWORD dwNegativeSaturation
Definition: dinput.h:1065
LONG lNegativeCoefficient
Definition: dinput.h:1063
LONG lPositiveCoefficient
Definition: dinput.h:1062
LONG lDeadBand
Definition: dinput.h:1066
LONG lMagnitude
Definition: dinput.h:1042
DWORD cAxes
Definition: dinput.h:1112
DWORD dwTriggerButton
Definition: dinput.h:1110
LPDIENVELOPE lpEnvelope
Definition: dinput.h:1115
DWORD dwDuration
Definition: dinput.h:1107
DWORD dwGain
Definition: dinput.h:1109
DWORD dwFlags
Definition: dinput.h:1106
DWORD dwTriggerRepeatInterval
Definition: dinput.h:1111
DWORD dwSize
Definition: dinput.h:1105
LPVOID lpvTypeSpecificParams
Definition: dinput.h:1117
LPLONG rglDirection
Definition: dinput.h:1114
DWORD dwSamplePeriod
Definition: dinput.h:1108
DWORD dwStartDelay
Definition: dinput.h:1118
DWORD cbTypeSpecificParams
Definition: dinput.h:1116
LPDWORD rgdwAxes
Definition: dinput.h:1113
DWORD dwAttackLevel
Definition: dinput.h:1080
DWORD dwAttackTime
Definition: dinput.h:1081
DWORD dwFadeLevel
Definition: dinput.h:1082
DWORD dwFadeTime
Definition: dinput.h:1083
DWORD dwPeriod
Definition: dinput.h:1056
LONG lOffset
Definition: dinput.h:1054
DWORD dwMagnitude
Definition: dinput.h:1053
DWORD dwPhase
Definition: dinput.h:1055
LONG lEnd
Definition: dinput.h:1048
LONG lStart
Definition: dinput.h:1047
Definition: scsiwmi.h:51
Definition: send.c:48
#define max(a, b)
Definition: svc.c:63
#define LIST_ENTRY(type)
Definition: queue.h:175
uint32_t * LPDWORD
Definition: typedefs.h:59
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define WINAPI
Definition: msvc.h:6
#define E_POINTER
Definition: winerror.h:2365
#define ioctl
Definition: wintirpc.h:60