2 * Copyright (c) 2002-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 29, 2002 Roger Smith <rsmith@apple.com>
31 #include <sys/types.h>
32 #include <mach/mach.h>
35 #include <CoreFoundation/CoreFoundation.h>
36 #include <CoreFoundation/CFRuntime.h>
38 #include <SystemConfiguration/SystemConfiguration.h>
39 #include <SystemConfiguration/SCValidation.h>
40 #include <SystemConfiguration/SCPrivate.h>
42 #include <IOKit/IOKitLib.h>
43 #include "dy_framework.h"
47 #include "DeviceOnHold.h"
50 #define kIODeviceSupportsHoldKey "V92Modem"
55 /* base CFType information */
58 /* device name (e.g. "modem") */
63 } DeviceOnHoldPrivate
, *DeviceOnHoldPrivateRef
;
67 __DeviceOnHoldCopyDescription(CFTypeRef cf
)
69 CFAllocatorRef allocator
= CFGetAllocator(cf
);
70 CFMutableStringRef result
;
72 result
= CFStringCreateMutable(allocator
, 0);
73 CFStringAppendFormat(result
, NULL
, CFSTR("<DeviceOnHold %p [%p]> {\n"), cf
, allocator
);
74 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
81 __DeviceOnHoldDeallocate(CFTypeRef cf
)
83 DeviceOnHoldPrivateRef DeviceOnHoldPrivate
= (DeviceOnHoldPrivateRef
)cf
;
85 /* release resources */
86 if (DeviceOnHoldPrivate
->name
) CFRelease(DeviceOnHoldPrivate
->name
);
87 if (DeviceOnHoldPrivate
->sock
!= -1) {
95 static CFTypeID __kDeviceOnHoldTypeID
= _kCFRuntimeNotATypeID
;
98 static const CFRuntimeClass __DeviceOnHoldClass
= {
100 "DeviceOnHold", // className
103 __DeviceOnHoldDeallocate
, // dealloc
106 NULL
, // copyFormattingDesc
107 __DeviceOnHoldCopyDescription
// copyDebugDesc
111 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
114 __DeviceOnHoldInitialize(void)
116 __kDeviceOnHoldTypeID
= _CFRuntimeRegisterClass(&__DeviceOnHoldClass
);
121 static DeviceOnHoldPrivateRef
122 __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator
)
124 DeviceOnHoldPrivateRef devicePrivate
;
127 /* initialize runtime */
128 pthread_once(&initialized
, __DeviceOnHoldInitialize
);
130 /* allocate session */
131 size
= sizeof(DeviceOnHoldPrivate
) - sizeof(CFRuntimeBase
);
132 devicePrivate
= (DeviceOnHoldPrivateRef
)_CFRuntimeCreateInstance(allocator
,
133 __kDeviceOnHoldTypeID
,
136 if (!devicePrivate
) {
140 devicePrivate
->name
= NULL
;
141 devicePrivate
->sock
= -1;
143 return devicePrivate
;
148 DeviceOnHoldGetTypeID(void) {
149 pthread_once(&initialized
, __DeviceOnHoldInitialize
); /* initialize runtime */
150 return __kDeviceOnHoldTypeID
;
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.
162 IsDeviceOnHoldSupported(CFStringRef deviceName
, // "modem"
163 CFDictionaryRef options
)
165 CFMutableDictionaryRef deviceToMatch
;
166 uint32_t deviceSupportsHoldValue
;
168 static mach_port_t masterPort
= MACH_PORT_NULL
;
169 io_iterator_t matchingServices
;
171 CFMutableDictionaryRef properties
;
172 Boolean result
= FALSE
;
173 io_service_t service
;
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
) {
183 deviceToMatch
= IOServiceMatching("InternalModemSupport");
184 if (deviceToMatch
== NULL
) {
188 kr
= IOServiceGetMatchingServices(masterPort
, deviceToMatch
, &matchingServices
);
189 if (kr
!= KERN_SUCCESS
) {
193 for ( ; (service
= IOIteratorNext(matchingServices
)) ; IOObjectRelease(service
)) {
196 kr
= IORegistryEntryGetPath(service
, kIOServicePlane
, path
);
197 assert( kr
== KERN_SUCCESS
);
199 // grab a copy of the properties
200 kr
= IORegistryEntryCreateCFProperties(service
, &properties
, kCFAllocatorDefault
, kNilOptions
);
201 assert( kr
== KERN_SUCCESS
);
203 num
= CFDictionaryGetValue(properties
, CFSTR(kIODeviceSupportsHoldKey
));
204 if (isA_CFNumber(num
)) {
205 CFNumberGetValue(num
, kCFNumberSInt32Type
, &deviceSupportsHoldValue
);
206 if (deviceSupportsHoldValue
== 1) {
211 CFRelease(properties
);
214 IOObjectRelease(matchingServices
);
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.
227 DeviceOnHoldCreate(CFAllocatorRef allocator
,
228 CFStringRef deviceName
, // "modem"
229 CFDictionaryRef options
)
231 DeviceOnHoldPrivateRef devicePrivate
;
234 if (CFStringCompare(deviceName
, CFSTR("modem"), 0) != kCFCompareEqualTo
) {
238 devicePrivate
= __DeviceOnHoldCreatePrivate(allocator
);
239 if (!devicePrivate
) {
243 status
= MOHInit(&devicePrivate
->sock
, deviceName
);
245 CFRelease(devicePrivate
);
249 devicePrivate
->name
= CFStringCreateCopy(NULL
, deviceName
);
251 return (DeviceOnHoldRef
)devicePrivate
;
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
);