Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 43 +++++++++++++++++++++++++++++++++----- dlls/dinput8/tests/hid.c | 30 ++++++++------------------ 2 files changed, 47 insertions(+), 26 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index e20d02224fe..3dc0776a1ec 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -854,15 +854,47 @@ static LONG sign_extend( ULONG value, const HIDP_VALUE_CAPS *caps )
static LONG scale_value( ULONG value, const HIDP_VALUE_CAPS *caps, LONG min, LONG max ) { - ULONG bit_max = (1 << caps->BitSize) - 1; LONG tmp = sign_extend( value, caps ); - - /* xinput HID gamepad have bogus logical value range, let's use the bit range instead */ - if (caps->LogicalMin == 0 && caps->LogicalMax == -1) return min + MulDiv( tmp, max - min, bit_max ); if (caps->LogicalMin > tmp || caps->LogicalMax < tmp) return -1; /* invalid / null value */ return min + MulDiv( tmp - caps->LogicalMin, max - min, caps->LogicalMax - caps->LogicalMin ); }
+static LONG scale_axis_value( ULONG value, const HIDP_VALUE_CAPS *caps ) +{ + LONG tmp = sign_extend( value, caps ), log_ctr, log_min, log_max, phy_ctr, phy_min, phy_max; + ULONG bit_max = (1 << caps->BitSize) - 1; + + log_min = caps->LogicalMin; + log_max = caps->LogicalMax; + phy_min = caps->PhysicalMin; + phy_max = caps->PhysicalMax; + /* xinput HID gamepad have bogus logical value range, let's use the bit range instead */ + if (log_min == 0 && log_max == -1) log_max = bit_max; + + if (phy_min == 0) phy_ctr = phy_max >> 1; + else phy_ctr = round( (phy_min + phy_max) / 2.0 ); + if (log_min == 0) log_ctr = log_max >> 1; + else log_ctr = round( (log_min + log_max) / 2.0 ); + + tmp -= log_ctr; + if (tmp <= 0) + { + log_max = 0; + log_min -= log_ctr; + phy_max = phy_ctr; + } + else + { + log_min = 0; + log_max -= log_ctr; + phy_min = phy_ctr; + } + + if (tmp <= log_min) return phy_min; + if (tmp >= log_max) return phy_max; + return phy_min + MulDiv( tmp - log_min, phy_max - phy_min, log_max - log_min ); +} + static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data ) { @@ -878,7 +910,8 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_caps &logical_value, impl->preparsed, report_buf, report_len ); if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_GetUsageValue %04x:%04x returned %#x\n", instance->wUsagePage, instance->wUsage, status ); - value = scale_value( logical_value, value_caps, value_caps->PhysicalMin, value_caps->PhysicalMax ); + if (instance->dwType & DIDFT_AXIS) value = scale_axis_value( logical_value, value_caps ); + else value = scale_value( logical_value, value_caps, value_caps->PhysicalMin, value_caps->PhysicalMax );
old_value = *(LONG *)(params->old_state + instance->dwOfs); *(LONG *)(impl->device_state + instance->dwOfs) = value; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index ae758837d36..ec5dffe70f5 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -4098,11 +4098,8 @@ static void test_simple_joystick(void) winetest_push_context( "state[%d]", i ); hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state ); ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr ); - todo_wine_if( i != 0 && i != 2 ) check_member( state, expect_state[i], "%d", lX ); - todo_wine_if( i != 0 && i != 2 ) check_member( state, expect_state[i], "%d", lY ); - todo_wine_if( i != 0 ) check_member( state, expect_state[i], "%d", lZ ); check_member( state, expect_state[i], "%d", lRx ); check_member( state, expect_state[i], "%#x", rgdwPOV[0] ); @@ -4114,20 +4111,17 @@ static void test_simple_joystick(void) send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
res = WaitForSingleObject( event, 100 ); - if (i == 0 || i == 3) todo_wine_if( i == 0 ) - ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" ); - else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); ResetEvent( event ); + if (i == 0 || i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" ); + else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); + ResetEvent( event ); winetest_pop_context(); }
hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state ); ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr ); winetest_push_context( "state[%d]", i ); - todo_wine check_member( state, expect_state[i], "%d", lX ); - todo_wine check_member( state, expect_state[i], "%d", lY ); - todo_wine check_member( state, expect_state[i], "%d", lZ ); check_member( state, expect_state[i], "%d", lRx ); check_member( state, expect_state[i], "%#x", rgdwPOV[0] ); @@ -4237,7 +4231,7 @@ static void test_simple_joystick(void) winetest_push_context( "objdata[%d]", i ); todo_wine check_member( objdata[i], expect_objdata[6 + i], "%#x", dwOfs ); - todo_wine_if( i != 3 && i != 4 && i != 7 ) + todo_wine_if( i == 1 || i == 2 || i == 6 ) check_member( objdata[i], expect_objdata[6 + i], "%#x", dwData ); ok( objdata[i].uAppData == -1, "got %p, expected %p\n", (void *)objdata[i].uAppData, (void *)-1 ); winetest_pop_context(); @@ -4250,11 +4244,8 @@ static void test_simple_joystick(void)
hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state ); ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr ); - todo_wine check_member( state, expect_state[3], "%d", lX ); - todo_wine check_member( state, expect_state[3], "%d", lY ); - todo_wine check_member( state, expect_state[3], "%d", lZ ); check_member( state, expect_state[3], "%d", lRx ); check_member( state, expect_state[3], "%d", rgdwPOV[0] ); @@ -4448,12 +4439,11 @@ static void test_simple_joystick(void) if (broken( state.lX == -10750 )) win_skip( "Ignoring 32-bit rounding\n" ); else { - todo_wine_if( i != 0 && i != 2 ) + todo_wine_if( i == 3 || i == 4 ) check_member( state, expect_state_abs[i], "%d", lX ); - todo_wine_if( i != 0 && i != 2 ) + todo_wine_if( i == 3 || i == 4 ) check_member( state, expect_state_abs[i], "%d", lY ); } - todo_wine_if( i != 0 ) check_member( state, expect_state_abs[i], "%d", lZ ); check_member( state, expect_state_abs[i], "%d", lRx ); check_member( state, expect_state_abs[i], "%d", rgdwPOV[0] ); @@ -4465,20 +4455,18 @@ static void test_simple_joystick(void) send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
res = WaitForSingleObject( event, 100 ); - if (i == 0 || i == 3) todo_wine_if( i == 0 ) - ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" ); - else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); ResetEvent( event ); + if (i == 0 || i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" ); + else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); + ResetEvent( event ); winetest_pop_context(); }
hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state ); ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr ); winetest_push_context( "state[%d]", i ); - todo_wine check_member( state, expect_state_abs[i], "%d", lX ); todo_wine check_member( state, expect_state_abs[i], "%d", lY ); - todo_wine check_member( state, expect_state_abs[i], "%d", lZ ); check_member( state, expect_state_abs[i], "%d", lRx ); check_member( state, expect_state_abs[i], "%d", rgdwPOV[0] );