Author: akhaldi Date: Thu Nov 17 21:57:53 2016 New Revision: 73252
URL: http://svn.reactos.org/svn/reactos?rev=73252&view=rev Log: [DINPUT] Sync with Wine Staging 1.9.23. CORE-12409
Modified: trunk/reactos/dll/directx/wine/dinput/device.c trunk/reactos/dll/directx/wine/dinput/dinput_main.c trunk/reactos/dll/directx/wine/dinput/effect_linuxinput.c trunk/reactos/dll/directx/wine/dinput/joystick.c trunk/reactos/dll/directx/wine/dinput/joystick_linux.c trunk/reactos/dll/directx/wine/dinput/joystick_linuxinput.c trunk/reactos/dll/directx/wine/dinput/joystick_osx.c trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/directx/wine/dinput/device.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/dev... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/device.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/device.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -69,6 +69,42 @@ TRACE("%s ",flags[i].name); TRACE("\n"); } +} + +static void _dump_ObjectDataFormat_flags(DWORD dwFlags) { + unsigned int i; + static const struct { + DWORD mask; + const char *name; + } flags[] = { +#define FE(x) { x, #x} + FE(DIDOI_FFACTUATOR), + FE(DIDOI_FFEFFECTTRIGGER), + FE(DIDOI_POLLED), + FE(DIDOI_GUIDISUSAGE) +#undef FE + }; + + if (!dwFlags) return; + + TRACE("Flags:"); + + /* First the flags */ + for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) { + if (flags[i].mask & dwFlags) + TRACE(" %s",flags[i].name); + } + + /* Now specific values */ +#define FE(x) case x: TRACE(" "#x); break + switch (dwFlags & DIDOI_ASPECTMASK) { + FE(DIDOI_ASPECTACCEL); + FE(DIDOI_ASPECTFORCE); + FE(DIDOI_ASPECTPOSITION); + FE(DIDOI_ASPECTVELOCITY); + } +#undef FE + }
static void _dump_EnumObjects_flags(DWORD dwFlags) { @@ -215,6 +251,7 @@ TRACE(" * dwType: 0x%08x\n", df->rgodf[i].dwType); TRACE(" "); _dump_EnumObjects_flags(df->rgodf[i].dwType); TRACE("\n"); TRACE(" * dwFlags: 0x%08x\n", df->rgodf[i].dwFlags); + TRACE(" "); _dump_ObjectDataFormat_flags(df->rgodf[i].dwFlags); TRACE("\n"); } }
@@ -431,16 +468,20 @@ debugstr_guid(asked_format->rgodf[j].pguid), _dump_dinput_GUID(asked_format->rgodf[j].pguid)); TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs); - TRACE(" * dwType: %08x\n", asked_format->rgodf[j].dwType); + TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType); TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n"); + TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags); + TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n"); TRACE(" - Wine (%d) :\n", i); TRACE(" * GUID: %s ('%s')\n", debugstr_guid(format->wine_df->rgodf[i].pguid), _dump_dinput_GUID(format->wine_df->rgodf[i].pguid)); TRACE(" * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs); - TRACE(" * dwType: %08x\n", format->wine_df->rgodf[i].dwType); + TRACE(" * dwType: 0x%08x\n", format->wine_df->rgodf[i].dwType); TRACE(" "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n"); + TRACE(" * dwFlags: 0x%08x\n", format->wine_df->rgodf[i].dwFlags); + TRACE(" "); _dump_ObjectDataFormat_flags(format->wine_df->rgodf[i].dwFlags); TRACE("\n"); if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON) dt[index].size = sizeof(BYTE); @@ -469,8 +510,10 @@ debugstr_guid(asked_format->rgodf[j].pguid), _dump_dinput_GUID(asked_format->rgodf[j].pguid)); TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs); - TRACE(" * dwType: %08x\n", asked_format->rgodf[j].dwType); + TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType); TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n"); + TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags); + TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n"); if (asked_format->rgodf[j].dwType & DIDFT_BUTTON) dt[index].size = sizeof(BYTE); @@ -1537,7 +1580,10 @@ LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) { FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter); - return DI_OK; + + FIXME("not available in the generic implementation\n"); + *ppdef = NULL; + return DIERR_UNSUPPORTED; }
HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff,
Modified: trunk/reactos/dll/directx/wine/dinput/dinput_main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/din... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/dinput_main.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/dinput_main.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -162,15 +162,26 @@ return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7W, (LPVOID *)ppDI, punkOuter); }
-static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) -{ - switch (dwDevType) { - case 0: return "All devices"; - case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE"; - case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD"; - case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK"; - case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE"; - default: return "Unknown"; +static const char *_dump_DIDEVTYPE_value(DWORD dwDevType, DWORD dwVersion) +{ + if (dwVersion < 0x0800) { + switch (dwDevType) { + case 0: return "All devices"; + case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE"; + case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD"; + case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK"; + case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE"; + default: return "Unknown"; + } + } else { + switch (dwDevType) { + case DI8DEVCLASS_ALL: return "All devices"; + case DI8DEVCLASS_POINTER: return "DI8DEVCLASS_POINTER"; + case DI8DEVCLASS_KEYBOARD: return "DI8DEVCLASS_KEYBOARD"; + case DI8DEVCLASS_DEVICE: return "DI8DEVCLASS_DEVICE"; + case DI8DEVCLASS_GAMECTRL: return "DI8DEVCLASS_GAMECTRL"; + default: return "Unknown"; + } } }
@@ -363,10 +374,11 @@ IDirectInputImpl *This = impl_from_IDirectInput7A(iface); DIDEVICEINSTANCEA devInstance; unsigned int i; - int j, r; - - TRACE("(this=%p,0x%04x '%s',%p,%p,%04x)\n", - This, dwDevType, _dump_DIDEVTYPE_value(dwDevType), + int j; + HRESULT r; + + TRACE("(this=%p,0x%04x '%s',%p,%p,0x%04x)\n", + This, dwDevType, _dump_DIDEVTYPE_value(dwDevType, This->dwVersion), lpCallback, pvRef, dwFlags); _dump_EnumDevices_dwFlags(dwFlags);
@@ -405,8 +417,8 @@ int j; HRESULT r;
- TRACE("(this=%p,0x%04x '%s',%p,%p,%04x)\n", - This, dwDevType, _dump_DIDEVTYPE_value(dwDevType), + TRACE("(this=%p,0x%04x '%s',%p,%p,0x%04x)\n", + This, dwDevType, _dump_DIDEVTYPE_value(dwDevType, This->dwVersion), lpCallback, pvRef, dwFlags); _dump_EnumDevices_dwFlags(dwFlags);
Modified: trunk/reactos/dll/directx/wine/dinput/effect_linuxinput.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/eff... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/effect_linuxinput.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/effect_linuxinput.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -72,6 +72,93 @@ return (dir & 0xffff) * M_PI / 0x8000; }
+static void ff_dump_effect(struct ff_effect *effect) +{ + const char *type = "(Unknown)", *length = "INFINITE"; + struct ff_envelope *env = NULL; + double angle; +#define FE(x) case x: type = #x; break + switch (effect->type) + { + FE(FF_RUMBLE); + FE(FF_PERIODIC); + FE(FF_CONSTANT); + FE(FF_SPRING); + FE(FF_FRICTION); + FE(FF_DAMPER); + FE(FF_INERTIA); + FE(FF_RAMP); + } +#undef FE + + /* rotate so 0 points right */ + angle = 360 - ff_effect_direction_to_rad(effect->direction + 0xc000) * 180 / M_PI; + + if (effect->replay.length) + length = wine_dbg_sprintf("%u ms", effect->replay.length); + + TRACE("type 0x%x %s, id %d, direction 0x%x (source angle %.2f), time length %s, start delay %u ms\n", + effect->type, type, effect->id, effect->direction, angle, length, effect->replay.delay); + if (effect->trigger.button || effect->trigger.interval) + TRACE(" -> trigger button %u, re-trigger interval %u ms\n", + effect->trigger.button, effect->trigger.interval); + + if (effect->type == FF_PERIODIC) + { + struct ff_periodic_effect *per = &effect->u.periodic; + const char *wave = "(Unknown)"; +#define FE(x) case x: wave = #x; break + switch (per->waveform) + { + FE(FF_SQUARE); + FE(FF_TRIANGLE); + FE(FF_SINE); + FE(FF_SAW_UP); + FE(FF_SAW_DOWN); + FE(FF_CUSTOM); + } +#undef FE + angle = ff_effect_direction_to_rad(per->phase) * 180 / M_PI; + TRACE(" -> waveform 0x%x %s, period %u ms, magnitude %d, offset %d, phase 0x%x (angle %.2f), custom len %d\n", + per->waveform, wave, per->period, per->magnitude, per->offset, per->phase, angle, per->custom_len); + env = &per->envelope; + } + else if (effect->type == FF_CONSTANT) + { + struct ff_constant_effect *cons = &effect->u.constant; + TRACE(" -> level %d\n", cons->level); + env = &cons->envelope; + } + else if (effect->type == FF_RAMP) + { + struct ff_ramp_effect *ramp = &effect->u.ramp; + TRACE(" -> start/end level %d/%d\n", ramp->start_level, ramp->end_level); + env = &ramp->envelope; + } + else if (effect->type == FF_RUMBLE) + { + struct ff_rumble_effect *rumble = &effect->u.rumble; + TRACE(" -> strong/weak magnitude %u/%u\n", rumble->strong_magnitude, rumble->weak_magnitude); + } + else if (effect->type == FF_SPRING || effect->type == FF_FRICTION || + effect->type == FF_DAMPER || effect->type == FF_INERTIA) + { + struct ff_condition_effect *cond = effect->u.condition; + int i; + for (i = 0; i < 2; i++) + { + /* format numbers here to make them align correctly */ + TRACE(" -> [%d] right/left saturation %5u/%5u, right/left coefficient %5d/%5d," + " deadband %5u, center %5d\n", i, cond[i].right_saturation, cond[i].left_saturation, + cond[i].right_coeff, cond[i].left_coeff, cond[i].deadband, cond[i].center); + } + } + + if (env) + TRACE(" -> envelope attack length(ms)/level %u/%u, fade length(ms)/level %u/%u\n", + env->attack_length, env->attack_level, env->fade_length, env->fade_level); +} + /****************************************************************************** * LinuxInputEffectImpl */ @@ -87,19 +174,37 @@ LPDIRECTINPUTEFFECT iface) { LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); + int ret, old_effect_id;
TRACE("(this=%p)\n", This); - - if (ioctl(*(This->fd), EVIOCSFF, &This->effect) == -1) { - if (errno == ENOMEM) { - return DIERR_DEVICEFULL; - } else { - FIXME("Could not upload effect. Assuming a disconnected device %d "%s".\n", *This->fd, strerror(errno)); - return DIERR_INPUTLOST; - } - } - - return DI_OK; + ff_dump_effect(&This->effect); + + old_effect_id = This->effect.id; + if (ioctl(*(This->fd), EVIOCSFF, &This->effect) != -1) + return DI_OK; + + /* Linux kernel < 3.14 has a bug that incorrectly assigns an effect ID even + * on error, restore it here if that is the case. */ + This->effect.id = old_effect_id; + + switch (errno) + { + case EINVAL: + ret = DIERR_INVALIDPARAM; + break; + case ENOSPC: + ret = DIERR_DEVICEFULL; + break; + case ENOMEM: + ret = DIERR_OUTOFMEMORY; + break; + default: + ret = DIERR_INPUTLOST; + break; + } + TRACE("Could not upload effect to fd %d, errno %d "%s", returning 0x%x.\n", + *This->fd, errno, strerror(errno), ret); + return ret; }
static HRESULT WINAPI LinuxInputEffectImpl_Escape( @@ -130,6 +235,9 @@ LPDWORD pdwFlags) { TRACE("(this=%p,%p)\n", iface, pdwFlags); + + if (!pdwFlags) + return E_POINTER;
/* linux sends the effect status through an event. * that event is trapped by our parent joystick driver @@ -195,8 +303,12 @@ } }
- if (dwFlags & DIEP_DURATION) { - peff->dwDuration = (DWORD)This->effect.replay.length * 1000; + if (dwFlags & DIEP_DURATION) + { + if (!This->effect.replay.length) /* infinite for the linux driver */ + peff->dwDuration = INFINITE; + else + peff->dwDuration = (DWORD)This->effect.replay.length * 1000; }
if (dwFlags & DIEP_ENVELOPE) { @@ -227,9 +339,8 @@ peff->dwSamplePeriod = 0; }
- if (dwFlags & DIEP_STARTDELAY) { - peff->dwStartDelay = This->effect.replay.delay * 1000; - } + if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5)) + peff->dwStartDelay = This->effect.replay.delay * 1000;
if (dwFlags & DIEP_TRIGGERBUTTON) { FIXME("LinuxInput button mapping needs redoing; for now, assuming we're using an actual joystick.\n"); @@ -409,52 +520,78 @@ /* one-axis effects must use cartesian coords */ return DIERR_INVALIDPARAM; } - } else { /* two axes */ - if (peff->dwFlags & DIEFF_CARTESIAN) { - LONG x, y; - if (This->first_axis_is_x) { - x = peff->rglDirection[0]; - y = peff->rglDirection[1]; - } else { - x = peff->rglDirection[1]; - y = peff->rglDirection[0]; - } - This->effect.direction = (int)((3 * M_PI / 2 - atan2(y, x)) * -0x7FFF / M_PI); - } else { - /* Polar and spherical are the same for 2 axes */ - /* Precision is important here, so we do double math with exact constants */ - This->effect.direction = (int)(((double)peff->rglDirection[0] - 90) / 35999) * 0x7FFF; - } - } + } + /* two axes */ + else + { + if (peff->dwFlags & DIEFF_CARTESIAN) + { + LONG x, y; + if (This->first_axis_is_x) + { + x = peff->rglDirection[0]; + y = peff->rglDirection[1]; + } + else + { + x = peff->rglDirection[1]; + y = peff->rglDirection[0]; + } + This->effect.direction = (unsigned int)((M_PI / 2 + atan2(y, x)) * 0x8000 / M_PI); + } + else + { + /* Polar and spherical are the same for 2 axes */ + /* Precision is important here, so we do double math with exact constants */ + This->effect.direction = (unsigned int)(((double)peff->rglDirection[0] / 18000) * 0x8000); + } + } }
if (dwFlags & DIEP_DURATION) - This->effect.replay.length = peff->dwDuration / 1000; - - if (dwFlags & DIEP_ENVELOPE) { + { + if (peff->dwDuration == INFINITE) + This->effect.replay.length = 0; /* infinite for the linux driver */ + else if(peff->dwDuration > 1000) + This->effect.replay.length = peff->dwDuration / 1000; + else + This->effect.replay.length = 1; + } + + if (dwFlags & DIEP_ENVELOPE) + { struct ff_envelope* env; - if (This->effect.type == FF_CONSTANT) env = &This->effect.u.constant.envelope; - else if (This->effect.type == FF_PERIODIC) env = &This->effect.u.periodic.envelope; - else if (This->effect.type == FF_RAMP) env = &This->effect.u.ramp.envelope; - else env = NULL; - - if (peff->lpEnvelope == NULL) { - /* if this type had an envelope, reset it */ - if (env) { - env->attack_length = 0; - env->attack_level = 0; - env->fade_length = 0; - env->fade_level = 0; - } - } else { - /* did we get passed an envelope for a type that doesn't even have one? */ - if (!env) return DIERR_INVALIDPARAM; - /* copy the envelope */ - env->attack_length = peff->lpEnvelope->dwAttackTime / 1000; - env->attack_level = (peff->lpEnvelope->dwAttackLevel / 10) * 32; - env->fade_length = peff->lpEnvelope->dwFadeTime / 1000; - env->fade_level = (peff->lpEnvelope->dwFadeLevel / 10) * 32; - } + if (This->effect.type == FF_CONSTANT) + env = &This->effect.u.constant.envelope; + else if (This->effect.type == FF_PERIODIC) + env = &This->effect.u.periodic.envelope; + else if (This->effect.type == FF_RAMP) + env = &This->effect.u.ramp.envelope; + else + env = NULL; + + /* copy the envelope if it is present and the linux effect supports it */ + if (peff->lpEnvelope && env) + { + env->attack_length = peff->lpEnvelope->dwAttackTime / 1000; + env->attack_level = (peff->lpEnvelope->dwAttackLevel / 10) * 32; + env->fade_length = peff->lpEnvelope->dwFadeTime / 1000; + env->fade_level = (peff->lpEnvelope->dwFadeLevel / 10) * 32; + } + /* if the dinput envelope is NULL we will clear the linux envelope */ + else if (env) + { + env->attack_length = 0; + env->attack_level = 0; + env->fade_length = 0; + env->fade_level = 0; + } + else if(peff->lpEnvelope) + { + if(peff->lpEnvelope->dwAttackTime || peff->lpEnvelope->dwAttackLevel || + peff->lpEnvelope->dwFadeTime || peff->lpEnvelope->dwFadeLevel) + WARN("Ignoring dinput envelope not supported in the linux effect\n"); + } }
/* Gain and Sample Period settings are not supported by the linux @@ -468,7 +605,8 @@ TRACE("Sample period requested but no sample period functionality present.\n");
if (dwFlags & DIEP_STARTDELAY) - This->effect.replay.delay = peff->dwStartDelay / 1000; + if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5)) + This->effect.replay.delay = peff->dwStartDelay / 1000;
if (dwFlags & DIEP_TRIGGERBUTTON) { if (peff->dwTriggerButton != -1) { @@ -481,19 +619,30 @@ if (dwFlags & DIEP_TRIGGERREPEATINTERVAL) This->effect.trigger.interval = peff->dwTriggerRepeatInterval / 1000;
- if (dwFlags & DIEP_TYPESPECIFICPARAMS) { - if (!(peff->lpvTypeSpecificParams)) - return DIERR_INCOMPLETEEFFECT; - if (type == DIEFT_PERIODIC) { - LPCDIPERIODIC tsp; + if (dwFlags & DIEP_TYPESPECIFICPARAMS) + { + if (!(peff->lpvTypeSpecificParams)) + return DIERR_INCOMPLETEEFFECT; + + if (type == DIEFT_PERIODIC) + { + DIPERIODIC *tsp; if (peff->cbTypeSpecificParams != sizeof(DIPERIODIC)) return DIERR_INVALIDPARAM; tsp = peff->lpvTypeSpecificParams; - This->effect.u.periodic.magnitude = (tsp->dwMagnitude / 10) * 32; - This->effect.u.periodic.offset = (tsp->lOffset / 10) * 32; - This->effect.u.periodic.phase = (tsp->dwPhase / 9) * 8; /* == (/ 36 * 32) */ - This->effect.u.periodic.period = tsp->dwPeriod / 1000; - } else if (type == DIEFT_CONSTANTFORCE) { + + This->effect.u.periodic.magnitude = (tsp->dwMagnitude / 10) * 32; + This->effect.u.periodic.offset = (tsp->lOffset / 10) * 32; + /* phase ranges from 0 - 35999 in dinput and 0 - 65535 on linux */ + This->effect.u.periodic.phase = (tsp->dwPhase / 36) * 65; + /* dinput uses microseconds, linux uses miliseconds */ + if (tsp->dwPeriod <= 1000) + This->effect.u.periodic.period = 1; + else + This->effect.u.periodic.period = tsp->dwPeriod / 1000; + } + else if (type == DIEFT_CONSTANTFORCE) + { LPCDICONSTANTFORCE tsp; if (peff->cbTypeSpecificParams != sizeof(DICONSTANTFORCE)) return DIERR_INVALIDPARAM; @@ -506,43 +655,49 @@ tsp = peff->lpvTypeSpecificParams; This->effect.u.ramp.start_level = (tsp->lStart / 10) * 32; This->effect.u.ramp.end_level = (tsp->lEnd / 10) * 32; - } else if (type == DIEFT_CONDITION) { - LPCDICONDITION tsp = peff->lpvTypeSpecificParams; - if (peff->cbTypeSpecificParams == sizeof(DICONDITION)) { - /* One condition block. This needs to be rotated to direction, - * and expanded to separate x and y conditions. */ - int i; - double factor[2], angle; - /* rotate so 0 points right */ - angle = ff_effect_direction_to_rad(This->effect.direction + 0xc000); - factor[0] = sin(angle); - factor[1] = -cos(angle); - for (i = 0; i < 2; ++i) { - This->effect.u.condition[i].center = (int)(factor[i] * (tsp->lOffset / 10) * 32); - This->effect.u.condition[i].right_coeff = (int)(factor[i] * (tsp->lPositiveCoefficient / 10) * 32); - This->effect.u.condition[i].left_coeff = (int)(factor[i] * (tsp->lNegativeCoefficient / 10) * 32); - This->effect.u.condition[i].right_saturation = (int)(factor[i] * (tsp->dwPositiveSaturation / 10) * 32); - This->effect.u.condition[i].left_saturation = (int)(factor[i] * (tsp->dwNegativeSaturation / 10) * 32); - This->effect.u.condition[i].deadband = (int)(factor[i] * (tsp->lDeadBand / 10) * 32); - } - } else if (peff->cbTypeSpecificParams == 2 * sizeof(DICONDITION)) { - /* Two condition blocks. Direct parameter copy. */ - int i; - for (i = 0; i < 2; ++i) { - This->effect.u.condition[i].center = (tsp[i].lOffset / 10) * 32; - This->effect.u.condition[i].right_coeff = (tsp[i].lPositiveCoefficient / 10) * 32; - This->effect.u.condition[i].left_coeff = (tsp[i].lNegativeCoefficient / 10) * 32; - This->effect.u.condition[i].right_saturation = (tsp[i].dwPositiveSaturation / 10) * 32; - This->effect.u.condition[i].left_saturation = (tsp[i].dwNegativeSaturation / 10) * 32; - This->effect.u.condition[i].deadband = (tsp[i].lDeadBand / 10) * 32; - } - } else { + } + else if (type == DIEFT_CONDITION) + { + DICONDITION *tsp = peff->lpvTypeSpecificParams; + struct ff_condition_effect *cond = This->effect.u.condition; + int i, j, sources; + double factor[2]; + + if (peff->cbTypeSpecificParams == sizeof(DICONDITION)) + { + /* One condition block. This needs to be rotated to direction, + * and expanded to separate x and y conditions. Ensures 0 points right */ + double angle = ff_effect_direction_to_rad(This->effect.direction + 0xc000); + factor[0] = sin(angle); + factor[1] = -cos(angle); + sources = 1; + } + else if (peff->cbTypeSpecificParams == 2 * sizeof(DICONDITION)) + { + /* Direct parameter copy without changes */ + factor[0] = factor[1] = 1; + sources = 2; + } + else return DIERR_INVALIDPARAM; - } - } else { - FIXME("Custom force types are not supported\n"); - return DIERR_INVALIDPARAM; - } + + for (i = j = 0; i < 2; ++i) + { + cond[i].center = (int)(factor[i] * (tsp[j].lOffset / 10) * 32); + cond[i].right_coeff = (int)(factor[i] * (tsp[j].lPositiveCoefficient / 10) * 32); + cond[i].left_coeff = (int)(factor[i] * (tsp[j].lNegativeCoefficient / 10) * 32); + cond[i].right_saturation = (int)(factor[i] * (tsp[j].dwPositiveSaturation / 10) * 65); + cond[i].left_saturation = (int)(factor[i] * (tsp[j].dwNegativeSaturation / 10) * 65); + cond[i].deadband = (int)(factor[i] * (tsp[j].lDeadBand / 10) * 32); + if (sources == 2) + j++; + } + } + else + { + FIXME("Custom force types are not supported\n"); + return DIERR_INVALIDPARAM; + } }
if (!(dwFlags & DIEP_NODOWNLOAD))
Modified: trunk/reactos/dll/directx/wine/dinput/joystick.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/joy... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/joystick.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/joystick.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -213,10 +213,14 @@ _dump_DIRAMPFORCE(eff->lpvTypeSpecificParams); } } else if (type == DIEFT_CONDITION) { - if (eff->cbTypeSpecificParams != sizeof(DICONDITION)) { + if (eff->cbTypeSpecificParams == sizeof(DICONDITION)) { + _dump_DICONDITION(eff->lpvTypeSpecificParams); + } else if (eff->cbTypeSpecificParams == 2 * sizeof(DICONDITION)) { + DICONDITION *condition = eff->lpvTypeSpecificParams; + _dump_DICONDITION(&condition[0]); + _dump_DICONDITION(&condition[1]); + } else { WARN("Effect claims to be a condition but the type-specific params are the wrong size!\n"); - } else { - _dump_DICONDITION(eff->lpvTypeSpecificParams); } } else if (type == DIEFT_CUSTOMFORCE) { if (eff->cbTypeSpecificParams != sizeof(DICUSTOMFORCE)) { @@ -289,6 +293,11 @@ case (DWORD_PTR)DIPROP_RANGE: { LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph; if (ph->dwHow == DIPH_DEVICE) { + + /* Many games poll the joystick immediately after setting the range + * for calibration purposes, so the old values need to be remapped + * to the new range before it does so */ + TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax); for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) {
@@ -322,8 +331,6 @@ TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj); if (obj >= 0) {
- /*ePSXe polls the joystick immediately after setting the range for calibration purposes, so the old values need to be remapped to the new range before it does so*/ - remap_props.lDevMin = This->props[obj].lMin; remap_props.lDevMax = This->props[obj].lMax;
@@ -333,7 +340,7 @@ remap_props.lMin = pr->lMin; remap_props.lMax = pr->lMax;
- switch (ph->dwObj) { + switch (This->base.data_format.wine_df->rgodf[obj].dwOfs) { case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; @@ -404,7 +411,7 @@ void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) { int type = GET_DIDEVICE_TYPE(lpDIDevCaps->dwDevType); - const char *str; + const char *str, *hid = ""; TRACE("dwSize: %d\n", lpDIDevCaps->dwSize); TRACE("dwFlags: %08x\n", lpDIDevCaps->dwFlags); switch(type) @@ -414,7 +421,6 @@ DEBUG_TYPE(DIDEVTYPE_MOUSE); DEBUG_TYPE(DIDEVTYPE_KEYBOARD); DEBUG_TYPE(DIDEVTYPE_JOYSTICK); - DEBUG_TYPE(DIDEVTYPE_HID); /* Direct X >= 8 definitions */ DEBUG_TYPE(DI8DEVTYPE_DEVICE); DEBUG_TYPE(DI8DEVTYPE_MOUSE); @@ -431,7 +437,10 @@ default: str = "UNKNOWN"; }
- TRACE("dwDevType: %08x %s\n", lpDIDevCaps->dwDevType, str); + if (lpDIDevCaps->dwDevType & DIDEVTYPE_HID) + hid = " (HID)"; + + TRACE("dwDevType: %08x %s%s\n", lpDIDevCaps->dwDevType, str, hid); TRACE("dwAxes: %d\n", lpDIDevCaps->dwAxes); TRACE("dwButtons: %d\n", lpDIDevCaps->dwButtons); TRACE("dwPOVs: %d\n", lpDIDevCaps->dwPOVs); @@ -493,9 +502,10 @@ res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow); if (res != DI_OK) return res;
- if (pdidoi->dwType & DIDFT_AXIS) + if (pdidoi->dwType & DIDFT_AXIS) { sprintfW(pdidoi->tszName, axisW, DIDFT_GETINSTANCE(pdidoi->dwType)); - else if (pdidoi->dwType & DIDFT_POV) + pdidoi->dwFlags |= DIDOI_ASPECTPOSITION; + } else if (pdidoi->dwType & DIDFT_POV) sprintfW(pdidoi->tszName, povW, DIDFT_GETINSTANCE(pdidoi->dwType)); else if (pdidoi->dwType & DIDFT_BUTTON) sprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType)); @@ -575,6 +585,7 @@ } break; } + case (DWORD_PTR) DIPROP_PRODUCTNAME: case (DWORD_PTR) DIPROP_INSTANCENAME: { DIPROPSTRING *ps = (DIPROPSTRING*) pdiph; DIDEVICEINSTANCEW didev; @@ -582,7 +593,10 @@ didev.dwSize = sizeof(didev);
IDirectInputDevice_GetDeviceInfo(iface, &didev); - lstrcpynW(ps->wsz, didev.tszInstanceName, MAX_PATH); + if (LOWORD(rguid) == (DWORD_PTR) DIPROP_PRODUCTNAME) + lstrcpynW(ps->wsz, didev.tszProductName, MAX_PATH); + else + lstrcpynW(ps->wsz, didev.tszInstanceName, MAX_PATH);
return DI_OK; }
Modified: trunk/reactos/dll/directx/wine/dinput/joystick_linux.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/joy... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/joystick_linux.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/joystick_linux.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -63,7 +63,7 @@ BYTE button_count; int *dev_axes_map;
- WORD vendor_id, product_id; + WORD vendor_id, product_id, bus_type; };
typedef struct JoystickImpl JoystickImpl; @@ -122,6 +122,29 @@
static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
+#define SYS_PATH_FORMAT "/sys/class/input/js%d/device/id/%s" +static BOOL read_sys_id_variable(int index, const char *property, WORD *value) +{ + char sys_path[sizeof(SYS_PATH_FORMAT) + 16], id_str[5]; + int sys_fd; + BOOL ret = FALSE; + + sprintf(sys_path, SYS_PATH_FORMAT, index, property); + if ((sys_fd = open(sys_path, O_RDONLY)) != -1) + { + if (read(sys_fd, id_str, 4) == 4) + { + id_str[4] = '\0'; + *value = strtol(id_str, NULL, 16); + ret = TRUE; + } + + close(sys_fd); + } + return ret; +} +#undef SYS_PATH_FORMAT + static INT find_joystick_devices(void) { INT i; @@ -131,16 +154,15 @@ joystick_devices_count = 0; for (i = 0; i < MAX_JOYSTICKS; i++) { - int fd, sys_fd; + int fd; struct JoyDev joydev, *new_joydevs; BYTE axes_map[ABS_MAX + 1]; - char sys_path[sizeof("/sys/class/input/js/device/id/product") + 10], id_str[5];
snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i); - if ((fd = open(joydev.device, O_RDONLY)) < 0) + if ((fd = open(joydev.device, O_RDONLY)) == -1) { snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_OLD, i); - if ((fd = open(joydev.device, O_RDONLY)) < 0) continue; + if ((fd = open(joydev.device, O_RDONLY)) == -1) continue; }
strcpy(joydev.name, "Wine Joystick"); @@ -205,31 +227,9 @@ joydev.vendor_id = 0; joydev.product_id = 0;
- sprintf(sys_path, "/sys/class/input/js%d/device/id/vendor", i); - sys_fd = open(sys_path, O_RDONLY); - if (sys_fd > 0) - { - if (read(sys_fd, id_str, 4) == 4) - { - id_str[4] = '\0'; - joydev.vendor_id = strtol(id_str, NULL, 16); - } - - close(sys_fd); - } - - sprintf(sys_path, "/sys/class/input/js%d/device/id/product", i); - sys_fd = open(sys_path, O_RDONLY); - if (sys_fd > 0) - { - if (read(sys_fd, id_str, 4) == 4) - { - id_str[4] = '\0'; - joydev.product_id = strtol(id_str, NULL, 16); - } - - close(sys_fd); - } + read_sys_id_variable(i, "vendor", &joydev.vendor_id); + read_sys_id_variable(i, "product", &joydev.product_id); + read_sys_id_variable(i, "bustype", &joydev.bus_type);
if (joydev.vendor_id == 0 || joydev.product_id == 0) { @@ -261,7 +261,7 @@ return joystick_devices_count; }
-static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) +static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) { DWORD dwSize = lpddi->dwSize;
@@ -278,33 +278,45 @@ lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); else lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); - strcpy(lpddi->tszInstanceName, joystick_devices[id].name); - strcpy(lpddi->tszProductName, joystick_devices[id].name); - - lpddi->guidFFDriver = GUID_NULL; -} - -static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ - DWORD dwSize = lpddi->dwSize; - - TRACE("%d %p\n", dwSize, lpddi); - memset(lpddi, 0, dwSize); - - /* Return joystick */ - lpddi->dwSize = dwSize; - lpddi->guidInstance = DInput_Wine_Joystick_GUID; - lpddi->guidInstance.Data3 = id; - lpddi->guidProduct = joystick_devices[id].guid_product; - /* we only support traditional joysticks for now */ - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + + /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ + if (joystick_devices[id].bus_type == BUS_USB && + joystick_devices[id].vendor_id && joystick_devices[id].product_id) + { + lpddi->dwDevType |= DIDEVTYPE_HID; + lpddi->wUsagePage = 0x01; /* Desktop */ + if (lpddi->dwDevType == DI8DEVTYPE_JOYSTICK || lpddi->dwDevType == DIDEVTYPE_JOYSTICK) + lpddi->wUsage = 0x04; /* Joystick */ + else + lpddi->wUsage = 0x05; /* Game Pad */ + }
MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszInstanceName, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszProductName, MAX_PATH); lpddi->guidFFDriver = GUID_NULL; +} + +static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) +{ + DIDEVICEINSTANCEW lpddiW; + DWORD dwSize = lpddi->dwSize; + + lpddiW.dwSize = sizeof(lpddiW); + fill_joystick_dideviceinstanceW(&lpddiW, version, id); + + TRACE("%d %p\n", dwSize, lpddi); + memset(lpddi, 0, dwSize); + + /* Convert W->A */ + lpddi->dwSize = dwSize; + lpddi->guidInstance = lpddiW.guidInstance; + lpddi->guidProduct = lpddiW.guidProduct; + lpddi->dwDevType = lpddiW.dwDevType; + strcpy(lpddi->tszInstanceName, joystick_devices[id].name); + strcpy(lpddi->tszProductName, joystick_devices[id].name); + lpddi->guidFFDriver = lpddiW.guidFFDriver; + lpddi->wUsagePage = lpddiW.wUsagePage; + lpddi->wUsage = lpddiW.wUsage; }
static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) @@ -322,14 +334,14 @@ ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { /* check whether we have a joystick */ - if ((fd = open(joystick_devices[id].device, O_RDONLY)) < 0) - { - WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].name, strerror(errno)); + if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1) + { + WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno)); return S_FALSE; } fill_joystick_dideviceinstanceA( lpddi, version, id ); close(fd); - TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, lpddi->tszProductName); + TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, joystick_devices[id].name); return S_OK; }
@@ -351,9 +363,9 @@ ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { /* check whether we have a joystick */ - if ((fd = open(joystick_devices[id].device, O_RDONLY)) < 0) - { - WARN("open(%s,O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno)); + if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1) + { + WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno)); return S_FALSE; } fill_joystick_dideviceinstanceW( lpddi, version, id ); @@ -373,6 +385,7 @@ HRESULT hr; LPDIDATAFORMAT df = NULL; int idx = 0; + DIDEVICEINSTANCEW ddi;
TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
@@ -463,10 +476,11 @@
newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps); newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED; - if (newDevice->generic.base.dinput->dwVersion >= 0x0800) - newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + + ddi.dwSize = sizeof(ddi); + fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index); + newDevice->generic.devcaps.dwDevType = ddi.dwDevType; + newDevice->generic.devcaps.dwFFSamplePeriod = 0; newDevice->generic.devcaps.dwFFMinTimeResolution = 0; newDevice->generic.devcaps.dwFirmwareRevision = 0; @@ -625,6 +639,16 @@
switch (LOWORD(rguid)) {
+ case (DWORD_PTR) DIPROP_VIDPID: + { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + + if (!This->joydev->product_id || !This->joydev->vendor_id) + return DIERR_UNSUPPORTED; + pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id); + TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData); + break; + } case (DWORD_PTR) DIPROP_JOYSTICKID: { LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
Modified: trunk/reactos/dll/directx/wine/dinput/joystick_linuxinput.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/joy... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/joystick_linuxinput.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/joystick_linuxinput.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -91,7 +91,7 @@ /* data returned by the EVIOCGABS() ioctl */ struct wine_input_absinfo axes[ABS_MAX];
- WORD vendor_id, product_id; + WORD vendor_id, product_id, bus_type; };
struct JoystickImpl @@ -296,6 +296,7 @@ { joydev.vendor_id = device_id.vendor; joydev.product_id = device_id.product; + joydev.bus_type = device_id.bustype;
/* Concatenate product_id with vendor_id to mimic Windows behaviour */ joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID; @@ -320,7 +321,7 @@ } }
-static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) +static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) { DWORD dwSize = lpddi->dwSize;
@@ -337,29 +338,43 @@ else lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
- strcpy(lpddi->tszInstanceName, joydevs[id].name); - strcpy(lpddi->tszProductName, joydevs[id].name); -} - -static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ + /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ + if (joydevs[id].bus_type == BUS_USB && + joydevs[id].vendor_id && joydevs[id].product_id) + { + lpddi->dwDevType |= DIDEVTYPE_HID; + lpddi->wUsagePage = 0x01; /* Desktop */ + if (lpddi->dwDevType == DI8DEVTYPE_JOYSTICK || lpddi->dwDevType == DIDEVTYPE_JOYSTICK) + lpddi->wUsage = 0x04; /* Joystick */ + else + lpddi->wUsage = 0x05; /* Game Pad */ + } + + MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH); + MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszProductName, MAX_PATH); +} + +static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) +{ + DIDEVICEINSTANCEW lpddiW; DWORD dwSize = lpddi->dwSize; + + lpddiW.dwSize = sizeof(lpddiW); + fill_joystick_dideviceinstanceW(&lpddiW, version, id);
TRACE("%d %p\n", dwSize, lpddi); memset(lpddi, 0, dwSize);
- lpddi->dwSize = dwSize; - lpddi->guidInstance = joydevs[id].guid; - lpddi->guidProduct = joydevs[id].guid_product; - lpddi->guidFFDriver = GUID_NULL; - - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); - - MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH); - MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszProductName, MAX_PATH); + /* Convert W->A */ + lpddi->dwSize = dwSize; + lpddi->guidInstance = lpddiW.guidInstance; + lpddi->guidProduct = lpddiW.guidProduct; + lpddi->dwDevType = lpddiW.dwDevType; + strcpy(lpddi->tszInstanceName, joydevs[id].name); + strcpy(lpddi->tszProductName, joydevs[id].name); + lpddi->guidFFDriver = lpddiW.guidFFDriver; + lpddi->wUsagePage = lpddiW.wUsagePage; + lpddi->wUsage = lpddiW.wUsage; }
static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) @@ -418,6 +433,7 @@ LPDIDATAFORMAT df = NULL; int i, idx = 0; int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2]; + DIDEVICEINSTANCEW ddi;
newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl)); if (!newDevice) return NULL; @@ -537,10 +553,10 @@ /* Fill the caps */ newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps); newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED; - if (newDevice->generic.base.dinput->dwVersion >= 0x0800) - newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + + ddi.dwSize = sizeof(ddi); + fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index); + newDevice->generic.devcaps.dwDevType = ddi.dwDevType;
if (newDevice->joydev->has_ff) newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK; @@ -1015,10 +1031,16 @@ JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
+ *ppdef = NULL; + if (!This->joydev->has_ff) + { + TRACE("No force feedback support\n"); + return DIERR_UNSUPPORTED; + } + #ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION - TRACE("not available (compiled w/o ff support)\n"); - *ppdef = NULL; - return DI_OK; + TRACE("not available (compiled w/o force feedback support)\n"); + return DIERR_UNSUPPORTED; #else
if (!(new_effect = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_effect))))
Modified: trunk/reactos/dll/directx/wine/dinput/joystick_osx.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/wine/dinput/joy... ============================================================================== --- trunk/reactos/dll/directx/wine/dinput/joystick_osx.c [iso-8859-1] (original) +++ trunk/reactos/dll/directx/wine/dinput/joystick_osx.c [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -1398,7 +1398,7 @@ if(!This->ff){ TRACE("No force feedback support\n"); *out = NULL; - return S_OK; + return DIERR_UNSUPPORTED; }
if(outer)
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=7... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Thu Nov 17 21:57:53 2016 @@ -30,7 +30,7 @@ reactos/dll/directx/wine/d3dxof # Synced to WineStaging-1.9.16 reactos/dll/directx/wine/ddraw # Synced to WineStaging-1.9.4 reactos/dll/directx/wine/devenum # Synced to WineStaging-1.9.16 -reactos/dll/directx/wine/dinput # Synced to WineStaging-1.9.16 +reactos/dll/directx/wine/dinput # Synced to WineStaging-1.9.23 reactos/dll/directx/wine/dinput8 # Synced to WineStaging-1.9.11 reactos/dll/directx/wine/dmusic # Synced to WineStaging-1.9.16 reactos/dll/directx/wine/dplay # Synced to WineStaging-1.9.11