Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 6bf887e4c7a..cc2f3268e6f 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3422,6 +3422,32 @@ static BOOL CALLBACK check_effect_count( const DIEFFECTINFOW *effect, void *args return DIENUM_CONTINUE; }
+static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect, void *context ) +{ + ok( 0, "unexpected effect %p\n", effect ); + return DIENUM_CONTINUE; +} + +struct check_created_effect_params +{ + IDirectInputEffect *expect_effect; + DWORD count; +}; + +static BOOL CALLBACK check_created_effect_objects( IDirectInputEffect *effect, void *context ) +{ + struct check_created_effect_params *params = context; + ULONG ref; + + ok( effect == params->expect_effect, "got effect %p, expected %p\n", effect, params->expect_effect ); + params->count++; + + IDirectInputEffect_AddRef( effect ); + ref = IDirectInputEffect_Release( effect ); + ok( ref == 1, "got ref %u, expected 1\n", ref ); + return DIENUM_CONTINUE; +} + static void test_simple_joystick(void) { #include "psh_hid_macros.h" @@ -4721,6 +4747,15 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL ); ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_CreateEffect returned %#x\n", hr );
+ hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, NULL, effect, 0 ); + ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); + hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef ); + todo_wine + ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); + hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, (void *)0xdeadbeef, 0 ); + todo_wine + ok( hr == DI_OK, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); + hr = IDirectInputDevice8_Escape( device, NULL ); todo_wine ok( hr == E_POINTER, "IDirectInputDevice8_Escape returned: %#x\n", hr ); @@ -5098,6 +5133,7 @@ static BOOL test_device_types(void)
static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) { + struct check_created_effect_params check_params = {0}; IDirectInputEffect *effect; HRESULT hr; ULONG ref; @@ -5117,6 +5153,16 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) ok( hr == DI_OK, "IDirectInputDevice8_CreateEffect returned %#x\n", hr ); if (hr != DI_OK) return;
+ hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef ); + todo_wine + ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); + check_params.expect_effect = effect; + hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_created_effect_objects, &check_params, 0 ); + todo_wine + ok( hr == DI_OK, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); + todo_wine + ok( check_params.count == 1, "got count %u, expected 1\n", check_params.count ); + ref = IDirectInputEffect_Release( effect ); ok( ref == 0, "IDirectInputDeviceW_Release returned %d\n", ref ); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 47 +++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 8f5dbee9dc3..b71f9f5f56b 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -90,6 +90,7 @@ struct pid_control_report struct hid_joystick { IDirectInputDeviceImpl base; + LONG ref;
HANDLE device; OVERLAPPED read_ovl; @@ -124,6 +125,8 @@ struct hid_joystick_effect { IDirectInputEffect IDirectInputEffect_iface; LONG ref; + + struct hid_joystick *joystick; };
static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface ) @@ -372,13 +375,17 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, return DIENUM_CONTINUE; }
-static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface ) +static ULONG hid_joystick_private_incref( struct hid_joystick *impl ) +{ + return IDirectInputDevice2WImpl_AddRef( &impl->base.IDirectInputDevice8W_iface ); +} + +static ULONG hid_joystick_private_decref( struct hid_joystick *impl ) { - struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); struct hid_joystick tmp = *impl; ULONG ref;
- if (!(ref = IDirectInputDevice2WImpl_Release( iface ))) + if (!(ref = IDirectInputDevice2WImpl_Release( &impl->base.IDirectInputDevice8W_iface ))) { HeapFree( GetProcessHeap(), 0, tmp.usages_buf ); HeapFree( GetProcessHeap(), 0, tmp.output_report_buf ); @@ -393,6 +400,23 @@ static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface ) return ref; }
+static ULONG WINAPI hid_joystick_AddRef( IDirectInputDevice8W *iface ) +{ + struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %u.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface ) +{ + struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %u.\n", iface, ref ); + if (!ref) hid_joystick_private_decref( impl ); + return ref; +} + static HRESULT WINAPI hid_joystick_GetCapabilities( IDirectInputDevice8W *iface, DIDEVCAPS *caps ) { struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); @@ -814,7 +838,7 @@ static HRESULT WINAPI hid_joystick_GetDeviceInfo( IDirectInputDevice8W *iface, D return S_OK; }
-static HRESULT hid_joystick_effect_create( IDirectInputEffect **out ); +static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirectInputEffect **out );
static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, const GUID *guid, const DIEFFECT *params, IDirectInputEffect **out, @@ -831,7 +855,7 @@ static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, co *out = NULL;
if (!(impl->dev_caps.dwFlags & DIDC_FORCEFEEDBACK)) return DIERR_UNSUPPORTED; - if (FAILED(hr = hid_joystick_effect_create( out ))) return hr; + if (FAILED(hr = hid_joystick_effect_create( impl, out ))) return hr;
hr = IDirectInputEffect_Initialize( *out, DINPUT_instance, impl->base.dinput->dwVersion, guid ); if (FAILED(hr)) goto failed; @@ -1035,7 +1059,7 @@ static const IDirectInputDevice8WVtbl hid_joystick_vtbl = { /*** IUnknown methods ***/ IDirectInputDevice2WImpl_QueryInterface, - IDirectInputDevice2WImpl_AddRef, + hid_joystick_AddRef, hid_joystick_Release, /*** IDirectInputDevice methods ***/ hid_joystick_GetCapabilities, @@ -1677,6 +1701,7 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID &attrs, &impl->caps, dinput->dwVersion ); if (hr != DI_OK) goto failed;
+ impl->ref = 1; impl->instance = instance; impl->attrs = attrs; impl->dev_caps.dwSize = sizeof(impl->dev_caps); @@ -1786,7 +1811,11 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface ) struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface ); ULONG ref = InterlockedDecrement( &impl->ref ); TRACE( "iface %p, ref %u.\n", iface, ref ); - if (!ref) HeapFree( GetProcessHeap(), 0, impl ); + if (!ref) + { + hid_joystick_private_decref( impl->joystick ); + HeapFree( GetProcessHeap(), 0, impl ); + } return ref; }
@@ -1874,7 +1903,7 @@ static IDirectInputEffectVtbl hid_joystick_effect_vtbl = hid_joystick_effect_Escape, };
-static HRESULT hid_joystick_effect_create( IDirectInputEffect **out ) +static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirectInputEffect **out ) { struct hid_joystick_effect *impl;
@@ -1882,6 +1911,8 @@ static HRESULT hid_joystick_effect_create( IDirectInputEffect **out ) return DIERR_OUTOFMEMORY; impl->IDirectInputEffect_iface.lpVtbl = &hid_joystick_effect_vtbl; impl->ref = 1; + impl->joystick = joystick; + hid_joystick_private_incref( joystick );
*out = &impl->IDirectInputEffect_iface; return DI_OK;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 19 ++++++++++++++++++- dlls/dinput8/tests/hid.c | 5 ----- 2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index b71f9f5f56b..a4f16168dfb 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -112,6 +112,7 @@ struct hid_joystick BYTE device_state_report_id; BYTE device_state[DEVICE_STATE_MAX_SIZE];
+ struct list effect_list; struct pid_control_report pid_device_control; };
@@ -126,6 +127,7 @@ struct hid_joystick_effect IDirectInputEffect IDirectInputEffect_iface; LONG ref;
+ struct list entry; struct hid_joystick *joystick; };
@@ -1014,11 +1016,18 @@ static HRESULT WINAPI hid_joystick_EnumCreatedEffectObjects( IDirectInputDevice8 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK callback, void *context, DWORD flags ) { + struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); + struct hid_joystick_effect *effect, *next; + FIXME( "iface %p, callback %p, context %p, flags %#x stub!\n", iface, callback, context, flags );
if (!callback) return DIERR_INVALIDPARAM; + if (flags) return DIERR_INVALIDPARAM;
- return DIERR_UNSUPPORTED; + LIST_FOR_EACH_ENTRY_SAFE(effect, next, &impl->effect_list, struct hid_joystick_effect, entry) + if (callback( &effect->IDirectInputEffect_iface, context ) != DIENUM_CONTINUE) break; + + return DI_OK; }
static HRESULT WINAPI hid_joystick_Poll( IDirectInputDevice8W *iface ) @@ -1707,6 +1716,7 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID impl->dev_caps.dwSize = sizeof(impl->dev_caps); impl->dev_caps.dwFlags = DIDC_ATTACHED | DIDC_EMULATED; impl->dev_caps.dwDevType = instance.dwDevType; + list_init( &impl->effect_list );
preparsed = (struct hid_preparsed_data *)impl->preparsed;
@@ -1813,6 +1823,9 @@ static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface ) TRACE( "iface %p, ref %u.\n", iface, ref ); if (!ref) { + EnterCriticalSection( &impl->joystick->base.crit ); + list_remove( &impl->entry ); + LeaveCriticalSection( &impl->joystick->base.crit ); hid_joystick_private_decref( impl->joystick ); HeapFree( GetProcessHeap(), 0, impl ); } @@ -1914,6 +1927,10 @@ static HRESULT hid_joystick_effect_create( struct hid_joystick *joystick, IDirec impl->joystick = joystick; hid_joystick_private_incref( joystick );
+ EnterCriticalSection( &joystick->base.crit ); + list_add_tail( &joystick->effect_list, &impl->entry ); + LeaveCriticalSection( &joystick->base.crit ); + *out = &impl->IDirectInputEffect_iface; return DI_OK; } diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index cc2f3268e6f..90e30cf0534 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -4750,10 +4750,8 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, NULL, effect, 0 ); ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, (void *)0xdeadbeef, 0 ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr );
hr = IDirectInputDevice8_Escape( device, NULL ); @@ -5154,13 +5152,10 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file ) if (hr != DI_OK) return;
hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); check_params.expect_effect = effect; hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_created_effect_objects, &check_params, 0 ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_EnumCreatedEffectObjects returned %#x\n", hr ); - todo_wine ok( check_params.count == 1, "got count %u, expected 1\n", check_params.count );
ref = IDirectInputEffect_Release( effect );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 9 ++++ dlls/winebus.sys/bus_udev.c | 9 ++++ dlls/winebus.sys/hid.c | 77 +++++++++++++++++++++++++++++++++ dlls/winebus.sys/unix_private.h | 2 + dlls/winebus.sys/unixlib.c | 14 ++++++ 5 files changed, 111 insertions(+)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 772ee092c83..bcdfd7a9c15 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -444,6 +444,14 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US return STATUS_NOT_SUPPORTED; }
+static NTSTATUS sdl_device_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + FIXME("iface %p, index %u, control %04x, iterations %u stub!\n", iface, index, control, iterations); + + return STATUS_NOT_IMPLEMENTED; +} + static const struct hid_device_vtbl sdl_device_vtbl = { sdl_device_destroy, @@ -451,6 +459,7 @@ static const struct hid_device_vtbl sdl_device_vtbl = sdl_device_stop, sdl_device_haptics_start, sdl_device_physical_device_control, + sdl_device_physical_effect_control, };
static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *event) diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 07aeec6e8ae..e0debd21f2d 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -868,6 +868,14 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, return STATUS_NOT_SUPPORTED; }
+static NTSTATUS lnxev_device_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + FIXME("iface %p, index %u, control %04x, iterations %u stub!\n", iface, index, control, iterations); + + return STATUS_NOT_IMPLEMENTED; +} + static const struct hid_device_vtbl lnxev_device_vtbl = { lnxev_device_destroy, @@ -875,6 +883,7 @@ static const struct hid_device_vtbl lnxev_device_vtbl = lnxev_device_stop, lnxev_device_haptics_start, lnxev_device_physical_device_control, + lnxev_device_physical_effect_control, }; #endif /* HAS_PROPER_INPUT_HEADER */
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 12db1706ede..4ddee27cff9 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -411,6 +411,21 @@ static const USAGE pid_device_control_usages[] = PID_USAGE_DC_DEVICE_PAUSE, PID_USAGE_DC_DEVICE_CONTINUE, }; + +struct pid_effect_control +{ + BYTE index; + BYTE control_index; + BYTE iterations; +}; + +static const USAGE pid_effect_control_usages[] = +{ + 0, /* HID nary collection indexes start at 1 */ + PID_USAGE_OP_EFFECT_START, + PID_USAGE_OP_EFFECT_START_SOLO, + PID_USAGE_OP_EFFECT_STOP, +}; #include "poppack.h"
BOOL hid_device_add_physical(struct unix_device *iface) @@ -437,6 +452,42 @@ BOOL hid_device_add_physical(struct unix_device *iface) END_COLLECTION, END_COLLECTION, }; + + const BYTE effect_control_report = ++desc->next_report_id[HidP_Output]; + const BYTE effect_control_header[] = + { + /* Control effect state */ + USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT), + COLLECTION(1, Logical), + REPORT_ID(1, effect_control_report), + + USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MAXIMUM(1, 0x7f), + LOGICAL_MINIMUM(1, 0x00), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + + USAGE(1, PID_USAGE_EFFECT_OPERATION), + COLLECTION(1, Logical), + }; + const BYTE effect_control_footer[] = + { + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 3), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Ary|Abs), + END_COLLECTION, + + USAGE(1, PID_USAGE_LOOP_COUNT), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(2, 0x00ff), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + END_COLLECTION, + }; ULONG i;
if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header))) @@ -449,7 +500,18 @@ BOOL hid_device_add_physical(struct unix_device *iface) if (!hid_report_descriptor_append(desc, device_control_footer, sizeof(device_control_footer))) return FALSE;
+ if (!hid_report_descriptor_append(desc, effect_control_header, sizeof(effect_control_header))) + return FALSE; + for (i = 1; i < ARRAY_SIZE(pid_effect_control_usages); ++i) + { + if (!hid_report_descriptor_append_usage(desc, pid_effect_control_usages[i])) + return FALSE; + } + if (!hid_report_descriptor_append(desc, effect_control_footer, sizeof(effect_control_footer))) + return FALSE; + iface->hid_physical.device_control_report = device_control_report; + iface->hid_physical.effect_control_report = effect_control_report; return TRUE; }
@@ -525,6 +587,21 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC else io->Status = iface->hid_vtbl->physical_device_control(iface, control); } + else if (packet->reportId == physical->effect_control_report) + { + struct pid_effect_control *report = (struct pid_effect_control *)(packet->reportBuffer + 1); + USAGE control; + + io->Information = sizeof(*report) + 1; + if (packet->reportBufferLen < io->Information) + io->Status = STATUS_BUFFER_TOO_SMALL; + else if (report->control_index >= ARRAY_SIZE(pid_effect_control_usages)) + io->Status = STATUS_INVALID_PARAMETER; + else if (!(control = pid_effect_control_usages[report->control_index])) + io->Status = STATUS_INVALID_PARAMETER; + else + io->Status = iface->hid_vtbl->physical_effect_control(iface, report->index, control, report->iterations); + } else { io->Information = 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index c62e4c9d0ab..2446b8de4a7 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -48,6 +48,7 @@ struct hid_device_vtbl NTSTATUS (*haptics_start)(struct unix_device *iface, DWORD duration_ms, USHORT rumble_intensity, USHORT buzz_intensity); NTSTATUS (*physical_device_control)(struct unix_device *iface, USAGE control); + NTSTATUS (*physical_effect_control)(struct unix_device *iface, BYTE index, USAGE control, BYTE iterations); };
struct hid_report_descriptor @@ -91,6 +92,7 @@ struct hid_haptics struct hid_physical { BYTE device_control_report; + BYTE effect_control_report; };
struct hid_device_state diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 28e4027d2a4..f69b447c852 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -97,6 +97,12 @@ static NTSTATUS mouse_physical_device_control(struct unix_device *iface, USAGE c return STATUS_NOT_SUPPORTED; }
+static NTSTATUS mouse_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + return STATUS_NOT_SUPPORTED; +} + static const struct hid_device_vtbl mouse_vtbl = { mouse_destroy, @@ -104,6 +110,7 @@ static const struct hid_device_vtbl mouse_vtbl = mouse_stop, mouse_haptics_start, mouse_physical_device_control, + mouse_physical_effect_control, };
static const struct device_desc mouse_device_desc = @@ -160,6 +167,12 @@ static NTSTATUS keyboard_physical_device_control(struct unix_device *iface, USAG return STATUS_NOT_SUPPORTED; }
+static NTSTATUS keyboard_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + return STATUS_NOT_SUPPORTED; +} + static const struct hid_device_vtbl keyboard_vtbl = { keyboard_destroy, @@ -167,6 +180,7 @@ static const struct hid_device_vtbl keyboard_vtbl = keyboard_stop, keyboard_haptics_start, keyboard_physical_device_control, + keyboard_physical_effect_control, };
static const struct device_desc keyboard_device_desc =
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index a4f16168dfb..95ee04d9e82 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -114,6 +114,7 @@ struct hid_joystick
struct list effect_list; struct pid_control_report pid_device_control; + struct pid_control_report pid_effect_control; };
static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface ) @@ -1587,6 +1588,7 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * DIDEVICEOBJECTINSTANCEW *instance, void *data ) { struct pid_control_report *device_control = &impl->pid_device_control; + struct pid_control_report *effect_control = &impl->pid_effect_control;
#define SET_COLLECTION( rep ) \ do \ @@ -1610,7 +1612,10 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * switch (instance->wUsage) { case PID_USAGE_DEVICE_CONTROL_REPORT: SET_COLLECTION( device_control ); break; + case PID_USAGE_EFFECT_OPERATION_REPORT: SET_COLLECTION( effect_control ); break; + case PID_USAGE_DEVICE_CONTROL: SET_SUB_COLLECTION( device_control, control_coll ); break; + case PID_USAGE_EFFECT_OPERATION: SET_SUB_COLLECTION( effect_control, control_coll ); break; } }
@@ -1624,6 +1629,7 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap DIDEVICEOBJECTINSTANCEW *instance, void *data ) { struct pid_control_report *device_control = &impl->pid_device_control; + struct pid_control_report *effect_control = &impl->pid_effect_control;
if (!(instance->dwType & DIDFT_OUTPUT)) return DIENUM_CONTINUE;
@@ -1638,6 +1644,8 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap
if (instance->wCollectionNumber == device_control->control_coll) SET_REPORT_ID( device_control ); + if (instance->wCollectionNumber == effect_control->control_coll) + SET_REPORT_ID( effect_control );
#undef SET_REPORT_ID
@@ -1741,6 +1749,7 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
TRACE( "device control id %u, coll %u, control coll %u\n", impl->pid_device_control.id, impl->pid_device_control.collection, impl->pid_device_control.control_coll ); + TRACE( "effect control id %u, coll %u\n", impl->pid_effect_control.id, impl->pid_effect_control.collection );
if (impl->pid_device_control.id) {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index bcdfd7a9c15..33386a80a34 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -104,6 +104,7 @@ MAKE_FUNCPTR(SDL_HapticRumbleSupported); MAKE_FUNCPTR(SDL_HapticRunEffect); MAKE_FUNCPTR(SDL_HapticSetGain); MAKE_FUNCPTR(SDL_HapticStopAll); +MAKE_FUNCPTR(SDL_HapticStopEffect); MAKE_FUNCPTR(SDL_HapticUnpause); MAKE_FUNCPTR(SDL_JoystickIsHaptic); MAKE_FUNCPTR(SDL_GameControllerAddMapping); @@ -447,9 +448,27 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US static NTSTATUS sdl_device_physical_effect_control(struct unix_device *iface, BYTE index, USAGE control, BYTE iterations) { - FIXME("iface %p, index %u, control %04x, iterations %u stub!\n", iface, index, control, iterations); + struct sdl_device *impl = impl_from_unix_device(iface); + int id = impl->effect_ids[index];
- return STATUS_NOT_IMPLEMENTED; + TRACE("iface %p, index %u, control %04x, iterations %u.\n", iface, index, control, iterations); + + if (impl->effect_ids[index] < 0) return STATUS_UNSUCCESSFUL; + + switch (control) + { + case PID_USAGE_OP_EFFECT_START_SOLO: + pSDL_HapticStopAll(impl->sdl_haptic); + /* fallthrough */ + case PID_USAGE_OP_EFFECT_START: + pSDL_HapticRunEffect(impl->sdl_haptic, id, iterations); + break; + case PID_USAGE_OP_EFFECT_STOP: + pSDL_HapticStopEffect(impl->sdl_haptic, id); + break; + } + + return STATUS_SUCCESS; }
static const struct hid_device_vtbl sdl_device_vtbl = @@ -721,6 +740,7 @@ NTSTATUS sdl_bus_init(void *args) LOAD_FUNCPTR(SDL_HapticRunEffect); LOAD_FUNCPTR(SDL_HapticSetGain); LOAD_FUNCPTR(SDL_HapticStopAll); + LOAD_FUNCPTR(SDL_HapticStopEffect); LOAD_FUNCPTR(SDL_HapticUnpause); LOAD_FUNCPTR(SDL_JoystickIsHaptic); LOAD_FUNCPTR(SDL_GameControllerAddMapping);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 48 +++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index e0debd21f2d..aad2d41760b 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -812,6 +812,27 @@ static NTSTATUS lnxev_device_haptics_start(struct unix_device *iface, DWORD dura return STATUS_SUCCESS; }
+static NTSTATUS lnxev_device_physical_effect_run(struct lnxev_device *impl, BYTE index, + int iterations) +{ + struct input_event ie = + { + .type = EV_FF, + .value = iterations, + }; + + if (impl->effect_ids[index] < 0) return STATUS_UNSUCCESSFUL; + ie.code = impl->effect_ids[index]; + + if (write(impl->base.device_fd, &ie, sizeof(ie)) == -1) + { + WARN("couldn't stop effect, write failed %d %s\n", errno, strerror(errno)); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} + static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, USAGE control) { struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); @@ -846,8 +867,12 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, return STATUS_SUCCESS; } case PID_USAGE_DC_STOP_ALL_EFFECTS: - FIXME("stop all not implemented!\n"); - return STATUS_NOT_IMPLEMENTED; + for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i) + { + if (impl->effect_ids[i] < 0) continue; + lnxev_device_physical_effect_run(impl, i, 0); + } + return STATUS_SUCCESS; case PID_USAGE_DC_DEVICE_RESET: for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i) { @@ -871,9 +896,24 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, static NTSTATUS lnxev_device_physical_effect_control(struct unix_device *iface, BYTE index, USAGE control, BYTE iterations) { - FIXME("iface %p, index %u, control %04x, iterations %u stub!\n", iface, index, control, iterations); + struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); + NTSTATUS status;
- return STATUS_NOT_IMPLEMENTED; + TRACE("iface %p, index %u, control %04x, iterations %u.\n", iface, index, control, iterations); + + switch (control) + { + case PID_USAGE_OP_EFFECT_START_SOLO: + if ((status = lnxev_device_physical_device_control(iface, PID_USAGE_DC_STOP_ALL_EFFECTS))) + return status; + /* fallthrough */ + case PID_USAGE_OP_EFFECT_START: + return lnxev_device_physical_effect_run(impl, index, iterations); + case PID_USAGE_OP_EFFECT_STOP: + return lnxev_device_physical_effect_run(impl, index, 0); + } + + return STATUS_SUCCESS; }
static const struct hid_device_vtbl lnxev_device_vtbl =