Zach Smith : dinput: OSX joystick driver separate device for each top level HID collection.
Alexandre Julliard
julliard at winehq.org
Tue Sep 21 13:59:32 CDT 2010
Module: wine
Branch: master
Commit: fa5f61f59d6cbd0bbcd12ae7ebdc4098729065bb
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fa5f61f59d6cbd0bbcd12ae7ebdc4098729065bb
Author: Zach Smith <IAmSparticle at gmail.com>
Date: Mon Sep 20 22:25:27 2010 -0400
dinput: OSX joystick driver separate device for each top level HID collection.
---
dlls/dinput/joystick_osx.c | 123 ++++++++++++++++++++++++++++++++++++-------
1 files changed, 103 insertions(+), 20 deletions(-)
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index bc6908b..fc218d3 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -119,7 +119,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
#ifdef HAVE_IOHIDMANAGERCREATE
static IOHIDManagerRef gIOHIDManagerRef = NULL;
-static CFArrayRef gDevices = NULL;
+static CFArrayRef gCollections = NULL;
typedef struct JoystickImpl JoystickImpl;
static const IDirectInputDevice8AVtbl JoystickAvt;
@@ -194,6 +194,64 @@ static CFMutableDictionaryRef creates_osx_device_match(int usage)
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)
{
IOReturn tIOReturn;
@@ -213,14 +271,14 @@ static int find_osx_devices(void)
&kCFTypeArrayCallBacks );
/* build matching dictionary */
- result = creates_osx_device_match(kHIDPage_Sport);
+ result = creates_osx_device_match(kHIDUsage_GD_Joystick);
if (!result)
{
CFRelease(matching);
return 0;
}
CFArrayAppendValue( ( CFMutableArrayRef )matching, result );
- result = creates_osx_device_match(kHIDPage_Game);
+ result = creates_osx_device_match(kHIDUsage_GD_GamePad);
if (!result)
{
CFRelease(matching);
@@ -232,17 +290,31 @@ static int find_osx_devices(void)
devset = IOHIDManagerCopyDevices( gIOHIDManagerRef );
if (devset)
{
- CFIndex count;
- gDevices = CFArrayCreateMutable( kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks );
+ CFIndex countDevices, countCollections, idx;
+ CFArrayRef gDevices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void*)gDevices);
- count = CFArrayGetCount( gDevices);
CFRelease( devset);
- count = CFArrayGetCount( gDevices);
+ countDevices = CFArrayGetCount(gDevices);
- TRACE("found %i device(s)\n",(int)count);
- return count;
+ gCollections = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ 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;
}
@@ -250,12 +322,21 @@ static int find_osx_devices(void)
static int get_osx_device_name(int id, char *name, int length)
{
CFStringRef str;
+ IOHIDElementRef tIOHIDElementRef;
IOHIDDeviceRef tIOHIDDeviceRef;
- if (!gDevices)
+ if (!gCollections)
+ return 0;
+
+ tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);
+
+ if (!tIOHIDElementRef)
+ {
+ ERR("Invalid Element requested %i\n",id);
return 0;
+ }
- tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, id );
+ tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);
if (name)
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])
{
- IOHIDDeviceRef tIOHIDDeviceRef;
+ IOHIDElementRef tIOHIDElementRef;
CFArrayRef gElementCFArrayRef;
DWORD axes = 0;
DWORD sliders = 0;
@@ -313,16 +394,16 @@ static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
device->elementCFArrayRef = NULL;
- if (!gDevices)
+ if (!gCollections)
return;
- tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, device->id );
+ tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, device->id);
- if (!tIOHIDDeviceRef)
+ if (!tIOHIDElementRef)
return;
- gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef,
- NULL, 0 );
+ gElementCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ get_element_children(tIOHIDElementRef, 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)
{
JoystickImpl *device = (JoystickImpl*)device_in;
+ IOHIDElementRef tIOHIDTopElementRef;
IOHIDDeviceRef tIOHIDDeviceRef;
CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;
TRACE("polling device %i\n",device->id);
- if (!gDevices)
+ if (!gCollections)
return;
- tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, device->id );
+ tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
+ tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);
if (!tIOHIDDeviceRef)
return;
More information about the wine-cvs
mailing list