dinput: Determine if OSX devices support force feedback.
This commit is contained in:
parent
0ba314ebfa
commit
e6450b4ea4
|
@ -693,6 +693,7 @@ DISKARBITRATIONLIB
|
||||||
LDEXECFLAGS
|
LDEXECFLAGS
|
||||||
CORESERVICESLIB
|
CORESERVICESLIB
|
||||||
APPLICATIONSERVICESLIB
|
APPLICATIONSERVICESLIB
|
||||||
|
FORCEFEEDBACKLIB
|
||||||
IOKITLIB
|
IOKITLIB
|
||||||
COREFOUNDATIONLIB
|
COREFOUNDATIONLIB
|
||||||
LIBWINE_RULES
|
LIBWINE_RULES
|
||||||
|
@ -6590,6 +6591,8 @@ clean::
|
||||||
|
|
||||||
IOKITLIB="-framework IOKit -framework CoreFoundation"
|
IOKITLIB="-framework IOKit -framework CoreFoundation"
|
||||||
|
|
||||||
|
FORCEFEEDBACKLIB="-framework ForceFeedback -framework CoreFoundation"
|
||||||
|
|
||||||
APPLICATIONSERVICESLIB="-framework ApplicationServices"
|
APPLICATIONSERVICESLIB="-framework ApplicationServices"
|
||||||
|
|
||||||
CORESERVICESLIB="-framework CoreServices"
|
CORESERVICESLIB="-framework CoreServices"
|
||||||
|
|
|
@ -741,6 +741,7 @@ clean::
|
||||||
dnl declare needed frameworks
|
dnl declare needed frameworks
|
||||||
AC_SUBST(COREFOUNDATIONLIB,"-framework CoreFoundation")
|
AC_SUBST(COREFOUNDATIONLIB,"-framework CoreFoundation")
|
||||||
AC_SUBST(IOKITLIB,"-framework IOKit -framework CoreFoundation")
|
AC_SUBST(IOKITLIB,"-framework IOKit -framework CoreFoundation")
|
||||||
|
AC_SUBST(FORCEFEEDBACKLIB,"-framework ForceFeedback -framework CoreFoundation")
|
||||||
AC_SUBST(APPLICATIONSERVICESLIB,"-framework ApplicationServices")
|
AC_SUBST(APPLICATIONSERVICESLIB,"-framework ApplicationServices")
|
||||||
AC_SUBST(CORESERVICESLIB,"-framework CoreServices")
|
AC_SUBST(CORESERVICESLIB,"-framework CoreServices")
|
||||||
case $host_os in
|
case $host_os in
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
MODULE = dinput.dll
|
MODULE = dinput.dll
|
||||||
IMPORTLIB = dinput
|
IMPORTLIB = dinput
|
||||||
IMPORTS = dxguid uuid comctl32 ole32 user32 advapi32
|
IMPORTS = dxguid uuid comctl32 ole32 user32 advapi32
|
||||||
EXTRALIBS = @IOKITLIB@
|
EXTRALIBS = @IOKITLIB@ @FORCEFEEDBACKLIB@
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
config.c \
|
config.c \
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
#if defined(HAVE_IOKIT_HID_IOHIDLIB_H)
|
#if defined(HAVE_IOKIT_HID_IOHIDLIB_H)
|
||||||
|
#define DWORD UInt32
|
||||||
|
#define LPDWORD UInt32*
|
||||||
|
#define LONG SInt32
|
||||||
|
#define LPLONG SInt32*
|
||||||
|
#define E_PENDING __carbon_E_PENDING
|
||||||
#define ULONG __carbon_ULONG
|
#define ULONG __carbon_ULONG
|
||||||
#define E_INVALIDARG __carbon_E_INVALIDARG
|
#define E_INVALIDARG __carbon_E_INVALIDARG
|
||||||
#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
|
#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
|
||||||
|
@ -44,7 +49,9 @@
|
||||||
#define MAKE_HRESULT __carbon_MAKE_HRESULT
|
#define MAKE_HRESULT __carbon_MAKE_HRESULT
|
||||||
#define HRESULT __carbon_HRESULT
|
#define HRESULT __carbon_HRESULT
|
||||||
#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
|
#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
|
#include <ForceFeedback/ForceFeedback.h>
|
||||||
#undef ULONG
|
#undef ULONG
|
||||||
#undef E_INVALIDARG
|
#undef E_INVALIDARG
|
||||||
#undef E_OUTOFMEMORY
|
#undef E_OUTOFMEMORY
|
||||||
|
@ -65,6 +72,11 @@
|
||||||
#undef MAKE_HRESULT
|
#undef MAKE_HRESULT
|
||||||
#undef HRESULT
|
#undef HRESULT
|
||||||
#undef STDMETHODCALLTYPE
|
#undef STDMETHODCALLTYPE
|
||||||
|
#undef DWORD
|
||||||
|
#undef LPDWORD
|
||||||
|
#undef LONG
|
||||||
|
#undef LPLONG
|
||||||
|
#undef E_PENDING
|
||||||
#endif /* HAVE_IOKIT_HID_IOHIDLIB_H */
|
#endif /* HAVE_IOKIT_HID_IOHIDLIB_H */
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
@ -98,6 +110,7 @@ struct JoystickImpl
|
||||||
int id;
|
int id;
|
||||||
CFMutableArrayRef elementCFArrayRef;
|
CFMutableArrayRef elementCFArrayRef;
|
||||||
ObjProps **propmap;
|
ObjProps **propmap;
|
||||||
|
FFDeviceObjectReference ff;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
|
static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
|
||||||
|
@ -120,6 +133,60 @@ static void CFSetApplierFunctionCopyToCFArray(const void *value, void *context)
|
||||||
CFArrayAppendValue( ( CFMutableArrayRef ) context, value );
|
CFArrayAppendValue( ( CFMutableArrayRef ) context, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IOHIDDeviceRef get_device_ref(int id)
|
||||||
|
{
|
||||||
|
IOHIDElementRef tIOHIDElementRef;
|
||||||
|
IOHIDDeviceRef tIOHIDDeviceRef;
|
||||||
|
|
||||||
|
if (!gCollections)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);
|
||||||
|
if (!tIOHIDElementRef)
|
||||||
|
{
|
||||||
|
ERR("Invalid Element requested %i\n",id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);
|
||||||
|
if (!tIOHIDDeviceRef)
|
||||||
|
{
|
||||||
|
ERR("Invalid Device requested %i\n",id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tIOHIDDeviceRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT get_ff(IOHIDDeviceRef device, FFDeviceObjectReference *ret)
|
||||||
|
{
|
||||||
|
io_service_t service;
|
||||||
|
CFMutableDictionaryRef matching;
|
||||||
|
CFTypeRef type;
|
||||||
|
|
||||||
|
matching = IOServiceMatching(kIOHIDDeviceKey);
|
||||||
|
if(!matching){
|
||||||
|
WARN("IOServiceMatching failed, force feedback disabled\n");
|
||||||
|
return DIERR_DEVICENOTREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey));
|
||||||
|
if(!matching){
|
||||||
|
CFRelease(matching);
|
||||||
|
WARN("IOHIDDeviceGetProperty failed, force feedback disabled\n");
|
||||||
|
return DIERR_DEVICENOTREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFDictionaryAddValue(matching, CFSTR(kIOHIDLocationIDKey), type);
|
||||||
|
|
||||||
|
service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
|
||||||
|
|
||||||
|
if(!ret)
|
||||||
|
return FFIsForceFeedback(service) == FF_OK ? S_OK : S_FALSE;
|
||||||
|
|
||||||
|
return FFCreateDevice(service, ret);
|
||||||
|
}
|
||||||
|
|
||||||
static CFMutableDictionaryRef creates_osx_device_match(int usage)
|
static CFMutableDictionaryRef creates_osx_device_match(int usage)
|
||||||
{
|
{
|
||||||
CFMutableDictionaryRef result;
|
CFMutableDictionaryRef result;
|
||||||
|
@ -298,30 +365,15 @@ static int find_osx_devices(void)
|
||||||
static int get_osx_device_name(int id, char *name, int length)
|
static int get_osx_device_name(int id, char *name, int length)
|
||||||
{
|
{
|
||||||
CFStringRef str;
|
CFStringRef str;
|
||||||
IOHIDElementRef tIOHIDElementRef;
|
|
||||||
IOHIDDeviceRef tIOHIDDeviceRef;
|
IOHIDDeviceRef tIOHIDDeviceRef;
|
||||||
|
|
||||||
if (!gCollections)
|
tIOHIDDeviceRef = get_device_ref(id);
|
||||||
return 0;
|
|
||||||
|
|
||||||
tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);
|
|
||||||
|
|
||||||
if (!tIOHIDElementRef)
|
|
||||||
{
|
|
||||||
ERR("Invalid Element requested %i\n",id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);
|
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
name[0] = 0;
|
name[0] = 0;
|
||||||
|
|
||||||
if (!tIOHIDDeviceRef)
|
if (!tIOHIDDeviceRef)
|
||||||
{
|
|
||||||
ERR("Invalid Device requested %i\n",id);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
str = IOHIDDeviceGetProperty(tIOHIDDeviceRef, CFSTR( kIOHIDProductKey ));
|
str = IOHIDDeviceGetProperty(tIOHIDDeviceRef, CFSTR( kIOHIDProductKey ));
|
||||||
if (str)
|
if (str)
|
||||||
|
@ -655,15 +707,17 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
||||||
{
|
{
|
||||||
if (id >= find_joystick_devices()) return E_FAIL;
|
if (id >= find_joystick_devices()) return E_FAIL;
|
||||||
|
|
||||||
if (dwFlags & DIEDFL_FORCEFEEDBACK) {
|
|
||||||
WARN("force feedback not supported\n");
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dwDevType == 0) ||
|
if ((dwDevType == 0) ||
|
||||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
((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) {
|
||||||
|
IOHIDDeviceRef device = get_device_ref(id);
|
||||||
|
if(!device)
|
||||||
|
return S_FALSE;
|
||||||
|
if(get_ff(device, NULL) != S_OK)
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
/* Return joystick */
|
/* Return joystick */
|
||||||
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||||
lpddi->guidInstance.Data3 = id;
|
lpddi->guidInstance.Data3 = id;
|
||||||
|
@ -692,14 +746,16 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
||||||
|
|
||||||
if (id >= find_joystick_devices()) return E_FAIL;
|
if (id >= find_joystick_devices()) return E_FAIL;
|
||||||
|
|
||||||
if (dwFlags & DIEDFL_FORCEFEEDBACK) {
|
|
||||||
WARN("force feedback not supported\n");
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dwDevType == 0) ||
|
if ((dwDevType == 0) ||
|
||||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
((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) {
|
||||||
|
IOHIDDeviceRef device = get_device_ref(id);
|
||||||
|
if(!device)
|
||||||
|
return S_FALSE;
|
||||||
|
if(get_ff(device, NULL) != S_OK)
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
/* Return joystick */
|
/* Return joystick */
|
||||||
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||||
lpddi->guidInstance.Data3 = id;
|
lpddi->guidInstance.Data3 = id;
|
||||||
|
@ -722,10 +778,26 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *osx_ff_axis_name(UInt8 axis)
|
||||||
|
{
|
||||||
|
static char ret[6];
|
||||||
|
switch(axis){
|
||||||
|
case FFJOFS_X:
|
||||||
|
return "FFJOFS_X";
|
||||||
|
case FFJOFS_Y:
|
||||||
|
return "FFJOFS_Y";
|
||||||
|
case FFJOFS_Z:
|
||||||
|
return "FFJOFS_Z";
|
||||||
|
}
|
||||||
|
sprintf(ret, "%u", (unsigned int)axis);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
|
static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
|
||||||
JoystickImpl **pdev, unsigned short index)
|
JoystickImpl **pdev, unsigned short index)
|
||||||
{
|
{
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
IOHIDDeviceRef device;
|
||||||
JoystickImpl* newDevice;
|
JoystickImpl* newDevice;
|
||||||
char name[MAX_PATH];
|
char name[MAX_PATH];
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -733,6 +805,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
int axis_map[8]; /* max axes */
|
int axis_map[8]; /* max axes */
|
||||||
int slider_count = 0;
|
int slider_count = 0;
|
||||||
|
FFCAPABILITIES ffcaps;
|
||||||
|
|
||||||
TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
|
TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
|
||||||
|
|
||||||
|
@ -758,6 +831,37 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
|
||||||
newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
|
newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
|
||||||
strcpy(newDevice->generic.name, name);
|
strcpy(newDevice->generic.name, name);
|
||||||
|
|
||||||
|
device = get_device_ref(index);
|
||||||
|
if(get_ff(device, &newDevice->ff) == S_OK){
|
||||||
|
newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
|
||||||
|
|
||||||
|
hr = FFDeviceGetForceFeedbackCapabilities(newDevice->ff, &ffcaps);
|
||||||
|
if(SUCCEEDED(hr)){
|
||||||
|
TRACE("FF Capabilities:\n");
|
||||||
|
TRACE("\tsupportedEffects: 0x%x\n", (unsigned int)ffcaps.supportedEffects);
|
||||||
|
TRACE("\temulatedEffects: 0x%x\n", (unsigned int)ffcaps.emulatedEffects);
|
||||||
|
TRACE("\tsubType: 0x%x\n", (unsigned int)ffcaps.subType);
|
||||||
|
TRACE("\tnumFfAxes: %u\n", (unsigned int)ffcaps.numFfAxes);
|
||||||
|
TRACE("\tffAxes: [");
|
||||||
|
for(i = 0; i < ffcaps.numFfAxes; ++i){
|
||||||
|
TRACE("%s", osx_ff_axis_name(ffcaps.ffAxes[i]));
|
||||||
|
if(i < ffcaps.numFfAxes - 1)
|
||||||
|
TRACE(", ");
|
||||||
|
}
|
||||||
|
TRACE("]\n");
|
||||||
|
TRACE("\tstorageCapacity: %u\n", (unsigned int)ffcaps.storageCapacity);
|
||||||
|
TRACE("\tplaybackCapacity: %u\n", (unsigned int)ffcaps.playbackCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_RESET);
|
||||||
|
if(FAILED(hr))
|
||||||
|
WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n", hr);
|
||||||
|
|
||||||
|
hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_SETACTUATORSON);
|
||||||
|
if(FAILED(hr))
|
||||||
|
WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr);
|
||||||
|
}
|
||||||
|
|
||||||
memset(axis_map, 0, sizeof(axis_map));
|
memset(axis_map, 0, sizeof(axis_map));
|
||||||
get_osx_device_elements(newDevice, axis_map);
|
get_osx_device_elements(newDevice, axis_map);
|
||||||
|
|
||||||
|
@ -830,7 +934,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
|
||||||
LeaveCriticalSection(&dinput->crit);
|
LeaveCriticalSection(&dinput->crit);
|
||||||
|
|
||||||
newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
|
newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
|
||||||
newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
|
newDevice->generic.devcaps.dwFlags |= DIDC_ATTACHED;
|
||||||
if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
|
if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
|
||||||
newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue