From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/joystick_hid.c | 11 +++++++- dlls/dinput/tests/force_feedback.c | 40 ------------------------------ 2 files changed, 10 insertions(+), 41 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 41fd0e24963..2ec218ffc09 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2641,7 +2641,9 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa impl->params.cbTypeSpecificParams = params->cbTypeSpecificParams; }
- if ((flags & DIEP_ENVELOPE) && params->lpEnvelope) + if (!(flags & DIEP_ENVELOPE)) + TRACE( "Keeping previous effect envelope\n" ); + else if (params->lpEnvelope) { if (params->lpEnvelope->dwSize != sizeof(DIENVELOPE)) return DIERR_INVALIDPARAM; impl->params.lpEnvelope = &impl->envelope; @@ -2649,6 +2651,13 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa impl->modified |= DIEP_ENVELOPE; memcpy( impl->params.lpEnvelope, params->lpEnvelope, sizeof(DIENVELOPE) ); } + else + { + flags &= ~DIEP_ENVELOPE; + impl->flags &= ~DIEP_ENVELOPE; + impl->modified &= ~DIEP_ENVELOPE; + impl->params.lpEnvelope = NULL; + }
if (flags & DIEP_DURATION) { diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index 1e68748a07d..f6157a84df7 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -458,14 +458,6 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO .report_len = 2, .report_buf = {0x05,0x19}, }, - /* set envelope (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 6, - .report_len = 7, - .report_buf = {0x06,0x19,0x4c,0x01,0x00,0x04,0x00}, - .todo = TRUE, .wine_only = TRUE, - }, /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, @@ -5683,14 +5675,6 @@ static void test_windows_gaming_input(void) .report_len = 10, .report_buf = {7,0x01,0x10,0x27,0x00,0x00,0x70,0xff,0xe8,0x03}, }, - /* set envelope (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 8, - .report_len = 8, - .report_buf = {8,0x01,0x00,0x00,0x00,0x00,0x00,0x00}, - .todo = TRUE, .wine_only = TRUE, - }, /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, @@ -5822,14 +5806,6 @@ static void test_windows_gaming_input(void) .report_len = 4, .report_buf = {9,0x01,0x18,0xfc}, }, - /* set envelope (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 8, - .report_len = 8, - .report_buf = {8,0x01,0x00,0x00,0x00,0x00,0x00,0x00}, - .todo = TRUE, .wine_only = TRUE, - }, /* update effect (wine) */ { .code = IOCTL_HID_WRITE_REPORT, @@ -5908,14 +5884,6 @@ static void test_windows_gaming_input(void) .report_len = 6, .report_buf = {10,0x01,0xe8,0x03,0xa0,0x0f}, }, - /* set envelope (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 8, - .report_len = 8, - .report_buf = {8,0x01,0x00,0x00,0x00,0x00,0x00,0x00}, - .todo = TRUE, .wine_only = TRUE, - }, /* update effect (wine) */ { .code = IOCTL_HID_WRITE_REPORT, @@ -5956,14 +5924,6 @@ static void test_windows_gaming_input(void) .report_len = 6, .report_buf = {10,0x01,0x18,0xfc,0x60,0xf0}, }, - /* set envelope (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 8, - .report_len = 8, - .report_buf = {8,0x01,0x00,0x00,0x00,0x00,0x00,0x00}, - .todo = TRUE, .wine_only = TRUE, - }, /* update effect (wine) */ { .code = IOCTL_HID_WRITE_REPORT,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/force_feedback.c | 9 --------- dlls/windows.gaming.input/force_feedback.c | 16 ++++++++-------- 2 files changed, 8 insertions(+), 17 deletions(-)
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index f6157a84df7..6fdfa20c130 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -5884,21 +5884,12 @@ static void test_windows_gaming_input(void) .report_len = 6, .report_buf = {10,0x01,0xe8,0x03,0xa0,0x0f}, }, - /* update effect (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 3, - .report_len = 18, - .report_buf = {3,0x01,0x05,0x04,0x8f,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x01,0x00,0x00}, - .todo = TRUE, .wine_only = TRUE, - }, /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 18, .report_buf = {3,0x01,0x05,0x04,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x01,0x00,0x00}, - .todo = TRUE, }, }; struct hid_expect expect_create_ramp_neg[] = diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c index f7a233b46d4..d404934c3a7 100644 --- a/dlls/windows.gaming.input/force_feedback.c +++ b/dlls/windows.gaming.input/force_feedback.c @@ -124,8 +124,8 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * case WineForceFeedbackEffectType_Constant: impl->repeat_count = params.constant.repeat_count; impl->constant_force.lMagnitude = round( params.constant.gain * params.constant.direction.X * 10000 ); - impl->params.dwDuration = params.constant.duration.Duration / 10; - impl->params.dwStartDelay = params.constant.start_delay.Duration / 10; + impl->params.dwDuration = min( max( params.constant.duration.Duration / 10, 0 ), INFINITE ); + impl->params.dwStartDelay = min( max( params.constant.start_delay.Duration / 10, 0 ), INFINITE ); if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( -params.constant.direction.X * 10000 ); if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( -params.constant.direction.Y * 10000 ); if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( -params.constant.direction.Z * 10000 ); @@ -135,8 +135,8 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * impl->repeat_count = params.ramp.repeat_count; impl->ramp_force.lStart = round( params.ramp.gain * params.ramp.start_vector.X * 10000 ); impl->ramp_force.lEnd = round( params.ramp.gain * params.ramp.end_vector.X * 10000 ); - impl->params.dwDuration = params.ramp.duration.Duration / 10; - impl->params.dwStartDelay = params.ramp.start_delay.Duration / 10; + impl->params.dwDuration = min( max( params.ramp.duration.Duration / 10, 0 ), INFINITE ); + impl->params.dwStartDelay = min( max( params.ramp.start_delay.Duration / 10, 0 ), INFINITE ); if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( -params.ramp.start_vector.X * 10000 ); if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( -params.ramp.start_vector.Y * 10000 ); if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( -params.ramp.start_vector.Z * 10000 ); @@ -152,8 +152,8 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * impl->periodic.dwPeriod = 1000000 / params.periodic.frequency; impl->periodic.dwPhase = round( params.periodic.phase * 36000 ); impl->periodic.lOffset = round( params.periodic.bias * 10000 ); - impl->params.dwDuration = params.periodic.duration.Duration / 10; - impl->params.dwStartDelay = params.periodic.start_delay.Duration / 10; + impl->params.dwDuration = min( max( params.periodic.duration.Duration / 10, 0 ), INFINITE ); + impl->params.dwStartDelay = min( max( params.periodic.start_delay.Duration / 10, 0 ), INFINITE ); if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( -params.periodic.direction.X * 10000 ); if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( -params.periodic.direction.Y * 10000 ); if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( -params.periodic.direction.Z * 10000 ); @@ -181,9 +181,9 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * if (!envelope) impl->params.lpEnvelope = NULL; else { - impl->envelope.dwAttackTime = envelope->attack_duration.Duration / 10; + impl->envelope.dwAttackTime = min( max( envelope->attack_duration.Duration / 10, 0 ), INFINITE ); impl->envelope.dwAttackLevel = round( envelope->attack_gain * 10000 ); - impl->envelope.dwFadeTime = impl->params.dwDuration - envelope->release_duration.Duration / 10; + impl->envelope.dwFadeTime = impl->params.dwDuration - min( max( envelope->release_duration.Duration / 10, 0 ), INFINITE ); impl->envelope.dwFadeLevel = round( envelope->release_gain * 10000 ); impl->params.lpEnvelope = &impl->envelope; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/windows.gaming.input/force_feedback.c | 63 +++++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-)
diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c index d404934c3a7..20b022ff317 100644 --- a/dlls/windows.gaming.input/force_feedback.c +++ b/dlls/windows.gaming.input/force_feedback.c @@ -109,37 +109,74 @@ static ULONG WINAPI effect_impl_Release( IWineForceFeedbackEffectImpl *iface ) return ref; }
+static int effect_reorient_direction( const WineForceFeedbackEffectParameters *params, Vector3 *direction ) +{ + int sign = +1; + + switch (params->type) + { + case WineForceFeedbackEffectType_Constant: + *direction = params->constant.direction; + break; + + case WineForceFeedbackEffectType_Ramp: + *direction = params->ramp.start_vector; + break; + + case WineForceFeedbackEffectType_Periodic_SineWave: + case WineForceFeedbackEffectType_Periodic_TriangleWave: + case WineForceFeedbackEffectType_Periodic_SquareWave: + case WineForceFeedbackEffectType_Periodic_SawtoothWaveDown: + case WineForceFeedbackEffectType_Periodic_SawtoothWaveUp: + *direction = params->periodic.direction; + break; + + case WineForceFeedbackEffectType_Condition_Spring: + case WineForceFeedbackEffectType_Condition_Damper: + case WineForceFeedbackEffectType_Condition_Inertia: + case WineForceFeedbackEffectType_Condition_Friction: + *direction = params->condition.direction; + sign = -1; + break; + } + + direction->X *= -sign; + direction->Y *= -sign; + direction->Z *= -sign; + + return sign; +} + static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl *iface, WineForceFeedbackEffectParameters params, WineForceFeedbackEffectEnvelope *envelope ) { struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface ); + Vector3 direction = {0}; DWORD count = 0; HRESULT hr; + int sign;
TRACE( "iface %p, params %p, envelope %p.\n", iface, ¶ms, envelope );
EnterCriticalSection( &impl->cs ); + + sign = effect_reorient_direction( ¶ms, &direction ); + switch (params.type) { case WineForceFeedbackEffectType_Constant: impl->repeat_count = params.constant.repeat_count; - impl->constant_force.lMagnitude = round( params.constant.gain * params.constant.direction.X * 10000 ); + impl->constant_force.lMagnitude = -sign * round( params.constant.gain * direction.X * 10000 ); impl->params.dwDuration = min( max( params.constant.duration.Duration / 10, 0 ), INFINITE ); impl->params.dwStartDelay = min( max( params.constant.start_delay.Duration / 10, 0 ), INFINITE ); - if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( -params.constant.direction.X * 10000 ); - if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( -params.constant.direction.Y * 10000 ); - if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( -params.constant.direction.Z * 10000 ); break;
case WineForceFeedbackEffectType_Ramp: impl->repeat_count = params.ramp.repeat_count; - impl->ramp_force.lStart = round( params.ramp.gain * params.ramp.start_vector.X * 10000 ); + impl->ramp_force.lStart = -sign * round( params.ramp.gain * direction.X * 10000 ); impl->ramp_force.lEnd = round( params.ramp.gain * params.ramp.end_vector.X * 10000 ); impl->params.dwDuration = min( max( params.ramp.duration.Duration / 10, 0 ), INFINITE ); impl->params.dwStartDelay = min( max( params.ramp.start_delay.Duration / 10, 0 ), INFINITE ); - if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( -params.ramp.start_vector.X * 10000 ); - if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( -params.ramp.start_vector.Y * 10000 ); - if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( -params.ramp.start_vector.Z * 10000 ); break;
case WineForceFeedbackEffectType_Periodic_SineWave: @@ -154,9 +191,6 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * impl->periodic.lOffset = round( params.periodic.bias * 10000 ); impl->params.dwDuration = min( max( params.periodic.duration.Duration / 10, 0 ), INFINITE ); impl->params.dwStartDelay = min( max( params.periodic.start_delay.Duration / 10, 0 ), INFINITE ); - if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( -params.periodic.direction.X * 10000 ); - if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( -params.periodic.direction.Y * 10000 ); - if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( -params.periodic.direction.Z * 10000 ); break;
case WineForceFeedbackEffectType_Condition_Spring: @@ -172,12 +206,13 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * impl->condition.lOffset = round( params.condition.bias * 10000 ); impl->params.dwDuration = -1; impl->params.dwStartDelay = 0; - if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( params.condition.direction.X * 10000 ); - if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( params.condition.direction.Y * 10000 ); - if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( params.condition.direction.Z * 10000 ); break; }
+ if (impl->axes[count] == DIJOFS_X) impl->directions[count++] = round( direction.X * 10000 ); + if (impl->axes[count] == DIJOFS_Y) impl->directions[count++] = round( direction.Y * 10000 ); + if (impl->axes[count] == DIJOFS_Z) impl->directions[count++] = round( direction.Z * 10000 ); + if (!envelope) impl->params.lpEnvelope = NULL; else {
From: Rémi Bernon rbernon@codeweavers.com
The magnitude already carries the sign of X direction. Having a signed direction will inverse the effective direction. The Y and Z direction sign and magnitude seem to be ignored. --- dlls/dinput/tests/force_feedback.c | 18 ------------------ dlls/windows.gaming.input/force_feedback.c | 9 +++++++-- 2 files changed, 7 insertions(+), 20 deletions(-)
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index 6fdfa20c130..5ffc6a43471 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -5806,21 +5806,12 @@ static void test_windows_gaming_input(void) .report_len = 4, .report_buf = {9,0x01,0x18,0xfc}, }, - /* update effect (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 3, - .report_len = 18, - .report_buf = {3,0x01,0x04,0x04,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x99,0x00,0x00,0x00}, - .wine_only = TRUE, .todo = TRUE, - }, /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 18, .report_buf = {3,0x01,0x04,0x04,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x4e,0x01,0x00,0x00}, - .todo = TRUE, }, }; struct hid_expect expect_create_ramp[] = @@ -5915,21 +5906,12 @@ static void test_windows_gaming_input(void) .report_len = 6, .report_buf = {10,0x01,0x18,0xfc,0x60,0xf0}, }, - /* update effect (wine) */ - { - .code = IOCTL_HID_WRITE_REPORT, - .report_id = 3, - .report_len = 18, - .report_buf = {3,0x01,0x05,0x04,0x8f,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x00,0x00,0x00}, - .wine_only = TRUE, .todo = TRUE, - }, /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 18, .report_buf = {3,0x01,0x05,0x04,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x01,0x00,0x00}, - .todo = TRUE, }, }; struct hid_expect expect_effect_start = diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c index 20b022ff317..cff3c184bf9 100644 --- a/dlls/windows.gaming.input/force_feedback.c +++ b/dlls/windows.gaming.input/force_feedback.c @@ -117,10 +117,12 @@ static int effect_reorient_direction( const WineForceFeedbackEffectParameters *p { case WineForceFeedbackEffectType_Constant: *direction = params->constant.direction; + sign = params->constant.direction.X < 0 ? -1 : +1; break;
case WineForceFeedbackEffectType_Ramp: *direction = params->ramp.start_vector; + sign = params->ramp.start_vector.X < 0 ? -1 : +1; break;
case WineForceFeedbackEffectType_Periodic_SineWave: @@ -152,6 +154,7 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * { struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface ); Vector3 direction = {0}; + double magnitude = 0; DWORD count = 0; HRESULT hr; int sign; @@ -161,19 +164,21 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * EnterCriticalSection( &impl->cs );
sign = effect_reorient_direction( ¶ms, &direction ); + /* Y and Z axes seems to be always ignored, is it really the case? */ + magnitude += direction.X * direction.X;
switch (params.type) { case WineForceFeedbackEffectType_Constant: impl->repeat_count = params.constant.repeat_count; - impl->constant_force.lMagnitude = -sign * round( params.constant.gain * direction.X * 10000 ); + impl->constant_force.lMagnitude = sign * round( params.constant.gain * sqrt( magnitude ) * 10000 ); impl->params.dwDuration = min( max( params.constant.duration.Duration / 10, 0 ), INFINITE ); impl->params.dwStartDelay = min( max( params.constant.start_delay.Duration / 10, 0 ), INFINITE ); break;
case WineForceFeedbackEffectType_Ramp: impl->repeat_count = params.ramp.repeat_count; - impl->ramp_force.lStart = -sign * round( params.ramp.gain * direction.X * 10000 ); + impl->ramp_force.lStart = sign * round( params.ramp.gain * sqrt( magnitude ) * 10000 ); impl->ramp_force.lEnd = round( params.ramp.gain * params.ramp.end_vector.X * 10000 ); impl->params.dwDuration = min( max( params.ramp.duration.Duration / 10, 0 ), INFINITE ); impl->params.dwStartDelay = min( max( params.ramp.start_delay.Duration / 10, 0 ), INFINITE );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/hid.c | 5 +++++ dlls/hid/hidp.c | 31 +++++++++++++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 5200892e95b..a5ede6ee29b 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -1841,6 +1841,11 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle ok( buffer[0] == (char)0xcd, "got report value %#x\n", buffer[0] ); ok( buffer[1] == (char)0xcd, "got report value %#x\n", buffer[1] );
+ status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, 0, &value, preparsed_data, report, caps.InputReportByteLength ); + ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetUsageValue returned %#lx\n", status ); + status = HidP_GetUsageValue( HidP_Input, 0, 0, HID_USAGE_GENERIC_X, &value, preparsed_data, report, caps.InputReportByteLength ); + ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetUsageValue returned %#lx\n", status ); + report[16] = 0xff; report[17] = 0xff; status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 83a4638b6ad..c24a98155b0 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -68,14 +68,17 @@ static NTSTATUS get_value_caps_range( struct hid_preparsed_data *preparsed, HIDP return HIDP_STATUS_SUCCESS; }
+#define USAGE_MASK 0xffff +#define USAGE_ANY 0x10000 + struct caps_filter { BOOLEAN buttons; BOOLEAN values; BOOLEAN array; - USAGE usage_page; + DWORD usage_page; USHORT collection; - USAGE usage; + DWORD usage; UCHAR report_id; };
@@ -84,10 +87,10 @@ static BOOL match_value_caps( const struct hid_value_caps *caps, const struct ca if (!caps->usage_min && !caps->usage_max) return FALSE; if (filter->buttons && !(caps->flags & HID_VALUE_CAPS_IS_BUTTON)) return FALSE; if (filter->values && (caps->flags & HID_VALUE_CAPS_IS_BUTTON)) return FALSE; - if (filter->usage_page && filter->usage_page != caps->usage_page) return FALSE; + if (filter->usage_page != USAGE_ANY && (filter->usage_page & USAGE_MASK) != caps->usage_page) return FALSE; if (filter->collection && filter->collection != caps->link_collection) return FALSE; - if (!filter->usage) return TRUE; - return caps->usage_min <= filter->usage && caps->usage_max >= filter->usage; + if (filter->usage == USAGE_ANY) return TRUE; + return caps->usage_min <= (filter->usage & USAGE_MASK) && caps->usage_max >= (filter->usage & USAGE_MASK); }
typedef NTSTATUS (*enum_value_caps_callback)( const struct hid_value_caps *caps, void *user ); @@ -384,7 +387,7 @@ NTSTATUS WINAPI HidP_GetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct get_usage_params params = {.usages = usages, .usages_end = usages + *usages_len, .report_buf = report_buf}; - struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection, .usage = USAGE_ANY}; NTSTATUS status; USHORT limit = -1;
@@ -441,7 +444,7 @@ static NTSTATUS get_usage_list_length( const struct hid_value_caps *caps, void * ULONG WINAPI HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type, USAGE usage_page, PHIDP_PREPARSED_DATA preparsed_data ) { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page | USAGE_ANY, .usage = USAGE_ANY}; USHORT limit = -1; ULONG count = 0;
@@ -590,7 +593,7 @@ NTSTATUS WINAPI HidP_SetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct set_usage_params params = {.report_buf = report_buf}; - struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection, .usage = USAGE_ANY}; NTSTATUS status; USHORT limit = 1; ULONG i, count = *usage_count; @@ -656,7 +659,7 @@ NTSTATUS WINAPI HidP_UnsetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct unset_usage_params params = {.report_buf = report_buf, .found = FALSE}; - struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection, .usage = USAGE_ANY}; NTSTATUS status; USHORT limit = 1; ULONG i, count = *usage_count; @@ -739,7 +742,7 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type, USAGE PHIDP_PREPARSED_DATA preparsed_data ) { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - const struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; + const struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page | USAGE_ANY, .collection = collection, .usage = usage | USAGE_ANY};
TRACE( "report_type %d, usage_page %u, collection %u, usage %u, caps %p, caps_count %p, preparsed_data %p.\n", report_type, usage_page, collection, usage, caps, caps_count, preparsed_data ); @@ -806,7 +809,7 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type, USAGE u PHIDP_PREPARSED_DATA preparsed_data ) { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - const struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; + const struct caps_filter filter = {.values = TRUE, .usage_page = usage_page | USAGE_ANY, .collection = collection, .usage = usage | USAGE_ANY};
TRACE( "report_type %d, usage_page %u, collection %u, usage %u, caps %p, caps_count %p, preparsed_data %p.\n", report_type, usage_page, collection, usage, caps, caps_count, preparsed_data ); @@ -869,7 +872,7 @@ NTSTATUS WINAPI HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type, USHORT collectio { struct get_usage_and_page_params params = {.usages = usages, .usages_end = usages + *usages_len, .report_buf = report_buf}; struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - struct caps_filter filter = {.buttons = TRUE, .collection = collection}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = USAGE_ANY, .collection = collection, .usage = USAGE_ANY}; NTSTATUS status; USHORT limit = -1;
@@ -899,7 +902,7 @@ static NTSTATUS count_data( const struct hid_value_caps *caps, void *user ) ULONG WINAPI HidP_MaxDataListLength( HIDP_REPORT_TYPE report_type, PHIDP_PREPARSED_DATA preparsed_data ) { struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - struct caps_filter filter = {}; + struct caps_filter filter = {.usage_page = USAGE_ANY, .usage = USAGE_ANY}; USHORT limit = -1; ULONG count = 0;
@@ -981,7 +984,7 @@ NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULO { struct find_all_data_params params = {.data = data, .data_end = data + *data_len, .report_buf = report_buf}; struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; - struct caps_filter filter = {}; + struct caps_filter filter = {.usage_page = USAGE_ANY, .usage = USAGE_ANY}; NTSTATUS status; USHORT limit = -1;