]> sigrok.org Git - libserialport.git/blame - macosx.c
Tidy up and split most OS-specific code to separate files.
[libserialport.git] / macosx.c
CommitLineData
e33dcf90
ML
1/*
2 * This file is part of the libserialport project.
3 *
4 * Copyright (C) 2013-2014 Martin Ling <martin-libserialport@earth.li>
5 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "libserialport.h"
22#include "libserialport_internal.h"
23
24enum sp_return get_port_details(struct sp_port *port)
25{
26 /* Description limited to 127 char,
27 anything longer would not be user friendly anyway */
28 char description[128];
29 int bus, address, vid, pid = -1;
30 char manufacturer[128], product[128], serial[128];
31 char baddr[32];
32 CFMutableDictionaryRef classes;
33 io_iterator_t iter;
34 io_object_t ioport;
35 CFTypeRef cf_property, cf_bus, cf_address, cf_vendor, cf_product;
36 Boolean result;
37 char path[PATH_MAX];
38
39 DEBUG("Getting serial port list");
40 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
41 RETURN_FAIL("IOServiceMatching() failed");
42
43 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
44 &iter) != KERN_SUCCESS)
45 RETURN_FAIL("IOServiceGetMatchingServices() failed");
46
47 DEBUG("Iterating over results");
48 while ((ioport = IOIteratorNext(iter))) {
49 if (!(cf_property = IORegistryEntryCreateCFProperty(ioport,
50 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0))) {
51 IOObjectRelease(ioport);
52 continue;
53 }
54 result = CFStringGetCString(cf_property, path, sizeof(path),
55 kCFStringEncodingASCII);
56 CFRelease(cf_property);
57 if (!result || strcmp(path, port->name)) {
58 IOObjectRelease(ioport);
59 continue;
60 }
61 DEBUG("Found port %s", path);
62
63 IORegistryEntryGetParentEntry(ioport, kIOServicePlane, &ioparent);
64 if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane,
65 CFSTR("IOProviderClass"), kCFAllocatorDefault,
66 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
67 if (CFStringGetCString(cf_property, class, sizeof(class),
68 kCFStringEncodingASCII) &&
69 strstr(class, "USB")) {
70 DEBUG("Found USB class device");
71 port->transport = SP_TRANSPORT_USB;
72 }
73 CFRelease(cf_property);
74 }
75 IOObjectRelease(ioparent);
76
77 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
78 CFSTR("USB Interface Name"), kCFAllocatorDefault,
79 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
80 (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
81 CFSTR("USB Product Name"), kCFAllocatorDefault,
82 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
83 (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
84 CFSTR("Product Name"), kCFAllocatorDefault,
85 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
86 (cf_property = IORegistryEntryCreateCFProperty(ioport,
87 CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
88 if (CFStringGetCString(cf_property, description, sizeof(description),
89 kCFStringEncodingASCII)) {
90 DEBUG("Found description %s", description);
91 port->description = strdup(description);
92 }
93 CFRelease(cf_property);
94 } else {
95 DEBUG("No description for this device");
96 }
97
98 cf_bus = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
99 CFSTR("USBBusNumber"),
100 kCFAllocatorDefault,
101 kIORegistryIterateRecursively
102 | kIORegistryIterateParents);
103 cf_address = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
104 CFSTR("USB Address"),
105 kCFAllocatorDefault,
106 kIORegistryIterateRecursively
107 | kIORegistryIterateParents);
108 if (cf_bus && cf_address &&
109 CFNumberGetValue(cf_bus , kCFNumberIntType, &bus) &&
110 CFNumberGetValue(cf_address, kCFNumberIntType, &address)) {
111 DEBUG("Found matching USB bus:address %03d:%03d", bus, address);
112 port->usb_bus = bus;
113 port->usb_address = address;
114 }
115 if (cf_bus ) CFRelease(cf_bus);
116 if (cf_address) CFRelease(cf_address);
117
118 cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
119 CFSTR("idVendor"),
120 kCFAllocatorDefault,
121 kIORegistryIterateRecursively
122 | kIORegistryIterateParents);
123 cf_product = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
124 CFSTR("idProduct"),
125 kCFAllocatorDefault,
126 kIORegistryIterateRecursively
127 | kIORegistryIterateParents);
128 if (cf_vendor && cf_product &&
129 CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
130 CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
131 DEBUG("Found matching USB vid:pid %04X:%04X", vid, pid);
132 port->usb_vid = vid;
133 port->usb_pid = pid;
134 }
135 if (cf_vendor ) CFRelease(cf_vendor);
136 if (cf_product) CFRelease(cf_product);
137
138 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
139 CFSTR("USB Vendor Name"), kCFAllocatorDefault,
140 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
141 if (CFStringGetCString(cf_property, manufacturer, sizeof(manufacturer),
142 kCFStringEncodingASCII)) {
143 DEBUG("Found manufacturer %s", manufacturer);
144 port->usb_manufacturer = strdup(manufacturer);
145 }
146 CFRelease(cf_property);
147 }
148
149 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
150 CFSTR("USB Product Name"), kCFAllocatorDefault,
151 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
152 if (CFStringGetCString(cf_property, product, sizeof(product),
153 kCFStringEncodingASCII)) {
154 DEBUG("Found product name %s", product);
155 port->usb_product = strdup(product);
156 }
157 CFRelease(cf_property);
158 }
159
160 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
161 CFSTR("USB Serial Number"), kCFAllocatorDefault,
162 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
163 if (CFStringGetCString(cf_property, serial, sizeof(serial),
164 kCFStringEncodingASCII)) {
165 DEBUG("Found serial number %s", serial);
166 port->usb_serial = strdup(serial);
167 }
168 CFRelease(cf_property);
169 }
170
171 IOObjectRelease(ioport);
172 break;
173 }
174 IOObjectRelease(iter);
175
176 RETURN_OK();
177}