File: libaltos_darwin.c

package info (click to toggle)
altos 1.6.8-5
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 63,748 kB
  • ctags: 36,577
  • sloc: ansic: 92,100; java: 36,273; makefile: 6,495; xml: 3,096; sh: 1,971; pascal: 1,581
file content (254 lines) | stat: -rw-r--r-- 6,024 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
 * Copyright © 2016 Keith Packard <keithp@keithp.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 */

#include "libaltos_private.h"
#include "libaltos_posix.h"

#include <IOKitLib.h>
#include <IOKit/usb/USBspec.h>
#include <IOKit/serial/IOSerialKeys.h>
#include <usb/IOUSBLib.h>
#include <usb/USBSpec.h>
#include <sys/param.h>
#include <paths.h>
#include <CFNumber.h>
#include <IOBSD.h>

/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
char *
altos_strndup (const char *s, size_t n)
{
    size_t len = strlen (s);
    char *ret;

    if (len <= n)
       return strdup (s);
    ret = malloc(n + 1);
    strncpy(ret, s, n);
    ret[n] = '\0';
    return ret;
}

struct altos_list {
	io_iterator_t iterator;
	int ftdi;
};

static char *
get_cfstring(CFTypeRef string, char result[512])
{
	Boolean		got_string;

	got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
	if (!got_string)
		strcpy(result, "CFStringGetCString failed");
	return result;
}

static int
get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
{
	CFTypeRef entry_as_string;
	Boolean got_string;
	char entry_string[512];

	entry_as_string = IORegistryEntrySearchCFProperty (object,
							   kIOServicePlane,
							   entry,
							   kCFAllocatorDefault,
							   kIORegistryIterateRecursively);
	if (entry_as_string) {
		got_string = CFStringGetCString(entry_as_string,
						result, result_len,
						kCFStringEncodingASCII);

		CFRelease(entry_as_string);
		if (got_string) {
			return 1;
		}
	}
	return 0;
}

static int
get_number(io_object_t object, CFStringRef entry, int *result)
{
	CFTypeRef entry_as_number;
	Boolean got_number;
	char entry_string[512];

	entry_as_number = IORegistryEntrySearchCFProperty (object,
							   kIOServicePlane,
							   entry,
							   kCFAllocatorDefault,
							   kIORegistryIterateRecursively);
	if (entry_as_number) {
		got_number = CFNumberGetValue(entry_as_number,
					      kCFNumberIntType,
					      result);
		if (got_number) {
			return 1;
		}
	}
	return 0;
}

PUBLIC struct altos_list *
altos_list_start(void)
{
	struct altos_list *list = calloc (sizeof (struct altos_list), 1);
	CFMutableDictionaryRef matching_dictionary;
	io_iterator_t tdIterator;
	io_object_t tdObject;
	kern_return_t ret;
	int i;

	matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
	if (matching_dictionary) {
		CFDictionarySetValue(matching_dictionary,
				     CFSTR(kIOSerialBSDTypeKey),
				     CFSTR(kIOSerialBSDAllTypes));
	}

	ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
	if (ret != kIOReturnSuccess) {
		free(list);
		return NULL;
	}
	list->ftdi = 0;
	return list;
}

PUBLIC struct altos_list *
altos_ftdi_list_start(void)
{
	struct altos_list *list = altos_list_start();

	if (list)
		list->ftdi = 1;
	return list;
}

static io_service_t get_usb_object(io_object_t serial_device)
{
	io_iterator_t iterator;
	io_service_t usb_device;
	io_service_t service;
	IOReturn status;

	status = IORegistryEntryCreateIterator(serial_device,
				      kIOServicePlane,
				      kIORegistryIterateParents | kIORegistryIterateRecursively,
				      &iterator);

	if (status != kIOReturnSuccess)
		return 0;

	while((service = IOIteratorNext(iterator))) {
		io_name_t servicename;
		status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);

		if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
			IOObjectRelease(iterator);
			return service;
		}
		IOObjectRelease(service);
	}
	IOObjectRelease(iterator);
	return 0;
}

PUBLIC int
altos_list_next(struct altos_list *list, struct altos_device *device)
{

	io_object_t object;
	io_service_t usb_device;
	char serial_string[128];

	for (;;) {
		object = IOIteratorNext(list->iterator);
		if (!object) {
			return 0;
		}

		usb_device = get_usb_object(object);

		if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
		    get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
		    get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
		    get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
		    get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
			device->serial = atoi(serial_string);
			IOObjectRelease(object);
			IOObjectRelease(usb_device);
			return 1;
		}
		IOObjectRelease(object);
		IOObjectRelease(usb_device);
	}
}

PUBLIC void
altos_list_finish(struct altos_list *list)
{
	IOObjectRelease (list->iterator);
	free(list);
}

struct altos_bt_list {
	int		sock;
	int		dev_id;
	int		rsp;
	int		num_rsp;
};

#define INQUIRY_MAX_RSP	255

struct altos_bt_list *
altos_bt_list_start(int inquiry_time)
{
	return NULL;
}

int
altos_bt_list_next(struct altos_bt_list *bt_list,
		   struct altos_bt_device *device)
{
	return 0;
}

void
altos_bt_list_finish(struct altos_bt_list *bt_list)
{
}

void
altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
{
	strncpy(device->name, name, sizeof (device->name));
	device->name[sizeof(device->name)-1] = '\0';
	strncpy(device->addr, addr, sizeof (device->addr));
	device->addr[sizeof(device->addr)-1] = '\0';
}

struct altos_file *
altos_bt_open(struct altos_bt_device *device)
{
	return NULL;
}