]> sigrok.org Git - libserialport.git/blobdiff - macosx.c
Tidy up and split most OS-specific code to separate files.
[libserialport.git] / macosx.c
diff --git a/macosx.c b/macosx.c
new file mode 100644 (file)
index 0000000..c1c5d91
--- /dev/null
+++ b/macosx.c
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the libserialport project.
+ *
+ * Copyright (C) 2013-2014 Martin Ling <martin-libserialport@earth.li>
+ * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "libserialport.h"
+#include "libserialport_internal.h"
+
+enum sp_return get_port_details(struct sp_port *port)
+{
+       /* 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;
+       CFTypeRef cf_property, cf_bus, cf_address, cf_vendor, cf_product;
+       Boolean result;
+       char path[PATH_MAX];
+
+       DEBUG("Getting serial port list");
+       if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
+               RETURN_FAIL("IOServiceMatching() failed");
+
+       if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
+                                        &iter) != KERN_SUCCESS)
+               RETURN_FAIL("IOServiceGetMatchingServices() failed");
+
+       DEBUG("Iterating over results");
+       while ((ioport = IOIteratorNext(iter))) {
+               if (!(cf_property = IORegistryEntryCreateCFProperty(ioport,
+                           CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0))) {
+                       IOObjectRelease(ioport);
+                       continue;
+               }
+               result = CFStringGetCString(cf_property, path, sizeof(path),
+                                           kCFStringEncodingASCII);
+               CFRelease(cf_property);
+               if (!result || strcmp(path, port->name)) {
+                       IOObjectRelease(ioport);
+                       continue;
+               }
+               DEBUG("Found port %s", path);
+
+               IORegistryEntryGetParentEntry(ioport, kIOServicePlane, &ioparent);
+               if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane,
+                          CFSTR("IOProviderClass"), kCFAllocatorDefault,
+                          kIORegistryIterateRecursively | kIORegistryIterateParents))) {
+                       if (CFStringGetCString(cf_property, class, sizeof(class),
+                                              kCFStringEncodingASCII) &&
+                           strstr(class, "USB")) {
+                               DEBUG("Found USB class device");
+                               port->transport = SP_TRANSPORT_USB;
+                       }
+                       CFRelease(cf_property);
+               }
+               IOObjectRelease(ioparent);
+
+               if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
+                        CFSTR("USB Interface Name"), kCFAllocatorDefault,
+                        kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
+                   (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
+                        CFSTR("USB Product Name"), kCFAllocatorDefault,
+                        kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
+                   (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
+                        CFSTR("Product Name"), kCFAllocatorDefault,
+                        kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
+                   (cf_property = IORegistryEntryCreateCFProperty(ioport,
+                        CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
+                       if (CFStringGetCString(cf_property, description, sizeof(description),
+                                              kCFStringEncodingASCII)) {
+                               DEBUG("Found description %s", description);
+                               port->description = strdup(description);
+                       }
+                       CFRelease(cf_property);
+               } else {
+                       DEBUG("No description for this device");
+               }
+
+               cf_bus = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
+                                                        CFSTR("USBBusNumber"),
+                                                        kCFAllocatorDefault,
+                                                        kIORegistryIterateRecursively
+                                                        | kIORegistryIterateParents);
+               cf_address = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
+                                                        CFSTR("USB Address"),
+                                                        kCFAllocatorDefault,
+                                                        kIORegistryIterateRecursively
+                                                        | kIORegistryIterateParents);
+               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);
+                       port->usb_bus = bus;
+                       port->usb_address = address;
+               }
+               if (cf_bus    )  CFRelease(cf_bus);
+               if (cf_address)  CFRelease(cf_address);
+
+               cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
+                                                        CFSTR("idVendor"),
+                                                        kCFAllocatorDefault,
+                                                        kIORegistryIterateRecursively
+                                                        | kIORegistryIterateParents);
+               cf_product = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
+                                                        CFSTR("idProduct"),
+                                                        kCFAllocatorDefault,
+                                                        kIORegistryIterateRecursively
+                                                        | kIORegistryIterateParents);
+               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);
+                       port->usb_vid = vid;
+                       port->usb_pid = pid;
+               }
+               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);
+                               port->usb_manufacturer = strdup(manufacturer);
+                       }
+                       CFRelease(cf_property);
+               }
+
+               if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
+                        CFSTR("USB Product Name"), kCFAllocatorDefault,
+                        kIORegistryIterateRecursively | kIORegistryIterateParents))) {
+                       if (CFStringGetCString(cf_property, product, sizeof(product),
+                                              kCFStringEncodingASCII)) {
+                               DEBUG("Found product name %s", product);
+                               port->usb_product = strdup(product);
+                       }
+                       CFRelease(cf_property);
+               }
+
+               if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
+                        CFSTR("USB Serial Number"), kCFAllocatorDefault,
+                        kIORegistryIterateRecursively | kIORegistryIterateParents))) {
+                       if (CFStringGetCString(cf_property, serial, sizeof(serial),
+                                              kCFStringEncodingASCII)) {
+                               DEBUG("Found serial number %s", serial);
+                               port->usb_serial = strdup(serial);
+                       }
+                       CFRelease(cf_property);
+               }
+
+               IOObjectRelease(ioport);
+               break;
+       }
+       IOObjectRelease(iter);
+
+       RETURN_OK();
+}