Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 162 ++++++++++++++++++++++++++++++++++++- dlls/dinput8/tests/hid.c | 48 ----------- 2 files changed, 160 insertions(+), 50 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index e0fd2842feb..3014e76603b 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -150,6 +150,12 @@ struct hid_joystick_effect struct list entry; struct hid_joystick *joystick;
+ DWORD axes[6]; + LONG directions[6]; + DIENVELOPE envelope; + DIPERIODIC periodic; + DIEFFECT params; + char *effect_control_buf; char *effect_update_buf; }; @@ -2120,10 +2126,155 @@ static HRESULT WINAPI hid_joystick_effect_GetEffectGuid( IDirectInputEffect *ifa return DI_OK; }
+static BOOL get_parameters_object_id( struct hid_joystick *impl, struct hid_value_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + *(DWORD *)data = instance->dwType; + return DIENUM_STOP; +} + +static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_value_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + DIDATAFORMAT *format = impl->base.data_format.wine_df; + int *offsets = impl->base.data_format.offsets; + ULONG i; + + if (!offsets) return DIENUM_CONTINUE; + for (i = 0; i < format->dwNumObjs; ++i) + if (format->rgodf[i].dwOfs == instance->dwOfs) break; + if (i == format->dwNumObjs) return DIENUM_CONTINUE; + *(DWORD *)data = offsets[i]; + + return DIENUM_STOP; +} + static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags ) { - FIXME( "iface %p, params %p, flags %#x stub!\n", iface, params, flags ); - return DIERR_UNSUPPORTED; + DIPROPHEADER filter = + { + .dwSize = sizeof(DIPROPHEADER), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_BYUSAGE, + }; + struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); + ULONG i, j, count, capacity, object_flags, direction_flags; + LONG tmp, directions[6] = {0}; + BOOL ret; + + TRACE( "iface %p, params %p, flags %#x.\n", iface, params, flags ); + + if (!params) return DI_OK; + if (params->dwSize != sizeof(DIEFFECT)) return DIERR_INVALIDPARAM; + capacity = params->cAxes; + object_flags = params->dwFlags & (DIEFF_OBJECTIDS | DIEFF_OBJECTOFFSETS); + direction_flags = params->dwFlags & (DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + if (flags & DIEP_AXES) + { + if (!object_flags) return DIERR_INVALIDPARAM; + params->cAxes = impl->params.cAxes; + if (capacity < impl->params.cAxes) return DIERR_MOREDATA; + + for (i = 0; i < impl->params.cAxes; ++i) + { + if (!params->rgdwAxes) return DIERR_INVALIDPARAM; + filter.dwObj = impl->params.rgdwAxes[i]; + if (object_flags & DIEFF_OBJECTIDS) + ret = enum_objects( impl->joystick, &filter, DIDFT_AXIS, get_parameters_object_id, + ¶ms->rgdwAxes[i] ); + else + ret = enum_objects( impl->joystick, &filter, DIDFT_AXIS, get_parameters_object_ofs, + ¶ms->rgdwAxes[i] ); + if (ret != DIENUM_STOP) params->rgdwAxes[i] = 0; + } + } + + if (flags & DIEP_DIRECTION) + { + if (!direction_flags) return DIERR_INVALIDPARAM; + params->dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + count = params->cAxes = impl->params.cAxes; + if (capacity < params->cAxes) return DIERR_MOREDATA; + if (!count) params->dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL); + + if (direction_flags & DIEFF_SPHERICAL) + memcpy( directions, impl->params.rglDirection, count * sizeof(LONG) ); + else if (direction_flags & DIEFF_POLAR) + { + if (count != 2) return DIERR_INVALIDPARAM; + directions[0] = (impl->params.rglDirection[0] + 9000) % 36000; + if (directions[0] < 0) directions[0] += 36000; + } + else if (direction_flags & DIEFF_CARTESIAN) + { + directions[0] = 10000; + for (i = 1; i <= count; ++i) + { + tmp = cos( impl->params.rglDirection[i - 1] * M_PI / 18000 ) * 10000; + for (j = 0; j < i; ++j) directions[j] = round( directions[j] * tmp / 10000.0 ); + directions[i] = sin( impl->params.rglDirection[i - 1] * M_PI / 18000 ) * 10000; + } + } + + if (!params->rglDirection) return DIERR_INVALIDPARAM; + else memcpy( params->rglDirection, directions, count * sizeof(LONG) ); + } + + if (flags & DIEP_TYPESPECIFICPARAMS) + { + switch (impl->type) + { + case PID_USAGE_ET_SQUARE: + case PID_USAGE_ET_SINE: + case PID_USAGE_ET_TRIANGLE: + case PID_USAGE_ET_SAWTOOTH_UP: + case PID_USAGE_ET_SAWTOOTH_DOWN: + if (!params->lpvTypeSpecificParams) return E_POINTER; + if (params->cbTypeSpecificParams != sizeof(DIPERIODIC)) return DIERR_INVALIDPARAM; + memcpy( params->lpvTypeSpecificParams, &impl->periodic, sizeof(DIPERIODIC) ); + break; + case PID_USAGE_ET_SPRING: + case PID_USAGE_ET_DAMPER: + case PID_USAGE_ET_INERTIA: + case PID_USAGE_ET_FRICTION: + case PID_USAGE_ET_CONSTANT_FORCE: + case PID_USAGE_ET_RAMP: + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + FIXME( "DIEP_TYPESPECIFICPARAMS not implemented!\n" ); + return DIERR_UNSUPPORTED; + } + } + + if (flags & DIEP_ENVELOPE) + { + if (!params->lpEnvelope) return E_POINTER; + if (params->lpEnvelope->dwSize != sizeof(DIENVELOPE)) return DIERR_INVALIDPARAM; + memcpy( params->lpEnvelope, &impl->envelope, sizeof(DIENVELOPE) ); + } + + if (flags & DIEP_DURATION) params->dwDuration = impl->params.dwDuration; + if (flags & DIEP_GAIN) params->dwGain = impl->params.dwGain; + if (flags & DIEP_SAMPLEPERIOD) params->dwSamplePeriod = impl->params.dwSamplePeriod; + if (flags & DIEP_STARTDELAY) params->dwStartDelay = impl->params.dwStartDelay; + if (flags & DIEP_TRIGGERREPEATINTERVAL) params->dwTriggerRepeatInterval = impl->params.dwTriggerRepeatInterval; + + if (flags & DIEP_TRIGGERBUTTON) + { + if (!object_flags) return DIERR_INVALIDPARAM; + + filter.dwObj = impl->params.dwTriggerButton; + if (object_flags & DIEFF_OBJECTIDS) + ret = enum_objects( impl->joystick, &filter, DIDFT_BUTTON, get_parameters_object_id, + ¶ms->dwTriggerButton ); + else + ret = enum_objects( impl->joystick, &filter, DIDFT_BUTTON, get_parameters_object_ofs, + ¶ms->dwTriggerButton ); + if (ret != DIENUM_STOP) params->dwTriggerButton = -1; + } + + return DI_OK; }
static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *iface, @@ -2296,6 +2447,13 @@ static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirec if (!(impl->effect_control_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed; if (!(impl->effect_update_buf = HeapAlloc( GetProcessHeap(), 0, report_len ))) goto failed;
+ impl->envelope.dwSize = sizeof(DIENVELOPE); + impl->params.dwSize = sizeof(DIEFFECT); + impl->params.lpEnvelope = &impl->envelope; + impl->params.rgdwAxes = impl->axes; + impl->params.rglDirection = impl->directions; + impl->params.dwTriggerButton = -1; + *out = &impl->IDirectInputEffect_iface; return DI_OK;
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index a53502ca8d4..fc6a235617c 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5289,17 +5289,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) debugstr_guid( &GUID_Square ) );
hr = IDirectInputEffect_GetParameters( effect, NULL, 0 ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, NULL, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); desc.dwSize = sizeof(DIEFFECT); hr = IDirectInputEffect_GetParameters( effect, &desc, 0 ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); @@ -5307,7 +5303,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "Unacquire returned: %#x\n", hr ); set_hid_expect( file, NULL, 0 ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); hr = IDirectInputDevice8_Acquire( device ); @@ -5316,24 +5311,17 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.dwDuration = 0xdeadbeef; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", dwDuration ); memset( &desc, 0xcd, sizeof(desc) ); desc.dwSize = sizeof(DIEFFECT); desc.dwFlags = 0; flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); - todo_wine check_member( desc, expect_desc_init, "%u", dwGain ); - todo_wine check_member( desc, expect_desc_init, "%u", dwStartDelay ); - todo_wine check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval );
memset( &desc, 0xcd, sizeof(desc) ); @@ -5341,15 +5329,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwFlags = 0; desc.lpEnvelope = NULL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == E_POINTER, "GetParameters returned %#x\n", hr ); desc.lpEnvelope = &envelope; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); envelope.dwSize = sizeof(DIENVELOPE); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
desc.dwFlags = 0; @@ -5360,58 +5345,43 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cbTypeSpecificParams = 0; desc.lpvTypeSpecificParams = NULL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); desc.dwFlags = DIEFF_OBJECTOFFSETS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); desc.dwFlags = DIEFF_OBJECTIDS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); desc.dwFlags |= DIEFF_CARTESIAN; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); desc.dwFlags |= DIEFF_POLAR; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS ); desc.dwFlags |= DIEFF_SPHERICAL; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); check_member( desc, expect_desc_init, "%u", cAxes ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
desc.dwFlags |= DIEFF_SPHERICAL; @@ -5419,15 +5389,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.rgdwAxes = axes; desc.rglDirection = directions; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%u", rgdwAxes[0] ); check_member( desc, expect_desc_init, "%u", rgdwAxes[1] ); todo_wine check_member( desc, expect_desc_init, "%p", rglDirection ); - todo_wine ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
desc.dwFlags |= DIEFF_SPHERICAL; @@ -5435,19 +5402,12 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.cbTypeSpecificParams = sizeof(periodic); desc.lpvTypeSpecificParams = &periodic; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ALLPARAMS ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); - todo_wine check_member( desc, expect_desc_init, "%u", dwDuration ); - todo_wine check_member( desc, expect_desc_init, "%u", dwSamplePeriod ); - todo_wine check_member( desc, expect_desc_init, "%u", dwGain ); - todo_wine check_member( desc, expect_desc_init, "%#x", dwTriggerButton ); - todo_wine check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval ); - todo_wine check_member( desc, expect_desc_init, "%u", cAxes ); check_member( desc, expect_desc_init, "%u", rgdwAxes[0] ); check_member( desc, expect_desc_init, "%u", rgdwAxes[1] ); @@ -5457,7 +5417,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) check_member( desc, expect_desc_init, "%p", lpEnvelope ); todo_wine check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams ); - todo_wine check_member( desc, expect_desc_init, "%u", dwStartDelay );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) ); @@ -5509,7 +5468,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.dwTriggerButton = -1; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( desc, expect_desc, "%u", dwDuration ); @@ -5538,7 +5496,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwDuration = 0; flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERREPEATINTERVAL; hr = IDirectInputEffect_GetParameters( effect, &desc, flags ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( desc, expect_desc, "%u", dwDuration ); @@ -5580,7 +5537,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.lpEnvelope = &envelope; envelope.dwSize = sizeof(DIENVELOPE); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( envelope, expect_envelope, "%u", dwAttackLevel ); @@ -5639,7 +5595,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) todo_wine check_member( desc, expect_desc, "%u", cAxes ); hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( desc, expect_desc, "%#x", dwTriggerButton ); @@ -5654,7 +5609,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
desc.dwFlags = DIEFF_OBJECTOFFSETS; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine ok( desc.dwTriggerButton == 0x30, "got %#x expected %#x\n", desc.dwTriggerButton, 0x30 ); @@ -5729,7 +5683,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) desc.dwFlags = DIEFF_POLAR; desc.cAxes = 3; hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
hr = IDirectInputEffect_Download( effect ); @@ -5753,7 +5706,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS ); - todo_wine ok( hr == DI_OK, "GetParameters returned %#x\n", hr ); todo_wine check_member( periodic, expect_periodic, "%u", dwMagnitude );