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 CFMutableArrayRef device_main_elements
= NULL
;
100 typedef struct JoystickImpl JoystickImpl
;
101 static const IDirectInputDevice8AVtbl JoystickAvt
;
102 static const IDirectInputDevice8WVtbl JoystickWvt
;
106 struct JoystickGenericImpl generic
;
112 FFDeviceObjectReference ff
;
116 static inline JoystickImpl
*impl_from_IDirectInputDevice8A(IDirectInputDevice8A
*iface
)
118 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface
, IDirectInputDeviceImpl
, IDirectInputDevice8A_iface
),
119 JoystickGenericImpl
, base
), JoystickImpl
, generic
);
121 static inline JoystickImpl
*impl_from_IDirectInputDevice8W(IDirectInputDevice8W
*iface
)
123 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface
, IDirectInputDeviceImpl
, IDirectInputDevice8W_iface
),
124 JoystickGenericImpl
, base
), JoystickImpl
, generic
);
127 typedef struct _EffectImpl
{
128 IDirectInputEffect IDirectInputEffect_iface
;
131 JoystickImpl
*device
;
132 FFEffectObjectReference effect
;
138 static EffectImpl
*impl_from_IDirectInputEffect(IDirectInputEffect
*iface
)
140 return CONTAINING_RECORD(iface
, EffectImpl
, IDirectInputEffect_iface
);
143 static const IDirectInputEffectVtbl EffectVtbl
;
145 static const GUID DInput_Wine_OsX_Joystick_GUID
= { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */
146 0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
149 static HRESULT
osx_to_win32_hresult(HRESULT in
)
151 /* OSX returns 16-bit COM runtime errors, which we should
152 * convert to win32 */
157 return E_OUTOFMEMORY
;
161 return E_NOINTERFACE
;
171 return E_ACCESSDENIED
;
178 static void CFSetApplierFunctionCopyToCFArray(const void *value
, void *context
)
180 CFArrayAppendValue( ( CFMutableArrayRef
) context
, value
);
183 static const char* debugstr_cf(CFTypeRef t
)
188 if (!t
) return "(null)";
190 if (CFGetTypeID(t
) == CFStringGetTypeID())
193 s
= CFCopyDescription(t
);
194 ret
= CFStringGetCStringPtr(s
, kCFStringEncodingUTF8
);
195 if (ret
) ret
= debugstr_a(ret
);
198 const UniChar
* u
= CFStringGetCharactersPtr(s
);
200 ret
= debugstr_wn((const WCHAR
*)u
, CFStringGetLength(s
));
205 int len
= min(CFStringGetLength(s
), sizeof(buf
)/sizeof(buf
[0]));
206 CFStringGetCharacters(s
, CFRangeMake(0, len
), buf
);
207 ret
= debugstr_wn(buf
, len
);
209 if (s
!= t
) CFRelease(s
);
213 static const char* debugstr_device(IOHIDDeviceRef device
)
215 return wine_dbg_sprintf("<IOHIDDevice %p product %s>", device
,
216 debugstr_cf(IOHIDDeviceGetProperty(device
, CFSTR(kIOHIDProductKey
))));
219 static const char* debugstr_element(IOHIDElementRef element
)
221 return wine_dbg_sprintf("<IOHIDElement %p type %d usage %u/%u device %p>", element
,
222 IOHIDElementGetType(element
), IOHIDElementGetUsagePage(element
),
223 IOHIDElementGetUsage(element
), IOHIDElementGetDevice(element
));
226 static IOHIDDeviceRef
get_device_ref(int id
)
228 IOHIDElementRef device_main_element
;
229 IOHIDDeviceRef hid_device
;
231 TRACE("id %d\n", id
);
233 if (!device_main_elements
|| id
>= CFArrayGetCount(device_main_elements
))
236 device_main_element
= (IOHIDElementRef
)CFArrayGetValueAtIndex(device_main_elements
, id
);
237 if (!device_main_element
)
239 ERR("Invalid Element requested %i\n",id
);
243 hid_device
= IOHIDElementGetDevice(device_main_element
);
246 ERR("Invalid Device requested %i\n",id
);
250 TRACE("-> %s\n", debugstr_device(hid_device
));
254 static HRESULT
get_ff(IOHIDDeviceRef device
, FFDeviceObjectReference
*ret
)
256 io_service_t service
;
257 CFMutableDictionaryRef matching
;
258 CFTypeRef location_id
;
261 TRACE("device %s\n", debugstr_device(device
));
263 matching
= IOServiceMatching(kIOHIDDeviceKey
);
265 WARN("IOServiceMatching failed, force feedback disabled\n");
266 return DIERR_DEVICENOTREG
;
269 location_id
= IOHIDDeviceGetProperty(device
, CFSTR(kIOHIDLocationIDKey
));
272 WARN("IOHIDDeviceGetProperty failed, force feedback disabled\n");
273 return DIERR_DEVICENOTREG
;
276 CFDictionaryAddValue(matching
, CFSTR(kIOHIDLocationIDKey
), location_id
);
278 service
= IOServiceGetMatchingService(kIOMasterPortDefault
, matching
);
281 hr
= osx_to_win32_hresult(FFCreateDevice(service
, ret
));
283 hr
= FFIsForceFeedback(service
) == FF_OK
? S_OK
: S_FALSE
;
285 IOObjectRelease(service
);
286 TRACE("-> hr 0x%08x *ret %p\n", hr
, ret
? *ret
: NULL
);
290 static CFMutableDictionaryRef
create_osx_device_match(int usage
)
292 CFMutableDictionaryRef result
;
294 TRACE("usage %d\n", usage
);
296 result
= CFDictionaryCreateMutable( kCFAllocatorDefault
, 0,
297 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
301 int number
= kHIDPage_GenericDesktop
;
302 CFNumberRef page
= CFNumberCreate( kCFAllocatorDefault
,
303 kCFNumberIntType
, &number
);
307 CFNumberRef cf_usage
;
309 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsagePageKey
), page
);
312 cf_usage
= CFNumberCreate( kCFAllocatorDefault
,
313 kCFNumberIntType
, &usage
);
316 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsageKey
), cf_usage
);
317 CFRelease( cf_usage
);
321 ERR("CFNumberCreate() failed.\n");
328 ERR("CFNumberCreate failed.\n");
335 ERR("CFDictionaryCreateMutable failed.\n");
342 static CFIndex
find_top_level(IOHIDDeviceRef hid_device
, CFMutableArrayRef main_elements
)
347 TRACE("hid_device %s\n", debugstr_device(hid_device
));
352 elements
= IOHIDDeviceCopyMatchingElements(hid_device
, NULL
, 0);
356 CFIndex idx
, cnt
= CFArrayGetCount(elements
);
357 for (idx
=0; idx
<cnt
; idx
++)
359 IOHIDElementRef element
= (IOHIDElementRef
)CFArrayGetValueAtIndex(elements
, idx
);
360 int type
= IOHIDElementGetType(element
);
362 TRACE("element %s\n", debugstr_element(element
));
364 /* Check for top-level gaming device collections */
365 if (type
== kIOHIDElementTypeCollection
&& IOHIDElementGetParent(element
) == 0)
367 int usage_page
= IOHIDElementGetUsagePage(element
);
368 int usage
= IOHIDElementGetUsage(element
);
370 if (usage_page
== kHIDPage_GenericDesktop
&&
371 (usage
== kHIDUsage_GD_Joystick
|| usage
== kHIDUsage_GD_GamePad
))
373 CFArrayAppendValue(main_elements
, element
);
381 TRACE("-> total %d\n", (int)total
);
385 static void get_element_children(IOHIDElementRef element
, CFMutableArrayRef all_children
)
388 CFArrayRef element_children
= IOHIDElementGetChildren(element
);
390 TRACE("element %s\n", debugstr_element(element
));
392 cnt
= CFArrayGetCount(element_children
);
394 /* Either add the element to the array or grab its children */
395 for (idx
=0; idx
<cnt
; idx
++)
397 IOHIDElementRef child
;
399 child
= (IOHIDElementRef
)CFArrayGetValueAtIndex(element_children
, idx
);
400 TRACE("child %s\n", debugstr_element(child
));
401 if (IOHIDElementGetType(child
) == kIOHIDElementTypeCollection
)
402 get_element_children(child
, all_children
);
404 CFArrayAppendValue(all_children
, child
);
408 static int find_osx_devices(void)
410 IOHIDManagerRef hid_manager
;
411 CFMutableDictionaryRef result
;
413 CFMutableArrayRef matching
;
417 hid_manager
= IOHIDManagerCreate( kCFAllocatorDefault
, 0L );
418 if (IOHIDManagerOpen( hid_manager
, 0 ) != kIOReturnSuccess
)
420 ERR("Couldn't open IOHIDManager.\n");
421 CFRelease( hid_manager
);
425 matching
= CFArrayCreateMutable( kCFAllocatorDefault
, 0,
426 &kCFTypeArrayCallBacks
);
428 /* build matching dictionary */
429 result
= create_osx_device_match(kHIDUsage_GD_Joystick
);
435 CFArrayAppendValue( matching
, result
);
437 result
= create_osx_device_match(kHIDUsage_GD_GamePad
);
443 CFArrayAppendValue( matching
, result
);
446 IOHIDManagerSetDeviceMatchingMultiple( hid_manager
, matching
);
447 CFRelease( matching
);
448 devset
= IOHIDManagerCopyDevices( hid_manager
);
451 CFIndex num_devices
, num_main_elements
, idx
;
452 CFMutableArrayRef devices
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
453 CFSetApplyFunction(devset
, CFSetApplierFunctionCopyToCFArray
, devices
);
455 num_devices
= CFArrayGetCount(devices
);
457 device_main_elements
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
458 if (!device_main_elements
)
460 CFRelease( devices
);
464 num_main_elements
= 0;
465 for (idx
= 0; idx
< num_devices
; idx
++)
468 IOHIDDeviceRef hid_device
;
470 hid_device
= (IOHIDDeviceRef
) CFArrayGetValueAtIndex(devices
, idx
);
471 TRACE("hid_device %s\n", debugstr_device(hid_device
));
472 top
= find_top_level(hid_device
, device_main_elements
);
473 num_main_elements
+= top
;
478 TRACE("found %i device(s), %i collection(s)\n",(int)num_devices
,(int)num_main_elements
);
479 return (int)num_main_elements
;
483 IOHIDManagerClose( hid_manager
, 0 );
484 CFRelease( hid_manager
);
488 static int get_osx_device_name(int id
, char *name
, int length
)
491 IOHIDDeviceRef hid_device
;
493 hid_device
= get_device_ref(id
);
495 TRACE("id %d hid_device %s\n", id
, debugstr_device(hid_device
));
503 str
= IOHIDDeviceGetProperty(hid_device
, CFSTR( kIOHIDProductKey
));
506 CFIndex len
= CFStringGetLength(str
);
509 CFStringGetCString(str
,name
,length
,kCFStringEncodingASCII
);
518 static CFComparisonResult
button_usage_comparator(const void *val1
, const void *val2
, void *context
)
520 IOHIDElementRef element1
= (IOHIDElementRef
)val1
, element2
= (IOHIDElementRef
)val2
;
521 int usage1
= IOHIDElementGetUsage(element1
), usage2
= IOHIDElementGetUsage(element2
);
524 return kCFCompareLessThan
;
526 return kCFCompareGreaterThan
;
527 return kCFCompareEqualTo
;
530 static void get_osx_device_elements(JoystickImpl
*device
, int axis_map
[8])
532 IOHIDElementRef device_main_element
;
533 CFMutableArrayRef elements
;
536 TRACE("device %p device->id %d\n", device
, device
->id
);
538 device
->elements
= NULL
;
540 if (!device_main_elements
|| device
->id
>= CFArrayGetCount(device_main_elements
))
543 device_main_element
= (IOHIDElementRef
)CFArrayGetValueAtIndex(device_main_elements
, device
->id
);
544 TRACE("device_main_element %s\n", debugstr_element(device_main_element
));
545 if (!device_main_element
)
548 elements
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
549 get_element_children(device_main_element
, elements
);
553 CFIndex idx
, cnt
= CFArrayGetCount( elements
);
554 CFMutableArrayRef axes
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
555 CFMutableArrayRef buttons
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
556 CFMutableArrayRef povs
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
558 for ( idx
= 0; idx
< cnt
; idx
++ )
560 IOHIDElementRef element
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( elements
, idx
);
561 int type
= IOHIDElementGetType( element
);
563 TRACE("element %s\n", debugstr_element(element
));
567 case kIOHIDElementTypeInput_Button
:
569 int usage_page
= IOHIDElementGetUsagePage( element
);
570 TRACE("kIOHIDElementTypeInput_Button usage_page %d\n", usage_page
);
571 if (usage_page
!= kHIDPage_Button
)
573 /* avoid strange elements found on the 360 controller */
577 if (CFArrayGetCount(buttons
) < 128)
578 CFArrayAppendValue(buttons
, element
);
581 case kIOHIDElementTypeInput_Axis
:
583 TRACE("kIOHIDElementTypeInput_Axis\n");
584 CFArrayAppendValue(axes
, element
);
587 case kIOHIDElementTypeInput_Misc
:
589 uint32_t usage
= IOHIDElementGetUsage( element
);
592 case kHIDUsage_GD_Hatswitch
:
594 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
595 CFArrayAppendValue(povs
, element
);
598 case kHIDUsage_GD_Slider
:
602 /* fallthrough, sliders are axis */
606 case kHIDUsage_GD_Rx
:
607 case kHIDUsage_GD_Ry
:
608 case kHIDUsage_GD_Rz
:
610 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_* (%d)\n", usage
);
611 axis_map
[CFArrayGetCount(axes
)]=usage
;
612 CFArrayAppendValue(axes
, element
);
616 FIXME("kIOHIDElementTypeInput_Misc / Unhandled usage %i\n", usage
);
621 FIXME("Unhandled type %i\n",type
);
625 /* Sort buttons into correct order */
626 CFArraySortValues(buttons
, CFRangeMake(0, CFArrayGetCount(buttons
)), button_usage_comparator
, NULL
);
628 device
->generic
.devcaps
.dwAxes
= CFArrayGetCount(axes
);
629 device
->generic
.devcaps
.dwButtons
= CFArrayGetCount(buttons
);
630 device
->generic
.devcaps
.dwPOVs
= CFArrayGetCount(povs
);
632 TRACE("axes %u povs %u buttons %u\n", device
->generic
.devcaps
.dwAxes
, device
->generic
.devcaps
.dwPOVs
,
633 device
->generic
.devcaps
.dwButtons
);
635 /* build our element array in the order that dinput expects */
636 CFArrayAppendArray(axes
, povs
, CFRangeMake(0, device
->generic
.devcaps
.dwPOVs
));
637 CFArrayAppendArray(axes
, buttons
, CFRangeMake(0, device
->generic
.devcaps
.dwButtons
));
638 device
->elements
= axes
;
647 device
->generic
.devcaps
.dwAxes
= 0;
648 device
->generic
.devcaps
.dwButtons
= 0;
649 device
->generic
.devcaps
.dwPOVs
= 0;
653 static void get_osx_device_elements_props(JoystickImpl
*device
)
655 TRACE("device %p\n", device
);
657 if (device
->elements
)
659 CFIndex idx
, cnt
= CFArrayGetCount( device
->elements
);
661 for ( idx
= 0; idx
< cnt
; idx
++ )
663 IOHIDElementRef element
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elements
, idx
);
665 TRACE("element %s\n", debugstr_element(element
));
667 device
->generic
.props
[idx
].lDevMin
= IOHIDElementGetLogicalMin(element
);
668 device
->generic
.props
[idx
].lDevMax
= IOHIDElementGetLogicalMax(element
);
669 device
->generic
.props
[idx
].lMin
= 0;
670 device
->generic
.props
[idx
].lMax
= 0xffff;
671 device
->generic
.props
[idx
].lDeadZone
= 0;
672 device
->generic
.props
[idx
].lSaturation
= 0;
677 static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface
)
679 JoystickImpl
*device
= impl_from_IDirectInputDevice8A(iface
);
680 IOHIDElementRef device_main_element
;
681 IOHIDDeviceRef hid_device
;
683 TRACE("device %p device->id %i\n", device
, device
->id
);
685 if (!device_main_elements
|| device
->id
>= CFArrayGetCount(device_main_elements
))
688 device_main_element
= (IOHIDElementRef
) CFArrayGetValueAtIndex(device_main_elements
, device
->id
);
689 hid_device
= IOHIDElementGetDevice(device_main_element
);
690 TRACE("main element %s hid_device %s\n", debugstr_element(device_main_element
), debugstr_device(hid_device
));
694 if (device
->elements
)
700 CFIndex idx
, cnt
= CFArrayGetCount( device
->elements
);
702 for ( idx
= 0; idx
< cnt
; idx
++ )
704 IOHIDValueRef valueRef
;
705 int val
, oldVal
, newVal
;
706 IOHIDElementRef element
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elements
, idx
);
707 int type
= IOHIDElementGetType( element
);
709 TRACE("element %s\n", debugstr_element(element
));
713 case kIOHIDElementTypeInput_Button
:
714 TRACE("kIOHIDElementTypeInput_Button\n");
717 IOHIDDeviceGetValue(hid_device
, element
, &valueRef
);
718 val
= IOHIDValueGetIntegerValue(valueRef
);
719 newVal
= val
? 0x80 : 0x0;
720 oldVal
= device
->generic
.js
.rgbButtons
[button_idx
];
721 device
->generic
.js
.rgbButtons
[button_idx
] = newVal
;
722 TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef
), val
, oldVal
, newVal
);
723 if (oldVal
!= newVal
)
725 inst_id
= DIDFT_MAKEINSTANCE(button_idx
) | DIDFT_PSHBUTTON
;
726 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
731 case kIOHIDElementTypeInput_Misc
:
733 uint32_t usage
= IOHIDElementGetUsage( element
);
736 case kHIDUsage_GD_Hatswitch
:
738 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
739 IOHIDDeviceGetValue(hid_device
, element
, &valueRef
);
740 val
= IOHIDValueGetIntegerValue(valueRef
);
741 oldVal
= device
->generic
.js
.rgdwPOV
[pov_idx
];
746 device
->generic
.js
.rgdwPOV
[pov_idx
] = newVal
;
747 TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef
), val
, oldVal
, newVal
);
748 if (oldVal
!= newVal
)
750 inst_id
= DIDFT_MAKEINSTANCE(pov_idx
) | DIDFT_POV
;
751 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
759 case kHIDUsage_GD_Rx
:
760 case kHIDUsage_GD_Ry
:
761 case kHIDUsage_GD_Rz
:
762 case kHIDUsage_GD_Slider
:
766 IOHIDDeviceGetValue(hid_device
, element
, &valueRef
);
767 val
= IOHIDValueGetIntegerValue(valueRef
);
768 newVal
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
772 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_X\n");
774 oldVal
= device
->generic
.js
.lX
;
775 device
->generic
.js
.lX
= newVal
;
778 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Y\n");
780 oldVal
= device
->generic
.js
.lY
;
781 device
->generic
.js
.lY
= newVal
;
784 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Z\n");
786 oldVal
= device
->generic
.js
.lZ
;
787 device
->generic
.js
.lZ
= newVal
;
789 case kHIDUsage_GD_Rx
:
790 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rx\n");
792 oldVal
= device
->generic
.js
.lRx
;
793 device
->generic
.js
.lRx
= newVal
;
795 case kHIDUsage_GD_Ry
:
796 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Ry\n");
798 oldVal
= device
->generic
.js
.lRy
;
799 device
->generic
.js
.lRy
= newVal
;
801 case kHIDUsage_GD_Rz
:
802 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rz\n");
804 oldVal
= device
->generic
.js
.lRz
;
805 device
->generic
.js
.lRz
= newVal
;
807 case kHIDUsage_GD_Slider
:
808 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider\n");
809 wine_obj
= 6 + slider_idx
;
810 oldVal
= device
->generic
.js
.rglSlider
[slider_idx
];
811 device
->generic
.js
.rglSlider
[slider_idx
] = newVal
;
815 TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef
), val
, oldVal
, newVal
);
816 if ((wine_obj
!= -1) &&
819 inst_id
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
820 queue_event(iface
,inst_id
,newVal
,GetCurrentTime(),device
->generic
.base
.dinput
->evsequence
++);
826 FIXME("kIOHIDElementTypeInput_Misc / unhandled usage %i\n", usage
);
831 FIXME("Unhandled type %i\n",type
);
837 static INT
find_joystick_devices(void)
839 static INT joystick_devices_count
= -1;
841 if (joystick_devices_count
!= -1) return joystick_devices_count
;
843 joystick_devices_count
= find_osx_devices();
845 return joystick_devices_count
;
848 static HRESULT
joydev_enum_deviceA(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
, DWORD version
, int id
)
850 TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType
, dwFlags
, version
, id
);
852 if (id
>= find_joystick_devices()) return E_FAIL
;
854 if ((dwDevType
== 0) ||
855 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
856 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800)))
858 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
859 IOHIDDeviceRef device
= get_device_ref(id
);
862 if(get_ff(device
, NULL
) != S_OK
)
865 /* Return joystick */
866 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
867 lpddi
->guidInstance
.Data3
= id
;
868 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
869 /* we only support traditional joysticks for now */
870 if (version
>= 0x0800)
871 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
873 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
874 sprintf(lpddi
->tszInstanceName
, "Joystick %d", id
);
876 /* get the device name */
877 get_osx_device_name(id
, lpddi
->tszProductName
, MAX_PATH
);
879 lpddi
->guidFFDriver
= GUID_NULL
;
886 static HRESULT
joydev_enum_deviceW(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEW lpddi
, DWORD version
, int id
)
891 TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType
, dwFlags
, version
, id
);
893 if (id
>= find_joystick_devices()) return E_FAIL
;
895 if ((dwDevType
== 0) ||
896 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
897 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800))) {
898 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
899 IOHIDDeviceRef device
= get_device_ref(id
);
902 if(get_ff(device
, NULL
) != S_OK
)
905 /* Return joystick */
906 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
907 lpddi
->guidInstance
.Data3
= id
;
908 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
909 /* we only support traditional joysticks for now */
910 if (version
>= 0x0800)
911 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
913 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
914 sprintf(friendly
, "Joystick %d", id
);
915 MultiByteToWideChar(CP_ACP
, 0, friendly
, -1, lpddi
->tszInstanceName
, MAX_PATH
);
916 /* get the device name */
917 get_osx_device_name(id
, name
, MAX_PATH
);
919 MultiByteToWideChar(CP_ACP
, 0, name
, -1, lpddi
->tszProductName
, MAX_PATH
);
920 lpddi
->guidFFDriver
= GUID_NULL
;
927 static const char *osx_ff_axis_name(UInt8 axis
)
938 sprintf(ret
, "%u", (unsigned int)axis
);
942 static BOOL
osx_axis_has_ff(FFCAPABILITIES
*ffcaps
, UInt8 axis
)
945 for(i
= 0; i
< ffcaps
->numFfAxes
; ++i
)
946 if(ffcaps
->ffAxes
[i
] == axis
)
951 static HRESULT
alloc_device(REFGUID rguid
, IDirectInputImpl
*dinput
,
952 JoystickImpl
**pdev
, unsigned short index
)
955 IOHIDDeviceRef device
;
956 JoystickImpl
* newDevice
;
959 LPDIDATAFORMAT df
= NULL
;
961 int axis_map
[8]; /* max axes */
962 int slider_count
= 0;
963 FFCAPABILITIES ffcaps
;
965 TRACE("%s %p %p %hu\n", debugstr_guid(rguid
), dinput
, pdev
, index
);
967 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(JoystickImpl
));
968 if (newDevice
== 0) {
969 WARN("out of memory\n");
971 return DIERR_OUTOFMEMORY
;
974 newDevice
->id
= index
;
976 newDevice
->generic
.guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
977 newDevice
->generic
.guidInstance
.Data3
= index
;
978 newDevice
->generic
.guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
979 newDevice
->generic
.joy_polldev
= poll_osx_device_state
;
981 /* get the device name */
982 get_osx_device_name(index
, name
, MAX_PATH
);
983 TRACE("Name %s\n",name
);
985 /* copy the device name */
986 newDevice
->generic
.name
= HeapAlloc(GetProcessHeap(),0,strlen(name
) + 1);
987 strcpy(newDevice
->generic
.name
, name
);
989 list_init(&newDevice
->effects
);
990 device
= get_device_ref(index
);
991 if(get_ff(device
, &newDevice
->ff
) == S_OK
){
992 newDevice
->generic
.devcaps
.dwFlags
|= DIDC_FORCEFEEDBACK
;
994 hr
= FFDeviceGetForceFeedbackCapabilities(newDevice
->ff
, &ffcaps
);
996 TRACE("FF Capabilities:\n");
997 TRACE("\tsupportedEffects: 0x%x\n", (unsigned int)ffcaps
.supportedEffects
);
998 TRACE("\temulatedEffects: 0x%x\n", (unsigned int)ffcaps
.emulatedEffects
);
999 TRACE("\tsubType: 0x%x\n", (unsigned int)ffcaps
.subType
);
1000 TRACE("\tnumFfAxes: %u\n", (unsigned int)ffcaps
.numFfAxes
);
1001 TRACE("\tffAxes: [");
1002 for(i
= 0; i
< ffcaps
.numFfAxes
; ++i
){
1003 TRACE("%s", osx_ff_axis_name(ffcaps
.ffAxes
[i
]));
1004 if(i
< ffcaps
.numFfAxes
- 1)
1008 TRACE("\tstorageCapacity: %u\n", (unsigned int)ffcaps
.storageCapacity
);
1009 TRACE("\tplaybackCapacity: %u\n", (unsigned int)ffcaps
.playbackCapacity
);
1012 hr
= FFDeviceSendForceFeedbackCommand(newDevice
->ff
, FFSFFC_RESET
);
1014 WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n", hr
);
1016 hr
= FFDeviceSendForceFeedbackCommand(newDevice
->ff
, FFSFFC_SETACTUATORSON
);
1018 WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr
);
1021 memset(axis_map
, 0, sizeof(axis_map
));
1022 get_osx_device_elements(newDevice
, axis_map
);
1024 TRACE("%i axes %i buttons %i povs\n",newDevice
->generic
.devcaps
.dwAxes
,newDevice
->generic
.devcaps
.dwButtons
,newDevice
->generic
.devcaps
.dwPOVs
);
1026 if (newDevice
->generic
.devcaps
.dwButtons
> 128)
1028 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice
->generic
.devcaps
.dwButtons
);
1029 newDevice
->generic
.devcaps
.dwButtons
= 128;
1032 newDevice
->generic
.base
.IDirectInputDevice8A_iface
.lpVtbl
= &JoystickAvt
;
1033 newDevice
->generic
.base
.IDirectInputDevice8W_iface
.lpVtbl
= &JoystickWvt
;
1034 newDevice
->generic
.base
.ref
= 1;
1035 newDevice
->generic
.base
.dinput
= dinput
;
1036 newDevice
->generic
.base
.guid
= *rguid
;
1037 InitializeCriticalSection(&newDevice
->generic
.base
.crit
);
1038 newDevice
->generic
.base
.crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": JoystickImpl*->generic.base.crit");
1040 /* Create copy of default data format */
1041 if (!(df
= HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2
.dwSize
))) goto FAILED
;
1042 memcpy(df
, &c_dfDIJoystick2
, c_dfDIJoystick2
.dwSize
);
1044 df
->dwNumObjs
= newDevice
->generic
.devcaps
.dwAxes
+ newDevice
->generic
.devcaps
.dwPOVs
+ newDevice
->generic
.devcaps
.dwButtons
;
1045 if (!(df
->rgodf
= HeapAlloc(GetProcessHeap(), 0, df
->dwNumObjs
* df
->dwObjSize
))) goto FAILED
;
1047 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwAxes
; i
++)
1050 BOOL has_ff
= FALSE
;
1051 switch (axis_map
[i
])
1053 case kHIDUsage_GD_X
:
1055 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_X
);
1057 case kHIDUsage_GD_Y
:
1059 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_Y
);
1061 case kHIDUsage_GD_Z
:
1063 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_Z
);
1065 case kHIDUsage_GD_Rx
:
1067 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_RX
);
1069 case kHIDUsage_GD_Ry
:
1071 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_RY
);
1073 case kHIDUsage_GD_Rz
:
1075 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_RZ
);
1077 case kHIDUsage_GD_Slider
:
1078 wine_obj
= 6 + slider_count
;
1079 has_ff
= (newDevice
->ff
!= 0) && osx_axis_has_ff(&ffcaps
, FFJOFS_SLIDER(slider_count
));
1083 if (wine_obj
< 0 ) continue;
1085 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[wine_obj
], df
->dwObjSize
);
1086 df
->rgodf
[idx
].dwType
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
1088 df
->rgodf
[idx
].dwFlags
|= DIDOI_FFACTUATOR
;
1092 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwPOVs
; i
++)
1094 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 8], df
->dwObjSize
);
1095 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_POV
;
1098 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwButtons
; i
++)
1100 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 12], df
->dwObjSize
);
1101 df
->rgodf
[idx
].pguid
= &GUID_Button
;
1102 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_PSHBUTTON
;
1104 newDevice
->generic
.base
.data_format
.wine_df
= df
;
1106 /* initialize default properties */
1107 get_osx_device_elements_props(newDevice
);
1109 IDirectInput_AddRef(&newDevice
->generic
.base
.dinput
->IDirectInput7A_iface
);
1111 EnterCriticalSection(&dinput
->crit
);
1112 list_add_tail(&dinput
->devices_list
, &newDevice
->generic
.base
.entry
);
1113 LeaveCriticalSection(&dinput
->crit
);
1115 newDevice
->generic
.devcaps
.dwSize
= sizeof(newDevice
->generic
.devcaps
);
1116 newDevice
->generic
.devcaps
.dwFlags
|= DIDC_ATTACHED
;
1117 if (newDevice
->generic
.base
.dinput
->dwVersion
>= 0x0800)
1118 newDevice
->generic
.devcaps
.dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
1120 newDevice
->generic
.devcaps
.dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
1121 newDevice
->generic
.devcaps
.dwFFSamplePeriod
= 0;
1122 newDevice
->generic
.devcaps
.dwFFMinTimeResolution
= 0;
1123 newDevice
->generic
.devcaps
.dwFirmwareRevision
= 0;
1124 newDevice
->generic
.devcaps
.dwHardwareRevision
= 0;
1125 newDevice
->generic
.devcaps
.dwFFDriverVersion
= 0;
1127 if (TRACE_ON(dinput
)) {
1128 TRACE("allocated device %p\n", newDevice
);
1129 _dump_DIDATAFORMAT(newDevice
->generic
.base
.data_format
.wine_df
);
1130 _dump_DIDEVCAPS(&newDevice
->generic
.devcaps
);
1138 hr
= DIERR_OUTOFMEMORY
;
1139 if (newDevice
->ff
) FFReleaseDevice(newDevice
->ff
);
1140 if (newDevice
->elements
) CFRelease(newDevice
->elements
);
1141 if (df
) HeapFree(GetProcessHeap(), 0, df
->rgodf
);
1142 HeapFree(GetProcessHeap(), 0, df
);
1143 release_DataFormat(&newDevice
->generic
.base
.data_format
);
1144 HeapFree(GetProcessHeap(),0,newDevice
->generic
.name
);
1145 HeapFree(GetProcessHeap(),0,newDevice
);
1151 /******************************************************************************
1152 * get_joystick_index : Get the joystick index from a given GUID
1154 static unsigned short get_joystick_index(REFGUID guid
)
1156 GUID wine_joystick
= DInput_Wine_OsX_Joystick_GUID
;
1157 GUID dev_guid
= *guid
;
1159 wine_joystick
.Data3
= 0;
1162 /* for the standard joystick GUID use index 0 */
1163 if(IsEqualGUID(&GUID_Joystick
,guid
)) return 0;
1165 /* for the wine joystick GUIDs use the index stored in Data3 */
1166 if(IsEqualGUID(&wine_joystick
, &dev_guid
)) return guid
->Data3
;
1171 static HRESULT
joydev_create_device(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPVOID
*pdev
, int unicode
)
1173 unsigned short index
;
1174 int joystick_devices_count
;
1176 TRACE("%p %s %s %p %i\n", dinput
, debugstr_guid(rguid
), debugstr_guid(riid
), pdev
, unicode
);
1179 if ((joystick_devices_count
= find_joystick_devices()) == 0)
1180 return DIERR_DEVICENOTREG
;
1182 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
1183 joystick_devices_count
&& index
< joystick_devices_count
)
1190 else if (IsEqualGUID(&IID_IDirectInputDeviceA
, riid
) ||
1191 IsEqualGUID(&IID_IDirectInputDevice2A
, riid
) ||
1192 IsEqualGUID(&IID_IDirectInputDevice7A
, riid
) ||
1193 IsEqualGUID(&IID_IDirectInputDevice8A
, riid
))
1197 else if (IsEqualGUID(&IID_IDirectInputDeviceW
, riid
) ||
1198 IsEqualGUID(&IID_IDirectInputDevice2W
, riid
) ||
1199 IsEqualGUID(&IID_IDirectInputDevice7W
, riid
) ||
1200 IsEqualGUID(&IID_IDirectInputDevice8W
, riid
))
1206 WARN("no interface\n");
1207 return DIERR_NOINTERFACE
;
1210 hr
= alloc_device(rguid
, dinput
, &This
, index
);
1211 if (!This
) return hr
;
1214 *pdev
= &This
->generic
.base
.IDirectInputDevice8W_iface
;
1216 *pdev
= &This
->generic
.base
.IDirectInputDevice8A_iface
;
1220 return DIERR_DEVICENOTREG
;
1223 static HRESULT
osx_set_autocenter(JoystickImpl
*This
,
1224 const DIPROPDWORD
*header
)
1229 return DIERR_UNSUPPORTED
;
1231 hr
= osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This
->ff
, FFPROP_AUTOCENTER
, &v
));
1232 TRACE("returning: %08x\n", hr
);
1236 static HRESULT
osx_set_ffgain(JoystickImpl
*This
, const DIPROPDWORD
*header
)
1241 return DIERR_UNSUPPORTED
;
1243 hr
= osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This
->ff
, FFPROP_FFGAIN
, &v
));
1244 TRACE("returning: %08x\n", hr
);
1248 static HRESULT WINAPI
JoystickWImpl_SetProperty(IDirectInputDevice8W
*iface
,
1249 const GUID
*prop
, const DIPROPHEADER
*header
)
1251 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1253 TRACE("%p %s %p\n", This
, debugstr_guid(prop
), header
);
1255 switch(LOWORD(prop
))
1257 case (DWORD_PTR
)DIPROP_AUTOCENTER
:
1258 return osx_set_autocenter(This
, (const DIPROPDWORD
*)header
);
1259 case (DWORD_PTR
)DIPROP_FFGAIN
:
1260 return osx_set_ffgain(This
, (const DIPROPDWORD
*)header
);
1263 return JoystickWGenericImpl_SetProperty(iface
, prop
, header
);
1266 static HRESULT WINAPI
JoystickAImpl_SetProperty(IDirectInputDevice8A
*iface
,
1267 const GUID
*prop
, const DIPROPHEADER
*header
)
1269 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1271 TRACE("%p %s %p\n", This
, debugstr_guid(prop
), header
);
1273 switch(LOWORD(prop
))
1275 case (DWORD_PTR
)DIPROP_AUTOCENTER
:
1276 return osx_set_autocenter(This
, (const DIPROPDWORD
*)header
);
1277 case (DWORD_PTR
)DIPROP_FFGAIN
:
1278 return osx_set_ffgain(This
, (const DIPROPDWORD
*)header
);
1281 return JoystickAGenericImpl_SetProperty(iface
, prop
, header
);
1284 static CFUUIDRef
effect_win_to_mac(const GUID
*effect
)
1287 if(IsEqualGUID(&GUID_##X, effect)) \
1288 return kFFEffectType_##X##_ID;
1289 DO_MAP(ConstantForce
)
1295 DO_MAP(SawtoothDown
)
1302 WARN("Unknown effect GUID! %s\n", debugstr_guid(effect
));
1306 static HRESULT WINAPI
JoystickWImpl_CreateEffect(IDirectInputDevice8W
*iface
,
1307 const GUID
*type
, const DIEFFECT
*params
, IDirectInputEffect
**out
,
1310 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1314 TRACE("%p %s %p %p %p\n", iface
, debugstr_guid(type
), params
, out
, outer
);
1315 dump_DIEFFECT(params
, type
, 0);
1318 TRACE("No force feedback support\n");
1324 WARN("aggregation not implemented\n");
1326 effect
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
1327 effect
->IDirectInputEffect_iface
.lpVtbl
= &EffectVtbl
;
1329 effect
->guid
= *type
;
1330 effect
->device
= This
;
1332 /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
1333 hr
= osx_to_win32_hresult(FFDeviceCreateEffect(This
->ff
,
1334 effect_win_to_mac(type
), (FFEFFECT
*)params
, &effect
->effect
));
1336 WARN("FFDeviceCreateEffect failed: %08x\n", hr
);
1337 HeapFree(GetProcessHeap(), 0, effect
);
1341 list_add_tail(&This
->effects
, &effect
->entry
);
1342 *out
= &effect
->IDirectInputEffect_iface
;
1344 TRACE("allocated effect: %p\n", effect
);
1349 static HRESULT WINAPI
JoystickAImpl_CreateEffect(IDirectInputDevice8A
*iface
,
1350 const GUID
*type
, const DIEFFECT
*params
, IDirectInputEffect
**out
,
1353 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1355 TRACE("%p %s %p %p %p\n", iface
, debugstr_guid(type
), params
, out
, outer
);
1357 return JoystickWImpl_CreateEffect(&This
->generic
.base
.IDirectInputDevice8W_iface
,
1358 type
, params
, out
, outer
);
1361 static HRESULT WINAPI
JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W
*iface
,
1364 JoystickImpl
*This
= impl_from_IDirectInputDevice8W(iface
);
1367 TRACE("%p 0x%x\n", This
, flags
);
1372 hr
= osx_to_win32_hresult(FFDeviceSendForceFeedbackCommand(This
->ff
, flags
));
1374 WARN("FFDeviceSendForceFeedbackCommand failed: %08x\n", hr
);
1381 static HRESULT WINAPI
JoystickAImpl_SendForceFeedbackCommand(IDirectInputDevice8A
*iface
,
1384 JoystickImpl
*This
= impl_from_IDirectInputDevice8A(iface
);
1386 TRACE("%p 0x%x\n", This
, flags
);
1388 return JoystickWImpl_SendForceFeedbackCommand(&This
->generic
.base
.IDirectInputDevice8W_iface
, flags
);
1391 const struct dinput_device joystick_osx_device
= {
1392 "Wine OS X joystick driver",
1393 joydev_enum_deviceA
,
1394 joydev_enum_deviceW
,
1395 joydev_create_device
1398 static const IDirectInputDevice8AVtbl JoystickAvt
=
1400 IDirectInputDevice2AImpl_QueryInterface
,
1401 IDirectInputDevice2AImpl_AddRef
,
1402 IDirectInputDevice2AImpl_Release
,
1403 JoystickAGenericImpl_GetCapabilities
,
1404 IDirectInputDevice2AImpl_EnumObjects
,
1405 JoystickAGenericImpl_GetProperty
,
1406 JoystickAImpl_SetProperty
,
1407 IDirectInputDevice2AImpl_Acquire
,
1408 IDirectInputDevice2AImpl_Unacquire
,
1409 JoystickAGenericImpl_GetDeviceState
,
1410 IDirectInputDevice2AImpl_GetDeviceData
,
1411 IDirectInputDevice2AImpl_SetDataFormat
,
1412 IDirectInputDevice2AImpl_SetEventNotification
,
1413 IDirectInputDevice2AImpl_SetCooperativeLevel
,
1414 JoystickAGenericImpl_GetObjectInfo
,
1415 JoystickAGenericImpl_GetDeviceInfo
,
1416 IDirectInputDevice2AImpl_RunControlPanel
,
1417 IDirectInputDevice2AImpl_Initialize
,
1418 JoystickAImpl_CreateEffect
,
1419 IDirectInputDevice2AImpl_EnumEffects
,
1420 IDirectInputDevice2AImpl_GetEffectInfo
,
1421 IDirectInputDevice2AImpl_GetForceFeedbackState
,
1422 JoystickAImpl_SendForceFeedbackCommand
,
1423 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
1424 IDirectInputDevice2AImpl_Escape
,
1425 JoystickAGenericImpl_Poll
,
1426 IDirectInputDevice2AImpl_SendDeviceData
,
1427 IDirectInputDevice7AImpl_EnumEffectsInFile
,
1428 IDirectInputDevice7AImpl_WriteEffectToFile
,
1429 JoystickAGenericImpl_BuildActionMap
,
1430 JoystickAGenericImpl_SetActionMap
,
1431 IDirectInputDevice8AImpl_GetImageInfo
1434 static const IDirectInputDevice8WVtbl JoystickWvt
=
1436 IDirectInputDevice2WImpl_QueryInterface
,
1437 IDirectInputDevice2WImpl_AddRef
,
1438 IDirectInputDevice2WImpl_Release
,
1439 JoystickWGenericImpl_GetCapabilities
,
1440 IDirectInputDevice2WImpl_EnumObjects
,
1441 JoystickWGenericImpl_GetProperty
,
1442 JoystickWImpl_SetProperty
,
1443 IDirectInputDevice2WImpl_Acquire
,
1444 IDirectInputDevice2WImpl_Unacquire
,
1445 JoystickWGenericImpl_GetDeviceState
,
1446 IDirectInputDevice2WImpl_GetDeviceData
,
1447 IDirectInputDevice2WImpl_SetDataFormat
,
1448 IDirectInputDevice2WImpl_SetEventNotification
,
1449 IDirectInputDevice2WImpl_SetCooperativeLevel
,
1450 JoystickWGenericImpl_GetObjectInfo
,
1451 JoystickWGenericImpl_GetDeviceInfo
,
1452 IDirectInputDevice2WImpl_RunControlPanel
,
1453 IDirectInputDevice2WImpl_Initialize
,
1454 JoystickWImpl_CreateEffect
,
1455 IDirectInputDevice2WImpl_EnumEffects
,
1456 IDirectInputDevice2WImpl_GetEffectInfo
,
1457 IDirectInputDevice2WImpl_GetForceFeedbackState
,
1458 JoystickWImpl_SendForceFeedbackCommand
,
1459 IDirectInputDevice2WImpl_EnumCreatedEffectObjects
,
1460 IDirectInputDevice2WImpl_Escape
,
1461 JoystickWGenericImpl_Poll
,
1462 IDirectInputDevice2WImpl_SendDeviceData
,
1463 IDirectInputDevice7WImpl_EnumEffectsInFile
,
1464 IDirectInputDevice7WImpl_WriteEffectToFile
,
1465 JoystickWGenericImpl_BuildActionMap
,
1466 JoystickWGenericImpl_SetActionMap
,
1467 IDirectInputDevice8WImpl_GetImageInfo
1470 static HRESULT WINAPI
effect_QueryInterface(IDirectInputEffect
*iface
,
1471 const GUID
*guid
, void **out
)
1473 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1475 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), out
);
1477 if(IsEqualIID(guid
, &IID_IDirectInputEffect
)){
1479 IDirectInputEffect_AddRef(iface
);
1483 return E_NOINTERFACE
;
1486 static ULONG WINAPI
effect_AddRef(IDirectInputEffect
*iface
)
1488 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1489 ULONG ref
= InterlockedIncrement(&This
->ref
);
1490 TRACE("%p, ref is now: %u\n", This
, ref
);
1494 static ULONG WINAPI
effect_Release(IDirectInputEffect
*iface
)
1496 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1497 ULONG ref
= InterlockedDecrement(&This
->ref
);
1498 TRACE("%p, ref is now: %u\n", This
, ref
);
1501 list_remove(&This
->entry
);
1502 FFDeviceReleaseEffect(This
->device
->ff
, This
->effect
);
1503 HeapFree(GetProcessHeap(), 0, This
);
1509 static HRESULT WINAPI
effect_Initialize(IDirectInputEffect
*iface
, HINSTANCE hinst
,
1510 DWORD version
, const GUID
*guid
)
1512 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1513 TRACE("%p %p 0x%x, %s\n", This
, hinst
, version
, debugstr_guid(guid
));
1517 static HRESULT WINAPI
effect_GetEffectGuid(IDirectInputEffect
*iface
, GUID
*out
)
1519 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1520 TRACE("%p %p\n", This
, out
);
1525 static HRESULT WINAPI
effect_GetParameters(IDirectInputEffect
*iface
,
1526 DIEFFECT
*effect
, DWORD flags
)
1528 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1529 TRACE("%p %p 0x%x\n", This
, effect
, flags
);
1530 return osx_to_win32_hresult(FFEffectGetParameters(This
->effect
, (FFEFFECT
*)effect
, flags
));
1533 static HRESULT WINAPI
effect_SetParameters(IDirectInputEffect
*iface
,
1534 const DIEFFECT
*effect
, DWORD flags
)
1536 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1537 TRACE("%p %p 0x%x\n", This
, effect
, flags
);
1538 dump_DIEFFECT(effect
, &This
->guid
, flags
);
1539 return osx_to_win32_hresult(FFEffectSetParameters(This
->effect
, (FFEFFECT
*)effect
, flags
));
1542 static HRESULT WINAPI
effect_Start(IDirectInputEffect
*iface
, DWORD iterations
,
1545 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1546 TRACE("%p 0x%x 0x%x\n", This
, iterations
, flags
);
1547 return osx_to_win32_hresult(FFEffectStart(This
->effect
, iterations
, flags
));
1550 static HRESULT WINAPI
effect_Stop(IDirectInputEffect
*iface
)
1552 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1553 TRACE("%p\n", This
);
1554 return osx_to_win32_hresult(FFEffectStop(This
->effect
));
1557 static HRESULT WINAPI
effect_GetEffectStatus(IDirectInputEffect
*iface
, DWORD
*flags
)
1559 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1560 TRACE("%p %p\n", This
, flags
);
1561 return osx_to_win32_hresult(FFEffectGetEffectStatus(This
->effect
, (UInt32
*)flags
));
1564 static HRESULT WINAPI
effect_Download(IDirectInputEffect
*iface
)
1566 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1567 TRACE("%p\n", This
);
1568 return osx_to_win32_hresult(FFEffectDownload(This
->effect
));
1571 static HRESULT WINAPI
effect_Unload(IDirectInputEffect
*iface
)
1573 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1574 TRACE("%p\n", This
);
1575 return osx_to_win32_hresult(FFEffectUnload(This
->effect
));
1578 static HRESULT WINAPI
effect_Escape(IDirectInputEffect
*iface
, DIEFFESCAPE
*escape
)
1580 EffectImpl
*This
= impl_from_IDirectInputEffect(iface
);
1581 TRACE("%p %p\n", This
, escape
);
1582 return osx_to_win32_hresult(FFEffectEscape(This
->effect
, (FFEFFESCAPE
*)escape
));
1585 static const IDirectInputEffectVtbl EffectVtbl
= {
1586 effect_QueryInterface
,
1590 effect_GetEffectGuid
,
1591 effect_GetParameters
,
1592 effect_SetParameters
,
1595 effect_GetEffectStatus
,
1601 #else /* HAVE_IOHIDMANAGERCREATE */
1603 const struct dinput_device joystick_osx_device
= {
1604 "Wine OS X joystick driver",
1610 #endif /* HAVE_IOHIDMANAGERCREATE */