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