[PATCH 2/3] dinput: Determine if OSX devices support force feedback
Andrew Eikum
aeikum at codeweavers.com
Mon May 20 14:10:30 CDT 2013
---
configure.ac | 1 +
dlls/dinput/Makefile.in | 2 +-
dlls/dinput/joystick_osx.c | 158 +++++++++++++++++++++++++++++++++++++--------
3 files changed, 133 insertions(+), 28 deletions(-)
diff --git a/configure.ac b/configure.ac
index 98b51e3..05794af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -741,6 +741,7 @@ clean::
dnl declare needed frameworks
AC_SUBST(COREFOUNDATIONLIB,"-framework CoreFoundation")
AC_SUBST(IOKITLIB,"-framework IOKit -framework CoreFoundation")
+ AC_SUBST(FORCEFEEDBACKLIB,"-framework ForceFeedback -framework CoreFoundation")
AC_SUBST(APPLICATIONSERVICESLIB,"-framework ApplicationServices")
AC_SUBST(CORESERVICESLIB,"-framework CoreServices")
case $host_os in
diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in
index 1be48c4..e7d23d7 100644
--- a/dlls/dinput/Makefile.in
+++ b/dlls/dinput/Makefile.in
@@ -1,7 +1,7 @@
MODULE = dinput.dll
IMPORTLIB = dinput
IMPORTS = dxguid uuid comctl32 ole32 user32 advapi32
-EXTRALIBS = @IOKITLIB@
+EXTRALIBS = @IOKITLIB@ @FORCEFEEDBACKLIB@
C_SRCS = \
config.c \
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 60db656..66a4acb 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -24,6 +24,11 @@
#include "wine/port.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 E_INVALIDARG __carbon_E_INVALIDARG
#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
@@ -44,7 +49,9 @@
#define MAKE_HRESULT __carbon_MAKE_HRESULT
#define HRESULT __carbon_HRESULT
#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
+#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
+#include <ForceFeedback/ForceFeedback.h>
#undef ULONG
#undef E_INVALIDARG
#undef E_OUTOFMEMORY
@@ -65,6 +72,11 @@
#undef MAKE_HRESULT
#undef HRESULT
#undef STDMETHODCALLTYPE
+#undef DWORD
+#undef LPDWORD
+#undef LONG
+#undef LPLONG
+#undef E_PENDING
#endif /* HAVE_IOKIT_HID_IOHIDLIB_H */
#include "wine/debug.h"
@@ -98,6 +110,7 @@ struct JoystickImpl
int id;
CFMutableArrayRef elementCFArrayRef;
ObjProps **propmap;
+ FFDeviceObjectReference ff;
};
static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
@@ -120,6 +133,60 @@ static void CFSetApplierFunctionCopyToCFArray(const void *value, void *context)
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)
{
CFMutableDictionaryRef result;
@@ -298,30 +365,15 @@ static int find_osx_devices(void)
static int get_osx_device_name(int id, char *name, int length)
{
CFStringRef str;
- 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);
+ tIOHIDDeviceRef = get_device_ref(id);
if (name)
name[0] = 0;
if (!tIOHIDDeviceRef)
- {
- ERR("Invalid Device requested %i\n",id);
return 0;
- }
str = IOHIDDeviceGetProperty(tIOHIDDeviceRef, CFSTR( kIOHIDProductKey ));
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 (dwFlags & DIEDFL_FORCEFEEDBACK) {
- WARN("force feedback not supported\n");
- return S_FALSE;
- }
-
if ((dwDevType == 0) ||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && 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 */
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
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 (dwFlags & DIEDFL_FORCEFEEDBACK) {
- WARN("force feedback not supported\n");
- return S_FALSE;
- }
-
if ((dwDevType == 0) ||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && 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 */
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
lpddi->guidInstance.Data3 = id;
@@ -722,10 +778,26 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
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,
JoystickImpl **pdev, unsigned short index)
{
DWORD i;
+ IOHIDDeviceRef device;
JoystickImpl* newDevice;
char name[MAX_PATH];
HRESULT hr;
@@ -733,6 +805,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
int idx = 0;
int axis_map[8]; /* max axes */
int slider_count = 0;
+ FFCAPABILITIES ffcaps;
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);
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));
get_osx_device_elements(newDevice, axis_map);
@@ -830,7 +934,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
LeaveCriticalSection(&dinput->crit);
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)
newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
else
--
1.8.2.3
More information about the wine-patches
mailing list