examples/send_receive: Fix receive check.
[libserialport/gsi.git] / macosx.c
bloba0df84e6b079d4e5ff9fa969a27020631115bbfe
1 /*
2 * This file is part of the libserialport project.
4 * Copyright (C) 2013-2014 Martin Ling <martin-libserialport@earth.li>
5 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
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.
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.
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/>.
21 #include <config.h>
22 #include "libserialport.h"
23 #include "libserialport_internal.h"
25 SP_PRIV enum sp_return get_port_details(struct sp_port *port)
28 * Description limited to 127 char, anything longer
29 * would not be user friendly anyway.
31 char description[128];
32 int bus, address, vid, pid = -1;
33 char manufacturer[128], product[128], serial[128];
34 CFMutableDictionaryRef classes;
35 io_iterator_t iter;
36 io_object_t ioport, ioparent;
37 CFTypeRef cf_property, cf_bus, cf_address, cf_vendor, cf_product;
38 Boolean result;
39 char path[PATH_MAX], class[16];
41 DEBUG("Getting serial port list");
42 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
43 RETURN_FAIL("IOServiceMatching() failed");
45 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
46 &iter) != KERN_SUCCESS)
47 RETURN_FAIL("IOServiceGetMatchingServices() failed");
49 DEBUG("Iterating over results");
50 while ((ioport = IOIteratorNext(iter))) {
51 if (!(cf_property = IORegistryEntryCreateCFProperty(ioport,
52 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0))) {
53 IOObjectRelease(ioport);
54 continue;
56 result = CFStringGetCString(cf_property, path, sizeof(path),
57 kCFStringEncodingASCII);
58 CFRelease(cf_property);
59 if (!result || strcmp(path, port->name)) {
60 IOObjectRelease(ioport);
61 continue;
63 DEBUG_FMT("Found port %s", path);
65 IORegistryEntryGetParentEntry(ioport, kIOServicePlane, &ioparent);
66 if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane,
67 CFSTR("IOClass"), kCFAllocatorDefault,
68 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
69 if (CFStringGetCString(cf_property, class, sizeof(class),
70 kCFStringEncodingASCII) &&
71 strstr(class, "USB")) {
72 DEBUG("Found USB class device");
73 port->transport = SP_TRANSPORT_USB;
75 CFRelease(cf_property);
77 if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane,
78 CFSTR("IOProviderClass"), kCFAllocatorDefault,
79 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
80 if (CFStringGetCString(cf_property, class, sizeof(class),
81 kCFStringEncodingASCII) &&
82 strstr(class, "USB")) {
83 DEBUG("Found USB class device");
84 port->transport = SP_TRANSPORT_USB;
86 CFRelease(cf_property);
88 IOObjectRelease(ioparent);
90 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
91 CFSTR("USB Interface Name"), kCFAllocatorDefault,
92 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
93 (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
94 CFSTR("USB Product Name"), kCFAllocatorDefault,
95 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
96 (cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
97 CFSTR("Product Name"), kCFAllocatorDefault,
98 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
99 (cf_property = IORegistryEntryCreateCFProperty(ioport,
100 CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
101 if (CFStringGetCString(cf_property, description, sizeof(description),
102 kCFStringEncodingASCII)) {
103 DEBUG_FMT("Found description %s", description);
104 port->description = strdup(description);
106 CFRelease(cf_property);
107 } else {
108 DEBUG("No description for this device");
111 cf_bus = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
112 CFSTR("USBBusNumber"),
113 kCFAllocatorDefault,
114 kIORegistryIterateRecursively
115 | kIORegistryIterateParents);
116 cf_address = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
117 CFSTR("USB Address"),
118 kCFAllocatorDefault,
119 kIORegistryIterateRecursively
120 | kIORegistryIterateParents);
121 if (cf_bus && cf_address &&
122 CFNumberGetValue(cf_bus , kCFNumberIntType, &bus) &&
123 CFNumberGetValue(cf_address, kCFNumberIntType, &address)) {
124 DEBUG_FMT("Found matching USB bus:address %03d:%03d", bus, address);
125 port->usb_bus = bus;
126 port->usb_address = address;
128 if (cf_bus)
129 CFRelease(cf_bus);
130 if (cf_address)
131 CFRelease(cf_address);
133 cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
134 CFSTR("idVendor"),
135 kCFAllocatorDefault,
136 kIORegistryIterateRecursively
137 | kIORegistryIterateParents);
138 cf_product = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane,
139 CFSTR("idProduct"),
140 kCFAllocatorDefault,
141 kIORegistryIterateRecursively
142 | kIORegistryIterateParents);
143 if (cf_vendor && cf_product &&
144 CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
145 CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
146 DEBUG_FMT("Found matching USB VID:PID %04X:%04X", vid, pid);
147 port->usb_vid = vid;
148 port->usb_pid = pid;
150 if (cf_vendor)
151 CFRelease(cf_vendor);
152 if (cf_product)
153 CFRelease(cf_product);
155 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
156 CFSTR("USB Vendor Name"), kCFAllocatorDefault,
157 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
158 if (CFStringGetCString(cf_property, manufacturer, sizeof(manufacturer),
159 kCFStringEncodingASCII)) {
160 DEBUG_FMT("Found manufacturer %s", manufacturer);
161 port->usb_manufacturer = strdup(manufacturer);
163 CFRelease(cf_property);
166 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
167 CFSTR("USB Product Name"), kCFAllocatorDefault,
168 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
169 if (CFStringGetCString(cf_property, product, sizeof(product),
170 kCFStringEncodingASCII)) {
171 DEBUG_FMT("Found product name %s", product);
172 port->usb_product = strdup(product);
174 CFRelease(cf_property);
177 if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane,
178 CFSTR("USB Serial Number"), kCFAllocatorDefault,
179 kIORegistryIterateRecursively | kIORegistryIterateParents))) {
180 if (CFStringGetCString(cf_property, serial, sizeof(serial),
181 kCFStringEncodingASCII)) {
182 DEBUG_FMT("Found serial number %s", serial);
183 port->usb_serial = strdup(serial);
185 CFRelease(cf_property);
188 IOObjectRelease(ioport);
189 break;
191 IOObjectRelease(iter);
193 RETURN_OK();
196 SP_PRIV enum sp_return list_ports(struct sp_port ***list)
198 CFMutableDictionaryRef classes;
199 io_iterator_t iter;
200 char path[PATH_MAX];
201 io_object_t port;
202 CFTypeRef cf_path;
203 Boolean result;
204 int ret = SP_OK;
206 DEBUG("Creating matching dictionary");
207 if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) {
208 SET_FAIL(ret, "IOServiceMatching() failed");
209 goto out_done;
212 DEBUG("Getting matching services");
213 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes,
214 &iter) != KERN_SUCCESS) {
215 SET_FAIL(ret, "IOServiceGetMatchingServices() failed");
216 goto out_done;
219 DEBUG("Iterating over results");
220 while ((port = IOIteratorNext(iter))) {
221 cf_path = IORegistryEntryCreateCFProperty(port,
222 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
223 if (cf_path) {
224 result = CFStringGetCString(cf_path, path, sizeof(path),
225 kCFStringEncodingASCII);
226 CFRelease(cf_path);
227 if (result) {
228 DEBUG_FMT("Found port %s", path);
229 if (!(*list = list_append(*list, path))) {
230 SET_ERROR(ret, SP_ERR_MEM, "List append failed");
231 IOObjectRelease(port);
232 goto out;
236 IOObjectRelease(port);
238 out:
239 IOObjectRelease(iter);
240 out_done:
242 return ret;