]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/DeviceOnHold.c
0ee06ce981e4c2f1fe867f178d14abb00b62d6a5
[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 * 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 SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__DeviceOnHoldDeallocate:"));
86
87 /* release resources */
88 if (DeviceOnHoldPrivate->name) CFRelease(DeviceOnHoldPrivate->name);
89 if (DeviceOnHoldPrivate->sock != -1) {
90
91 }
92
93 return;
94 }
95
96
97 static CFTypeID __kDeviceOnHoldTypeID = _kCFRuntimeNotATypeID;
98
99
100 static const CFRuntimeClass __DeviceOnHoldClass = {
101 0, // version
102 "DeviceOnHold", // className
103 NULL, // init
104 NULL, // copy
105 __DeviceOnHoldDeallocate, // dealloc
106 NULL, // equal
107 NULL, // hash
108 NULL, // copyFormattingDesc
109 __DeviceOnHoldCopyDescription // copyDebugDesc
110 };
111
112
113 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
114
115 static void
116 __DeviceOnHoldInitialize(void)
117 {
118 __kDeviceOnHoldTypeID = _CFRuntimeRegisterClass(&__DeviceOnHoldClass);
119 return;
120 }
121
122
123 static DeviceOnHoldPrivateRef
124 __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator)
125 {
126 DeviceOnHoldPrivateRef devicePrivate;
127 uint32_t 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 devicePrivate;
146 }
147
148
149 CFTypeID
150 DeviceOnHoldGetTypeID(void) {
151 pthread_once(&initialized, __DeviceOnHoldInitialize); /* initialize runtime */
152 return __kDeviceOnHoldTypeID;
153 }
154
155
156 /*
157 * TBD: We determine whether a device supports on hold capability by looking at
158 * the numeric property DeviceSupportsHold (1 - yes, 0 or no property - no). For
159 * the Apple Dash II internal modem we also use the property V92Modem to track
160 * this same capability.
161 */
162
163 Boolean
164 IsDeviceOnHoldSupported(CFStringRef deviceName, // "modem"
165 CFDictionaryRef options)
166 {
167 CFMutableDictionaryRef deviceToMatch;
168 uint32_t deviceSupportsHoldValue;
169 kern_return_t kr;
170 mach_port_t masterPort;
171 io_iterator_t matchingServices;
172 CFNumberRef num;
173 CFMutableDictionaryRef properties;
174 Boolean result = FALSE;
175 io_service_t service;
176
177 if (CFStringCompare(deviceName, CFSTR("modem"), NULL) == kCFCompareEqualTo) {
178 kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
179 if (kr != KERN_SUCCESS) {
180 goto errorExit;
181 }
182
183 deviceToMatch = IOServiceMatching("InternalModemSupport");
184 if (!deviceToMatch) {
185 goto errorExit;
186 }
187
188 kr = IOServiceGetMatchingServices(masterPort, deviceToMatch, &matchingServices);
189 if (kr != KERN_SUCCESS) {
190 goto errorExit;
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 errorExit:
225
226 return FALSE;
227 }
228
229
230 DeviceOnHoldRef
231 DeviceOnHoldCreate(CFAllocatorRef allocator,
232 CFStringRef deviceName, // "modem"
233 CFDictionaryRef options)
234 {
235 DeviceOnHoldPrivateRef devicePrivate;
236 int status;
237
238 if (CFStringCompare(deviceName, CFSTR("modem"), NULL) != kCFCompareEqualTo) {
239 return NULL;
240 }
241
242 devicePrivate = __DeviceOnHoldCreatePrivate(allocator);
243 if (!devicePrivate) {
244 return NULL;
245 }
246
247 status = MOHInit(&devicePrivate->sock, deviceName);
248 if (status != 0) {
249 CFRelease(devicePrivate);
250 return NULL;
251 }
252
253 devicePrivate->name = CFStringCreateCopy(NULL, deviceName);
254
255 return (DeviceOnHoldRef)devicePrivate;
256 }
257
258
259
260 int32_t
261 DeviceOnHoldGetStatus(DeviceOnHoldRef device)
262 {
263 DeviceOnHoldPrivateRef devicePrivate = (DeviceOnHoldPrivateRef)device;
264 int err;
265 u_long link = 1;
266 void *replyBuf;
267 u_long replyBufLen;
268 int32_t result = -1;
269
270 if (!device) {
271 return -1;
272 }
273
274 if (devicePrivate->sock == -1) {
275 return -1;
276 }
277
278 err = MOHExec(devicePrivate->sock,
279 link,
280 MOH_SESSION_GET_STATUS,
281 NULL,
282 0,
283 &replyBuf,
284 &replyBufLen);
285
286 if (err != 0) {
287 return -1;
288 }
289
290 if (replyBufLen == sizeof(result)) {
291 result = *(int32_t *)replyBuf;
292 }
293
294 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
295 return result;
296 }
297
298
299 Boolean
300 DeviceOnHoldSuspend(DeviceOnHoldRef device)
301 {
302 DeviceOnHoldPrivateRef devicePrivate = (DeviceOnHoldPrivateRef)device;
303 int err;
304 u_long link = 1;
305 void *replyBuf;
306 u_long replyBufLen;
307 Boolean result = FALSE;
308
309 if (!device) {
310 return FALSE;
311 }
312
313 if (devicePrivate->sock == -1) {
314 return FALSE;
315 }
316
317 err = MOHExec(devicePrivate->sock,
318 link,
319 MOH_PUT_SESSION_ON_HOLD,
320 NULL,
321 0,
322 &replyBuf,
323 &replyBufLen);
324
325 if (err != 0) {
326 return -1;
327 }
328
329 if (replyBufLen == sizeof(result)) {
330 result = (*(int32_t *)replyBuf) ? TRUE : FALSE;
331 }
332
333 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
334 return result;
335 }
336
337
338 Boolean
339 DeviceOnHoldResume(DeviceOnHoldRef device)
340 {
341 DeviceOnHoldPrivateRef devicePrivate = (DeviceOnHoldPrivateRef)device;
342 int err;
343 u_long link = 1;
344 void *replyBuf;
345 u_long replyBufLen;
346 Boolean result = FALSE;
347
348 if (!device) {
349 return FALSE;
350 }
351
352 if (devicePrivate->sock == -1) {
353 return FALSE;
354 }
355
356 err = MOHExec(devicePrivate->sock,
357 link,
358 MOH_RESUME_SESSION_ON_HOLD,NULL,
359 0,
360 &replyBuf,
361 &replyBufLen);
362
363 if (err != 0) {
364 return -1;
365 }
366
367 if (replyBufLen == sizeof(result)) {
368 result = (*(int32_t *)replyBuf) ? TRUE : FALSE;
369 }
370
371 if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
372 return result;
373 }