dinput: OSX joystick driver separate device for each top level HID collection.

oldstable
Zach Smith 2010-09-20 22:25:27 -04:00 committed by Alexandre Julliard
parent af0c074d7b
commit fa5f61f59d
1 changed files with 103 additions and 20 deletions

View File

@ -119,7 +119,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
#ifdef HAVE_IOHIDMANAGERCREATE #ifdef HAVE_IOHIDMANAGERCREATE
static IOHIDManagerRef gIOHIDManagerRef = NULL; static IOHIDManagerRef gIOHIDManagerRef = NULL;
static CFArrayRef gDevices = NULL; static CFArrayRef gCollections = NULL;
typedef struct JoystickImpl JoystickImpl; typedef struct JoystickImpl JoystickImpl;
static const IDirectInputDevice8AVtbl JoystickAvt; static const IDirectInputDevice8AVtbl JoystickAvt;
@ -194,6 +194,64 @@ static CFMutableDictionaryRef creates_osx_device_match(int usage)
return result; return result;
} }
static CFIndex find_top_level(IOHIDDeviceRef tIOHIDDeviceRef, CFArrayRef topLevels)
{
CFArrayRef gElementCFArrayRef;
CFIndex numTops = 0;
if (!tIOHIDDeviceRef)
return 0;
gElementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef, NULL, 0);
if (gElementCFArrayRef)
{
CFIndex idx, cnt = CFArrayGetCount(gElementCFArrayRef);
for (idx=0; idx<cnt; idx++)
{
IOHIDElementRef tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gElementCFArrayRef, idx);
int eleType = IOHIDElementGetType(tIOHIDElementRef);
/* Check for top-level gaming device collections */
if (eleType == kIOHIDElementTypeCollection && IOHIDElementGetParent(tIOHIDElementRef) == 0)
{
int tUsagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
int tUsage = IOHIDElementGetUsage(tIOHIDElementRef);
if (tUsagePage == kHIDPage_GenericDesktop &&
(tUsage == kHIDUsage_GD_Joystick || tUsage == kHIDUsage_GD_GamePad))
{
CFArrayAppendValue((CFMutableArrayRef)topLevels, tIOHIDElementRef);
numTops++;
}
}
}
}
return numTops;
}
static void get_element_children(IOHIDElementRef tElement, CFArrayRef childElements)
{
CFIndex idx, cnt;
CFArrayRef tElementChildrenArray = IOHIDElementGetChildren(tElement);
cnt = CFArrayGetCount(tElementChildrenArray);
if (cnt < 1)
return;
/* Either add the element to the array or grab its children */
for (idx=0; idx<cnt; idx++)
{
IOHIDElementRef tChildElementRef;
tChildElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(tElementChildrenArray, idx);
if (IOHIDElementGetType(tChildElementRef) == kIOHIDElementTypeCollection)
get_element_children(tChildElementRef, childElements);
else
CFArrayAppendValue((CFMutableArrayRef)childElements, tChildElementRef);
}
}
static int find_osx_devices(void) static int find_osx_devices(void)
{ {
IOReturn tIOReturn; IOReturn tIOReturn;
@ -213,14 +271,14 @@ static int find_osx_devices(void)
&kCFTypeArrayCallBacks ); &kCFTypeArrayCallBacks );
/* build matching dictionary */ /* build matching dictionary */
result = creates_osx_device_match(kHIDPage_Sport); result = creates_osx_device_match(kHIDUsage_GD_Joystick);
if (!result) if (!result)
{ {
CFRelease(matching); CFRelease(matching);
return 0; return 0;
} }
CFArrayAppendValue( ( CFMutableArrayRef )matching, result ); CFArrayAppendValue( ( CFMutableArrayRef )matching, result );
result = creates_osx_device_match(kHIDPage_Game); result = creates_osx_device_match(kHIDUsage_GD_GamePad);
if (!result) if (!result)
{ {
CFRelease(matching); CFRelease(matching);
@ -232,17 +290,31 @@ static int find_osx_devices(void)
devset = IOHIDManagerCopyDevices( gIOHIDManagerRef ); devset = IOHIDManagerCopyDevices( gIOHIDManagerRef );
if (devset) if (devset)
{ {
CFIndex count; CFIndex countDevices, countCollections, idx;
gDevices = CFArrayCreateMutable( kCFAllocatorDefault, 0, CFArrayRef gDevices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
&kCFTypeArrayCallBacks );
CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void*)gDevices); CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void*)gDevices);
count = CFArrayGetCount( gDevices);
CFRelease( devset); CFRelease( devset);
count = CFArrayGetCount( gDevices); countDevices = CFArrayGetCount(gDevices);
TRACE("found %i device(s)\n",(int)count); gCollections = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
return count; if (!gCollections)
return 0;
countCollections = 0;
for (idx = 0; idx < countDevices; idx++)
{
CFIndex tTop;
IOHIDDeviceRef tDevice;
tDevice = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDevices, idx);
tTop = find_top_level(tDevice, gCollections);
countCollections += tTop;
}
CFRelease(gDevices);
TRACE("found %i device(s), %i collection(s)\n",(int)countDevices,(int)countCollections);
return (int)countCollections;
} }
return 0; return 0;
} }
@ -250,12 +322,21 @@ static int find_osx_devices(void)
static int get_osx_device_name(int id, char *name, int length) static int get_osx_device_name(int id, char *name, int length)
{ {
CFStringRef str; CFStringRef str;
IOHIDElementRef tIOHIDElementRef;
IOHIDDeviceRef tIOHIDDeviceRef; IOHIDDeviceRef tIOHIDDeviceRef;
if (!gDevices) if (!gCollections)
return 0; return 0;
tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, id ); tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);
if (!tIOHIDElementRef)
{
ERR("Invalid Element requested %i\n",id);
return 0;
}
tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);
if (name) if (name)
name[0] = 0; name[0] = 0;
@ -304,7 +385,7 @@ static void insert_sort_button(int header, IOHIDElementRef tIOHIDElementRef,
static void get_osx_device_elements(JoystickImpl *device, int axis_map[8]) static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
{ {
IOHIDDeviceRef tIOHIDDeviceRef; IOHIDElementRef tIOHIDElementRef;
CFArrayRef gElementCFArrayRef; CFArrayRef gElementCFArrayRef;
DWORD axes = 0; DWORD axes = 0;
DWORD sliders = 0; DWORD sliders = 0;
@ -313,16 +394,16 @@ static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
device->elementCFArrayRef = NULL; device->elementCFArrayRef = NULL;
if (!gDevices) if (!gCollections)
return; return;
tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, device->id ); tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, device->id);
if (!tIOHIDDeviceRef) if (!tIOHIDElementRef)
return; return;
gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef, gElementCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
NULL, 0 ); get_element_children(tIOHIDElementRef, gElementCFArrayRef);
if (gElementCFArrayRef) if (gElementCFArrayRef)
{ {
@ -439,15 +520,17 @@ static void get_osx_device_elements_props(JoystickImpl *device)
static void poll_osx_device_state(JoystickGenericImpl *device_in) static void poll_osx_device_state(JoystickGenericImpl *device_in)
{ {
JoystickImpl *device = (JoystickImpl*)device_in; JoystickImpl *device = (JoystickImpl*)device_in;
IOHIDElementRef tIOHIDTopElementRef;
IOHIDDeviceRef tIOHIDDeviceRef; IOHIDDeviceRef tIOHIDDeviceRef;
CFArrayRef gElementCFArrayRef = device->elementCFArrayRef; CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;
TRACE("polling device %i\n",device->id); TRACE("polling device %i\n",device->id);
if (!gDevices) if (!gCollections)
return; return;
tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, device->id ); tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);
if (!tIOHIDDeviceRef) if (!tIOHIDDeviceRef)
return; return;