dinput: Implement DIPROP_AUTOCENTER.
Autocenter is a default effect playing on the device following power up or reset. It is disabled by stopping all effects. On at least some devices (all?) it is a spring effect playing in slot 1. Capturing Windows USB packets reveals it dinput acquire does (1) a reset (this enabled autocenter) and, if autocenter is disabled, (2) a stop all effects (this disabled autocenter). This logic works regardless of whether autocenter is a spring effect playing in slot 1 or not. It does mean autocenter can only be set when the device is not acquired. Testing on Windows reveals setting autocenter properties while acquired returns DIERR_ACQUIRED even if the device is exclusively acquired, so this is consistent.
This commit is contained in:
parent
63562c05f6
commit
9dc1ddf801
5 changed files with 32 additions and 5 deletions
|
@ -899,7 +899,7 @@ static HRESULT check_property( struct dinput_device *impl, const GUID *guid, con
|
|||
switch (LOWORD( guid ))
|
||||
{
|
||||
case (DWORD_PTR)DIPROP_AUTOCENTER:
|
||||
if (impl->status == STATUS_ACQUIRED && !is_exclusively_acquired( impl )) return DIERR_ACQUIRED;
|
||||
if (impl->status == STATUS_ACQUIRED) return DIERR_ACQUIRED;
|
||||
break;
|
||||
case (DWORD_PTR)DIPROP_AXISMODE:
|
||||
case (DWORD_PTR)DIPROP_BUFFERSIZE:
|
||||
|
@ -1290,8 +1290,6 @@ static HRESULT dinput_device_set_property( IDirectInputDevice8W *iface, const GU
|
|||
{
|
||||
const DIPROPDWORD *value = (const DIPROPDWORD *)header;
|
||||
if (!(impl->caps.dwFlags & DIDC_FORCEFEEDBACK)) return DIERR_UNSUPPORTED;
|
||||
|
||||
FIXME( "DIPROP_AUTOCENTER stub!\n" );
|
||||
impl->autocenter = value->dwData;
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -2131,6 +2129,7 @@ void dinput_device_init( struct dinput_device *device, const struct dinput_devic
|
|||
device->caps.dwSize = sizeof(DIDEVCAPS);
|
||||
device->caps.dwFlags = DIDC_ATTACHED | DIDC_EMULATED;
|
||||
device->device_gain = 10000;
|
||||
device->autocenter = DIPROPAUTOCENTER_ON;
|
||||
device->force_feedback_state = DIGFFS_STOPPED | DIGFFS_EMPTY;
|
||||
InitializeCriticalSection( &device->crit );
|
||||
dinput_internal_addref( (device->dinput = dinput) );
|
||||
|
|
|
@ -1072,7 +1072,12 @@ static HRESULT hid_joystick_send_force_feedback_command( IDirectInputDevice8W *i
|
|||
if (status != HIDP_STATUS_SUCCESS) return status;
|
||||
|
||||
if (!WriteFile( impl->device, report_buf, report_len, NULL, NULL )) return DIERR_INPUTLOST;
|
||||
if (!unacquire && command == DISFFC_RESET) hid_joystick_send_device_gain( iface, impl->base.device_gain );
|
||||
if (!unacquire && command == DISFFC_RESET)
|
||||
{
|
||||
if (impl->base.autocenter == DIPROPAUTOCENTER_OFF)
|
||||
hid_joystick_send_force_feedback_command( iface, DISFFC_STOPALL, FALSE );
|
||||
hid_joystick_send_device_gain( iface, impl->base.device_gain );
|
||||
}
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
|
|
@ -2222,7 +2222,6 @@ static BOOL test_force_feedback_joystick( DWORD version )
|
|||
.report_len = 2,
|
||||
.report_buf = {1, 0x02},
|
||||
.broken_id = 8, /* Win8 sends them in the reverse order */
|
||||
.todo = TRUE,
|
||||
},
|
||||
{
|
||||
.code = IOCTL_HID_WRITE_REPORT,
|
||||
|
|
|
@ -105,6 +105,7 @@ MAKE_FUNCPTR(SDL_HapticRumbleStop);
|
|||
MAKE_FUNCPTR(SDL_HapticRumbleSupported);
|
||||
MAKE_FUNCPTR(SDL_HapticRunEffect);
|
||||
MAKE_FUNCPTR(SDL_HapticSetGain);
|
||||
MAKE_FUNCPTR(SDL_HapticSetAutocenter);
|
||||
MAKE_FUNCPTR(SDL_HapticStopAll);
|
||||
MAKE_FUNCPTR(SDL_HapticStopEffect);
|
||||
MAKE_FUNCPTR(SDL_HapticUnpause);
|
||||
|
@ -550,6 +551,7 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US
|
|||
return STATUS_SUCCESS;
|
||||
case PID_USAGE_DC_STOP_ALL_EFFECTS:
|
||||
pSDL_HapticStopAll(impl->sdl_haptic);
|
||||
pSDL_HapticSetAutocenter(impl->sdl_haptic, 0);
|
||||
return STATUS_SUCCESS;
|
||||
case PID_USAGE_DC_DEVICE_RESET:
|
||||
pSDL_HapticStopAll(impl->sdl_haptic);
|
||||
|
@ -559,6 +561,7 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US
|
|||
pSDL_HapticDestroyEffect(impl->sdl_haptic, impl->effect_ids[i]);
|
||||
impl->effect_ids[i] = -1;
|
||||
}
|
||||
pSDL_HapticSetAutocenter(impl->sdl_haptic, 100);
|
||||
return STATUS_SUCCESS;
|
||||
case PID_USAGE_DC_DEVICE_PAUSE:
|
||||
pSDL_HapticPause(impl->sdl_haptic);
|
||||
|
@ -1121,6 +1124,7 @@ NTSTATUS sdl_bus_init(void *args)
|
|||
LOAD_FUNCPTR(SDL_HapticRumbleSupported);
|
||||
LOAD_FUNCPTR(SDL_HapticRunEffect);
|
||||
LOAD_FUNCPTR(SDL_HapticSetGain);
|
||||
LOAD_FUNCPTR(SDL_HapticSetAutocenter);
|
||||
LOAD_FUNCPTR(SDL_HapticStopAll);
|
||||
LOAD_FUNCPTR(SDL_HapticStopEffect);
|
||||
LOAD_FUNCPTR(SDL_HapticUnpause);
|
||||
|
|
|
@ -929,6 +929,24 @@ static NTSTATUS lnxev_device_physical_effect_run(struct lnxev_device *impl, BYTE
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS lnxev_device_physical_device_set_autocenter(struct unix_device *iface, BYTE percent)
|
||||
{
|
||||
struct lnxev_device *impl = lnxev_impl_from_unix_device(iface);
|
||||
struct input_event ie =
|
||||
{
|
||||
.type = EV_FF,
|
||||
.code = FF_AUTOCENTER,
|
||||
.value = 0xffff * percent / 100,
|
||||
};
|
||||
|
||||
TRACE("iface %p, percent %#x.\n", iface, percent);
|
||||
|
||||
if (write(impl->base.device_fd, &ie, sizeof(ie)) == -1)
|
||||
WARN("write failed %d %s\n", errno, strerror(errno));
|
||||
|
||||
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);
|
||||
|
@ -972,6 +990,7 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface,
|
|||
if (impl->effect_ids[i] < 0) continue;
|
||||
lnxev_device_physical_effect_run(impl, i, 0);
|
||||
}
|
||||
lnxev_device_physical_device_set_autocenter(iface, 0);
|
||||
return STATUS_SUCCESS;
|
||||
case PID_USAGE_DC_DEVICE_RESET:
|
||||
for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i)
|
||||
|
@ -981,6 +1000,7 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface,
|
|||
WARN("couldn't free effect, EVIOCRMFF ioctl failed: %d %s\n", errno, strerror(errno));
|
||||
impl->effect_ids[i] = -1;
|
||||
}
|
||||
lnxev_device_physical_device_set_autocenter(iface, 100);
|
||||
return STATUS_SUCCESS;
|
||||
case PID_USAGE_DC_DEVICE_PAUSE:
|
||||
WARN("device pause not supported\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue