From: Aric Stewart Subject: [2/2]dinput: Add force feedback interfaces for the Graphic Driver joystick Message-Id: <5527E442.1070304@codeweavers.com> Date: Fri, 10 Apr 2015 09:54:58 -0500 --- dlls/dinput/joystick_driver.c | 537 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 514 insertions(+), 23 deletions(-) diff --git a/dlls/dinput/joystick_driver.c b/dlls/dinput/joystick_driver.c index 1bd5621..6c5319e 100644 --- a/dlls/dinput/joystick_driver.c +++ b/dlls/dinput/joystick_driver.c @@ -46,6 +46,20 @@ enum { DRIVER_AXIS_X = 0, DRIVER_AXIS_RZ, DRIVER_AXIS_OTHER}; +enum { + DRIVER_CONSTANTFORCE = 0x00000001, + DRIVER_RAMPFORCE = 0x00000002, + DRIVER_SQUARE = 0x00000004, + DRIVER_SINE = 0x00000008, + DRIVER_TRIANGLE = 0x00000010, + DRIVER_SAWTOOTHUP = 0x00000020, + DRIVER_SAWTOOTHDOWN = 0x00000040, + DRIVER_SPRING = 0x00000080, + DRIVER_DAMPER = 0x00000100, + DRIVER_INERTIA = 0x00000200, + DRIVER_FRICTION = 0x00000400, +}; + typedef struct tagGAMEPAD_DRIVER { INT (CDECL *pGamePadCount)(void); VOID (CDECL *pGamePadName)(int id, char *name, int length); @@ -56,6 +70,18 @@ typedef struct tagGAMEPAD_DRIVER { /* Aid in driver management */ BOOL (CDECL *pGamePadAlloc)(int id); VOID (CDECL *pGamePadDealloc)(int id); + + /* Force feedback interfaces */ + BOOL (CDECL *pGamePadHasForceFeedback)(int id, DWORD *effects); + BOOL (CDECL *pGamePadElementHasForceFeedback)(int id, int element); + VOID (CDECL *pGamePadGetForceFeedbackState)(int id, DWORD *state); + HRESULT (CDECL *pGamePadSetAutocenter)(int id, DWORD data); + HRESULT (CDECL *pGamePadGetAutocenter)(int id, DWORD *data); + HRESULT (CDECL *pGamePadSetFFGain)(int id, DWORD data); + HRESULT (CDECL *pGamePadGetFFGain)(int id, DWORD *data); + HRESULT (CDECL *pGamePadSendForceFeedbackCommand)(int id, DWORD flags); + DWORD (CDECL *pGamePadCreateDinputEffect)(int id, const GUID *type, const DIEFFECT *params, IDirectInputEffect **out, IUnknown *outer); + VOID (CDECL *pGamePadStopAllForceFeedbackEffects) (int id, int release); } GAMEPAD_DRIVER; static GAMEPAD_DRIVER null_driver, lazy_load_driver; @@ -116,8 +142,8 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { if (dwFlags & DIEDFL_FORCEFEEDBACK) { - /* No FF in Yet */ - return S_FALSE; + if (!GAMEPAD_Driver->pGamePadHasForceFeedback(id, NULL)) + return S_FALSE; } /* Return joystick */ lpddi->guidInstance = DInput_Wine_driver_Joystick_GUID; @@ -148,13 +174,13 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id); if (id >= find_joystick_devices()) return E_FAIL; - if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) || - (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { + (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) + { if (dwFlags & DIEDFL_FORCEFEEDBACK) { - /* No FF in Yet */ - return S_FALSE; + if (!GAMEPAD_Driver->pGamePadHasForceFeedback(id, NULL)) + return S_FALSE; } /* Return joystick */ lpddi->guidInstance = DInput_Wine_driver_Joystick_GUID; @@ -225,6 +251,9 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput, &newDevice->generic.devcaps.dwButtons, &newDevice->generic.devcaps.dwPOVs, newDevice->axis_map); + if (GAMEPAD_Driver->pGamePadHasForceFeedback(index, NULL)) + newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK; + TRACE("%i axes %i buttons %i povs\n",newDevice->generic.devcaps.dwAxes,newDevice->generic.devcaps.dwButtons,newDevice->generic.devcaps.dwPOVs); if (newDevice->generic.devcaps.dwButtons > 128) @@ -253,7 +282,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput, for (i = 0; i < newDevice->generic.devcaps.dwAxes; i++) { int wine_obj = newDevice->axis_map[i]; - BOOL has_ff = FALSE; if (wine_obj == DRIVER_AXIS_OTHER) { wine_obj = DRIVER_AXIS_OTHER + slider_count; @@ -263,7 +291,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput, memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize); df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS; - if(has_ff) + if (GAMEPAD_Driver->pGamePadElementHasForceFeedback(index, idx)) df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR; ++idx; } @@ -452,6 +480,20 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF break; } + case (DWORD_PTR)DIPROP_AUTOCENTER: + { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + hr = GAMEPAD_Driver->pGamePadGetAutocenter(This->id, &pd->dwData); + break; + } + + case (DWORD_PTR)DIPROP_FFGAIN: + { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + hr = GAMEPAD_Driver->pGamePadGetFFGain(This->id, &pd->dwData); + break; + } + default: return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); } @@ -465,6 +507,15 @@ static HRESULT WINAPI JoystickWImpl_SetProperty(IDirectInputDevice8W *iface, JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); TRACE("%p %s %p\n", This, debugstr_guid(prop), header); + switch(LOWORD(prop)) + { + case (DWORD_PTR)DIPROP_AUTOCENTER: + return GAMEPAD_Driver->pGamePadSetAutocenter(This->id, + ((const DIPROPDWORD *)header)->dwData); + case (DWORD_PTR)DIPROP_FFGAIN: + return GAMEPAD_Driver->pGamePadSetFFGain(This->id, + ((const DIPROPDWORD *)header)->dwData); + } return JoystickWGenericImpl_SetProperty(iface, prop, header); } @@ -483,19 +534,51 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(IDirectInputDevice8A *iface, TRACE("%p %s %p\n", This, debugstr_guid(prop), header); + switch(LOWORD(prop)) + { + case (DWORD_PTR)DIPROP_AUTOCENTER: + return GAMEPAD_Driver->pGamePadSetAutocenter(This->id, + ((const DIPROPDWORD *)header)->dwData); + case (DWORD_PTR)DIPROP_FFGAIN: + return GAMEPAD_Driver->pGamePadSetFFGain(This->id, + ((const DIPROPDWORD *)header)->dwData); + } + return JoystickAGenericImpl_SetProperty(iface, prop, header); } +static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); + HRESULT res; + + TRACE("(this=%p)\n",This); + res = IDirectInputDevice2WImpl_Unacquire(iface); + if (res==DI_OK) { + GAMEPAD_Driver->pGamePadStopAllForceFeedbackEffects(This->id, FALSE); + /* Enable autocenter. */ + GAMEPAD_Driver->pGamePadSetAutocenter(This->id, DIPROPAUTOCENTER_ON); + } + return res; +} + +static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8A(iface); + return JoystickWImpl_Unacquire(&This->generic.base.IDirectInputDevice8W_iface); +} + + static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface, const GUID *type, const DIEFFECT *params, IDirectInputEffect **out, IUnknown *outer) { + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer); dump_DIEFFECT(params, type, 0); - TRACE("No force feedback support\n"); - *out = NULL; - return S_OK; + return GAMEPAD_Driver->pGamePadCreateDinputEffect(This->id, type, params, + out, outer); } static HRESULT WINAPI JoystickAImpl_CreateEffect(IDirectInputDevice8A *iface, @@ -516,8 +599,7 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8 JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); TRACE("%p 0x%x\n", This, flags); - - return DI_NOEFFECT; + return GAMEPAD_Driver->pGamePadSendForceFeedbackCommand(This->id, flags); } static HRESULT WINAPI JoystickAImpl_SendForceFeedbackCommand(IDirectInputDevice8A *iface, @@ -530,6 +612,284 @@ static HRESULT WINAPI JoystickAImpl_SendForceFeedbackCommand(IDirectInputDevice8 return JoystickWImpl_SendForceFeedbackCommand(&This->generic.base.IDirectInputDevice8W_iface, flags); } +static HRESULT WINAPI JoystickAImpl_EnumEffects(LPDIRECTINPUTDEVICE8A iface, + LPDIENUMEFFECTSCALLBACKA lpCallback, + LPVOID pvRef, + DWORD dwEffType) +{ + DIEFFECTINFOA dei; /* feif */ + DWORD type = DIEFT_GETTYPE(dwEffType); + DWORD effects; + JoystickImpl* This = impl_from_IDirectInputDevice8A(iface); + + TRACE("(this=%p,%p,%d) type=%d\n", This, pvRef, dwEffType, type); + + if (GAMEPAD_Driver->pGamePadHasForceFeedback(This->id, &effects)) + { + dei.dwSize = sizeof(DIEFFECTINFOA); + + if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE) && + effects & DRIVER_CONSTANTFORCE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce); + (*lpCallback)(&dei, pvRef); + } + + if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)) + { + if (effects & DRIVER_SQUARE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_SINE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_TRIANGLE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_SAWTOOTHUP) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_SAWTOOTHDOWN) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown); + (*lpCallback)(&dei, pvRef); + } + } + + if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE) && + effects & DRIVER_RAMPFORCE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce); + (*lpCallback)(&dei, pvRef); + } + + if (type == DIEFT_ALL || type == DIEFT_CONDITION) { + if (effects & DRIVER_SPRING) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_DAMPER) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_INERTIA) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_FRICTION) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction); + (*lpCallback)(&dei, pvRef); + } + } + } + return DI_OK; +} + +static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, + LPDIENUMEFFECTSCALLBACKW lpCallback, + LPVOID pvRef, + DWORD dwEffType) +{ + /* seems silly to duplicate all this code but all the structures and functions + * are actually different (A/W) */ + DIEFFECTINFOW dei; /* feif */ + DWORD type = DIEFT_GETTYPE(dwEffType); + DWORD effects; + JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); + + TRACE("(this=%p,%p,%d) type=%d\n", This, pvRef, dwEffType, type); + + if (GAMEPAD_Driver->pGamePadHasForceFeedback(This->id, &effects)) + { + dei.dwSize = sizeof(DIEFFECTINFOW); + + if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE) && + effects & DRIVER_CONSTANTFORCE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce); + (*lpCallback)(&dei, pvRef); + } + + if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)) + { + if (effects & DRIVER_SQUARE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_SINE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_TRIANGLE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_SAWTOOTHUP) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_SAWTOOTHDOWN) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown); + (*lpCallback)(&dei, pvRef); + } + } + + if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE) && + effects & DRIVER_RAMPFORCE) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce); + (*lpCallback)(&dei, pvRef); + } + + if (type == DIEFT_ALL || type == DIEFT_CONDITION) { + if (effects & DRIVER_SPRING) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_DAMPER) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_INERTIA) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia); + (*lpCallback)(&dei, pvRef); + } + if (effects & DRIVER_FRICTION) + { + IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction); + (*lpCallback)(&dei, pvRef); + } + } + } + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8A iface, + LPDIEFFECTINFOA pdei, + REFGUID guid) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8A(iface); + + TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid)); + + if (GAMEPAD_Driver->pGamePadHasForceFeedback(This->id, NULL)) + { + DWORD type = typeFromGUID(guid); + + TRACE("(%s, %p) type=%d\n", _dump_dinput_GUID(guid), pdei, type); + + if (!pdei) return E_POINTER; + + if (pdei->dwSize != sizeof(DIEFFECTINFOA)) return DIERR_INVALIDPARAM; + + pdei->guid = *guid; + + pdei->dwEffType = type; + /* the event device API does not support querying for all these things + * therefore we assume that we have support for them + * that's not as dangerous as it sounds, since drivers are allowed to + * ignore parameters they claim to support anyway */ + pdei->dwEffType |= DIEFT_DEADBAND | DIEFT_FFATTACK | DIEFT_FFFADE + | DIEFT_POSNEGCOEFFICIENTS | DIEFT_POSNEGSATURATION + | DIEFT_SATURATION | DIEFT_STARTDELAY; + + /* again, assume we have support for everything */ + pdei->dwStaticParams = DIEP_ALLPARAMS; + pdei->dwDynamicParams = pdei->dwStaticParams; + + /* yes, this is windows behavior (print the GUID_Name for name) */ + strcpy(pdei->tszName, _dump_dinput_GUID(guid)); + } + + return DI_OK; +} + + +static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, + LPDIEFFECTINFOW pdei, + REFGUID guid) +{ + JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); + + TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid)); + + if (GAMEPAD_Driver->pGamePadHasForceFeedback(This->id, NULL)) + { + DWORD type = typeFromGUID(guid); + + TRACE("(%s, %p) type=%d\n", _dump_dinput_GUID(guid), pdei, type); + + if (!pdei) return E_POINTER; + + if (pdei->dwSize != sizeof(DIEFFECTINFOW)) return DIERR_INVALIDPARAM; + + pdei->guid = *guid; + + pdei->dwEffType = type; + /* the event device API does not support querying for all these things + * therefore we assume that we have support for them + * that's not as dangerous as it sounds, since drivers are allowed to + * ignore parameters they claim to support anyway */ + pdei->dwEffType |= DIEFT_DEADBAND | DIEFT_FFATTACK | DIEFT_FFFADE + | DIEFT_POSNEGCOEFFICIENTS | DIEFT_POSNEGSATURATION + | DIEFT_SATURATION | DIEFT_STARTDELAY; + + /* again, assume we have support for everything */ + pdei->dwStaticParams = DIEP_ALLPARAMS; + pdei->dwDynamicParams = pdei->dwStaticParams; + + /* yes, this is windows behavior (print the GUID_Name for name) */ + MultiByteToWideChar(CP_ACP, 0, _dump_dinput_GUID(guid), -1, + pdei->tszName, MAX_PATH); + } + + return DI_OK; +} + +static HRESULT WINAPI JoystickWImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) +{ + JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); + + TRACE("(this=%p,%p)\n", This, pdwOut); + + (*pdwOut) = 0; + GAMEPAD_Driver->pGamePadGetForceFeedbackState(This->id, pdwOut); + + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut) +{ + JoystickImpl* This = impl_from_IDirectInputDevice8A(iface); + + TRACE("(this=%p,%p)\n", This, pdwOut); + + (*pdwOut) = 0; + GAMEPAD_Driver->pGamePadGetForceFeedbackState(This->id, pdwOut); + + return DI_OK; +} + const struct dinput_device joystick_driver_device = { "Wine Graphic Driver joystick driver", joydev_enum_deviceA, @@ -547,7 +907,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = JoystickAImpl_GetProperty, JoystickAImpl_SetProperty, IDirectInputDevice2AImpl_Acquire, - IDirectInputDevice2AImpl_Unacquire, + JoystickAImpl_Unacquire, JoystickAGenericImpl_GetDeviceState, IDirectInputDevice2AImpl_GetDeviceData, IDirectInputDevice2AImpl_SetDataFormat, @@ -558,9 +918,9 @@ static const IDirectInputDevice8AVtbl JoystickAvt = IDirectInputDevice2AImpl_RunControlPanel, IDirectInputDevice2AImpl_Initialize, JoystickAImpl_CreateEffect, - IDirectInputDevice2AImpl_EnumEffects, - IDirectInputDevice2AImpl_GetEffectInfo, - IDirectInputDevice2AImpl_GetForceFeedbackState, + JoystickAImpl_EnumEffects, + JoystickAImpl_GetEffectInfo, + JoystickAImpl_GetForceFeedbackState, JoystickAImpl_SendForceFeedbackCommand, IDirectInputDevice2AImpl_EnumCreatedEffectObjects, IDirectInputDevice2AImpl_Escape, @@ -583,7 +943,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt = JoystickWImpl_GetProperty, JoystickWImpl_SetProperty, IDirectInputDevice2WImpl_Acquire, - IDirectInputDevice2WImpl_Unacquire, + JoystickWImpl_Unacquire, JoystickWGenericImpl_GetDeviceState, IDirectInputDevice2WImpl_GetDeviceData, IDirectInputDevice2WImpl_SetDataFormat, @@ -594,9 +954,9 @@ static const IDirectInputDevice8WVtbl JoystickWvt = IDirectInputDevice2WImpl_RunControlPanel, IDirectInputDevice2WImpl_Initialize, JoystickWImpl_CreateEffect, - IDirectInputDevice2WImpl_EnumEffects, - IDirectInputDevice2WImpl_GetEffectInfo, - IDirectInputDevice2WImpl_GetForceFeedbackState, + JoystickWImpl_EnumEffects, + JoystickWImpl_GetEffectInfo, + JoystickWImpl_GetForceFeedbackState, JoystickWImpl_SendForceFeedbackCommand, IDirectInputDevice2WImpl_EnumCreatedEffectObjects, IDirectInputDevice2WImpl_Escape, @@ -753,6 +1113,16 @@ static const GAMEPAD_DRIVER *load_driver(void) GET_USER_FUNC(GamePadPollValues); GET_USER_FUNC(GamePadAlloc); GET_USER_FUNC(GamePadDealloc); + GET_USER_FUNC(GamePadHasForceFeedback); + GET_USER_FUNC(GamePadGetForceFeedbackState); + GET_USER_FUNC(GamePadElementHasForceFeedback); + GET_USER_FUNC(GamePadSetAutocenter); + GET_USER_FUNC(GamePadGetAutocenter); + GET_USER_FUNC(GamePadSetFFGain); + GET_USER_FUNC(GamePadGetFFGain); + GET_USER_FUNC(GamePadSendForceFeedbackCommand); + GET_USER_FUNC(GamePadCreateDinputEffect); + GET_USER_FUNC(GamePadStopAllForceFeedbackEffects); #undef GET_USER_FUNC } @@ -804,6 +1174,56 @@ static VOID CDECL loaderdrv_GamePadDealloc(int id) load_driver()->pGamePadDealloc(id); } +static BOOL CDECL loaderdrv_GamePadHasForceFeedback(int id, DWORD *effects) +{ + return load_driver()->pGamePadHasForceFeedback(id, effects); +} + +static BOOL CDECL loaderdrv_GamePadElementHasForceFeedback(int id, int element) +{ + return load_driver()->pGamePadElementHasForceFeedback(id, element); +} + +static VOID CDECL loaderdrv_GamePadGetForceFeedbackState(int id, DWORD *state) +{ + load_driver()->pGamePadGetForceFeedbackState(id, state); +} + +static HRESULT CDECL loaderdrv_GamePadSetAutocenter(int id, DWORD data) +{ + return load_driver()->pGamePadSetAutocenter(id, data); +} + +static HRESULT CDECL loaderdrv_GamePadGetAutocenter(int id, DWORD *data) +{ + return load_driver()->pGamePadGetAutocenter(id, data); +} + +static HRESULT CDECL loaderdrv_GamePadSetFFGain(int id, DWORD data) +{ + return load_driver()->pGamePadSetFFGain(id, data); +} + +static HRESULT CDECL loaderdrv_GamePadGetFFGain(int id, DWORD *data) +{ + return load_driver()->pGamePadGetFFGain(id, data); +} + +static HRESULT CDECL loaderdrv_GamePadSendForceFeedbackCommand(int id, DWORD flags) +{ + return load_driver()->pGamePadSendForceFeedbackCommand(id, flags); +} + +static DWORD CDECL loaderdrv_GamePadCreateDinputEffect(int id, const GUID *type, const DIEFFECT *params, IDirectInputEffect **out, IUnknown *outer) +{ + return load_driver()->pGamePadCreateDinputEffect(id, type, params, out, outer); +} + +static VOID CDECL loaderdrv_GamePadStopAllForceFeedbackEffects(int id, int release) +{ + load_driver()->pGamePadStopAllForceFeedbackEffects(id, release); +} + static GAMEPAD_DRIVER lazy_load_driver = { loaderdrv_GamePadCount, @@ -812,7 +1232,17 @@ static GAMEPAD_DRIVER lazy_load_driver = loaderdrv_GamePadElementProps, loaderdrv_GamePadPollValues, loaderdrv_GamePadAlloc, - loaderdrv_GamePadDealloc + loaderdrv_GamePadDealloc, + loaderdrv_GamePadHasForceFeedback, + loaderdrv_GamePadElementHasForceFeedback, + loaderdrv_GamePadGetForceFeedbackState, + loaderdrv_GamePadSetAutocenter, + loaderdrv_GamePadGetAutocenter, + loaderdrv_GamePadSetFFGain, + loaderdrv_GamePadGetFFGain, + loaderdrv_GamePadSendForceFeedbackCommand, + loaderdrv_GamePadCreateDinputEffect, + loaderdrv_GamePadStopAllForceFeedbackEffects }; static INT CDECL nulldrv_GamePadCount(void) @@ -845,6 +1275,57 @@ static VOID CDECL nulldrv_GamePadDealloc(int id) { } +static BOOL CDECL nulldrv_GamePadHasForceFeedback(int id, DWORD *effects) +{ + return FALSE; +} + +static VOID CDECL nulldrv_GamePadGetForceFeedbackState(int id, DWORD *state) +{ + *state = 0; +} + +static BOOL CDECL nulldrv_GamePadElementHasForceFeedback(int id, int element) +{ + return FALSE; +} + +static HRESULT CDECL nulldrv_GamePadSetAutocenter(int id, DWORD data) +{ + return DIERR_UNSUPPORTED; +} + +static HRESULT CDECL nulldrv_GamePadGetAutocenter(int id, DWORD *data) +{ + return DIERR_UNSUPPORTED; +} + +static HRESULT CDECL nulldrv_GamePadSetFFGain(int id, DWORD data) +{ + return DIERR_UNSUPPORTED; +} + +static HRESULT CDECL nulldrv_GamePadGetFFGain(int id, DWORD *data) +{ + return DIERR_UNSUPPORTED; +} + +static HRESULT CDECL nulldrv_GamePadSendForceFeedbackCommand(int id, DWORD flags) +{ + return DI_NOEFFECT; +} + +static DWORD CDECL nulldrv_GamePadCreateDinputEffect(int id, const GUID *type, const DIEFFECT *params, IDirectInputEffect **out, IUnknown *outer) +{ + TRACE("No effects support\n"); + *out = NULL; + return DI_NOEFFECT; +} + +static VOID CDECL nulldrv_GamePadStopAllForceFeedbackEffects(int id, int release) +{ +} + static GAMEPAD_DRIVER null_driver = { nulldrv_GamePadCount, @@ -853,5 +1334,15 @@ static GAMEPAD_DRIVER null_driver = nulldrv_GamePadElementProps, nulldrv_GamePadPollValues, nulldrv_GamePadAlloc, - nulldrv_GamePadDealloc + nulldrv_GamePadDealloc, + nulldrv_GamePadHasForceFeedback, + nulldrv_GamePadElementHasForceFeedback, + nulldrv_GamePadGetForceFeedbackState, + nulldrv_GamePadSetAutocenter, + nulldrv_GamePadGetAutocenter, + nulldrv_GamePadSetFFGain, + nulldrv_GamePadGetFFGain, + nulldrv_GamePadSendForceFeedbackCommand, + nulldrv_GamePadCreateDinputEffect, + nulldrv_GamePadStopAllForceFeedbackEffects };