]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/DeviceOnHold.c
fbeea30c419da4ca49b743a39965a3ef56698400
[apple/configd.git] / SystemConfiguration.fproj / DeviceOnHold.c
1 /*
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * May 29, 2002 Roger Smith <rsmith@apple.com>
27 * - initial revision
28 */
29
30 #include <sys/types.h>
31 #include <mach/mach.h>
32 #include <pthread.h>
33
34 #include <CoreFoundation/CoreFoundation.h>
35 #include <CoreFoundation/CFRuntime.h>
36
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCValidation.h>
39 #include <SystemConfiguration/SCPrivate.h>
40
41 #include <IOKit/IOKitLib.h>
42 #include "dy_framework.h"
43
44 #include "moh_msg.h"
45 #include "moh.h"
46 #include "DeviceOnHold.h"
47
48
49 #define kIODeviceSupportsHoldKey "DeviceSupportsHold"
50
51
52 typedef struct {
53
54 /* base CFType information */
55 CFRuntimeBase cfBase;
56
57 /* device name (e.g. "modem") */
58 CFStringRef name;
59
60 int sock;
61
62 } DeviceOnHoldPrivate, *DeviceOnHoldPrivateRef;
63
64
65 static CFStringRef
66 __DeviceOnHoldCopyDescription(CFTypeRef cf)
67 {
68 CFAllocatorRef allocator = CFGetAllocator(cf);
69 CFMutableStringRef result;
70
71 result = CFStringCreateMutable(allocator, 0);
72 CFStringAppendFormat(result, NULL, CFSTR("<DeviceOnHold %p [%p]> {\n"), cf, allocator);
73 CFStringAppendFormat(result, NULL, CFSTR("}"));
74
75 return result;
76 }
77
78
79 static void
80 __DeviceOnHoldDeallocate(CFTypeRef cf)
81 {
82 DeviceOnHoldPrivateRef DeviceOnHoldPrivate = (DeviceOnHoldPrivateRef)cf;
83
84 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__DeviceOnHoldDeallocate:"));
85
86 /* release resources */
87 if (DeviceOnHoldPrivate->name) CFRelease(DeviceOnHoldPrivate->name);
88 if (DeviceOnHoldPrivate->sock != -1) {
89
90 }
91
92 return;
93 }
94
95
96 static CFTypeID __kDeviceOnHoldTypeID = _kCFRuntimeNotATypeID;
97
98
99 static const CFRuntimeClass __DeviceOnHoldClass = {
100 0, // version
101 "DeviceOnHold", // className
102 NULL, // init
103 NULL, // copy
104 __DeviceOnHoldDeallocate, // dealloc
105 NULL, // equal
106 NULL, // hash
107 NULL, // copyFormattingDesc
108 __DeviceOnHoldCopyDescription // copyDebugDesc
109 };
110
111
112 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
113
114
115 static void
116 __DeviceOnHoldInitialize(void)
117 {
118 __kDeviceOnHoldTypeID = _CFRuntimeRegisterClass(&__DeviceOnHoldClass);
119 return;
120 }
121
122
123 DeviceOnHoldRef
124 __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator)
125 {
126 DeviceOnHoldPrivateRef devicePrivate;
127 UInt32 size;
128
129 /* initialize runtime */
130 pthread_once(&initialized, __DeviceOnHoldInitialize);
131
132 /* allocate session */
133 size = sizeof(DeviceOnHoldPrivate) - sizeof(CFRuntimeBase);
134 devicePrivate = (DeviceOnHoldPrivateRef)_CFRuntimeCreateInstance(allocator,
135 __kDeviceOnHoldTypeID,
136 size,
137 NULL);
138 if (!devicePrivate) {
139 return NULL;
140 }
141
142 devicePrivate->name = NULL;
143 devicePrivate->sock = -1;
144
145 return (DeviceOnHoldRef)devicePrivate;
146 }
147
148
149 /*
150 * TBD: We determine whether a device supports on hold capability by looking at
151 * the numeric property DeviceSupportsHold (1 - yes, 0 or no property - no). For
152 * the Apple Dash II internal modem we also use the property V92Modem to track
153 * this same capability.
154 */
155
156 Boolean
157 IsDeviceOnHoldSupported(CFStringRef deviceName, // "modem"
158 CFDictionaryRef options)
159 {
160 CFMutableDictionaryRef deviceToMatch;
161 u_int32_t deviceSupportsHoldValue;
162 kern_return_t kr;
163 mach_port_t masterPort;
164 io_iterator_t matchingServices;
165 CFNumberRef num;
166 CFMutableDictionaryRef properties;
167 Boolean result = FALSE;
168 io_service_t service;
169
170 if (CFStringCompare(deviceName, CFSTR("modem"), NULL) == kCFCompareEqualTo) {
171 kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
172 if (kr != KERN_SUCCESS) {
173 goto errorExit;
174 }
175
176 deviceToMatch = IOServiceMatching("InternalModemSupport");
177 if (!deviceToMatch) {
178 goto errorExit;
179 }
180
181 kr = IOServiceGetMatchingServices(masterPort, deviceToMatch, &matchingServices);
182 if (kr != KERN_SUCCESS) {
183 goto errorExit;
184 }
185
186 for ( ; service = IOIteratorNext(matchingServices) ; IOObjectRelease(service)) {
187 io_string_t path;
188
189 kr = IORegistryEntryGetPath(service, kIOServicePlane, path);
190 assert( kr == KERN_SUCCESS );
191
192 // grab a copy of the properties
193 kr = IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions);
194 assert( kr == KERN_SUCCESS );
195
196 num = CFDictionaryGetValue(properties, CFSTR(kIODeviceSupportsHoldKey));
197 if (isA_CFNumber(num)) {
198 CFNumberGetValue(num, kCFNumberSInt32Type, &deviceSupportsHoldValue);
199 if (deviceSupportsHoldValue == 1) {
200 result = TRUE;
201 }
202 }
203
204 CFRelease(properties);
205 }
206
207 IOObjectRelease(matchingServices);
208 }
209
210 // Note: The issue for the general case is how to go from the SystemConfiguration
211 // dynamic store to the actual driver. The devicesupportshold property is not
212 // copied the either of the setup/state descriptions so the caller would need
213 // to know the exact driver they are searching for.
214
215 return result;
216
217 errorExit:
218
219 return FALSE;
220 }
221
222
223 DeviceOnHoldRef
224 DeviceOnHoldCreate(CFAllocatorRef allocator,
225 CFStringRef deviceName, // "modem"
226 CFDictionaryRef options)
227 {
228 DeviceOnHoldRef device = NULL;
229 DeviceOnHoldPrivateRef devicePrivate;
230 int status;
231
232 if (CFStringCompare(deviceName, CFSTR("modem"), NULL) != kCFCompareEqualTo) {
233 return NULL;
234 }
235
236 device = __DeviceOnHoldCreatePrivate(allocator);
237 if (!device) {
238 return NULL;
239 }
240
241 devicePrivate = (DeviceOnHoldPrivateRef)device;
242
243 status = MOHInit(&devicePrivate->sock, deviceName);
244 if (status != 0) {
245 CFRelease(device);
246 return NULL;
247 }
248
249 devicePrivate->name = CFRetain(deviceName);
250
251 return device;
252 }
253
254
255
256 int32_t
257 DeviceOnHoldGetStatus(DeviceOnHoldRef device)
258 {
259 DeviceOnHoldPrivateRef devicePrivate = (DeviceOnHoldPrivateRef)device;
260 int err;
261 u_long link = 1;
262 void *replyBuf;
263 u_long replyBufLen;
264 int32_t result = -1;
265
266 if (!device) {
267 return -1;
268 }
269
270 if (devicePrivate->sock == -1) {
271 return -1;
272 }
273
274 err = MOHExec(devicePrivate->sock,
275 link,
276 MOH_SESSION_GET_STATUS,
277 NULL,
278 0,
279 &replyBuf,
280 &replyBufLen);
281
282 if (err != 0) {
283 return -1;
284 }
285
286 if (replyBufLen == sizeof(result)) {
287 result = *(int32_t *)replyBuf;
288 }
289
290 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
291 return result;
292 }
293
294
295 Boolean
296 DeviceOnHoldSuspend(DeviceOnHoldRef device)
297 {
298 DeviceOnHoldPrivateRef devicePrivate = (DeviceOnHoldPrivateRef)device;
299 int err;
300 u_long link = 1;
301 void *replyBuf;
302 u_long replyBufLen;
303 Boolean result = FALSE;
304
305 if (!device) {
306 return FALSE;
307 }
308
309 if (devicePrivate->sock == -1) {
310 return FALSE;
311 }
312
313 err = MOHExec(devicePrivate->sock,
314 link,
315 MOH_PUT_SESSION_ON_HOLD,
316 NULL,
317 0,
318 &replyBuf,
319 &replyBufLen);
320
321 if (err != 0) {
322 return -1;
323 }
324
325 if (replyBufLen == sizeof(result)) {
326 result = (*(int32_t *)replyBuf) ? TRUE : FALSE;
327 }
328
329 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
330 return result;
331 }
332
333
334 Boolean
335 DeviceOnHoldResume(DeviceOnHoldRef device)
336 {
337 DeviceOnHoldPrivateRef devicePrivate = (DeviceOnHoldPrivateRef)device;
338 int err;
339 u_long link = 1;
340 void *replyBuf;
341 u_long replyBufLen;
342 Boolean result = FALSE;
343
344 if (!device) {
345 return FALSE;
346 }
347
348 if (devicePrivate->sock == -1) {
349 return FALSE;
350 }
351
352 err = MOHExec(devicePrivate->sock,
353 link,
354 MOH_RESUME_SESSION_ON_HOLD,NULL,
355 0,
356 &replyBuf,
357 &replyBufLen);
358
359 if (err != 0) {
360 return -1;
361 }
362
363 if (replyBufLen == sizeof(result)) {
364 result = (*(int32_t *)replyBuf) ? TRUE : FALSE;
365 }
366
367 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
368 return result;
369 }