24#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
28#ifdef HAVE_LINUX_INPUT_H
29# include <linux/input.h>
39#include "wine/unicode.h"
50static const IDirectInputEffectVtbl LinuxInputEffectVtbl;
51typedef struct LinuxInputEffectImpl LinuxInputEffectImpl;
52struct LinuxInputEffectImpl
54 IDirectInputEffect IDirectInputEffect_iface;
58 struct ff_effect effect;
65static inline LinuxInputEffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
70static double ff_effect_direction_to_rad(
unsigned int dir)
72 return (
dir & 0xffff) *
M_PI / 0x8000;
75static void ff_dump_effect(
struct ff_effect *effect)
77 const char *
type =
"(Unknown)", *
length =
"INFINITE";
80#define FE(x) case x: type = #x; break
95 angle = 360 - ff_effect_direction_to_rad(effect->direction + 0xc000) * 180 /
M_PI;
97 if (effect->replay.length)
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);
106 if (effect->type == FF_PERIODIC)
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)
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;
126 else if (effect->type == FF_CONSTANT)
128 struct ff_constant_effect *
cons = &effect->u.constant;
132 else if (effect->type == FF_RAMP)
134 struct ff_ramp_effect *
ramp = &effect->u.ramp;
135 TRACE(
" -> start/end level %d/%d\n",
ramp->start_level,
ramp->end_level);
138 else if (effect->type == FF_RUMBLE)
140 struct ff_rumble_effect *rumble = &effect->u.rumble;
141 TRACE(
" -> strong/weak magnitude %u/%u\n", rumble->strong_magnitude, rumble->weak_magnitude);
143 else if (effect->type == FF_SPRING || effect->type == FF_FRICTION ||
144 effect->type == FF_DAMPER || effect->type == FF_INERTIA)
146 struct ff_condition_effect *cond = effect->u.condition;
148 for (
i = 0;
i < 2;
i++)
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);
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);
169 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
178 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
179 int ret, old_effect_id;
182 ff_dump_effect(&
This->effect);
184 old_effect_id =
This->effect.id;
190 This->effect.id = old_effect_id;
207 TRACE(
"Could not upload effect to fd %d, errno %d \"%s\", returning 0x%x.\n",
216 WARN(
"(this=%p,%p): invalid: no hardware-specific escape codes in this"
217 " driver!\n", iface, pesc);
226 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
239 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
246 if (
This->effect.id == -1)
252 FIXME(
"Not enough information to provide a status.\n");
265 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
276 if (peff->
cAxes < 2 )
296 double angle = ff_effect_direction_to_rad(
This->effect.direction + 0xc000);
315 if (!
This->effect.replay.length)
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;
353 FIXME(
"LinuxInput button mapping needs redoing; for now, assuming we're using an actual joystick.\n");
362 DWORD expectedsize = 0;
363 if (
This->effect.type == FF_PERIODIC) {
365 }
else if (
This->effect.type == FF_CONSTANT) {
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) {
372 }
else if (
This->effect.type == FF_RAMP) {
381 if (
This->effect.type == FF_PERIODIC) {
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) {
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) {
396 for (
i = 0;
i < 2; ++
i) {
397 tsp[
i].
lOffset = (
This->effect.u.condition[
i].center / 33) * 10;
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;
421 FIXME(
"(this=%p,%p,%d,%s): stub!\n",
432 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
438 LinuxInputEffectImpl_AddRef(iface);
443 TRACE(
"Unsupported interface!\n");
452 struct input_event
event;
453 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
459 if (
This->effect.id == -1) {
460 HRESULT res = LinuxInputEffectImpl_Download(iface);
467 FIXME(
"Solo mode requested: should be stopping all effects here!\n");
471 event.code =
This->effect.id;
474 FIXME(
"Unable to write event. Assuming device disconnected.\n");
486 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
505 else if (peff->
cAxes < 1)
514 if (peff->
cAxes == 1) {
518 This->effect.direction = 0x4000;
520 This->effect.direction = 0xC000;
522 This->effect.direction = 0;
524 This->effect.direction = 0x8000;
537 if (
This->first_axis_is_x)
561 This->effect.replay.length = 0;
565 This->effect.replay.length = 1;
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;
591 env->attack_length = 0;
592 env->attack_level = 0;
593 env->fade_length = 0;
600 WARN(
"Ignoring dinput envelope not supported in the linux effect\n");
608 TRACE(
"Effect gain requested but no effect gain functionality present.\n");
612 TRACE(
"Sample period requested but no sample period functionality present.\n");
620 FIXME(
"Linuxinput button mapping needs redoing, assuming we're using a joystick.\n");
621 FIXME(
"Trigger button translation not yet implemented!\n");
623 This->effect.trigger.button = 0;
642 This->effect.u.periodic.offset = (tsp->
lOffset / 10) * 32;
644 This->effect.u.periodic.phase = (tsp->
dwPhase / 36) * 65;
647 This->effect.u.periodic.period = 1;
663 This->effect.u.ramp.start_level = (tsp->
lStart / 10) * 32;
664 This->effect.u.ramp.end_level = (tsp->
lEnd / 10) * 32;
669 struct ff_condition_effect *cond =
This->effect.u.condition;
677 double angle = ff_effect_direction_to_rad(
This->effect.direction + 0xc000);
691 for (
i =
j = 0;
i < 2; ++
i)
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);
705 FIXME(
"Custom force types are not supported\n");
711 retval = LinuxInputEffectImpl_Download(iface);
716 TRACE(
"DIEP_NORESTART: not handled (we have no control of that).\n");
719 retval = LinuxInputEffectImpl_Start(iface, 1, 0);
729 struct input_event
event;
730 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
735 event.code =
This->effect.id;
746 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
754 This->effect.id = -1;
761 LinuxInputEffectImpl *
This = impl_from_IDirectInputEffect(iface);
768 LinuxInputEffectImpl_Stop(iface);
769 LinuxInputEffectImpl_Unload(iface);
784 struct list *parent_list_entry,
791 newEffect->IDirectInputEffect_iface.lpVtbl = &LinuxInputEffectVtbl;
793 newEffect->guid = *rguid;
795 newEffect->gain = 0xFFFF;
800 newEffect->effect.type = FF_PERIODIC;
802 newEffect->effect.u.periodic.waveform = FF_SINE;
804 newEffect->effect.u.periodic.waveform = FF_TRIANGLE;
806 newEffect->effect.u.periodic.waveform = FF_SQUARE;
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;
814 newEffect->effect.type = FF_CONSTANT;
817 newEffect->effect.type = FF_RAMP;
821 newEffect->effect.type = FF_SPRING;
823 newEffect->effect.type = FF_FRICTION;
825 newEffect->effect.type = FF_INERTIA;
827 newEffect->effect.type = FF_DAMPER;
831 FIXME(
"Custom forces are not supported.\n");
835 FIXME(
"Unknown force type 0x%x.\n",
type);
841 newEffect->effect.id = -1;
843 newEffect->entry = parent_list_entry;
845 *peff = &newEffect->IDirectInputEffect_iface;
847 TRACE(
"Creating linux input system effect (%p) with guid %s\n",
879 info->dwDynamicParams =
info->dwStaticParams;
913 info->dwDynamicParams =
info->dwStaticParams;
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
_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)
char * strcpy(char *DstString, const char *SrcString)
#define InterlockedIncrement
#define InterlockedDecrement
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
pair cons(caddr_t car, pair cdr)
static void list_remove(struct list_entry *entry)
static LPCWSTR LPCWSTR LPCWSTR env
const char * wine_dbg_sprintf(const char *format,...)
#define HeapFree(x, y, z)
#define MultiByteToWideChar
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei GLenum type
GLint GLint GLint GLint GLint GLint y
GLuint GLsizei GLsizei * length
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
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
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
static const BYTE ramp[17]
const char * strerror(int err)
#define IsEqualGUID(rguid1, rguid2)
DWORD dwPositiveSaturation
DWORD dwNegativeSaturation
LONG lNegativeCoefficient
LONG lPositiveCoefficient
DWORD dwTriggerRepeatInterval
LPVOID lpvTypeSpecificParams
DWORD cbTypeSpecificParams
#define CONTAINING_RECORD(address, type, field)
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject