X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=macosx.c;fp=macosx.c;h=c1c5d9106387c9a595bbc149c292248dc8941637;hb=e33dcf90a0b0e510eb990c657eab88243d0ac5fd;hp=0000000000000000000000000000000000000000;hpb=a93fb468885de8775f1d200625dac114d3050b1d;p=libserialport.git diff --git a/macosx.c b/macosx.c new file mode 100644 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 + * Copyright (C) 2014 Aurelien Jacobs + * + * 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 . + */ + +#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(); +}