1 /* DirectInput Joystick device for Mac OS/X
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2009 CodeWeavers, Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
26 #if defined(HAVE_IOKIT_HID_IOHIDLIB_H)
28 #define LPDWORD UInt32*
30 #define LPLONG SInt32*
31 #define E_PENDING __carbon_E_PENDING
32 #define ULONG __carbon_ULONG
33 #define E_INVALIDARG __carbon_E_INVALIDARG
34 #define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
35 #define E_HANDLE __carbon_E_HANDLE
36 #define E_ACCESSDENIED __carbon_E_ACCESSDENIED
37 #define E_UNEXPECTED __carbon_E_UNEXPECTED
38 #define E_FAIL __carbon_E_FAIL
39 #define E_ABORT __carbon_E_ABORT
40 #define E_POINTER __carbon_E_POINTER
41 #define E_NOINTERFACE __carbon_E_NOINTERFACE
42 #define E_NOTIMPL __carbon_E_NOTIMPL
43 #define S_FALSE __carbon_S_FALSE
44 #define S_OK __carbon_S_OK
45 #define HRESULT_FACILITY __carbon_HRESULT_FACILITY
46 #define IS_ERROR __carbon_IS_ERROR
47 #define FAILED __carbon_FAILED
48 #define SUCCEEDED __carbon_SUCCEEDED
49 #define MAKE_HRESULT __carbon_MAKE_HRESULT
50 #define HRESULT __carbon_HRESULT
51 #define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
52 #include <IOKit/IOKitLib.h>
53 #include <IOKit/hid/IOHIDLib.h>
54 #include <ForceFeedback/ForceFeedback.h>
68 #undef HRESULT_FACILITY
74 #undef STDMETHODCALLTYPE
80 #endif /* HAVE_IOKIT_HID_IOHIDLIB_H */
82 #include "wine/debug.h"
83 #include "wine/unicode.h"
90 #include "dinput_private.h"
91 #include "device_private.h"
92 #include "joystick_private.h"
94 #ifdef HAVE_IOHIDMANAGERCREATE
96 WINE_DEFAULT_DEBUG_CHANNEL(dinput
);
98 static IOHIDManagerRef gIOHIDManagerRef
= NULL
;
99 static CFArrayRef gCollections
= NULL
;
101 typedef struct JoystickImpl JoystickImpl
;
102 static const IDirectInputDevice8AVtbl JoystickAvt
;
103 static const IDirectInputDevice8WVtbl JoystickWvt
;
107 struct JoystickGenericImpl generic
;
111 CFMutableArrayRef elementCFArrayRef
;
113 FFDeviceObjectReference ff
;
117 static inline JoystickImpl
*impl_from_IDirectInputDevice8A(IDirectInputDevice8A
*iface
)
119 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface
, IDirectInputDeviceImpl
, IDirectInputDevice8A_iface
),
120 JoystickGenericImpl
, base
), JoystickImpl
, generic
);
122 static inline JoystickImpl
*impl_from_IDirectInputDevice8W(IDirectInputDevice8W
*iface
)
124 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface
, IDirectInputDeviceImpl
, IDirectInputDevice8W_iface
),
125 JoystickGenericImpl
, base
), JoystickImpl
, generic
);
128 typedef struct _EffectImpl
{
129 IDirectInputEffect IDirectInputEffect_iface
;
132 JoystickImpl
*device
;
133 FFEffectObjectReference effect
;
139 static EffectImpl
*impl_from_IDirectInputEffect(IDirectInputEffect
*iface
)
141 return CONTAINING_RECORD(iface
, EffectImpl
, IDirectInputEffect_iface
);
144 static const IDirectInputEffectVtbl EffectVtbl
;
146 static const GUID DInput_Wine_OsX_Joystick_GUID
= { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */
147 0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
150 static HRESULT
osx_to_win32_hresult(HRESULT in
)
152 /* OSX returns 16-bit COM runtime errors, which we should
153 * convert to win32 */
158 return E_OUTOFMEMORY
;
162 return E_NOINTERFACE
;
172 return E_ACCESSDENIED
;
179 static void CFSetApplierFunctionCopyToCFArray(const void *value
, void *context
)
181 CFArrayAppendValue( ( CFMutableArrayRef
) context
, value
);
184 static IOHIDDeviceRef
get_device_ref(int id
)
186 IOHIDElementRef tIOHIDElementRef
;
187 IOHIDDeviceRef tIOHIDDeviceRef
;
192 tIOHIDElementRef
= (IOHIDElementRef
)CFArrayGetValueAtIndex(gCollections
, id
);
193 if (!tIOHIDElementRef
)
195 ERR("Invalid Element requested %i\n",id
);
199 tIOHIDDeviceRef
= IOHIDElementGetDevice(tIOHIDElementRef
);
200 if (!tIOHIDDeviceRef
)
202 ERR("Invalid Device requested %i\n",id
);
206 return tIOHIDDeviceRef
;
209 static HRESULT
get_ff(IOHIDDeviceRef device
, FFDeviceObjectReference
*ret
)
211 io_service_t service
;
212 CFMutableDictionaryRef matching
;
215 matching
= IOServiceMatching(kIOHIDDeviceKey
);
217 WARN("IOServiceMatching failed, force feedback disabled\n");
218 return DIERR_DEVICENOTREG
;
221 type
= IOHIDDeviceGetProperty(device
, CFSTR(kIOHIDLocationIDKey
));
224 WARN("IOHIDDeviceGetProperty failed, force feedback disabled\n");
225 return DIERR_DEVICENOTREG
;
228 CFDictionaryAddValue(matching
, CFSTR(kIOHIDLocationIDKey
), type
);
230 service
= IOServiceGetMatchingService(kIOMasterPortDefault
, matching
);
233 return FFIsForceFeedback(service
) == FF_OK
? S_OK
: S_FALSE
;
235 return osx_to_win32_hresult(FFCreateDevice(service
, ret
));
238 static CFMutableDictionaryRef
creates_osx_device_match(int usage
)
240 CFMutableDictionaryRef result
;
242 result
= CFDictionaryCreateMutable( kCFAllocatorDefault
, 0,
243 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
247 int number
= kHIDPage_GenericDesktop
;
248 CFNumberRef pageCFNumberRef
= CFNumberCreate( kCFAllocatorDefault
,
249 kCFNumberIntType
, &number
);
251 if ( pageCFNumberRef
)
253 CFNumberRef usageCFNumberRef
;
255 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsagePageKey
),
257 CFRelease( pageCFNumberRef
);
259 usageCFNumberRef
= CFNumberCreate( kCFAllocatorDefault
,
260 kCFNumberIntType
, &usage
);
261 if ( usageCFNumberRef
)
263 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsageKey
),
265 CFRelease( usageCFNumberRef
);
269 ERR("CFNumberCreate() failed.\n");
275 ERR("CFNumberCreate failed.\n");
281 ERR("CFDictionaryCreateMutable failed.\n");
288 static CFIndex
find_top_level(IOHIDDeviceRef tIOHIDDeviceRef
, CFArrayRef topLevels
)
290 CFArrayRef gElementCFArrayRef
;
293 if (!tIOHIDDeviceRef
)
296 gElementCFArrayRef
= IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef
, NULL
, 0);
298 if (gElementCFArrayRef
)
300 CFIndex idx
, cnt
= CFArrayGetCount(gElementCFArrayRef
);
301 for (idx
=0; idx
<cnt
; idx
++)
303 IOHIDElementRef tIOHIDElementRef
= (IOHIDElementRef
)CFArrayGetValueAtIndex(gElementCFArrayRef
, idx
);
304 int eleType
= IOHIDElementGetType(tIOHIDElementRef
);
306 /* Check for top-level gaming device collections */
307 if (eleType
== kIOHIDElementTypeCollection
&& IOHIDElementGetParent(tIOHIDElementRef
) == 0)
309 int tUsagePage
= IOHIDElementGetUsagePage(tIOHIDElementRef
);
310 int tUsage
= IOHIDElementGetUsage(tIOHIDElementRef
);
312 if (tUsagePage
== kHIDPage_GenericDesktop
&&
313 (tUsage
== kHIDUsage_GD_Joystick
|| tUsage
== kHIDUsage_GD_GamePad
))
315 CFArrayAppendValue((CFMutableArrayRef
)topLevels
, tIOHIDElementRef
);
324 static void get_element_children(IOHIDElementRef tElement
, CFArrayRef childElements
)
327 CFArrayRef tElementChildrenArray
= IOHIDElementGetChildren(tElement
);
329 cnt
= CFArrayGetCount(tElementChildrenArray
);
333 /* Either add the element to the array or grab its children */
334 for (idx
=0; idx
<cnt
; idx
++)
336 IOHIDElementRef tChildElementRef
;
338 tChildElementRef
= (IOHIDElementRef
)CFArrayGetValueAtIndex(tElementChildrenArray
, idx
);
339 if (IOHIDElementGetType(tChildElementRef
) == kIOHIDElementTypeCollection
)
340 get_element_children(tChildElementRef
, childElements
);
342 CFArrayAppendValue((CFMutableArrayRef
)childElements
, tChildElementRef
);
346 static int find_osx_devices(void)
349 CFMutableDictionaryRef result
;
353 gIOHIDManagerRef
= IOHIDManagerCreate( kCFAllocatorDefault
, 0L );
354 tIOReturn
= IOHIDManagerOpen( gIOHIDManagerRef
, 0L);
355 if ( kIOReturnSuccess
!= tIOReturn
)
357 ERR("Couldn't open IOHIDManager.\n");
361 matching
= CFArrayCreateMutable( kCFAllocatorDefault
, 0,
362 &kCFTypeArrayCallBacks
);
364 /* build matching dictionary */
365 result
= creates_osx_device_match(kHIDUsage_GD_Joystick
);
371 CFArrayAppendValue( ( CFMutableArrayRef
)matching
, result
);
372 result
= creates_osx_device_match(kHIDUsage_GD_GamePad
);
378 CFArrayAppendValue( ( CFMutableArrayRef
)matching
, result
);
380 IOHIDManagerSetDeviceMatchingMultiple( gIOHIDManagerRef
, matching
);
381 devset
= IOHIDManagerCopyDevices( gIOHIDManagerRef
);
384 CFIndex countDevices
, countCollections
, idx
;
385 CFArrayRef gDevices
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
386 CFSetApplyFunction(devset
, CFSetApplierFunctionCopyToCFArray
, (void*)gDevices
);
388 countDevices
= CFArrayGetCount(gDevices
);
390 gCollections
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
394 countCollections
= 0;
395 for (idx
= 0; idx
< countDevices
; idx
++)
398 IOHIDDeviceRef tDevice
;
400 tDevice
= (IOHIDDeviceRef
) CFArrayGetValueAtIndex(gDevices
, idx
);
401 tTop
= find_top_level(tDevice
, gCollections
);
402 countCollections
+= tTop
;
407 TRACE("found %i device(s), %i collection(s)\n",(int)countDevices
,(int)countCollections
);
408 return (int)countCollections
;
413 static int get_osx_device_name(int id
, char *name
, int length
)
416 IOHIDDeviceRef tIOHIDDeviceRef
;
418 tIOHIDDeviceRef
= get_device_ref(id
);
423 if (!tIOHIDDeviceRef
)
426 str
= IOHIDDeviceGetProperty(tIOHIDDeviceRef
, CFSTR( kIOHIDProductKey
));
429 CFIndex len
= CFStringGetLength(str
);
432 CFStringGetCString(str
,name
,length
,kCFStringEncodingASCII
);
441 static void insert_sort_button(int header
, IOHIDElementRef tIOHIDElementRef
,
442 CFMutableArrayRef elementCFArrayRef
, int index
,
445 IOHIDElementRef targetElement
;
448 CFArraySetValueAtIndex(elementCFArrayRef
, header
+index
, NULL
);
449 targetElement
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( elementCFArrayRef
, header
+target
);
450 if (targetElement
== NULL
)
452 CFArraySetValueAtIndex(elementCFArrayRef
, header
+target
,tIOHIDElementRef
);
455 usage
= IOHIDElementGetUsage( targetElement
);
456 usage
--; /* usage 1 based index */
458 insert_sort_button(header
, targetElement
, elementCFArrayRef
, target
, usage
);
459 CFArraySetValueAtIndex(elementCFArrayRef
, header
+target
,tIOHIDElementRef
);
462 static void get_osx_device_elements(JoystickImpl
*device
, int axis_map
[8])
464 IOHIDElementRef tIOHIDElementRef
;
465 CFArrayRef gElementCFArrayRef
;
471 device
->elementCFArrayRef
= NULL
;
476 tIOHIDElementRef
= (IOHIDElementRef
)CFArrayGetValueAtIndex(gCollections
, device
->id
);
478 if (!tIOHIDElementRef
)
481 gElementCFArrayRef
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
482 get_element_children(tIOHIDElementRef
, gElementCFArrayRef
);
484 if (gElementCFArrayRef
)
486 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
487 /* build our element array in the order that dinput expects */
488 device
->elementCFArrayRef
= CFArrayCreateMutable(NULL
,0,NULL
);
490 for ( idx
= 0; idx
< cnt
; idx
++ )
492 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
493 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
496 case kIOHIDElementTypeInput_Button
:
498 int usagePage
= IOHIDElementGetUsagePage( tIOHIDElementRef
);
499 if (usagePage
!= kHIDPage_Button
)
501 /* avoid strange elements found on the 360 controller */
507 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
+buttons
), tIOHIDElementRef
);
512 case kIOHIDElementTypeInput_Axis
:
514 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
518 case kIOHIDElementTypeInput_Misc
:
520 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
523 case kHIDUsage_GD_Hatswitch
:
525 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
), tIOHIDElementRef
);
529 case kHIDUsage_GD_Slider
:
533 /* fallthrough, sliders are axis */
537 case kHIDUsage_GD_Rx
:
538 case kHIDUsage_GD_Ry
:
539 case kHIDUsage_GD_Rz
:
541 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
542 axis_map
[axes
]=usage
;
547 FIXME("Unhandled usage %i\n",usage
);
552 FIXME("Unhandled type %i\n",eleType
);
557 device
->generic
.devcaps
.dwAxes
= axes
;
558 device
->generic
.devcaps
.dwButtons
= buttons
;
559 device
->generic
.devcaps
.dwPOVs
= povs
;
561 /* Sort buttons into correct order */
562 for (buttons
= 0; buttons
< device
->generic
.devcaps
.dwButtons
; buttons
++)
564 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elementCFArrayRef
, axes
+povs
+buttons
);
565 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
566 usage
--; /* usage is 1 indexed we need 0 indexed */
567 if (usage
== buttons
)
570 insert_sort_button(axes
+povs
, tIOHIDElementRef
, device
->elementCFArrayRef
,buttons
,usage
);
574 static void get_osx_device_elements_props(JoystickImpl
*device
)
576 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
578 if (gElementCFArrayRef
)
580 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
582 for ( idx
= 0; idx
< cnt
; idx
++ )
584 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
586 device
->generic
.props
[idx
].lDevMin
= IOHIDElementGetLogicalMin(tIOHIDElementRef
);
587 device
->generic
.props
[idx
].lDevMax
= IOHIDElementGetLogicalMax(tIOHIDElementRef
);
588 device
->generic
.props
[idx
].lMin
= 0;
589 device
->generic
.props
[idx
].lMax
= 0xffff;
590 device
->generic
.props
[idx
].lDeadZone
= 0;
591 device
->generic
.props
[idx
].lSaturation
= 0;
596 static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface
)
598 JoystickImpl
*device
= impl_from_IDirectInputDevice8A(iface
);
599 IOHIDElementRef tIOHIDTopElementRef
;
600 IOHIDDeviceRef tIOHIDDeviceRef
;
601 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
603 TRACE("polling device %i\n",device
->id
);
608 tIOHIDTopElementRef
= (IOHIDElementRef
) CFArrayGetValueAtIndex(gCollections
, device
->id
);
609 tIOHIDDeviceRef
= IOHIDElementGetDevice(tIOHIDTopElementRef
);
611 if (!tIOHIDDeviceRef
)
614 if (gElementCFArrayRef
)
620 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
622 for ( idx
= 0; idx
< cnt
; idx
++ )
624 IOHIDValueRef valueRef
;
625 int val
, oldVal
, newVal
;
626 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
627 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
631 case kIOHIDElementTypeInput_Button
:
634 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
635 val
= IOHIDValueGetIntegerValue(valueRef
);
636 newVal
= val
? 0x80 : 0x0;
637 oldVal
= device
->generic
.js
.rgbButtons
[button_idx
];
638 device
->generic
.js
.rgbButtons
[button_idx
] = newVal
;
639 if (oldVal
!= newVal
)
641 inst_id
= DIDFT_MAKEINSTANCE(button_idx
) | DIDFT_PSHBUTTON
;
642 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
647 case kIOHIDElementTypeInput_Misc
:
649 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
652 case kHIDUsage_GD_Hatswitch
:
654 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
655 val
= IOHIDValueGetIntegerValue(valueRef
);
656 oldVal
= device
->generic
.js
.rgdwPOV
[pov_idx
];
661 device
->generic
.js
.rgdwPOV
[pov_idx
] = newVal
;
662 if (oldVal
!= newVal
)
664 inst_id
= DIDFT_MAKEINSTANCE(pov_idx
) | DIDFT_POV
;
665 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
673 case kHIDUsage_GD_Rx
:
674 case kHIDUsage_GD_Ry
:
675 case kHIDUsage_GD_Rz
:
676 case kHIDUsage_GD_Slider
:
680 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
681 val
= IOHIDValueGetIntegerValue(valueRef
);
682 newVal
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
687 oldVal
= device
->generic
.js
.lX
;
688 device
->generic
.js
.lX
= newVal
;
692 oldVal
= device
->generic
.js
.lY
;
693 device
->generic
.js
.lY
= newVal
;
697 oldVal
= device
->generic
.js
.lZ
;
698 device
->generic
.js
.lZ
= newVal
;
700 case kHIDUsage_GD_Rx
:
702 oldVal
= device
->generic
.js
.lRx
;
703 device
->generic
.js
.lRx
= newVal
;
705 case kHIDUsage_GD_Ry
:
707 oldVal
= device
->generic
.js
.lRy
;
708 device
->generic
.js
.lRy
= newVal
;
710 case kHIDUsage_GD_Rz
:
712 oldVal
= device
->generic
.js
.lRz
;
713 device
->generic
.js
.lRz
= newVal
;
715 case kHIDUsage_GD_Slider
:
716 wine_obj
= 6 + slider_idx
;
717 oldVal
= device
->generic
.js
.rglSlider
[slider_idx
];
718 device
->generic
.js
.rglSlider
[slider_idx
] = newVal
;
722 if ((wine_obj
!= -1) &&
725 inst_id
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
726 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
732 FIXME("unhandled usage %i\n",usage
);
737 FIXME("Unhandled type %i\n",eleType
);
743 static INT
find_joystick_devices(void)
745 static INT joystick_devices_count
= -1;
747 if (joystick_devices_count
!= -1) return joystick_devices_count
;
749 joystick_devices_count
= find_osx_devices();
751 return joystick_devices_count
;
754 static HRESULT
joydev_enum_deviceA(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
, DWORD version
, int id
)
756 if (id
>= find_joystick_devices()) return E_FAIL
;
758 if ((dwDevType
== 0) ||
759 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
760 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800)))
762 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
763 IOHIDDeviceRef device
= get_device_ref(id
);
766 if(get_ff(device
, NULL
) != S_OK
)
769 /* Return joystick */
770 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
771 lpddi
->guidInstance
.Data3
= id
;
772 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
773 /* we only support traditional joysticks for now */
774 if (version
>= 0x0800)
775 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
777 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
778 sprintf(lpddi
->tszInstanceName
, "Joystick %d", id
);
780 /* get the device name */
781 get_osx_device_name(id
, lpddi
->tszProductName
, MAX_PATH
);
783 lpddi
->guidFFDriver
= GUID_NULL
;
790 static HRESULT
joydev_enum_deviceW(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEW lpddi
, DWORD version
, int id
)
795 if (id
>= find_joystick_devices()) return E_FAIL
;
797 if ((dwDevType
== 0) ||
798 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
799 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800))) {
800 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
801 IOHIDDeviceRef device
= get_device_ref(id
);
804 if(get_ff(device
, NULL
) != S_OK
)
807 /* Return joystick */
808 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
809 lpddi
->guidInstance
.Data3
= id
;
810 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
811 /* we only support traditional joysticks for now */
812 if (version
>= 0x0800)
813 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
815 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
816 sprintf(friendly
, "Joystick %d", id
);
817 MultiByteToWideChar(CP_ACP
, 0, friendly
, -1, lpddi
->tszInstanceName
, MAX_PATH
);
818 /* get the device name */
819 get_osx_device_name(id
, name
, MAX_PATH
);
821 MultiByteToWideChar(CP_ACP
, 0, name
, -1, lpddi
->tszProductName
, MAX_PATH
);
822 lpddi
->guidFFDriver
= GUID_NULL
;
829 static const char *osx_ff_axis_name(UInt8 axis
)
840 sprintf(ret
, "%u", (unsigned int)axis
);
844 static HRESULT
alloc_device(REFGUID rguid
, IDirectInputImpl
*dinput
,
845 JoystickImpl
**pdev
, unsigned short index
)
848 IOHIDDeviceRef device
;
849 JoystickImpl
* newDevice
;
852 LPDIDATAFORMAT df
= NULL
;
854 int axis_map
[8]; /* max axes */
855 int slider_count
= 0;
856 FFCAPABILITIES ffcaps
;
858 TRACE("%s %p %p %hu\n", debugstr_guid(rguid
), dinput
, pdev
, index
);
860 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(JoystickImpl
));
861 if (newDevice
== 0) {
862 WARN("out of memory\n");
864 return DIERR_OUTOFMEMORY
;
867 newDevice
->id
= index
;
869 newDevice
->generic
.guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
870 newDevice
->generic
.guidInstance
.Data3
= index
;
871 newDevice
->generic
.guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
872 newDevice
->generic
.joy_polldev
= poll_osx_device_state
;
874 /* get the device name */
875 get_osx_device_name(index
, name
, MAX_PATH
);
876 TRACE("Name %s\n",name
);
878 /* copy the device name */
879 newDevice
->generic
.name
= HeapAlloc(GetProcessHeap(),0,strlen(name
) + 1);
880 strcpy(newDevice
->generic
.name
, name
);
882 list_init(&newDevice
->effects
);
883 device
= get_device_ref(index
);
884 if(get_ff(device
, &newDevice
->ff
) == S_OK
){
885 newDevice
->generic
.devcaps
.dwFlags
|= DIDC_FORCEFEEDBACK
;
887 hr
= FFDeviceGetForceFeedbackCapabilities(newDevice
->ff
, &ffcaps
);
889 TRACE("FF Capabilities:\n");
890 TRACE("\tsupportedEffects: 0x%x\n", (unsigned int)ffcaps
.supportedEffects
);
891 TRACE("\temulatedEffects: 0x%x\n", (unsigned int)ffcaps
.emulatedEffects
);
892 TRACE("\tsubType: 0x%x\n", (unsigned int)ffcaps
.subType
);
893 TRACE("\tnumFfAxes: %u\n", (unsigned int)ffcaps
.numFfAxes
);
894 TRACE("\tffAxes: [");
895 for(i
= 0; i
< ffcaps
.numFfAxes
; ++i
){
896 TRACE("%s", osx_ff_axis_name(ffcaps
.ffAxes
[i
]));
897 if(i
< ffcaps
.numFfAxes
- 1)
901 TRACE("\tstorageCapacity: %u\n", (unsigned int)ffcaps
.storageCapacity
);
902 TRACE("\tplaybackCapacity: %u\n", (unsigned int)ffcaps
.playbackCapacity
);
905 hr
= FFDeviceSendForceFeedbackCommand(newDevice
->ff
, FFSFFC_RESET
);
907 WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n", hr
);
909 hr
= FFDeviceSendForceFeedbackCommand(newDevice
->ff
, FFSFFC_SETACTUATORSON
);
911 WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr
);
914 memset(axis_map
, 0, sizeof(axis_map
));
915 get_osx_device_elements(newDevice
, axis_map
);
917 TRACE("%i axes %i buttons %i povs\n",newDevice
->generic
.devcaps
.dwAxes
,newDevice
->generic
.devcaps
.dwButtons
,newDevice
->generic
.devcaps
.dwPOVs
);
919 if (newDevice
->generic
.devcaps
.dwButtons
> 128)
921 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice
->generic
.devcaps
.dwButtons
);
922 newDevice
->generic
.devcaps
.dwButtons
= 128;
925 newDevice
->generic
.base
.IDirectInputDevice8A_iface
.lpVtbl
= &JoystickAvt
;
926 newDevice
->generic
.base
.IDirectInputDevice8W_iface
.lpVtbl
= &JoystickWvt
;
927 newDevice
->generic
.base
.ref
= 1;
928 newDevice
->generic
.base
.dinput
= dinput
;
929 newDevice
->generic
.base
.guid
= *rguid
;
930 InitializeCriticalSection(&newDevice
->generic
.base
.crit
);
931 newDevice
->generic
.base
.crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": JoystickImpl*->generic.base.crit");
933 /* Create copy of default data format */
934 if (!(df
= HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2
.dwSize
))) goto FAILED
;
935 memcpy(df
, &c_dfDIJoystick2
, c_dfDIJoystick2
.dwSize
);
937 df
->dwNumObjs
= newDevice
->generic
.devcaps
.dwAxes
+ newDevice
->generic
.devcaps
.dwPOVs
+ newDevice
->generic
.devcaps
.dwButtons
;
938 if (!(df
->rgodf
= HeapAlloc(GetProcessHeap(), 0, df
->dwNumObjs
* df
->dwObjSize
))) goto FAILED
;
940 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwAxes
; i
++)
945 case kHIDUsage_GD_X
: wine_obj
= 0; break;
946 case kHIDUsage_GD_Y
: wine_obj
= 1; break;
947 case kHIDUsage_GD_Z
: wine_obj
= 2; break;
948 case kHIDUsage_GD_Rx
: wine_obj
= 3; break;
949 case kHIDUsage_GD_Ry
: wine_obj
= 4; break;
950 case kHIDUsage_GD_Rz
: wine_obj
= 5; break;
951 case kHIDUsage_GD_Slider
:
952 wine_obj
= 6 + slider_count
;
956 if (wine_obj
< 0 ) continue;
958 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[wine_obj
], df
->dwObjSize
);
959 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
962 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwPOVs
; i
++)
964 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 8], df
->dwObjSize
);
965 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_POV
;
968 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwButtons
; i
++)
970 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 12], df
->dwObjSize
);
971 df
->rgodf
[idx
].pguid
= &GUID_Button
;
972 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_PSHBUTTON
;
974 newDevice
->generic
.base
.data_format
.wine_df
= df
;
976 /* initialize default properties */
977 get_osx_device_elements_props(newDevice
);
979 IDirectInput_AddRef(&newDevice
->generic
.base
.dinput
->IDirectInput7A_iface
);
981 EnterCriticalSection(&dinput
->crit
);
982 list_add_tail(&dinput
->devices_list
, &newDevice
->generic
.base
.entry
);
983 LeaveCriticalSection(&dinput
->crit
);
985 newDevice
->generic
.devcaps
.dwSize
= sizeof(newDevice
->generic
.devcaps
);
986 newDevice
->generic
.devcaps
.dwFlags
|= DIDC_ATTACHED
;
987 if (newDevice
->generic
.base
.dinput
->dwVersion
>= 0x0800)
988 newDevice
->generic
.devcaps
.dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
990 newDevice
->generic
.devcaps
.dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
991 newDevice
->generic
.devcaps
.dwFFSamplePeriod
= 0;
992 newDevice
->generic
.devcaps
.dwFFMinTimeResolution
= 0;
993 newDevice
->generic
.devcaps
.dwFirmwareRevision
= 0;
994 newDevice
->generic
.devcaps
.dwHardwareRevision
= 0;
995 newDevice
->generic
.devcaps
.dwFFDriverVersion
= 0;
997 if (TRACE_ON(dinput
)) {
998 _dump_DIDATAFORMAT(newDevice
->generic
.base
.data_format
.wine_df
);
999 _dump_DIDEVCAPS(&newDevice
->generic
.devcaps
);
1007 hr
= DIERR_OUTOFMEMORY
;
1008 if (df
) HeapFree(GetProcessHeap(), 0, df
->rgodf
);
1009 HeapFree(GetProcessHeap(), 0, df
);
1010 release_DataFormat(&newDevice
->generic
.base
.data_format
);
1011 HeapFree(GetProcessHeap(),0,newDevice
->generic
.name
);
1012 HeapFree(GetProcessHeap(),0,newDevice
);
1018 /******************************************************************************
1019 * get_joystick_index : Get the joystick index from a given GUID
1021 static unsigned short get_joystick_index(REFGUID guid
)
1023 GUID wine_joystick
= DInput_Wine_OsX_Joystick_GUID
;
1024 GUID dev_guid
= *guid
;
1026 wine_joystick
.Data3
= 0;
1029 /* for the standard joystick GUID use index 0 */
1030 if(IsEqualGUID(&GUID_Joystick
,guid
)) return 0;
1032 /* for the wine joystick GUIDs use the index stored in Data3 */
1033 if(IsEqualGUID(&wine_joystick
, &dev_guid
)) return guid
->Data3
;
1038 static HRESULT
joydev_create_device(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPVOID
*pdev
, int unicode
)
1040 unsigned short index
;
1041 int joystick_devices_count
;
1043 TRACE("%p %s %s %p %i\n", dinput
, debugstr_guid(rguid
), debugstr_guid(riid
), pdev
, unicode
);
1046 if ((joystick_devices_count
= find_joystick_devices()) == 0)
1047 return DIERR_DEVICENOTREG
;
1049 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
1050 joystick_devices_count
&& index
< joystick_devices_count
)
1057 else if (IsEqualGUID(&IID_IDirectInputDeviceA
, riid
) ||
1058 IsEqualGUID(&IID_IDirectInputDevice2A
, riid
) ||
1059 IsEqualGUID(&IID_IDirectInputDevice7A
, riid
) ||
1060 IsEqualGUID(&IID_IDirectInputDevice8A
, riid
))
1064 else if (IsEqualGUID(&IID_IDirectInputDeviceW
, riid
) ||
1065 IsEqualGUID(&IID_IDirectInputDevice2W
, riid
) ||
1066 IsEqualGUID(&IID_IDirectInputDevice7W
, riid
) ||
1067 IsEqualGUID(&IID_IDirectInputDevice8W
, riid
))
1073 WARN("no interface\n");
1074 return DIERR_NOINTERFACE
;
1077 hr
= alloc_device(rguid
, dinput
, &This
, index
);
1078 if (!This
) return hr
;
1081 *pdev
= &This
->generic
.base
.IDirectInputDevice8W_iface
;
1083 *pdev
= &This
->generic
.base
.IDirectInputDevice8A_iface
;
1087 return DIERR_DEVICENOTREG
;
1090 static CFUUIDRef
effect_win_to_mac(const GUID
*effect
)
1093 if(IsEqualGUID(&GUID_##X, effect)) \
1094 return kFFEffectType_##X##_ID;
1095 DO_MAP(ConstantForce
)
1101 DO_MAP(SawtoothDown
)
1108 WARN("Unknown effect GUID! %s\n", debugstr_guid(effect
));
1112 static HRESULT WINAPI
JoystickWImpl_CreateEffect(IDirectInputDevice8W
*iface
,
1113 const GUID
*type
, const DIEFFECT
*params
, IDirectInputEffect
**out
,
1116 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1120 TRACE("%p %s %p %p %p\n", iface
, debugstr_guid(type
), params
, out
, outer
);
1121 dump_DIEFFECT(params
, type
, 0);
1124 TRACE("No force feedback support\n");
1130 WARN("aggregation not implemented\n");
1132 effect
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
1133 effect
->IDirectInputEffect_iface
.lpVtbl
= &EffectVtbl
;
1135 effect
->guid
= *type
;
1136 effect
->device
= This
;
1138 /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
1139 hr
= osx_to_win32_hresult(FFDeviceCreateEffect(This
->ff
,
1140 effect_win_to_mac(type
), (FFEFFECT
*)params
, &effect
->effect
));
1142 WARN("FFDeviceCreateEffect failed: %08x\n", hr
);
1143 HeapFree(GetProcessHeap(), 0, effect
);
1147 list_add_tail(&This
->effects
, &effect
->entry
);
1148 *out
= &effect
->IDirectInputEffect_iface
;
1150 TRACE("allocated effect: %p\n", effect
);
1155 static HRESULT WINAPI
JoystickAImpl_CreateEffect(IDirectInputDevice8A
*iface
,
1156 const GUID
*type
, const DIEFFECT
*params
, IDirectInputEffect
**out
,
1159 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1161 TRACE("%p %s %p %p %p\n", iface
, debugstr_guid(type
), params
, out
, outer
);
1163 return JoystickWImpl_CreateEffect(&This
->generic
.base
.IDirectInputDevice8W_iface
,
1164 type
, params
, out
, outer
);
1167 const struct dinput_device joystick_osx_device
= {
1168 "Wine OS X joystick driver",
1169 joydev_enum_deviceA
,
1170 joydev_enum_deviceW
,
1171 joydev_create_device
1174 static const IDirectInputDevice8AVtbl JoystickAvt
=
1176 IDirectInputDevice2AImpl_QueryInterface
,
1177 IDirectInputDevice2AImpl_AddRef
,
1178 IDirectInputDevice2AImpl_Release
,
1179 JoystickAGenericImpl_GetCapabilities
,
1180 IDirectInputDevice2AImpl_EnumObjects
,
1181 JoystickAGenericImpl_GetProperty
,
1182 JoystickAGenericImpl_SetProperty
,
1183 IDirectInputDevice2AImpl_Acquire
,
1184 IDirectInputDevice2AImpl_Unacquire
,
1185 JoystickAGenericImpl_GetDeviceState
,
1186 IDirectInputDevice2AImpl_GetDeviceData
,
1187 IDirectInputDevice2AImpl_SetDataFormat
,
1188 IDirectInputDevice2AImpl_SetEventNotification
,
1189 IDirectInputDevice2AImpl_SetCooperativeLevel
,
1190 JoystickAGenericImpl_GetObjectInfo
,
1191 JoystickAGenericImpl_GetDeviceInfo
,
1192 IDirectInputDevice2AImpl_RunControlPanel
,
1193 IDirectInputDevice2AImpl_Initialize
,
1194 JoystickAImpl_CreateEffect
,
1195 IDirectInputDevice2AImpl_EnumEffects
,
1196 IDirectInputDevice2AImpl_GetEffectInfo
,
1197 IDirectInputDevice2AImpl_GetForceFeedbackState
,
1198 IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
1199 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
1200 IDirectInputDevice2AImpl_Escape
,
1201 JoystickAGenericImpl_Poll
,
1202 IDirectInputDevice2AImpl_SendDeviceData
,
1203 IDirectInputDevice7AImpl_EnumEffectsInFile
,
1204 IDirectInputDevice7AImpl_WriteEffectToFile
,
1205 JoystickAGenericImpl_BuildActionMap
,
1206 JoystickAGenericImpl_SetActionMap
,
1207 IDirectInputDevice8AImpl_GetImageInfo
1210 static const IDirectInputDevice8WVtbl JoystickWvt
=
1212 IDirectInputDevice2WImpl_QueryInterface
,
1213 IDirectInputDevice2WImpl_AddRef
,
1214 IDirectInputDevice2WImpl_Release
,
1215 JoystickWGenericImpl_GetCapabilities
,
1216 IDirectInputDevice2WImpl_EnumObjects
,
1217 JoystickWGenericImpl_GetProperty
,
1218 JoystickWGenericImpl_SetProperty
,
1219 IDirectInputDevice2WImpl_Acquire
,
1220 IDirectInputDevice2WImpl_Unacquire
,
1221 JoystickWGenericImpl_GetDeviceState
,
1222 IDirectInputDevice2WImpl_GetDeviceData
,
1223 IDirectInputDevice2WImpl_SetDataFormat
,
1224 IDirectInputDevice2WImpl_SetEventNotification
,
1225 IDirectInputDevice2WImpl_SetCooperativeLevel
,
1226 JoystickWGenericImpl_GetObjectInfo
,
1227 JoystickWGenericImpl_GetDeviceInfo
,
1228 IDirectInputDevice2WImpl_RunControlPanel
,
1229 IDirectInputDevice2WImpl_Initialize
,
1230 JoystickWImpl_CreateEffect
,
1231 IDirectInputDevice2WImpl_EnumEffects
,
1232 IDirectInputDevice2WImpl_GetEffectInfo
,
1233 IDirectInputDevice2WImpl_GetForceFeedbackState
,
1234 IDirectInputDevice2WImpl_SendForceFeedbackCommand
,
1235 IDirectInputDevice2WImpl_EnumCreatedEffectObjects
,
1236 IDirectInputDevice2WImpl_Escape
,
1237 JoystickWGenericImpl_Poll
,
1238 IDirectInputDevice2WImpl_SendDeviceData
,
1239 IDirectInputDevice7WImpl_EnumEffectsInFile
,
1240 IDirectInputDevice7WImpl_WriteEffectToFile
,
1241 JoystickWGenericImpl_BuildActionMap
,
1242 JoystickWGenericImpl_SetActionMap
,
1243 IDirectInputDevice8WImpl_GetImageInfo
1246 static HRESULT WINAPI
effect_QueryInterface(IDirectInputEffect
*iface
,
1247 const GUID
*guid
, void **out
)
1249 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1251 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), out
);
1253 if(IsEqualIID(guid
, &IID_IDirectInputEffect
)){
1255 IDirectInputEffect_AddRef(iface
);
1259 return E_NOINTERFACE
;
1262 static ULONG WINAPI
effect_AddRef(IDirectInputEffect
*iface
)
1264 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1265 ULONG ref
= InterlockedIncrement(&This
->ref
);
1266 TRACE("%p, ref is now: %u\n", This
, ref
);
1270 static ULONG WINAPI
effect_Release(IDirectInputEffect
*iface
)
1272 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1273 ULONG ref
= InterlockedDecrement(&This
->ref
);
1274 TRACE("%p, ref is now: %u\n", This
, ref
);
1277 list_remove(&This
->entry
);
1278 FFDeviceReleaseEffect(This
->device
->ff
, This
->effect
);
1279 HeapFree(GetProcessHeap(), 0, This
);
1285 static HRESULT WINAPI
effect_Initialize(IDirectInputEffect
*iface
, HINSTANCE hinst
,
1286 DWORD version
, const GUID
*guid
)
1288 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1289 TRACE("%p %p 0x%x, %s\n", This
, hinst
, version
, debugstr_guid(guid
));
1293 static HRESULT WINAPI
effect_GetEffectGuid(IDirectInputEffect
*iface
, GUID
*out
)
1295 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1296 TRACE("%p %p\n", This
, out
);
1301 static HRESULT WINAPI
effect_GetParameters(IDirectInputEffect
*iface
,
1302 DIEFFECT
*effect
, DWORD flags
)
1304 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1305 TRACE("%p %p 0x%x\n", This
, effect
, flags
);
1306 return osx_to_win32_hresult(FFEffectGetParameters(This
->effect
, (FFEFFECT
*)effect
, flags
));
1309 static HRESULT WINAPI
effect_SetParameters(IDirectInputEffect
*iface
,
1310 const DIEFFECT
*effect
, DWORD flags
)
1312 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1313 TRACE("%p %p 0x%x\n", This
, effect
, flags
);
1314 dump_DIEFFECT(effect
, &This
->guid
, flags
);
1315 return osx_to_win32_hresult(FFEffectSetParameters(This
->effect
, (FFEFFECT
*)effect
, flags
));
1318 static HRESULT WINAPI
effect_Start(IDirectInputEffect
*iface
, DWORD iterations
,
1321 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1322 TRACE("%p 0x%x 0x%x\n", This
, iterations
, flags
);
1323 return osx_to_win32_hresult(FFEffectStart(This
->effect
, iterations
, flags
));
1326 static HRESULT WINAPI
effect_Stop(IDirectInputEffect
*iface
)
1328 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1329 TRACE("%p\n", This
);
1330 return osx_to_win32_hresult(FFEffectStop(This
->effect
));
1333 static HRESULT WINAPI
effect_GetEffectStatus(IDirectInputEffect
*iface
, DWORD
*flags
)
1335 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1336 TRACE("%p %p\n", This
, flags
);
1337 return osx_to_win32_hresult(FFEffectGetEffectStatus(This
->effect
, (UInt32
*)flags
));
1340 static HRESULT WINAPI
effect_Download(IDirectInputEffect
*iface
)
1342 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1343 TRACE("%p\n", This
);
1344 return osx_to_win32_hresult(FFEffectDownload(This
->effect
));
1347 static HRESULT WINAPI
effect_Unload(IDirectInputEffect
*iface
)
1349 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1350 TRACE("%p\n", This
);
1351 return osx_to_win32_hresult(FFEffectUnload(This
->effect
));
1354 static HRESULT WINAPI
effect_Escape(IDirectInputEffect
*iface
, DIEFFESCAPE
*escape
)
1356 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1357 TRACE("%p %p\n", This
, escape
);
1358 return osx_to_win32_hresult(FFEffectEscape(This
->effect
, (FFEFFESCAPE
*)escape
));
1361 static const IDirectInputEffectVtbl EffectVtbl
= {
1362 effect_QueryInterface
,
1366 effect_GetEffectGuid
,
1367 effect_GetParameters
,
1368 effect_SetParameters
,
1371 effect_GetEffectStatus
,
1377 #else /* HAVE_IOHIDMANAGERCREATE */
1379 const struct dinput_device joystick_osx_device
= {
1380 "Wine OS X joystick driver",
1386 #endif /* HAVE_IOHIDMANAGERCREATE */