26#if defined(HAVE_IOKIT_HID_IOHIDLIB_H)
28#define LPDWORD UInt32*
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
83#include "wine/unicode.h"
95#ifdef HAVE_IOHIDMANAGERCREATE
99static CFMutableArrayRef device_main_elements =
NULL;
101typedef struct JoystickImpl JoystickImpl;
102static const IDirectInputDevice8AVtbl JoystickAvt;
103static const IDirectInputDevice8WVtbl JoystickWvt;
113 FFDeviceObjectReference ff;
130 return &
This->generic.base.IDirectInputDevice8W_iface;
133typedef struct _EffectImpl {
134 IDirectInputEffect IDirectInputEffect_iface;
138 FFEffectObjectReference effect;
144static EffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
149static const IDirectInputEffectVtbl EffectVtbl;
151static const GUID DInput_Wine_OsX_Joystick_GUID = {
152 0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
184static long get_device_property_long(IOHIDDeviceRef
device, CFStringRef
key)
195 if (
ref && CFNumberGetTypeID() == CFGetTypeID(
ref))
196 CFNumberGetValue((CFNumberRef)
ref, kCFNumberLongType, &
result);
202static CFStringRef copy_device_name(IOHIDDeviceRef
device)
212 ref_name = IOHIDDeviceGetProperty(
device, CFSTR(kIOHIDProductKey));
214 if (ref_name && CFStringGetTypeID() == CFGetTypeID(ref_name))
215 name = CFStringCreateCopy(kCFAllocatorDefault, ref_name);
220 vendID = get_device_property_long(
device, CFSTR(kIOHIDVendorIDKey));
221 prodID = get_device_property_long(
device, CFSTR(kIOHIDProductIDKey));
222 name = CFStringCreateWithFormat(kCFAllocatorDefault,
NULL, CFSTR(
"0x%04lx 0x%04lx"), vendID, prodID);
227 ERR(
"NULL device\n");
228 name = CFStringCreateCopy(kCFAllocatorDefault, CFSTR(
""));
234static long get_device_location_ID(IOHIDDeviceRef
device)
236 return get_device_property_long(
device, CFSTR(kIOHIDLocationIDKey));
239static void copy_set_to_array(
const void *
value,
void *
context)
244static CFComparisonResult device_name_comparator(IOHIDDeviceRef device1, IOHIDDeviceRef device2)
246 CFStringRef
name1 = copy_device_name(device1),
name2 = copy_device_name(device2);
247 CFComparisonResult
result = CFStringCompare(
name1,
name2, (kCFCompareForcedOrdering | kCFCompareNumerically));
253static CFComparisonResult device_location_name_comparator(
const void *val1,
const void *val2,
void *
context)
255 IOHIDDeviceRef device1 = (IOHIDDeviceRef)val1, device2 = (IOHIDDeviceRef)val2;
256 long loc1 = get_device_location_ID(device1), loc2 = get_device_location_ID(device2);
259 return kCFCompareLessThan;
260 else if (loc1 > loc2)
261 return kCFCompareGreaterThan;
263 return device_name_comparator(device1, device2);
266static const char* debugstr_cf(CFTypeRef
t)
271 if (!
t)
return "(null)";
273 if (CFGetTypeID(
t) == CFStringGetTypeID())
276 s = CFCopyDescription(
t);
277 ret = CFStringGetCStringPtr(
s, kCFStringEncodingUTF8);
281 const UniChar*
u = CFStringGetCharactersPtr(
s);
289 CFStringGetCharacters(
s, CFRangeMake(0,
len),
buf);
292 if (
s !=
t) CFRelease(
s);
296static const char* debugstr_device(IOHIDDeviceRef
device)
299 debugstr_cf(IOHIDDeviceGetProperty(
device, CFSTR(kIOHIDProductKey))),
300 get_device_location_ID(
device));
303static const char* debugstr_element(IOHIDElementRef
element)
310static IOHIDDeviceRef get_device_ref(
int id)
312 IOHIDElementRef device_main_element;
313 IOHIDDeviceRef hid_device;
315 TRACE(
"id %d\n",
id);
317 if (!device_main_elements ||
id >= CFArrayGetCount(device_main_elements))
320 device_main_element = (IOHIDElementRef)CFArrayGetValueAtIndex(device_main_elements,
id);
321 if (!device_main_element)
323 ERR(
"Invalid Element requested %i\n",
id);
327 hid_device = IOHIDElementGetDevice(device_main_element);
330 ERR(
"Invalid Device requested %i\n",
id);
334 TRACE(
"-> %s\n", debugstr_device(hid_device));
340 io_service_t service;
341 CFMutableDictionaryRef matching;
342 CFTypeRef location_id;
347 matching = IOServiceMatching(kIOHIDDeviceKey);
349 WARN(
"IOServiceMatching failed, force feedback disabled\n");
353 location_id = IOHIDDeviceGetProperty(
device, CFSTR(kIOHIDLocationIDKey));
356 WARN(
"IOHIDDeviceGetProperty failed, force feedback disabled\n");
360 CFDictionaryAddValue(matching, CFSTR(kIOHIDLocationIDKey), location_id);
362 service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
365 hr = osx_to_win32_hresult(FFCreateDevice(service,
ret));
369 IOObjectRelease(service);
374static CFMutableDictionaryRef create_osx_device_match(
int usage)
376 CFMutableDictionaryRef
result;
380 result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
381 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
385 int number = kHIDPage_GenericDesktop;
386 CFNumberRef
page = CFNumberCreate( kCFAllocatorDefault,
387 kCFNumberIntType, &
number);
391 CFNumberRef cf_usage;
393 CFDictionarySetValue(
result, CFSTR( kIOHIDDeviceUsagePageKey ),
page );
396 cf_usage = CFNumberCreate( kCFAllocatorDefault,
397 kCFNumberIntType, &
usage);
400 CFDictionarySetValue(
result, CFSTR( kIOHIDDeviceUsageKey ), cf_usage );
401 CFRelease( cf_usage );
405 ERR(
"CFNumberCreate() failed.\n");
412 ERR(
"CFNumberCreate failed.\n");
419 ERR(
"CFDictionaryCreateMutable failed.\n");
426static CFIndex find_top_level(IOHIDDeviceRef hid_device, CFMutableArrayRef main_elements)
431 TRACE(
"hid_device %s\n", debugstr_device(hid_device));
436 elements = IOHIDDeviceCopyMatchingElements(hid_device,
NULL, 0);
440 CFIndex
idx, cnt = CFArrayGetCount(elements);
443 IOHIDElementRef
element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements,
idx);
449 if (
type == kIOHIDElementTypeCollection && IOHIDElementGetParent(
element) == 0)
451 int usage_page = IOHIDElementGetUsagePage(
element);
454 if (usage_page == kHIDPage_GenericDesktop &&
455 (
usage == kHIDUsage_GD_Joystick ||
usage == kHIDUsage_GD_GamePad))
457 CFArrayAppendValue(main_elements,
element);
469static void get_element_children(IOHIDElementRef
element, CFMutableArrayRef all_children)
472 CFArrayRef element_children = IOHIDElementGetChildren(
element);
476 cnt = CFArrayGetCount(element_children);
481 IOHIDElementRef
child;
483 child = (IOHIDElementRef)CFArrayGetValueAtIndex(element_children,
idx);
485 if (IOHIDElementGetType(
child) == kIOHIDElementTypeCollection)
486 get_element_children(
child, all_children);
488 CFArrayAppendValue(all_children,
child);
492static int find_osx_devices(
void)
494 IOHIDManagerRef hid_manager;
495 CFMutableDictionaryRef
result;
497 CFMutableArrayRef matching;
501 hid_manager = IOHIDManagerCreate( kCFAllocatorDefault, 0
L );
502 if (IOHIDManagerOpen( hid_manager, 0 ) != kIOReturnSuccess)
504 ERR(
"Couldn't open IOHIDManager.\n");
505 CFRelease( hid_manager );
509 matching = CFArrayCreateMutable( kCFAllocatorDefault, 0,
510 &kCFTypeArrayCallBacks );
513 result = create_osx_device_match(kHIDUsage_GD_Joystick);
519 CFArrayAppendValue( matching,
result );
521 result = create_osx_device_match(kHIDUsage_GD_GamePad);
527 CFArrayAppendValue( matching,
result );
530 IOHIDManagerSetDeviceMatchingMultiple( hid_manager, matching);
531 CFRelease( matching );
532 devset = IOHIDManagerCopyDevices( hid_manager );
535 CFIndex num_devices, num_main_elements,
idx;
538 num_devices = CFSetGetCount(devset);
539 devices = CFArrayCreateMutable(kCFAllocatorDefault, num_devices, &kCFTypeArrayCallBacks);
540 CFSetApplyFunction(devset, copy_set_to_array,
devices);
542 CFArraySortValues(
devices, CFRangeMake(0, num_devices), device_location_name_comparator,
NULL);
544 device_main_elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
545 if (!device_main_elements)
551 num_main_elements = 0;
555 IOHIDDeviceRef hid_device;
557 hid_device = (IOHIDDeviceRef) CFArrayGetValueAtIndex(
devices,
idx);
558 TRACE(
"hid_device %s\n", debugstr_device(hid_device));
559 top = find_top_level(hid_device, device_main_elements);
560 num_main_elements +=
top;
565 TRACE(
"found %i device(s), %i collection(s)\n",(
int)num_devices,(
int)num_main_elements);
566 return (
int)num_main_elements;
570 IOHIDManagerClose( hid_manager, 0 );
571 CFRelease( hid_manager );
575static int get_osx_device_name(
int id,
char *
name,
int length)
578 IOHIDDeviceRef hid_device;
580 hid_device = get_device_ref(
id);
582 TRACE(
"id %d hid_device %s\n",
id, debugstr_device(hid_device));
590 str = IOHIDDeviceGetProperty(hid_device, CFSTR( kIOHIDProductKey ));
593 CFIndex
len = CFStringGetLength(
str);
605static CFComparisonResult button_usage_comparator(
const void *val1,
const void *val2,
void *
context)
607 IOHIDElementRef element1 = (IOHIDElementRef)val1, element2 = (IOHIDElementRef)val2;
608 int usage1 = IOHIDElementGetUsage(element1), usage2 = IOHIDElementGetUsage(element2);
611 return kCFCompareLessThan;
613 return kCFCompareGreaterThan;
614 return kCFCompareEqualTo;
617static void get_osx_device_elements(JoystickImpl *
device,
int axis_map[8])
619 IOHIDElementRef device_main_element;
620 CFMutableArrayRef elements;
627 if (!device_main_elements ||
device->id >= CFArrayGetCount(device_main_elements))
630 device_main_element = (IOHIDElementRef)CFArrayGetValueAtIndex(device_main_elements,
device->id);
631 TRACE(
"device_main_element %s\n", debugstr_element(device_main_element));
632 if (!device_main_element)
635 elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
636 get_element_children(device_main_element, elements);
640 CFIndex
idx, cnt = CFArrayGetCount( elements );
641 CFMutableArrayRef axes = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
642 CFMutableArrayRef
buttons = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
643 CFMutableArrayRef povs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
647 IOHIDElementRef
element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elements,
idx );
649 int usage_page = IOHIDElementGetUsagePage(
element );
653 if (usage_page >= kHIDPage_VendorDefinedStart)
661 case kIOHIDElementTypeInput_Button:
663 TRACE(
"kIOHIDElementTypeInput_Button usage_page %d\n", usage_page);
664 if (usage_page != kHIDPage_Button)
670 if (CFArrayGetCount(
buttons) < 128)
674 case kIOHIDElementTypeInput_Axis:
676 TRACE(
"kIOHIDElementTypeInput_Axis\n");
677 CFArrayAppendValue(axes,
element);
680 case kIOHIDElementTypeInput_Misc:
685 case kHIDUsage_GD_Hatswitch:
687 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
688 CFArrayAppendValue(povs,
element);
691 case kHIDUsage_GD_Slider:
699 case kHIDUsage_GD_Rx:
700 case kHIDUsage_GD_Ry:
701 case kHIDUsage_GD_Rz:
703 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_* (%d)\n",
usage);
704 axis_map[CFArrayGetCount(axes)]=
usage;
705 CFArrayAppendValue(axes,
element);
709 FIXME(
"kIOHIDElementTypeInput_Misc / Unhandled usage %i\n",
usage);
719 CFArraySortValues(
buttons, CFRangeMake(0, CFArrayGetCount(
buttons)), button_usage_comparator,
NULL);
721 device->generic.devcaps.dwAxes = CFArrayGetCount(axes);
722 device->generic.devcaps.dwButtons = CFArrayGetCount(
buttons);
723 device->generic.devcaps.dwPOVs = CFArrayGetCount(povs);
725 TRACE(
"axes %u povs %u buttons %u\n",
device->generic.devcaps.dwAxes,
device->generic.devcaps.dwPOVs,
726 device->generic.devcaps.dwButtons);
729 CFArrayAppendArray(axes, povs, CFRangeMake(0,
device->generic.devcaps.dwPOVs));
730 CFArrayAppendArray(axes,
buttons, CFRangeMake(0,
device->generic.devcaps.dwButtons));
740 device->generic.devcaps.dwAxes = 0;
741 device->generic.devcaps.dwButtons = 0;
742 device->generic.devcaps.dwPOVs = 0;
746static void get_osx_device_elements_props(JoystickImpl *
device)
752 CFIndex
idx, cnt = CFArrayGetCount(
device->elements );
756 IOHIDElementRef
element = ( IOHIDElementRef ) CFArrayGetValueAtIndex(
device->elements,
idx );
763 device->generic.props[
idx].lMax = 0xffff;
764 device->generic.props[
idx].lDeadZone = 0;
765 device->generic.props[
idx].lSaturation = 0;
773 IOHIDElementRef device_main_element;
774 IOHIDDeviceRef hid_device;
778 if (!device_main_elements ||
device->id >= CFArrayGetCount(device_main_elements))
781 device_main_element = (IOHIDElementRef) CFArrayGetValueAtIndex(device_main_elements,
device->id);
782 hid_device = IOHIDElementGetDevice(device_main_element);
783 TRACE(
"main element %s hid_device %s\n", debugstr_element(device_main_element), debugstr_device(hid_device));
793 CFIndex
idx, cnt = CFArrayGetCount(
device->elements );
797 IOHIDValueRef valueRef;
798 int val, oldVal, newVal;
799 IOHIDElementRef
element = ( IOHIDElementRef ) CFArrayGetValueAtIndex(
device->elements,
idx );
806 case kIOHIDElementTypeInput_Button:
807 TRACE(
"kIOHIDElementTypeInput_Button\n");
811 if (IOHIDDeviceGetValue(hid_device,
element, &valueRef) != kIOReturnSuccess)
813 if (valueRef ==
NULL)
815 val = IOHIDValueGetIntegerValue(valueRef);
816 newVal =
val ? 0x80 : 0x0;
817 oldVal =
device->generic.js.rgbButtons[button_idx];
818 device->generic.js.rgbButtons[button_idx] = newVal;
819 TRACE(
"valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef),
val, oldVal, newVal);
820 if (oldVal != newVal)
822 button_idx =
device->generic.button_map[button_idx];
830 case kIOHIDElementTypeInput_Misc:
835 case kHIDUsage_GD_Hatswitch:
837 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
839 if (IOHIDDeviceGetValue(hid_device,
element, &valueRef) != kIOReturnSuccess)
841 if (valueRef ==
NULL)
843 val = IOHIDValueGetIntegerValue(valueRef);
844 oldVal =
device->generic.js.rgdwPOV[pov_idx];
849 device->generic.js.rgdwPOV[pov_idx] = newVal;
850 TRACE(
"valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef),
val, oldVal, newVal);
851 if (oldVal != newVal)
862 case kHIDUsage_GD_Rx:
863 case kHIDUsage_GD_Ry:
864 case kHIDUsage_GD_Rz:
865 case kHIDUsage_GD_Slider:
870 if (IOHIDDeviceGetValue(hid_device,
element, &valueRef) != kIOReturnSuccess)
872 if (valueRef ==
NULL)
874 val = IOHIDValueGetIntegerValue(valueRef);
879 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_X\n");
881 oldVal =
device->generic.js.lX;
882 device->generic.js.lX = newVal;
885 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Y\n");
887 oldVal =
device->generic.js.lY;
888 device->generic.js.lY = newVal;
891 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Z\n");
893 oldVal =
device->generic.js.lZ;
894 device->generic.js.lZ = newVal;
896 case kHIDUsage_GD_Rx:
897 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rx\n");
899 oldVal =
device->generic.js.lRx;
900 device->generic.js.lRx = newVal;
902 case kHIDUsage_GD_Ry:
903 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Ry\n");
905 oldVal =
device->generic.js.lRy;
906 device->generic.js.lRy = newVal;
908 case kHIDUsage_GD_Rz:
909 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rz\n");
911 oldVal =
device->generic.js.lRz;
912 device->generic.js.lRz = newVal;
914 case kHIDUsage_GD_Slider:
915 TRACE(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider\n");
916 wine_obj = 6 + slider_idx;
917 oldVal =
device->generic.js.rglSlider[slider_idx];
918 device->generic.js.rglSlider[slider_idx] = newVal;
922 TRACE(
"valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef),
val, oldVal, newVal);
923 if ((wine_obj != -1) &&
933 FIXME(
"kIOHIDElementTypeInput_Misc / unhandled usage %i\n",
usage);
944static INT find_joystick_devices(
void)
946 static INT joystick_devices_count = -1;
948 if (joystick_devices_count != -1)
return joystick_devices_count;
950 joystick_devices_count = find_osx_devices();
952 return joystick_devices_count;
959 vendID = get_device_property_long(
device, CFSTR(kIOHIDVendorIDKey));
960 prodID = get_device_property_long(
device, CFSTR(kIOHIDProductIDKey));
970 TRACE(
"dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType,
dwFlags,
version,
id);
972 if (
id >= find_joystick_devices())
return E_FAIL;
974 device = get_device_ref(
id);
976 if ((dwDevType == 0) ||
986 is_joystick = get_device_property_long(
device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
1018 TRACE(
"dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType,
dwFlags,
version,
id);
1020 if (
id >= find_joystick_devices())
return E_FAIL;
1022 device = get_device_ref(
id);
1024 if ((dwDevType == 0) ||
1034 is_joystick = get_device_property_long(
device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
1047 sprintf(friendly,
"Joystick %d",
id);
1061static const char *osx_ff_axis_name(
UInt8 axis)
1076static BOOL osx_axis_has_ff(FFCAPABILITIES *ffcaps,
UInt8 axis)
1079 for(
i = 0;
i < ffcaps->numFfAxes; ++
i)
1080 if(ffcaps->ffAxes[
i] == axis)
1086 JoystickImpl **pdev,
unsigned short index)
1090 JoystickImpl* newDevice;
1096 int slider_count = 0;
1097 FFCAPABILITIES ffcaps;
1102 if (newDevice == 0) {
1103 WARN(
"out of memory\n");
1108 newDevice->id =
index;
1112 newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID;
1113 newDevice->generic.guidInstance.Data3 =
index;
1115 newDevice->generic.guidProduct.Data1 = make_vid_pid(
device);
1116 newDevice->generic.joy_polldev = poll_osx_device_state;
1130 hr = FFDeviceGetForceFeedbackCapabilities(newDevice->ff, &ffcaps);
1132 TRACE(
"FF Capabilities:\n");
1133 TRACE(
"\tsupportedEffects: 0x%x\n", (
unsigned int)ffcaps.supportedEffects);
1134 TRACE(
"\temulatedEffects: 0x%x\n", (
unsigned int)ffcaps.emulatedEffects);
1135 TRACE(
"\tsubType: 0x%x\n", (
unsigned int)ffcaps.subType);
1136 TRACE(
"\tnumFfAxes: %u\n", (
unsigned int)ffcaps.numFfAxes);
1137 TRACE(
"\tffAxes: [");
1138 for(
i = 0;
i < ffcaps.numFfAxes; ++
i){
1139 TRACE(
"%s", osx_ff_axis_name(ffcaps.ffAxes[
i]));
1140 if(
i < ffcaps.numFfAxes - 1)
1144 TRACE(
"\tstorageCapacity: %u\n", (
unsigned int)ffcaps.storageCapacity);
1145 TRACE(
"\tplaybackCapacity: %u\n", (
unsigned int)ffcaps.playbackCapacity);
1148 hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_RESET);
1150 WARN(
"FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n",
hr);
1152 hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_SETACTUATORSON);
1154 WARN(
"FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n",
hr);
1157 memset(axis_map, 0,
sizeof(axis_map));
1158 get_osx_device_elements(newDevice, axis_map);
1160 TRACE(
"%i axes %i buttons %i povs\n",newDevice->generic.devcaps.dwAxes,newDevice->generic.devcaps.dwButtons,newDevice->generic.devcaps.dwPOVs);
1162 if (newDevice->generic.devcaps.dwButtons > 128)
1164 WARN(
"Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
1165 newDevice->generic.devcaps.dwButtons = 128;
1168 newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
1169 newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
1170 newDevice->generic.base.ref = 1;
1171 newDevice->generic.base.dinput = dinput;
1172 newDevice->generic.base.guid = *rguid;
1174 newDevice->generic.base.crit.DebugInfo->Spare[0] = (
DWORD_PTR)(__FILE__
": JoystickImpl*->generic.base.crit");
1180 df->
dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
1183 for (
i = 0;
i < newDevice->generic.devcaps.dwAxes;
i++)
1187 switch (axis_map[
i])
1189 case kHIDUsage_GD_X:
1191 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_X);
1193 case kHIDUsage_GD_Y:
1195 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Y);
1197 case kHIDUsage_GD_Z:
1199 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Z);
1201 case kHIDUsage_GD_Rx:
1203 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RX);
1205 case kHIDUsage_GD_Ry:
1207 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RY);
1209 case kHIDUsage_GD_Rz:
1211 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RZ);
1213 case kHIDUsage_GD_Slider:
1214 wine_obj = 6 + slider_count;
1215 has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_SLIDER(slider_count));
1219 if (wine_obj < 0 )
continue;
1228 for (
i = 0;
i < newDevice->generic.devcaps.dwPOVs;
i++)
1234 for (
i = 0;
i < newDevice->generic.devcaps.dwButtons;
i++)
1240 newDevice->generic.base.data_format.wine_df = df;
1243 get_osx_device_elements_props(newDevice);
1251 newDevice->generic.devcaps.dwSize =
sizeof(newDevice->generic.devcaps);
1253 if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
1257 newDevice->generic.devcaps.dwFFSamplePeriod = 0;
1258 newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
1259 newDevice->generic.devcaps.dwFirmwareRevision = 0;
1260 newDevice->generic.devcaps.dwHardwareRevision = 0;
1261 newDevice->generic.devcaps.dwFFDriverVersion = 0;
1264 TRACE(
"allocated device %p\n", newDevice);
1275 if (newDevice->ff) FFReleaseDevice(newDevice->ff);
1276 if (newDevice->elements) CFRelease(newDevice->elements);
1290static unsigned short get_joystick_index(
REFGUID guid)
1292 GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID;
1295 wine_joystick.Data3 = 0;
1309 unsigned short index;
1310 int joystick_devices_count;
1315 if ((joystick_devices_count = find_joystick_devices()) == 0)
1318 if ((
index = get_joystick_index(rguid)) < 0xffff &&
1319 joystick_devices_count &&
index < joystick_devices_count)
1342 WARN(
"no interface\n");
1350 *pdev = &
This->generic.base.IDirectInputDevice8W_iface;
1352 *pdev = &
This->generic.base.IDirectInputDevice8A_iface;
1371 static const WCHAR formatW[] = {
'\\',
'\\',
'?',
'\\',
'h',
'i',
'd',
'#',
'v',
'i',
'd',
'_',
'%',
'0',
'4',
'x',
'&',
1372 'p',
'i',
'd',
'_',
'%',
'0',
'4',
'x',
'&',
'%',
's',
'_',
'%',
'i',0};
1373 static const WCHAR miW[] = {
'm',
'i',0};
1374 static const WCHAR igW[] = {
'i',
'g',0};
1377 IOHIDDeviceRef
device = get_device_ref(
This->id);
1379 WORD vid = get_device_property_long(
device, CFSTR(kIOHIDVendorIDKey));
1380 WORD pid = get_device_property_long(
device, CFSTR(kIOHIDProductIDKey));
1406static HRESULT osx_set_autocenter(JoystickImpl *
This,
1414 hr = osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(
This->ff, FFPROP_AUTOCENTER, &
v));
1415 TRACE(
"returning: %08x\n",
hr);
1426 hr = osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(
This->ff, FFPROP_FFGAIN, &
v));
1427 TRACE(
"returning: %08x\n",
hr);
1431static HRESULT WINAPI JoystickWImpl_SetProperty(IDirectInputDevice8W *iface,
1449static HRESULT WINAPI JoystickAImpl_SetProperty(IDirectInputDevice8A *iface,
1467static CFUUIDRef effect_win_to_mac(
const GUID *effect)
1470 if(IsEqualGUID(&GUID_##X, effect)) \
1471 return kFFEffectType_##X##_ID;
1472 DO_MAP(ConstantForce)
1478 DO_MAP(SawtoothDown)
1489static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
1501 TRACE(
"No force feedback support\n");
1507 WARN(
"aggregation not implemented\n");
1510 effect->IDirectInputEffect_iface.lpVtbl = &EffectVtbl;
1512 effect->guid = *
type;
1513 effect->device =
This;
1516 hr = osx_to_win32_hresult(FFDeviceCreateEffect(
This->ff,
1517 effect_win_to_mac(
type), (FFEFFECT*)
params, &effect->effect));
1519 WARN(
"FFDeviceCreateEffect failed: %08x\n",
hr);
1525 *
out = &effect->IDirectInputEffect_iface;
1527 TRACE(
"allocated effect: %p\n", effect);
1532static HRESULT WINAPI JoystickAImpl_CreateEffect(IDirectInputDevice8A *iface,
1540 return JoystickWImpl_CreateEffect(&
This->generic.base.IDirectInputDevice8W_iface,
1544static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W *iface,
1555 hr = osx_to_win32_hresult(FFDeviceSendForceFeedbackCommand(
This->ff,
flags));
1557 WARN(
"FFDeviceSendForceFeedbackCommand failed: %08x\n",
hr);
1564static HRESULT WINAPI JoystickAImpl_SendForceFeedbackCommand(IDirectInputDevice8A *iface,
1571 return JoystickWImpl_SendForceFeedbackCommand(&
This->generic.base.IDirectInputDevice8W_iface,
flags);
1575 "Wine OS X joystick driver",
1576 joydev_enum_deviceA,
1577 joydev_enum_deviceW,
1578 joydev_create_device
1581static const IDirectInputDevice8AVtbl JoystickAvt =
1588 JoystickAImpl_GetProperty,
1589 JoystickAImpl_SetProperty,
1601 JoystickAImpl_CreateEffect,
1605 JoystickAImpl_SendForceFeedbackCommand,
1617static const IDirectInputDevice8WVtbl JoystickWvt =
1624 JoystickWImpl_GetProperty,
1625 JoystickWImpl_SetProperty,
1637 JoystickWImpl_CreateEffect,
1641 JoystickWImpl_SendForceFeedbackCommand,
1653static HRESULT WINAPI effect_QueryInterface(IDirectInputEffect *iface,
1656 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1669static ULONG WINAPI effect_AddRef(IDirectInputEffect *iface)
1671 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1677static ULONG WINAPI effect_Release(IDirectInputEffect *iface)
1679 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1685 FFDeviceReleaseEffect(
This->device->ff,
This->effect);
1695 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1702 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1708static HRESULT WINAPI effect_GetParameters(IDirectInputEffect *iface,
1711 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1713 return osx_to_win32_hresult(FFEffectGetParameters(
This->effect, (FFEFFECT*)effect,
flags));
1716static HRESULT WINAPI effect_SetParameters(IDirectInputEffect *iface,
1719 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1722 return osx_to_win32_hresult(FFEffectSetParameters(
This->effect, (FFEFFECT*)effect,
flags));
1728 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1730 return osx_to_win32_hresult(FFEffectStart(
This->effect, iterations,
flags));
1735 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1737 return osx_to_win32_hresult(FFEffectStop(
This->effect));
1742 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1744 return osx_to_win32_hresult(FFEffectGetEffectStatus(
This->effect, (
UInt32*)
flags));
1747static HRESULT WINAPI effect_Download(IDirectInputEffect *iface)
1749 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1751 return osx_to_win32_hresult(FFEffectDownload(
This->effect));
1754static HRESULT WINAPI effect_Unload(IDirectInputEffect *iface)
1756 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1758 return osx_to_win32_hresult(FFEffectUnload(
This->effect));
1763 EffectImpl *
This = impl_from_IDirectInputEffect(iface);
1765 return osx_to_win32_hresult(FFEffectEscape(
This->effect, (FFEFFESCAPE*)
escape));
1768static const IDirectInputEffectVtbl EffectVtbl = {
1769 effect_QueryInterface,
1773 effect_GetEffectGuid,
1774 effect_GetParameters,
1775 effect_SetParameters,
1778 effect_GetEffectStatus,
1787 "Wine OS X joystick driver",
ACPI_SIZE strlen(const char *String)
char * strcpy(char *DstString, const char *SrcString)
#define InterlockedIncrement
#define InterlockedDecrement
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
static void list_remove(struct list_entry *entry)
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
static void list_init(struct list_entry *head)
LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN
const char * wine_dbg_sprintf(const char *format,...)
#define HeapFree(x, y, z)
#define MultiByteToWideChar
static const WCHAR version[]
static struct all_devices * devices
GLuint GLuint GLsizei GLenum type
GLdouble GLdouble GLdouble GLdouble top
GLenum const GLfloat * params
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei GLsizei * length
GLsizeiptr const GLvoid GLenum usage
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
const struct dinput_device joystick_osx_device
#define memcpy(s1, s2, n)
#define sprintf(buf, format,...)
static unsigned int number
#define IsEqualGUID(rguid1, rguid2)
#define IsEqualIID(riid1, riid2)
CHAR tszInstanceName[MAX_PATH]
CHAR tszProductName[MAX_PATH]
WCHAR tszProductName[MAX_PATH]
WCHAR tszInstanceName[MAX_PATH]
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
#define CONTAINING_RECORD(address, type, field)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid