2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 #include "libaltos_private.h"
19 #include "libaltos_posix.h"
22 #include <IOKit/usb/USBspec.h>
23 #include <IOKit/serial/IOSerialKeys.h>
24 #include <usb/IOUSBLib.h>
25 #include <usb/USBSpec.h>
26 #include <sys/param.h>
31 /* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
33 altos_strndup (const char *s, size_t n)
35 size_t len = strlen (s);
47 io_iterator_t iterator;
52 get_cfstring(CFTypeRef string, char result[512])
56 got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
58 strcpy(result, "CFStringGetCString failed");
63 get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
65 CFTypeRef entry_as_string;
67 char entry_string[512];
69 entry_as_string = IORegistryEntrySearchCFProperty (object,
73 kIORegistryIterateRecursively);
74 if (entry_as_string) {
75 got_string = CFStringGetCString(entry_as_string,
77 kCFStringEncodingASCII);
79 CFRelease(entry_as_string);
88 get_number(io_object_t object, CFStringRef entry, int *result)
90 CFTypeRef entry_as_number;
92 char entry_string[512];
94 entry_as_number = IORegistryEntrySearchCFProperty (object,
98 kIORegistryIterateRecursively);
99 if (entry_as_number) {
100 got_number = CFNumberGetValue(entry_as_number,
110 PUBLIC struct altos_list *
111 altos_list_start(void)
113 struct altos_list *list = calloc (sizeof (struct altos_list), 1);
114 CFMutableDictionaryRef matching_dictionary;
115 io_iterator_t tdIterator;
116 io_object_t tdObject;
120 matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
121 if (matching_dictionary) {
122 CFDictionarySetValue(matching_dictionary,
123 CFSTR(kIOSerialBSDTypeKey),
124 CFSTR(kIOSerialBSDAllTypes));
127 ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
128 if (ret != kIOReturnSuccess) {
136 PUBLIC struct altos_list *
137 altos_ftdi_list_start(void)
139 struct altos_list *list = altos_list_start();
146 static io_service_t get_usb_object(io_object_t serial_device)
148 io_iterator_t iterator;
149 io_service_t usb_device;
150 io_service_t service;
153 status = IORegistryEntryCreateIterator(serial_device,
155 kIORegistryIterateParents | kIORegistryIterateRecursively,
158 if (status != kIOReturnSuccess)
161 while((service = IOIteratorNext(iterator))) {
162 io_name_t servicename;
163 status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);
165 if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
166 IOObjectRelease(iterator);
169 IOObjectRelease(service);
171 IOObjectRelease(iterator);
176 altos_list_next(struct altos_list *list, struct altos_device *device)
180 io_service_t usb_device;
181 char serial_string[128];
184 object = IOIteratorNext(list->iterator);
189 usb_device = get_usb_object(object);
191 if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
192 get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
193 get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
194 get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
195 get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
196 device->serial = atoi(serial_string);
197 IOObjectRelease(object);
198 IOObjectRelease(usb_device);
201 IOObjectRelease(object);
202 IOObjectRelease(usb_device);
207 altos_list_finish(struct altos_list *list)
209 IOObjectRelease (list->iterator);
213 struct altos_bt_list {
220 #define INQUIRY_MAX_RSP 255
222 struct altos_bt_list *
223 altos_bt_list_start(int inquiry_time)
229 altos_bt_list_next(struct altos_bt_list *bt_list,
230 struct altos_bt_device *device)
236 altos_bt_list_finish(struct altos_bt_list *bt_list)
241 altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
243 strncpy(device->name, name, sizeof (device->name));
244 device->name[sizeof(device->name)-1] = '\0';
245 strncpy(device->addr, addr, sizeof (device->addr));
246 device->addr[sizeof(device->addr)-1] = '\0';
250 altos_bt_open(struct altos_bt_device *device)