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