]> sigrok.org Git - libserialport.git/blobdiff - macosx.c
Fix a potential segfault in sp_get_port_handle().
[libserialport.git] / macosx.c
index c1c5d9106387c9a595bbc149c292248dc8941637..b1e0b4579524ff716174d83f800564f8dc51bb96 100644 (file)
--- a/macosx.c
+++ b/macosx.c
 #include "libserialport.h"
 #include "libserialport_internal.h"
 
-enum sp_return get_port_details(struct sp_port *port)
+SP_PRIV enum sp_return get_port_details(struct sp_port *port)
 {
-       /* Description limited to 127 char,
-          anything longer would not be user friendly anyway */
+       /*
+        * Description limited to 127 char, anything longer
+        * would not be user friendly anyway.
+        */
        char description[128];
        int bus, address, vid, pid = -1;
        char manufacturer[128], product[128], serial[128];
-       char baddr[32];
        CFMutableDictionaryRef classes;
        io_iterator_t iter;
-       io_object_t ioport;
+       io_object_t ioport, ioparent;
        CFTypeRef cf_property, cf_bus, cf_address, cf_vendor, cf_product;
        Boolean result;
-       char path[PATH_MAX];
+       char path[PATH_MAX], class[16];
 
        DEBUG("Getting serial port list");
        if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
@@ -58,7 +59,7 @@ enum sp_return get_port_details(struct sp_port *port)
                        IOObjectRelease(ioport);
                        continue;
                }
-               DEBUG("Found port %s", path);
+               DEBUG_FMT("Found port %s", path);
 
                IORegistryEntryGetParentEntry(ioport, kIOServicePlane, &ioparent);
                if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane,
@@ -87,7 +88,7 @@ enum sp_return get_port_details(struct sp_port *port)
                         CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
                        if (CFStringGetCString(cf_property, description, sizeof(description),
                                               kCFStringEncodingASCII)) {
-                               DEBUG("Found description %s", description);
+                               DEBUG_FMT("Found description %s", description);
                                port->description = strdup(description);
                        }
                        CFRelease(cf_property);
@@ -108,12 +109,14 @@ enum sp_return get_port_details(struct sp_port *port)
                if (cf_bus && cf_address &&
                    CFNumberGetValue(cf_bus    , kCFNumberIntType, &bus) &&
                    CFNumberGetValue(cf_address, kCFNumberIntType, &address)) {
-                       DEBUG("Found matching USB bus:address %03d:%03d", bus, address);
+                       DEBUG_FMT("Found matching USB bus:address %03d:%03d", bus, address);
                        port->usb_bus = bus;
                        port->usb_address = address;
                }
-               if (cf_bus    )  CFRelease(cf_bus);
-               if (cf_address)  CFRelease(cf_address);
+               if (cf_bus)
+                       CFRelease(cf_bus);
+               if (cf_address)
+                       CFRelease(cf_address);
 
                cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
                                                         CFSTR("idVendor"),
@@ -128,19 +131,21 @@ enum sp_return get_port_details(struct sp_port *port)
                if (cf_vendor && cf_product &&
                    CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
                    CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
-                       DEBUG("Found matching USB vid:pid %04X:%04X", vid, pid);
+                       DEBUG_FMT("Found matching USB VID:PID %04X:%04X", vid, pid);
                        port->usb_vid = vid;
                        port->usb_pid = pid;
                }
-               if (cf_vendor )  CFRelease(cf_vendor);
-               if (cf_product)  CFRelease(cf_product);
+               if (cf_vendor)
+                       CFRelease(cf_vendor);
+               if (cf_product)
+                       CFRelease(cf_product);
 
                if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
                         CFSTR("USB Vendor Name"), kCFAllocatorDefault,
                         kIORegistryIterateRecursively | kIORegistryIterateParents))) {
                        if (CFStringGetCString(cf_property, manufacturer, sizeof(manufacturer),
                                               kCFStringEncodingASCII)) {
-                               DEBUG("Found manufacturer %s", manufacturer);
+                               DEBUG_FMT("Found manufacturer %s", manufacturer);
                                port->usb_manufacturer = strdup(manufacturer);
                        }
                        CFRelease(cf_property);
@@ -151,7 +156,7 @@ enum sp_return get_port_details(struct sp_port *port)
                         kIORegistryIterateRecursively | kIORegistryIterateParents))) {
                        if (CFStringGetCString(cf_property, product, sizeof(product),
                                               kCFStringEncodingASCII)) {
-                               DEBUG("Found product name %s", product);
+                               DEBUG_FMT("Found product name %s", product);
                                port->usb_product = strdup(product);
                        }
                        CFRelease(cf_property);
@@ -162,7 +167,7 @@ enum sp_return get_port_details(struct sp_port *port)
                         kIORegistryIterateRecursively | kIORegistryIterateParents))) {
                        if (CFStringGetCString(cf_property, serial, sizeof(serial),
                                               kCFStringEncodingASCII)) {
-                               DEBUG("Found serial number %s", serial);
+                               DEBUG_FMT("Found serial number %s", serial);
                                port->usb_serial = strdup(serial);
                        }
                        CFRelease(cf_property);
@@ -175,3 +180,52 @@ enum sp_return get_port_details(struct sp_port *port)
 
        RETURN_OK();
 }
+
+SP_PRIV enum sp_return list_ports(struct sp_port ***list)
+{
+       CFMutableDictionaryRef classes;
+       io_iterator_t iter;
+       char path[PATH_MAX];
+       io_object_t port;
+       CFTypeRef cf_path;
+       Boolean result;
+       int ret = SP_OK;
+
+       DEBUG("Creating matching dictionary");
+       if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
+               SET_FAIL(ret, "IOServiceMatching() failed");
+               goto out_done;
+       }
+
+       DEBUG("Getting matching services");
+       if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
+                                        &iter) != KERN_SUCCESS) {
+               SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
+               goto out_done;
+       }
+
+       DEBUG("Iterating over results");
+       while ((port = IOIteratorNext(iter))) {
+               cf_path = IORegistryEntryCreateCFProperty(port,
+                               CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
+               if (cf_path) {
+                       result = CFStringGetCString(cf_path, path, sizeof(path),
+                                                   kCFStringEncodingASCII);
+                       CFRelease(cf_path);
+                       if (result) {
+                               DEBUG_FMT("Found port %s", path);
+                               if (!(*list = list_append(*list, path))) {
+                                       SET_ERROR(ret, SP_ERR_MEM, "List append failed");
+                                       IOObjectRelease(port);
+                                       goto out;
+                               }
+                       }
+               }
+               IOObjectRelease(port);
+       }
+out:
+       IOObjectRelease(iter);
+out_done:
+
+       return ret;
+}