2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * May 29, 2002 Roger Smith <rsmith@apple.com>
30 #include <sys/types.h>
31 #include <mach/mach.h>
34 #include <CoreFoundation/CoreFoundation.h>
35 #include <CoreFoundation/CFRuntime.h>
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCValidation.h>
39 #include <SystemConfiguration/SCPrivate.h>
41 #include <IOKit/IOKitLib.h>
42 #include "dy_framework.h"
46 #include "DeviceOnHold.h"
49 #define kIODeviceSupportsHoldKey "DeviceSupportsHold"
54 /* base CFType information */
57 /* device name (e.g. "modem") */
62 } DeviceOnHoldPrivate
, *DeviceOnHoldPrivateRef
;
66 __DeviceOnHoldCopyDescription(CFTypeRef cf
)
68 CFAllocatorRef allocator
= CFGetAllocator(cf
);
69 CFMutableStringRef result
;
71 result
= CFStringCreateMutable(allocator
, 0);
72 CFStringAppendFormat(result
, NULL
, CFSTR("<DeviceOnHold %p [%p]> {\n"), cf
, allocator
);
73 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
80 __DeviceOnHoldDeallocate(CFTypeRef cf
)
82 DeviceOnHoldPrivateRef DeviceOnHoldPrivate
= (DeviceOnHoldPrivateRef
)cf
;
84 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__DeviceOnHoldDeallocate:"));
86 /* release resources */
87 if (DeviceOnHoldPrivate
->name
) CFRelease(DeviceOnHoldPrivate
->name
);
88 if (DeviceOnHoldPrivate
->sock
!= -1) {
96 static CFTypeID __kDeviceOnHoldTypeID
= _kCFRuntimeNotATypeID
;
99 static const CFRuntimeClass __DeviceOnHoldClass
= {
101 "DeviceOnHold", // className
104 __DeviceOnHoldDeallocate
, // dealloc
107 NULL
, // copyFormattingDesc
108 __DeviceOnHoldCopyDescription
// copyDebugDesc
112 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
116 __DeviceOnHoldInitialize(void)
118 __kDeviceOnHoldTypeID
= _CFRuntimeRegisterClass(&__DeviceOnHoldClass
);
124 __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator
)
126 DeviceOnHoldPrivateRef devicePrivate
;
129 /* initialize runtime */
130 pthread_once(&initialized
, __DeviceOnHoldInitialize
);
132 /* allocate session */
133 size
= sizeof(DeviceOnHoldPrivate
) - sizeof(CFRuntimeBase
);
134 devicePrivate
= (DeviceOnHoldPrivateRef
)_CFRuntimeCreateInstance(allocator
,
135 __kDeviceOnHoldTypeID
,
138 if (!devicePrivate
) {
142 devicePrivate
->name
= NULL
;
143 devicePrivate
->sock
= -1;
145 return (DeviceOnHoldRef
)devicePrivate
;
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.
157 IsDeviceOnHoldSupported(CFStringRef deviceName
, // "modem"
158 CFDictionaryRef options
)
160 CFMutableDictionaryRef deviceToMatch
;
161 u_int32_t deviceSupportsHoldValue
;
163 mach_port_t masterPort
;
164 io_iterator_t matchingServices
;
166 CFMutableDictionaryRef properties
;
167 Boolean result
= FALSE
;
168 io_service_t service
;
170 if (CFStringCompare(deviceName
, CFSTR("modem"), NULL
) == kCFCompareEqualTo
) {
171 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
172 if (kr
!= KERN_SUCCESS
) {
176 deviceToMatch
= IOServiceMatching("InternalModemSupport");
177 if (!deviceToMatch
) {
181 kr
= IOServiceGetMatchingServices(masterPort
, deviceToMatch
, &matchingServices
);
182 if (kr
!= KERN_SUCCESS
) {
186 for ( ; service
= IOIteratorNext(matchingServices
) ; IOObjectRelease(service
)) {
189 kr
= IORegistryEntryGetPath(service
, kIOServicePlane
, path
);
190 assert( kr
== KERN_SUCCESS
);
192 // grab a copy of the properties
193 kr
= IORegistryEntryCreateCFProperties(service
, &properties
, kCFAllocatorDefault
, kNilOptions
);
194 assert( kr
== KERN_SUCCESS
);
196 num
= CFDictionaryGetValue(properties
, CFSTR(kIODeviceSupportsHoldKey
));
197 if (isA_CFNumber(num
)) {
198 CFNumberGetValue(num
, kCFNumberSInt32Type
, &deviceSupportsHoldValue
);
199 if (deviceSupportsHoldValue
== 1) {
204 CFRelease(properties
);
207 IOObjectRelease(matchingServices
);
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.
224 DeviceOnHoldCreate(CFAllocatorRef allocator
,
225 CFStringRef deviceName
, // "modem"
226 CFDictionaryRef options
)
228 DeviceOnHoldRef device
= NULL
;
229 DeviceOnHoldPrivateRef devicePrivate
;
232 if (CFStringCompare(deviceName
, CFSTR("modem"), NULL
) != kCFCompareEqualTo
) {
236 device
= __DeviceOnHoldCreatePrivate(allocator
);
241 devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
243 status
= MOHInit(&devicePrivate
->sock
, deviceName
);
249 devicePrivate
->name
= CFRetain(deviceName
);
257 DeviceOnHoldGetStatus(DeviceOnHoldRef device
)
259 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
270 if (devicePrivate
->sock
== -1) {
274 err
= MOHExec(devicePrivate
->sock
,
276 MOH_SESSION_GET_STATUS
,
286 if (replyBufLen
== sizeof(result
)) {
287 result
= *(int32_t *)replyBuf
;
290 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
296 DeviceOnHoldSuspend(DeviceOnHoldRef device
)
298 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
303 Boolean result
= FALSE
;
309 if (devicePrivate
->sock
== -1) {
313 err
= MOHExec(devicePrivate
->sock
,
315 MOH_PUT_SESSION_ON_HOLD
,
325 if (replyBufLen
== sizeof(result
)) {
326 result
= (*(int32_t *)replyBuf
) ? TRUE
: FALSE
;
329 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
335 DeviceOnHoldResume(DeviceOnHoldRef device
)
337 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
342 Boolean result
= FALSE
;
348 if (devicePrivate
->sock
== -1) {
352 err
= MOHExec(devicePrivate
->sock
,
354 MOH_RESUME_SESSION_ON_HOLD
,NULL
,
363 if (replyBufLen
== sizeof(result
)) {
364 result
= (*(int32_t *)replyBuf
) ? TRUE
: FALSE
;
367 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);