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