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 hid_manager
= NULL
;
99 static CFMutableArrayRef device_main_elements
= NULL
;
101 typedef struct JoystickImpl JoystickImpl
;
102 static const IDirectInputDevice8AVtbl JoystickAvt
;
103 static const IDirectInputDevice8WVtbl JoystickWvt
;
107 struct JoystickGenericImpl generic
;
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 device_main_element
;
187 IOHIDDeviceRef hid_device
;
189 if (!device_main_elements
|| id
>= CFArrayGetCount(device_main_elements
))
192 device_main_element
= (IOHIDElementRef
)CFArrayGetValueAtIndex(device_main_elements
, id
);
193 if (!device_main_element
)
195 ERR("Invalid Element requested %i\n",id
);
199 hid_device
= IOHIDElementGetDevice(device_main_element
);
202 ERR("Invalid Device requested %i\n",id
);
209 static HRESULT
get_ff(IOHIDDeviceRef device
, FFDeviceObjectReference
*ret
)
211 io_service_t service
;
212 CFMutableDictionaryRef matching
;
213 CFTypeRef location_id
;
215 matching
= IOServiceMatching(kIOHIDDeviceKey
);
217 WARN("IOServiceMatching failed, force feedback disabled\n");
218 return DIERR_DEVICENOTREG
;
221 location_id
= IOHIDDeviceGetProperty(device
, CFSTR(kIOHIDLocationIDKey
));
224 WARN("IOHIDDeviceGetProperty failed, force feedback disabled\n");
225 return DIERR_DEVICENOTREG
;
228 CFDictionaryAddValue(matching
, CFSTR(kIOHIDLocationIDKey
), location_id
);
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
create_osx_device_match(int usage
)
240 CFMutableDictionaryRef result
;
242 result
= CFDictionaryCreateMutable( kCFAllocatorDefault
, 0,
243 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
247 int number
= kHIDPage_GenericDesktop
;
248 CFNumberRef page
= CFNumberCreate( kCFAllocatorDefault
,
249 kCFNumberIntType
, &number
);
253 CFNumberRef cf_usage
;
255 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsagePageKey
), page
);
258 cf_usage
= CFNumberCreate( kCFAllocatorDefault
,
259 kCFNumberIntType
, &usage
);
262 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsageKey
), cf_usage
);
263 CFRelease( cf_usage
);
267 ERR("CFNumberCreate() failed.\n");
273 ERR("CFNumberCreate failed.\n");
279 ERR("CFDictionaryCreateMutable failed.\n");
286 static CFIndex
find_top_level(IOHIDDeviceRef hid_device
, CFMutableArrayRef main_elements
)
294 elements
= IOHIDDeviceCopyMatchingElements(hid_device
, NULL
, 0);
298 CFIndex idx
, cnt
= CFArrayGetCount(elements
);
299 for (idx
=0; idx
<cnt
; idx
++)
301 IOHIDElementRef element
= (IOHIDElementRef
)CFArrayGetValueAtIndex(elements
, idx
);
302 int type
= IOHIDElementGetType(element
);
304 /* Check for top-level gaming device collections */
305 if (type
== kIOHIDElementTypeCollection
&& IOHIDElementGetParent(element
) == 0)
307 int usage_page
= IOHIDElementGetUsagePage(element
);
308 int usage
= IOHIDElementGetUsage(element
);
310 if (usage_page
== kHIDPage_GenericDesktop
&&
311 (usage
== kHIDUsage_GD_Joystick
|| usage
== kHIDUsage_GD_GamePad
))
313 CFArrayAppendValue(main_elements
, element
);
322 static void get_element_children(IOHIDElementRef element
, CFMutableArrayRef all_children
)
325 CFArrayRef element_children
= IOHIDElementGetChildren(element
);
327 cnt
= CFArrayGetCount(element_children
);
329 /* Either add the element to the array or grab its children */
330 for (idx
=0; idx
<cnt
; idx
++)
332 IOHIDElementRef child
;
334 child
= (IOHIDElementRef
)CFArrayGetValueAtIndex(element_children
, idx
);
335 if (IOHIDElementGetType(child
) == kIOHIDElementTypeCollection
)
336 get_element_children(child
, all_children
);
338 CFArrayAppendValue(all_children
, child
);
342 static int find_osx_devices(void)
344 CFMutableDictionaryRef result
;
346 CFMutableArrayRef matching
;
348 hid_manager
= IOHIDManagerCreate( kCFAllocatorDefault
, 0L );
349 if (IOHIDManagerOpen( hid_manager
, 0 ) != kIOReturnSuccess
)
351 ERR("Couldn't open IOHIDManager.\n");
355 matching
= CFArrayCreateMutable( kCFAllocatorDefault
, 0,
356 &kCFTypeArrayCallBacks
);
358 /* build matching dictionary */
359 result
= create_osx_device_match(kHIDUsage_GD_Joystick
);
365 CFArrayAppendValue( matching
, result
);
366 result
= create_osx_device_match(kHIDUsage_GD_GamePad
);
372 CFArrayAppendValue( matching
, result
);
374 IOHIDManagerSetDeviceMatchingMultiple( hid_manager
, matching
);
375 devset
= IOHIDManagerCopyDevices( hid_manager
);
378 CFIndex num_devices
, num_main_elements
, idx
;
379 CFMutableArrayRef devices
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
380 CFSetApplyFunction(devset
, CFSetApplierFunctionCopyToCFArray
, devices
);
382 num_devices
= CFArrayGetCount(devices
);
384 device_main_elements
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
385 if (!device_main_elements
)
388 num_main_elements
= 0;
389 for (idx
= 0; idx
< num_devices
; idx
++)
392 IOHIDDeviceRef hid_device
;
394 hid_device
= (IOHIDDeviceRef
) CFArrayGetValueAtIndex(devices
, idx
);
395 top
= find_top_level(hid_device
, device_main_elements
);
396 num_main_elements
+= top
;
401 TRACE("found %i device(s), %i collection(s)\n",(int)num_devices
,(int)num_main_elements
);
402 return (int)num_main_elements
;
407 static int get_osx_device_name(int id
, char *name
, int length
)
410 IOHIDDeviceRef hid_device
;
412 hid_device
= get_device_ref(id
);
420 str
= IOHIDDeviceGetProperty(hid_device
, CFSTR( kIOHIDProductKey
));
423 CFIndex len
= CFStringGetLength(str
);
426 CFStringGetCString(str
,name
,length
,kCFStringEncodingASCII
);
435 static CFComparisonResult
button_usage_comparator(const void *val1
, const void *val2
, void *context
)
437 IOHIDElementRef element1
= (IOHIDElementRef
)val1
, element2
= (IOHIDElementRef
)val2
;
438 int usage1
= IOHIDElementGetUsage(element1
), usage2
= IOHIDElementGetUsage(element2
);
441 return kCFCompareLessThan
;
443 return kCFCompareGreaterThan
;
444 return kCFCompareEqualTo
;
447 static void get_osx_device_elements(JoystickImpl
*device
, int axis_map
[8])
449 IOHIDElementRef device_main_element
;
450 CFMutableArrayRef elements
;
453 device
->elements
= NULL
;
455 if (!device_main_elements
|| device
->id
>= CFArrayGetCount(device_main_elements
))
458 device_main_element
= (IOHIDElementRef
)CFArrayGetValueAtIndex(device_main_elements
, device
->id
);
460 if (!device_main_element
)
463 elements
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
464 get_element_children(device_main_element
, elements
);
468 CFIndex idx
, cnt
= CFArrayGetCount( elements
);
469 CFMutableArrayRef axes
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
470 CFMutableArrayRef buttons
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
471 CFMutableArrayRef povs
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
473 for ( idx
= 0; idx
< cnt
; idx
++ )
475 IOHIDElementRef element
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( elements
, idx
);
476 int type
= IOHIDElementGetType( element
);
479 case kIOHIDElementTypeInput_Button
:
481 int usage_page
= IOHIDElementGetUsagePage( element
);
482 if (usage_page
!= kHIDPage_Button
)
484 /* avoid strange elements found on the 360 controller */
488 if (CFArrayGetCount(buttons
) < 128)
489 CFArrayAppendValue(buttons
, element
);
492 case kIOHIDElementTypeInput_Axis
:
494 CFArrayAppendValue(axes
, element
);
497 case kIOHIDElementTypeInput_Misc
:
499 uint32_t usage
= IOHIDElementGetUsage( element
);
502 case kHIDUsage_GD_Hatswitch
:
504 CFArrayAppendValue(povs
, element
);
507 case kHIDUsage_GD_Slider
:
511 /* fallthrough, sliders are axis */
515 case kHIDUsage_GD_Rx
:
516 case kHIDUsage_GD_Ry
:
517 case kHIDUsage_GD_Rz
:
519 axis_map
[CFArrayGetCount(axes
)]=usage
;
520 CFArrayAppendValue(axes
, element
);
524 FIXME("Unhandled usage %i\n",usage
);
529 FIXME("Unhandled type %i\n",type
);
533 /* Sort buttons into correct order */
534 CFArraySortValues(buttons
, CFRangeMake(0, CFArrayGetCount(buttons
)), button_usage_comparator
, NULL
);
536 device
->generic
.devcaps
.dwAxes
= CFArrayGetCount(axes
);
537 device
->generic
.devcaps
.dwButtons
= CFArrayGetCount(buttons
);
538 device
->generic
.devcaps
.dwPOVs
= CFArrayGetCount(povs
);
540 /* build our element array in the order that dinput expects */
541 CFArrayAppendArray(axes
, povs
, CFRangeMake(0, device
->generic
.devcaps
.dwPOVs
));
542 CFArrayAppendArray(axes
, buttons
, CFRangeMake(0, device
->generic
.devcaps
.dwButtons
));
543 device
->elements
= axes
;
552 device
->generic
.devcaps
.dwAxes
= 0;
553 device
->generic
.devcaps
.dwButtons
= 0;
554 device
->generic
.devcaps
.dwPOVs
= 0;
558 static void get_osx_device_elements_props(JoystickImpl
*device
)
560 if (device
->elements
)
562 CFIndex idx
, cnt
= CFArrayGetCount( device
->elements
);
564 for ( idx
= 0; idx
< cnt
; idx
++ )
566 IOHIDElementRef element
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elements
, idx
);
568 device
->generic
.props
[idx
].lDevMin
= IOHIDElementGetLogicalMin(element
);
569 device
->generic
.props
[idx
].lDevMax
= IOHIDElementGetLogicalMax(element
);
570 device
->generic
.props
[idx
].lMin
= 0;
571 device
->generic
.props
[idx
].lMax
= 0xffff;
572 device
->generic
.props
[idx
].lDeadZone
= 0;
573 device
->generic
.props
[idx
].lSaturation
= 0;
578 static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface
)
580 JoystickImpl
*device
= impl_from_IDirectInputDevice8A(iface
);
581 IOHIDElementRef device_main_element
;
582 IOHIDDeviceRef hid_device
;
584 TRACE("polling device %i\n",device
->id
);
586 if (!device_main_elements
|| device
->id
>= CFArrayGetCount(device_main_elements
))
589 device_main_element
= (IOHIDElementRef
) CFArrayGetValueAtIndex(device_main_elements
, device
->id
);
590 hid_device
= IOHIDElementGetDevice(device_main_element
);
595 if (device
->elements
)
601 CFIndex idx
, cnt
= CFArrayGetCount( device
->elements
);
603 for ( idx
= 0; idx
< cnt
; idx
++ )
605 IOHIDValueRef valueRef
;
606 int val
, oldVal
, newVal
;
607 IOHIDElementRef element
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elements
, idx
);
608 int type
= IOHIDElementGetType( element
);
612 case kIOHIDElementTypeInput_Button
:
615 IOHIDDeviceGetValue(hid_device
, element
, &valueRef
);
616 val
= IOHIDValueGetIntegerValue(valueRef
);
617 newVal
= val
? 0x80 : 0x0;
618 oldVal
= device
->generic
.js
.rgbButtons
[button_idx
];
619 device
->generic
.js
.rgbButtons
[button_idx
] = newVal
;
620 if (oldVal
!= newVal
)
622 inst_id
= DIDFT_MAKEINSTANCE(button_idx
) | DIDFT_PSHBUTTON
;
623 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
628 case kIOHIDElementTypeInput_Misc
:
630 uint32_t usage
= IOHIDElementGetUsage( element
);
633 case kHIDUsage_GD_Hatswitch
:
635 IOHIDDeviceGetValue(hid_device
, element
, &valueRef
);
636 val
= IOHIDValueGetIntegerValue(valueRef
);
637 oldVal
= device
->generic
.js
.rgdwPOV
[pov_idx
];
642 device
->generic
.js
.rgdwPOV
[pov_idx
] = newVal
;
643 if (oldVal
!= newVal
)
645 inst_id
= DIDFT_MAKEINSTANCE(pov_idx
) | DIDFT_POV
;
646 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
654 case kHIDUsage_GD_Rx
:
655 case kHIDUsage_GD_Ry
:
656 case kHIDUsage_GD_Rz
:
657 case kHIDUsage_GD_Slider
:
661 IOHIDDeviceGetValue(hid_device
, element
, &valueRef
);
662 val
= IOHIDValueGetIntegerValue(valueRef
);
663 newVal
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
668 oldVal
= device
->generic
.js
.lX
;
669 device
->generic
.js
.lX
= newVal
;
673 oldVal
= device
->generic
.js
.lY
;
674 device
->generic
.js
.lY
= newVal
;
678 oldVal
= device
->generic
.js
.lZ
;
679 device
->generic
.js
.lZ
= newVal
;
681 case kHIDUsage_GD_Rx
:
683 oldVal
= device
->generic
.js
.lRx
;
684 device
->generic
.js
.lRx
= newVal
;
686 case kHIDUsage_GD_Ry
:
688 oldVal
= device
->generic
.js
.lRy
;
689 device
->generic
.js
.lRy
= newVal
;
691 case kHIDUsage_GD_Rz
:
693 oldVal
= device
->generic
.js
.lRz
;
694 device
->generic
.js
.lRz
= newVal
;
696 case kHIDUsage_GD_Slider
:
697 wine_obj
= 6 + slider_idx
;
698 oldVal
= device
->generic
.js
.rglSlider
[slider_idx
];
699 device
->generic
.js
.rglSlider
[slider_idx
] = newVal
;
703 if ((wine_obj
!= -1) &&
706 inst_id
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
707 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
713 FIXME("unhandled usage %i\n",usage
);
718 FIXME("Unhandled type %i\n",type
);
724 static INT
find_joystick_devices(void)
726 static INT joystick_devices_count
= -1;
728 if (joystick_devices_count
!= -1) return joystick_devices_count
;
730 joystick_devices_count
= find_osx_devices();
732 return joystick_devices_count
;
735 static HRESULT
joydev_enum_deviceA(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
, DWORD version
, int id
)
737 if (id
>= find_joystick_devices()) return E_FAIL
;
739 if ((dwDevType
== 0) ||
740 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
741 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800)))
743 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
744 IOHIDDeviceRef device
= get_device_ref(id
);
747 if(get_ff(device
, NULL
) != S_OK
)
750 /* Return joystick */
751 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
752 lpddi
->guidInstance
.Data3
= id
;
753 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
754 /* we only support traditional joysticks for now */
755 if (version
>= 0x0800)
756 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
758 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
759 sprintf(lpddi
->tszInstanceName
, "Joystick %d", id
);
761 /* get the device name */
762 get_osx_device_name(id
, lpddi
->tszProductName
, MAX_PATH
);
764 lpddi
->guidFFDriver
= GUID_NULL
;
771 static HRESULT
joydev_enum_deviceW(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEW lpddi
, DWORD version
, int id
)
776 if (id
>= find_joystick_devices()) return E_FAIL
;
778 if ((dwDevType
== 0) ||
779 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
780 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800))) {
781 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
782 IOHIDDeviceRef device
= get_device_ref(id
);
785 if(get_ff(device
, NULL
) != S_OK
)
788 /* Return joystick */
789 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
790 lpddi
->guidInstance
.Data3
= id
;
791 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
792 /* we only support traditional joysticks for now */
793 if (version
>= 0x0800)
794 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
796 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
797 sprintf(friendly
, "Joystick %d", id
);
798 MultiByteToWideChar(CP_ACP
, 0, friendly
, -1, lpddi
->tszInstanceName
, MAX_PATH
);
799 /* get the device name */
800 get_osx_device_name(id
, name
, MAX_PATH
);
802 MultiByteToWideChar(CP_ACP
, 0, name
, -1, lpddi
->tszProductName
, MAX_PATH
);
803 lpddi
->guidFFDriver
= GUID_NULL
;
810 static const char *osx_ff_axis_name(UInt8 axis
)
821 sprintf(ret
, "%u", (unsigned int)axis
);
825 static BOOL
osx_axis_has_ff(FFCAPABILITIES
*ffcaps
, UInt8 axis
)
828 for(i
= 0; i
< ffcaps
->numFfAxes
; ++i
)
829 if(ffcaps
->ffAxes
[i
] == axis
)
834 static HRESULT
alloc_device(REFGUID rguid
, IDirectInputImpl
*dinput
,
835 JoystickImpl
**pdev
, unsigned short index
)
838 IOHIDDeviceRef device
;
839 JoystickImpl
* newDevice
;
842 LPDIDATAFORMAT df
= NULL
;
844 int axis_map
[8]; /* max axes */
845 int slider_count
= 0;
846 FFCAPABILITIES ffcaps
;
848 TRACE("%s %p %p %hu\n", debugstr_guid(rguid
), dinput
, pdev
, index
);
850 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(JoystickImpl
));
851 if (newDevice
== 0) {
852 WARN("out of memory\n");
854 return DIERR_OUTOFMEMORY
;
857 newDevice
->id
= index
;
859 newDevice
->generic
.guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
860 newDevice
->generic
.guidInstance
.Data3
= index
;
861 newDevice
->generic
.guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
862 newDevice
->generic
.joy_polldev
= poll_osx_device_state
;
864 /* get the device name */
865 get_osx_device_name(index
, name
, MAX_PATH
);
866 TRACE("Name %s\n",name
);
868 /* copy the device name */
869 newDevice
->generic
.name
= HeapAlloc(GetProcessHeap(),0,strlen(name
) + 1);
870 strcpy(newDevice
->generic
.name
, name
);
872 list_init(&newDevice
->effects
);
873 device
= get_device_ref(index
);
874 if(get_ff(device
, &newDevice
->ff
) == S_OK
){
875 newDevice
->generic
.devcaps
.dwFlags
|= DIDC_FORCEFEEDBACK
;
877 hr
= FFDeviceGetForceFeedbackCapabilities(newDevice
->ff
, &ffcaps
);
879 TRACE("FF Capabilities:\n");
880 TRACE("\tsupportedEffects: 0x%x\n", (unsigned int)ffcaps
.supportedEffects
);
881 TRACE("\temulatedEffects: 0x%x\n", (unsigned int)ffcaps
.emulatedEffects
);
882 TRACE("\tsubType: 0x%x\n", (unsigned int)ffcaps
.subType
);
883 TRACE("\tnumFfAxes: %u\n", (unsigned int)ffcaps
.numFfAxes
);
884 TRACE("\tffAxes: [");
885 for(i
= 0; i
< ffcaps
.numFfAxes
; ++i
){
886 TRACE("%s", osx_ff_axis_name(ffcaps
.ffAxes
[i
]));
887 if(i
< ffcaps
.numFfAxes
- 1)
891 TRACE("\tstorageCapacity: %u\n", (unsigned int)ffcaps
.storageCapacity
);
892 TRACE("\tplaybackCapacity: %u\n", (unsigned int)ffcaps
.playbackCapacity
);
895 hr
= FFDeviceSendForceFeedbackCommand(newDevice
->ff
, FFSFFC_RESET
);
897 WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n", hr
);
899 hr
= FFDeviceSendForceFeedbackCommand(newDevice
->ff
, FFSFFC_SETACTUATORSON
);
901 WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr
);
904 memset(axis_map
, 0, sizeof(axis_map
));
905 get_osx_device_elements(newDevice
, axis_map
);
907 TRACE("%i axes %i buttons %i povs\n",newDevice
->generic
.devcaps
.dwAxes
,newDevice
->generic
.devcaps
.dwButtons
,newDevice
->generic
.devcaps
.dwPOVs
);
909 if (newDevice
->generic
.devcaps
.dwButtons
> 128)
911 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice
->generic
.devcaps
.dwButtons
);
912 newDevice
->generic
.devcaps
.dwButtons
= 128;
915 newDevice
->generic
.base
.IDirectInputDevice8A_iface
.lpVtbl
= &JoystickAvt
;
916 newDevice
->generic
.base
.IDirectInputDevice8W_iface
.lpVtbl
= &JoystickWvt
;
917 newDevice
->generic
.base
.ref
= 1;
918 newDevice
->generic
.base
.dinput
= dinput
;
919 newDevice
->generic
.base
.guid
= *rguid
;
920 InitializeCriticalSection(&newDevice
->generic
.base
.crit
);
921 newDevice
->generic
.base
.crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": JoystickImpl*->generic.base.crit");
923 /* Create copy of default data format */
924 if (!(df
= HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2
.dwSize
))) goto FAILED
;
925 memcpy(df
, &c_dfDIJoystick2
, c_dfDIJoystick2
.dwSize
);
927 df
->dwNumObjs
= newDevice
->generic
.devcaps
.dwAxes
+ newDevice
->generic
.devcaps
.dwPOVs
+ newDevice
->generic
.devcaps
.dwButtons
;
928 if (!(df
->rgodf
= HeapAlloc(GetProcessHeap(), 0, df
->dwNumObjs
* df
->dwObjSize
))) goto FAILED
;
930 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwAxes
; i
++)
938 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_X
);
942 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_Y
);
946 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_Z
);
948 case kHIDUsage_GD_Rx
:
950 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_RX
);
952 case kHIDUsage_GD_Ry
:
954 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_RY
);
956 case kHIDUsage_GD_Rz
:
958 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_RZ
);
960 case kHIDUsage_GD_Slider
:
961 wine_obj
= 6 + slider_count
;
962 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_SLIDER(slider_count
));
966 if (wine_obj
< 0 ) continue;
968 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[wine_obj
], df
->dwObjSize
);
969 df
->rgodf
[idx
].dwType
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
971 df
->rgodf
[idx
].dwFlags
|= DIDOI_FFACTUATOR
;
975 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwPOVs
; i
++)
977 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 8], df
->dwObjSize
);
978 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_POV
;
981 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwButtons
; i
++)
983 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 12], df
->dwObjSize
);
984 df
->rgodf
[idx
].pguid
= &GUID_Button
;
985 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_PSHBUTTON
;
987 newDevice
->generic
.base
.data_format
.wine_df
= df
;
989 /* initialize default properties */
990 get_osx_device_elements_props(newDevice
);
992 IDirectInput_AddRef(&newDevice
->generic
.base
.dinput
->IDirectInput7A_iface
);
994 EnterCriticalSection(&dinput
->crit
);
995 list_add_tail(&dinput
->devices_list
, &newDevice
->generic
.base
.entry
);
996 LeaveCriticalSection(&dinput
->crit
);
998 newDevice
->generic
.devcaps
.dwSize
= sizeof(newDevice
->generic
.devcaps
);
999 newDevice
->generic
.devcaps
.dwFlags
|= DIDC_ATTACHED
;
1000 if (newDevice
->generic
.base
.dinput
->dwVersion
>= 0x0800)
1001 newDevice
->generic
.devcaps
.dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
1003 newDevice
->generic
.devcaps
.dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
1004 newDevice
->generic
.devcaps
.dwFFSamplePeriod
= 0;
1005 newDevice
->generic
.devcaps
.dwFFMinTimeResolution
= 0;
1006 newDevice
->generic
.devcaps
.dwFirmwareRevision
= 0;
1007 newDevice
->generic
.devcaps
.dwHardwareRevision
= 0;
1008 newDevice
->generic
.devcaps
.dwFFDriverVersion
= 0;
1010 if (TRACE_ON(dinput
)) {
1011 _dump_DIDATAFORMAT(newDevice
->generic
.base
.data_format
.wine_df
);
1012 _dump_DIDEVCAPS(&newDevice
->generic
.devcaps
);
1020 hr
= DIERR_OUTOFMEMORY
;
1021 if (df
) HeapFree(GetProcessHeap(), 0, df
->rgodf
);
1022 HeapFree(GetProcessHeap(), 0, df
);
1023 release_DataFormat(&newDevice
->generic
.base
.data_format
);
1024 HeapFree(GetProcessHeap(),0,newDevice
->generic
.name
);
1025 HeapFree(GetProcessHeap(),0,newDevice
);
1031 /******************************************************************************
1032 * get_joystick_index : Get the joystick index from a given GUID
1034 static unsigned short get_joystick_index(REFGUID guid
)
1036 GUID wine_joystick
= DInput_Wine_OsX_Joystick_GUID
;
1037 GUID dev_guid
= *guid
;
1039 wine_joystick
.Data3
= 0;
1042 /* for the standard joystick GUID use index 0 */
1043 if(IsEqualGUID(&GUID_Joystick
,guid
)) return 0;
1045 /* for the wine joystick GUIDs use the index stored in Data3 */
1046 if(IsEqualGUID(&wine_joystick
, &dev_guid
)) return guid
->Data3
;
1051 static HRESULT
joydev_create_device(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPVOID
*pdev
, int unicode
)
1053 unsigned short index
;
1054 int joystick_devices_count
;
1056 TRACE("%p %s %s %p %i\n", dinput
, debugstr_guid(rguid
), debugstr_guid(riid
), pdev
, unicode
);
1059 if ((joystick_devices_count
= find_joystick_devices()) == 0)
1060 return DIERR_DEVICENOTREG
;
1062 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
1063 joystick_devices_count
&& index
< joystick_devices_count
)
1070 else if (IsEqualGUID(&IID_IDirectInputDeviceA
, riid
) ||
1071 IsEqualGUID(&IID_IDirectInputDevice2A
, riid
) ||
1072 IsEqualGUID(&IID_IDirectInputDevice7A
, riid
) ||
1073 IsEqualGUID(&IID_IDirectInputDevice8A
, riid
))
1077 else if (IsEqualGUID(&IID_IDirectInputDeviceW
, riid
) ||
1078 IsEqualGUID(&IID_IDirectInputDevice2W
, riid
) ||
1079 IsEqualGUID(&IID_IDirectInputDevice7W
, riid
) ||
1080 IsEqualGUID(&IID_IDirectInputDevice8W
, riid
))
1086 WARN("no interface\n");
1087 return DIERR_NOINTERFACE
;
1090 hr
= alloc_device(rguid
, dinput
, &This
, index
);
1091 if (!This
) return hr
;
1094 *pdev
= &This
->generic
.base
.IDirectInputDevice8W_iface
;
1096 *pdev
= &This
->generic
.base
.IDirectInputDevice8A_iface
;
1100 return DIERR_DEVICENOTREG
;
1103 static HRESULT
osx_set_autocenter(JoystickImpl
*This
,
1104 const DIPROPDWORD
*header
)
1109 return DIERR_UNSUPPORTED
;
1111 hr
= osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This
->ff
, FFPROP_AUTOCENTER
, &v
));
1112 TRACE("returning: %08x\n", hr
);
1116 static HRESULT
osx_set_ffgain(JoystickImpl
*This
, const DIPROPDWORD
*header
)
1121 return DIERR_UNSUPPORTED
;
1123 hr
= osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This
->ff
, FFPROP_FFGAIN
, &v
));
1124 TRACE("returning: %08x\n", hr
);
1128 static HRESULT WINAPI
JoystickWImpl_SetProperty(IDirectInputDevice8W
*iface
,
1129 const GUID
*prop
, const DIPROPHEADER
*header
)
1131 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1133 TRACE("%p %s %p\n", This
, debugstr_guid(prop
), header
);
1135 switch(LOWORD(prop
))
1137 case (DWORD_PTR
)DIPROP_AUTOCENTER
:
1138 return osx_set_autocenter(This
, (const DIPROPDWORD
*)header
);
1139 case (DWORD_PTR
)DIPROP_FFGAIN
:
1140 return osx_set_ffgain(This
, (const DIPROPDWORD
*)header
);
1143 return JoystickWGenericImpl_SetProperty(iface
, prop
, header
);
1146 static HRESULT WINAPI
JoystickAImpl_SetProperty(IDirectInputDevice8A
*iface
,
1147 const GUID
*prop
, const DIPROPHEADER
*header
)
1149 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1151 TRACE("%p %s %p\n", This
, debugstr_guid(prop
), header
);
1153 switch(LOWORD(prop
))
1155 case (DWORD_PTR
)DIPROP_AUTOCENTER
:
1156 return osx_set_autocenter(This
, (const DIPROPDWORD
*)header
);
1157 case (DWORD_PTR
)DIPROP_FFGAIN
:
1158 return osx_set_ffgain(This
, (const DIPROPDWORD
*)header
);
1161 return JoystickAGenericImpl_SetProperty(iface
, prop
, header
);
1164 static CFUUIDRef
effect_win_to_mac(const GUID
*effect
)
1167 if(IsEqualGUID(&GUID_##X, effect)) \
1168 return kFFEffectType_##X##_ID;
1169 DO_MAP(ConstantForce
)
1175 DO_MAP(SawtoothDown
)
1182 WARN("Unknown effect GUID! %s\n", debugstr_guid(effect
));
1186 static HRESULT WINAPI
JoystickWImpl_CreateEffect(IDirectInputDevice8W
*iface
,
1187 const GUID
*type
, const DIEFFECT
*params
, IDirectInputEffect
**out
,
1190 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1194 TRACE("%p %s %p %p %p\n", iface
, debugstr_guid(type
), params
, out
, outer
);
1195 dump_DIEFFECT(params
, type
, 0);
1198 TRACE("No force feedback support\n");
1204 WARN("aggregation not implemented\n");
1206 effect
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
1207 effect
->IDirectInputEffect_iface
.lpVtbl
= &EffectVtbl
;
1209 effect
->guid
= *type
;
1210 effect
->device
= This
;
1212 /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
1213 hr
= osx_to_win32_hresult(FFDeviceCreateEffect(This
->ff
,
1214 effect_win_to_mac(type
), (FFEFFECT
*)params
, &effect
->effect
));
1216 WARN("FFDeviceCreateEffect failed: %08x\n", hr
);
1217 HeapFree(GetProcessHeap(), 0, effect
);
1221 list_add_tail(&This
->effects
, &effect
->entry
);
1222 *out
= &effect
->IDirectInputEffect_iface
;
1224 TRACE("allocated effect: %p\n", effect
);
1229 static HRESULT WINAPI
JoystickAImpl_CreateEffect(IDirectInputDevice8A
*iface
,
1230 const GUID
*type
, const DIEFFECT
*params
, IDirectInputEffect
**out
,
1233 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1235 TRACE("%p %s %p %p %p\n", iface
, debugstr_guid(type
), params
, out
, outer
);
1237 return JoystickWImpl_CreateEffect(&This
->generic
.base
.IDirectInputDevice8W_iface
,
1238 type
, params
, out
, outer
);
1241 static HRESULT WINAPI
JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W
*iface
,
1244 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1247 TRACE("%p 0x%x\n", This
, flags
);
1252 hr
= osx_to_win32_hresult(FFDeviceSendForceFeedbackCommand(This
->ff
, flags
));
1254 WARN("FFDeviceSendForceFeedbackCommand failed: %08x\n", hr
);
1261 static HRESULT WINAPI
JoystickAImpl_SendForceFeedbackCommand(IDirectInputDevice8A
*iface
,
1264 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1266 TRACE("%p 0x%x\n", This
, flags
);
1268 return JoystickWImpl_SendForceFeedbackCommand(&This
->generic
.base
.IDirectInputDevice8W_iface
, flags
);
1271 const struct dinput_device joystick_osx_device
= {
1272 "Wine OS X joystick driver",
1273 joydev_enum_deviceA
,
1274 joydev_enum_deviceW
,
1275 joydev_create_device
1278 static const IDirectInputDevice8AVtbl JoystickAvt
=
1280 IDirectInputDevice2AImpl_QueryInterface
,
1281 IDirectInputDevice2AImpl_AddRef
,
1282 IDirectInputDevice2AImpl_Release
,
1283 JoystickAGenericImpl_GetCapabilities
,
1284 IDirectInputDevice2AImpl_EnumObjects
,
1285 JoystickAGenericImpl_GetProperty
,
1286 JoystickAImpl_SetProperty
,
1287 IDirectInputDevice2AImpl_Acquire
,
1288 IDirectInputDevice2AImpl_Unacquire
,
1289 JoystickAGenericImpl_GetDeviceState
,
1290 IDirectInputDevice2AImpl_GetDeviceData
,
1291 IDirectInputDevice2AImpl_SetDataFormat
,
1292 IDirectInputDevice2AImpl_SetEventNotification
,
1293 IDirectInputDevice2AImpl_SetCooperativeLevel
,
1294 JoystickAGenericImpl_GetObjectInfo
,
1295 JoystickAGenericImpl_GetDeviceInfo
,
1296 IDirectInputDevice2AImpl_RunControlPanel
,
1297 IDirectInputDevice2AImpl_Initialize
,
1298 JoystickAImpl_CreateEffect
,
1299 IDirectInputDevice2AImpl_EnumEffects
,
1300 IDirectInputDevice2AImpl_GetEffectInfo
,
1301 IDirectInputDevice2AImpl_GetForceFeedbackState
,
1302 JoystickAImpl_SendForceFeedbackCommand
,
1303 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
1304 IDirectInputDevice2AImpl_Escape
,
1305 JoystickAGenericImpl_Poll
,
1306 IDirectInputDevice2AImpl_SendDeviceData
,
1307 IDirectInputDevice7AImpl_EnumEffectsInFile
,
1308 IDirectInputDevice7AImpl_WriteEffectToFile
,
1309 JoystickAGenericImpl_BuildActionMap
,
1310 JoystickAGenericImpl_SetActionMap
,
1311 IDirectInputDevice8AImpl_GetImageInfo
1314 static const IDirectInputDevice8WVtbl JoystickWvt
=
1316 IDirectInputDevice2WImpl_QueryInterface
,
1317 IDirectInputDevice2WImpl_AddRef
,
1318 IDirectInputDevice2WImpl_Release
,
1319 JoystickWGenericImpl_GetCapabilities
,
1320 IDirectInputDevice2WImpl_EnumObjects
,
1321 JoystickWGenericImpl_GetProperty
,
1322 JoystickWImpl_SetProperty
,
1323 IDirectInputDevice2WImpl_Acquire
,
1324 IDirectInputDevice2WImpl_Unacquire
,
1325 JoystickWGenericImpl_GetDeviceState
,
1326 IDirectInputDevice2WImpl_GetDeviceData
,
1327 IDirectInputDevice2WImpl_SetDataFormat
,
1328 IDirectInputDevice2WImpl_SetEventNotification
,
1329 IDirectInputDevice2WImpl_SetCooperativeLevel
,
1330 JoystickWGenericImpl_GetObjectInfo
,
1331 JoystickWGenericImpl_GetDeviceInfo
,
1332 IDirectInputDevice2WImpl_RunControlPanel
,
1333 IDirectInputDevice2WImpl_Initialize
,
1334 JoystickWImpl_CreateEffect
,
1335 IDirectInputDevice2WImpl_EnumEffects
,
1336 IDirectInputDevice2WImpl_GetEffectInfo
,
1337 IDirectInputDevice2WImpl_GetForceFeedbackState
,
1338 JoystickWImpl_SendForceFeedbackCommand
,
1339 IDirectInputDevice2WImpl_EnumCreatedEffectObjects
,
1340 IDirectInputDevice2WImpl_Escape
,
1341 JoystickWGenericImpl_Poll
,
1342 IDirectInputDevice2WImpl_SendDeviceData
,
1343 IDirectInputDevice7WImpl_EnumEffectsInFile
,
1344 IDirectInputDevice7WImpl_WriteEffectToFile
,
1345 JoystickWGenericImpl_BuildActionMap
,
1346 JoystickWGenericImpl_SetActionMap
,
1347 IDirectInputDevice8WImpl_GetImageInfo
1350 static HRESULT WINAPI
effect_QueryInterface(IDirectInputEffect
*iface
,
1351 const GUID
*guid
, void **out
)
1353 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1355 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), out
);
1357 if(IsEqualIID(guid
, &IID_IDirectInputEffect
)){
1359 IDirectInputEffect_AddRef(iface
);
1363 return E_NOINTERFACE
;
1366 static ULONG WINAPI
effect_AddRef(IDirectInputEffect
*iface
)
1368 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1369 ULONG ref
= InterlockedIncrement(&This
->ref
);
1370 TRACE("%p, ref is now: %u\n", This
, ref
);
1374 static ULONG WINAPI
effect_Release(IDirectInputEffect
*iface
)
1376 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1377 ULONG ref
= InterlockedDecrement(&This
->ref
);
1378 TRACE("%p, ref is now: %u\n", This
, ref
);
1381 list_remove(&This
->entry
);
1382 FFDeviceReleaseEffect(This
->device
->ff
, This
->effect
);
1383 HeapFree(GetProcessHeap(), 0, This
);
1389 static HRESULT WINAPI
effect_Initialize(IDirectInputEffect
*iface
, HINSTANCE hinst
,
1390 DWORD version
, const GUID
*guid
)
1392 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1393 TRACE("%p %p 0x%x, %s\n", This
, hinst
, version
, debugstr_guid(guid
));
1397 static HRESULT WINAPI
effect_GetEffectGuid(IDirectInputEffect
*iface
, GUID
*out
)
1399 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1400 TRACE("%p %p\n", This
, out
);
1405 static HRESULT WINAPI
effect_GetParameters(IDirectInputEffect
*iface
,
1406 DIEFFECT
*effect
, DWORD flags
)
1408 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1409 TRACE("%p %p 0x%x\n", This
, effect
, flags
);
1410 return osx_to_win32_hresult(FFEffectGetParameters(This
->effect
, (FFEFFECT
*)effect
, flags
));
1413 static HRESULT WINAPI
effect_SetParameters(IDirectInputEffect
*iface
,
1414 const DIEFFECT
*effect
, DWORD flags
)
1416 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1417 TRACE("%p %p 0x%x\n", This
, effect
, flags
);
1418 dump_DIEFFECT(effect
, &This
->guid
, flags
);
1419 return osx_to_win32_hresult(FFEffectSetParameters(This
->effect
, (FFEFFECT
*)effect
, flags
));
1422 static HRESULT WINAPI
effect_Start(IDirectInputEffect
*iface
, DWORD iterations
,
1425 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1426 TRACE("%p 0x%x 0x%x\n", This
, iterations
, flags
);
1427 return osx_to_win32_hresult(FFEffectStart(This
->effect
, iterations
, flags
));
1430 static HRESULT WINAPI
effect_Stop(IDirectInputEffect
*iface
)
1432 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1433 TRACE("%p\n", This
);
1434 return osx_to_win32_hresult(FFEffectStop(This
->effect
));
1437 static HRESULT WINAPI
effect_GetEffectStatus(IDirectInputEffect
*iface
, DWORD
*flags
)
1439 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1440 TRACE("%p %p\n", This
, flags
);
1441 return osx_to_win32_hresult(FFEffectGetEffectStatus(This
->effect
, (UInt32
*)flags
));
1444 static HRESULT WINAPI
effect_Download(IDirectInputEffect
*iface
)
1446 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1447 TRACE("%p\n", This
);
1448 return osx_to_win32_hresult(FFEffectDownload(This
->effect
));
1451 static HRESULT WINAPI
effect_Unload(IDirectInputEffect
*iface
)
1453 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1454 TRACE("%p\n", This
);
1455 return osx_to_win32_hresult(FFEffectUnload(This
->effect
));
1458 static HRESULT WINAPI
effect_Escape(IDirectInputEffect
*iface
, DIEFFESCAPE
*escape
)
1460 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1461 TRACE("%p %p\n", This
, escape
);
1462 return osx_to_win32_hresult(FFEffectEscape(This
->effect
, (FFEFFESCAPE
*)escape
));
1465 static const IDirectInputEffectVtbl EffectVtbl
= {
1466 effect_QueryInterface
,
1470 effect_GetEffectGuid
,
1471 effect_GetParameters
,
1472 effect_SetParameters
,
1475 effect_GetEffectStatus
,
1481 #else /* HAVE_IOHIDMANAGERCREATE */
1483 const struct dinput_device joystick_osx_device
= {
1484 "Wine OS X joystick driver",
1490 #endif /* HAVE_IOHIDMANAGERCREATE */