From: Ivo Ivanov logos128@gmail.com Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 81 +++++++++++++++++++++++++++++++++----- dlls/dinput8/tests/hid.c | 3 -- 2 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index a43a73fff17..12ff10d7865 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -174,6 +174,7 @@ struct hid_joystick
char *input_report_buf; char *output_report_buf; + char *feature_report_buf; USAGE_AND_PAGE *usages_buf; ULONG usages_count;
@@ -401,15 +402,54 @@ static const WCHAR *object_usage_to_string( DIDEVICEOBJECTINSTANCEW *instance ) } }
-static HRESULT find_next_effect_id( struct hid_joystick *impl, ULONG *index ) +static HRESULT find_next_effect_id( struct hid_joystick *impl, DWORD *index, USAGE type ) { - ULONG i; + struct pid_device_pool *device_pool = &impl->pid_device_pool; + struct pid_new_effect *new_effect = &impl->pid_new_effect; + struct pid_block_load *block_load = &impl->pid_block_load; + ULONG i, count, report_len = impl->caps.FeatureReportByteLength; + NTSTATUS status; + USAGE usage;
- for (i = 0; i < ARRAY_SIZE(impl->effect_inuse); ++i) - if (!impl->effect_inuse[i]) break; - if (i == ARRAY_SIZE(impl->effect_inuse)) return DIERR_DEVICEFULL; - impl->effect_inuse[i] = TRUE; - *index = i + 1; + if (!device_pool->device_managed_caps) + { + for (i = 0; i < ARRAY_SIZE(impl->effect_inuse); ++i) + if (!impl->effect_inuse[i]) break; + if (i == ARRAY_SIZE(impl->effect_inuse)) return DIERR_DEVICEFULL; + impl->effect_inuse[i] = TRUE; + *index = i + 1; + } + else + { + status = HidP_InitializeReportForID( HidP_Feature, new_effect->id, impl->preparsed, + impl->feature_report_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return status; + + count = 1; + status = HidP_SetUsages( HidP_Feature, HID_USAGE_PAGE_PID, new_effect->type_coll, + &type, &count, impl->preparsed, impl->feature_report_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return status; + + if (!HidD_SetFeature( impl->device, impl->feature_report_buf, report_len )) return DIERR_INPUTLOST; + + status = HidP_InitializeReportForID( HidP_Feature, block_load->id, impl->preparsed, + impl->feature_report_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return status; + + if (!HidD_GetFeature( impl->device, impl->feature_report_buf, report_len )) return DIERR_INPUTLOST; + + count = 1; + status = HidP_GetUsages( HidP_Feature, HID_USAGE_PAGE_PID, block_load->status_coll, + &usage, &count, impl->preparsed, impl->feature_report_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return status; + + if (count != 1 || usage == PID_USAGE_BLOCK_LOAD_ERROR) return DIERR_INPUTLOST; + if (usage == PID_USAGE_BLOCK_LOAD_FULL) return DIERR_DEVICEFULL; + + status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_PID, 0, PID_USAGE_EFFECT_BLOCK_INDEX, + index, impl->preparsed, impl->feature_report_buf, report_len ); + if (status != HIDP_STATUS_SUCCESS) return status; + }
return DI_OK; } @@ -732,6 +772,7 @@ static void hid_joystick_release( IDirectInputDevice8W *iface ) if (!ref) { free( impl->usages_buf ); + free( impl->feature_report_buf ); free( impl->output_report_buf ); free( impl->input_report_buf ); HidD_FreePreparsedData( impl->preparsed ); @@ -1893,6 +1934,9 @@ HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID *guid, size = impl->caps.OutputReportByteLength; if (!(buffer = malloc( size ))) goto failed; impl->output_report_buf = buffer; + size = impl->caps.FeatureReportByteLength; + if (!(buffer = malloc( size ))) goto failed; + impl->feature_report_buf = buffer; impl->usages_count = HidP_MaxUsageListLength( HidP_Input, 0, impl->preparsed ); size = impl->usages_count * sizeof(USAGE_AND_PAGE); if (!(usages = malloc( size ))) goto failed; @@ -2703,7 +2747,7 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface ) hr = DIERR_NOTEXCLUSIVEACQUIRED; else if ((impl->flags & complete_mask) != complete_mask) hr = DIERR_INCOMPLETEEFFECT; - else if (!impl->index && SUCCEEDED(hr = find_next_effect_id( impl->joystick, &impl->index ))) + else if (!impl->index && SUCCEEDED(hr = find_next_effect_id( impl->joystick, &impl->index, impl->type ))) { if (!impl->type_specific_buf[0]) status = HIDP_STATUS_SUCCESS; else status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_EFFECT_BLOCK_INDEX, @@ -2857,7 +2901,11 @@ static HRESULT WINAPI hid_joystick_effect_Unload( IDirectInputEffect *iface ) { struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); struct hid_joystick *joystick = impl->joystick; + struct pid_device_pool *device_pool = &joystick->pid_device_pool; + struct pid_block_free *block_free = &joystick->pid_block_free; + ULONG report_len = joystick->caps.OutputReportByteLength; HRESULT hr = DI_OK; + NTSTATUS status;
TRACE( "iface %p\n", iface );
@@ -2866,7 +2914,22 @@ static HRESULT WINAPI hid_joystick_effect_Unload( IDirectInputEffect *iface ) hr = DI_NOEFFECT; else if (SUCCEEDED(hr = IDirectInputEffect_Stop( iface ))) { - impl->joystick->effect_inuse[impl->index - 1] = FALSE; + if (!device_pool->device_managed_caps) + joystick->effect_inuse[impl->index - 1] = FALSE; + else if (block_free->id) + { + status = HidP_InitializeReportForID( HidP_Output, block_free->id, joystick->preparsed, + joystick->output_report_buf, report_len ); + + if (status != HIDP_STATUS_SUCCESS) hr = status; + else status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_EFFECT_BLOCK_INDEX, + impl->index, joystick->preparsed, joystick->output_report_buf, report_len ); + + if (status != HIDP_STATUS_SUCCESS) hr = status; + else if (WriteFile( joystick->device, joystick->output_report_buf, report_len, NULL, NULL )) hr = DI_OK; + else hr = DIERR_INPUTLOST; + } + impl->index = 0; } LeaveCriticalSection( &joystick->base.crit ); diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 564ae7335e8..596d318acd9 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -8403,7 +8403,6 @@ static void test_device_managed_effect(void) .report_id = 9, .report_len = 2, .report_buf = {9,0x03}, - .todo = TRUE, }, /* block load */ { @@ -8411,7 +8410,6 @@ static void test_device_managed_effect(void) .report_id = 10, .report_len = 3, .report_buf = {10,0x01,0x01}, - .todo = TRUE, }, /* set condition */ { @@ -8450,7 +8448,6 @@ static void test_device_managed_effect(void) .report_id = 11, .report_len = 2, .report_buf = {11,0x01}, - .todo = TRUE, }, }; static const DWORD expect_axes[3] =