]> sigrok.org Git - libserialport.git/blame - macosx.c
Build: Use GNUMAKEFLAGS and $@
[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
970f279a 24SP_PRIV enum sp_return get_port_details(struct sp_port *port)
e33dcf90 25{
dc422c04
UH
26 /*
27 * Description limited to 127 char, anything longer
28 * would not be user friendly anyway.
29 */
e33dcf90
ML
30 char description[128];
31 int bus, address, vid, pid = -1;
32 char manufacturer[128], product[128], serial[128];
e33dcf90
ML
33 CFMutableDictionaryRef classes;
34 io_iterator_t iter;
23526999 35 io_object_t ioport, ioparent;
e33dcf90
ML
36 CFTypeRef cf_property, cf_bus, cf_address, cf_vendor, cf_product;
37 Boolean result;
23526999 38 char path[PATH_MAX], class[16];
e33dcf90
ML
39
40 DEBUG("Getting serial port list");
41 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
42 RETURN_FAIL("IOServiceMatching() failed");
43
44 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
45 &iter) != KERN_SUCCESS)
46 RETURN_FAIL("IOServiceGetMatchingServices() failed");
47
48 DEBUG("Iterating over results");
49 while ((ioport = IOIteratorNext(iter))) {
50 if (!(cf_property = IORegistryEntryCreateCFProperty(ioport,
51 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0))) {
52 IOObjectRelease(ioport);
53 continue;
54 }
55 result = CFStringGetCString(cf_property, path, sizeof(path),
56 kCFStringEncodingASCII);
57 CFRelease(cf_property);
58 if (!result || strcmp(path, port->name)) {
59 IOObjectRelease(ioport);
60 continue;
61 }
23ef3bf1 62 DEBUG_FMT("Found port %s", path);
e33dcf90
ML
63
64 IORegistryEntryGetParentEntry(ioport, kIOServicePlane, &ioparent);
65 if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane,
66 CFSTR("IOProviderClass"), kCFAllocatorDefault,
67 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
68 if (CFStringGetCString(cf_property, class, sizeof(class),
69 kCFStringEncodingASCII) &&
70 strstr(class, "USB")) {
71 DEBUG("Found USB class device");
72 port->transport = SP_TRANSPORT_USB;
73 }
74 CFRelease(cf_property);
75 }
76 IOObjectRelease(ioparent);
77
78 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
79 CFSTR("USB Interface Name"), kCFAllocatorDefault,
80 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
81 (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
82 CFSTR("USB Product Name"), kCFAllocatorDefault,
83 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
84 (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
85 CFSTR("Product Name"), kCFAllocatorDefault,
86 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
87 (cf_property = IORegistryEntryCreateCFProperty(ioport,
88 CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
89 if (CFStringGetCString(cf_property, description, sizeof(description),
90 kCFStringEncodingASCII)) {
23ef3bf1 91 DEBUG_FMT("Found description %s", description);
e33dcf90
ML
92 port->description = strdup(description);
93 }
94 CFRelease(cf_property);
95 } else {
96 DEBUG("No description for this device");
97 }
98
99 cf_bus = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
100 CFSTR("USBBusNumber"),
101 kCFAllocatorDefault,
102 kIORegistryIterateRecursively
103 | kIORegistryIterateParents);
104 cf_address = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
105 CFSTR("USB Address"),
106 kCFAllocatorDefault,
107 kIORegistryIterateRecursively
108 | kIORegistryIterateParents);
109 if (cf_bus && cf_address &&
110 CFNumberGetValue(cf_bus , kCFNumberIntType, &bus) &&
111 CFNumberGetValue(cf_address, kCFNumberIntType, &address)) {
23ef3bf1 112 DEBUG_FMT("Found matching USB bus:address %03d:%03d", bus, address);
e33dcf90
ML
113 port->usb_bus = bus;
114 port->usb_address = address;
115 }
dc422c04
UH
116 if (cf_bus)
117 CFRelease(cf_bus);
118 if (cf_address)
119 CFRelease(cf_address);
e33dcf90
ML
120
121 cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
122 CFSTR("idVendor"),
123 kCFAllocatorDefault,
124 kIORegistryIterateRecursively
125 | kIORegistryIterateParents);
126 cf_product = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
127 CFSTR("idProduct"),
128 kCFAllocatorDefault,
129 kIORegistryIterateRecursively
130 | kIORegistryIterateParents);
131 if (cf_vendor && cf_product &&
132 CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
133 CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
dc422c04 134 DEBUG_FMT("Found matching USB VID:PID %04X:%04X", vid, pid);
e33dcf90
ML
135 port->usb_vid = vid;
136 port->usb_pid = pid;
137 }
dc422c04
UH
138 if (cf_vendor)
139 CFRelease(cf_vendor);
140 if (cf_product)
141 CFRelease(cf_product);
e33dcf90
ML
142
143 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
144 CFSTR("USB Vendor Name"), kCFAllocatorDefault,
145 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
146 if (CFStringGetCString(cf_property, manufacturer, sizeof(manufacturer),
147 kCFStringEncodingASCII)) {
23ef3bf1 148 DEBUG_FMT("Found manufacturer %s", manufacturer);
e33dcf90
ML
149 port->usb_manufacturer = strdup(manufacturer);
150 }
151 CFRelease(cf_property);
152 }
153
154 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
155 CFSTR("USB Product Name"), kCFAllocatorDefault,
156 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
157 if (CFStringGetCString(cf_property, product, sizeof(product),
158 kCFStringEncodingASCII)) {
23ef3bf1 159 DEBUG_FMT("Found product name %s", product);
e33dcf90
ML
160 port->usb_product = strdup(product);
161 }
162 CFRelease(cf_property);
163 }
164
165 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
166 CFSTR("USB Serial Number"), kCFAllocatorDefault,
167 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
168 if (CFStringGetCString(cf_property, serial, sizeof(serial),
169 kCFStringEncodingASCII)) {
23ef3bf1 170 DEBUG_FMT("Found serial number %s", serial);
e33dcf90
ML
171 port->usb_serial = strdup(serial);
172 }
173 CFRelease(cf_property);
174 }
175
176 IOObjectRelease(ioport);
177 break;
178 }
179 IOObjectRelease(iter);
180
181 RETURN_OK();
182}
48a4076f 183
970f279a 184SP_PRIV enum sp_return list_ports(struct sp_port ***list)
48a4076f
AJ
185{
186 CFMutableDictionaryRef classes;
187 io_iterator_t iter;
188 char path[PATH_MAX];
189 io_object_t port;
190 CFTypeRef cf_path;
191 Boolean result;
192 int ret = SP_OK;
193
194 DEBUG("Creating matching dictionary");
195 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
196 SET_FAIL(ret, "IOServiceMatching() failed");
197 goto out_done;
198 }
199
200 DEBUG("Getting matching services");
201 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
202 &iter) != KERN_SUCCESS) {
203 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
204 goto out_done;
205 }
206
207 DEBUG("Iterating over results");
208 while ((port = IOIteratorNext(iter))) {
209 cf_path = IORegistryEntryCreateCFProperty(port,
210 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
211 if (cf_path) {
212 result = CFStringGetCString(cf_path, path, sizeof(path),
213 kCFStringEncodingASCII);
214 CFRelease(cf_path);
215 if (result) {
23ef3bf1 216 DEBUG_FMT("Found port %s", path);
48a4076f 217 if (!(*list = list_append(*list, path))) {
dc422c04 218 SET_ERROR(ret, SP_ERR_MEM, "List append failed");
48a4076f
AJ
219 IOObjectRelease(port);
220 goto out;
221 }
222 }
223 }
224 IOObjectRelease(port);
225 }
226out:
227 IOObjectRelease(iter);
228out_done:
229
230 return ret;
231}