libaltos: Fix for Mac OS X El Capitan
authorKeith Packard <keithp@keithp.com>
Thu, 21 Apr 2016 00:27:47 +0000 (20:27 -0400)
committerKeith Packard <keithp@keithp.com>
Fri, 22 Apr 2016 01:35:24 +0000 (21:35 -0400)
USB enumeration for serial devices changed

Signed-off-by: Keith Packard <keithp@keithp.com>
libaltos/Makefile-standalone
libaltos/libaltos.dylib
libaltos/libaltos_darwin.c

index 9a44b8e079a286e052ac676c3b9fe6bc869ad601..1430aacb2fb07cdd65d1be3a56ececd3096edb8e 100644 (file)
@@ -33,8 +33,8 @@ OS_SRCS=libaltos_posix.c libaltos_darwin.c
 #      -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
 #      -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
 
-XCODE=/Applications/Xcode.app
-SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
+XCODE=/Applications/Xcode-beta.app
+SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
 MINVERSION=10.5
 
 OS_LIB_CFLAGS=\
@@ -43,7 +43,7 @@ OS_LIB_CFLAGS=\
        -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
        -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
        -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS) -O0 -g
 
 OS_LDFLAGS =\
        -framework IOKit -framework CoreFoundation
index 8b491c580c9c06e913b9438e083ae7274734f5d8..c18493ea7836aca971c0f9ebe8b3b04b1b8d85de 100755 (executable)
Binary files a/libaltos/libaltos.dylib and b/libaltos/libaltos.dylib differ
index bf3cf094270193a5c330e81e2cc9b7fac67f3598..04194d9ac5809392e228ac3681c143867ffaffda 100644 (file)
@@ -20,6 +20,9 @@
 
 #include <IOKitLib.h>
 #include <IOKit/usb/USBspec.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#include <usb/IOUSBLib.h>
+#include <usb/USBSpec.h>
 #include <sys/param.h>
 #include <paths.h>
 #include <CFNumber.h>
@@ -45,11 +48,23 @@ struct altos_list {
        int ftdi;
 };
 
+static char *
+get_cfstring(CFTypeRef string, char result[512])
+{
+       Boolean         got_string;
+
+       got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
+       if (!got_string)
+               strcpy(result, "CFStringGetCString failed");
+       return result;
+}
+
 static int
 get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
 {
        CFTypeRef entry_as_string;
        Boolean got_string;
+       char entry_string[512];
 
        entry_as_string = IORegistryEntrySearchCFProperty (object,
                                                           kIOServicePlane,
@@ -62,8 +77,9 @@ get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
                                                kCFStringEncodingASCII);
 
                CFRelease(entry_as_string);
-               if (got_string)
+               if (got_string) {
                        return 1;
+               }
        }
        return 0;
 }
@@ -73,6 +89,7 @@ get_number(io_object_t object, CFStringRef entry, int *result)
 {
        CFTypeRef entry_as_number;
        Boolean got_number;
+       char entry_string[512];
 
        entry_as_number = IORegistryEntrySearchCFProperty (object,
                                                           kIOServicePlane,
@@ -83,8 +100,9 @@ get_number(io_object_t object, CFStringRef entry, int *result)
                got_number = CFNumberGetValue(entry_as_number,
                                              kCFNumberIntType,
                                              result);
-               if (got_number)
+               if (got_number) {
                        return 1;
+               }
        }
        return 0;
 }
@@ -93,12 +111,19 @@ PUBLIC struct altos_list *
 altos_list_start(void)
 {
        struct altos_list *list = calloc (sizeof (struct altos_list), 1);
-       CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
+       CFMutableDictionaryRef matching_dictionary;
        io_iterator_t tdIterator;
        io_object_t tdObject;
        kern_return_t ret;
        int i;
 
+       matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
+       if (matching_dictionary) {
+               CFDictionarySetValue(matching_dictionary,
+                                    CFSTR(kIOSerialBSDTypeKey),
+                                    CFSTR(kIOSerialBSDAllTypes));
+       }
+
        ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
        if (ret != kIOReturnSuccess) {
                free(list);
@@ -118,26 +143,63 @@ altos_ftdi_list_start(void)
        return list;
 }
 
+static io_service_t get_usb_object(io_object_t serial_device)
+{
+       io_iterator_t iterator;
+       io_service_t usb_device;
+       io_service_t service;
+       IOReturn status;
+
+       status = IORegistryEntryCreateIterator(serial_device,
+                                     kIOServicePlane,
+                                     kIORegistryIterateParents | kIORegistryIterateRecursively,
+                                     &iterator);
+
+       if (status != kIOReturnSuccess)
+               return 0;
+
+       while((service = IOIteratorNext(iterator))) {
+               io_name_t servicename;
+               status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);
+
+               if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
+                       IOObjectRelease(iterator);
+                       return service;
+               }
+               IOObjectRelease(service);
+       }
+       IOObjectRelease(iterator);
+       return 0;
+}
+
 PUBLIC int
 altos_list_next(struct altos_list *list, struct altos_device *device)
 {
+
        io_object_t object;
+       io_service_t usb_device;
        char serial_string[128];
 
        for (;;) {
                object = IOIteratorNext(list->iterator);
-               if (!object)
+               if (!object) {
                        return 0;
+               }
+
+               usb_device = get_usb_object(object);
 
-               if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
-                   !get_number (object, CFSTR(kUSBProductID), &device->product))
-                       continue;
-               if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
-                   get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
-                   get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
+               if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
+                   get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
+                   get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
+                   get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
+                   get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
                        device->serial = atoi(serial_string);
+                       IOObjectRelease(object);
+                       IOObjectRelease(usb_device);
                        return 1;
                }
+               IOObjectRelease(object);
+               IOObjectRelease(usb_device);
        }
 }