2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * May 29, 2002 Roger Smith <rsmith@apple.com>
33 #include <sys/types.h>
34 #include <mach/mach.h>
37 #include <CoreFoundation/CoreFoundation.h>
38 #include <CoreFoundation/CFRuntime.h>
40 #include <SystemConfiguration/SystemConfiguration.h>
41 #include <SystemConfiguration/SCValidation.h>
42 #include <SystemConfiguration/SCPrivate.h>
44 #include <IOKit/IOKitLib.h>
45 #include "dy_framework.h"
49 #include "DeviceOnHold.h"
52 #define kIODeviceSupportsHoldKey "V92Modem"
57 /* base CFType information */
60 /* device name (e.g. "modem") */
65 } DeviceOnHoldPrivate
, *DeviceOnHoldPrivateRef
;
69 __DeviceOnHoldCopyDescription(CFTypeRef cf
)
71 CFAllocatorRef allocator
= CFGetAllocator(cf
);
72 CFMutableStringRef result
;
74 result
= CFStringCreateMutable(allocator
, 0);
75 CFStringAppendFormat(result
, NULL
, CFSTR("<DeviceOnHold %p [%p]> {\n"), cf
, allocator
);
76 CFStringAppendFormat(result
, NULL
, CFSTR("}"));
83 __DeviceOnHoldDeallocate(CFTypeRef cf
)
85 DeviceOnHoldPrivateRef DeviceOnHoldPrivate
= (DeviceOnHoldPrivateRef
)cf
;
87 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__DeviceOnHoldDeallocate:"));
89 /* release resources */
90 if (DeviceOnHoldPrivate
->name
) CFRelease(DeviceOnHoldPrivate
->name
);
91 if (DeviceOnHoldPrivate
->sock
!= -1) {
99 static CFTypeID __kDeviceOnHoldTypeID
= _kCFRuntimeNotATypeID
;
102 static const CFRuntimeClass __DeviceOnHoldClass
= {
104 "DeviceOnHold", // className
107 __DeviceOnHoldDeallocate
, // dealloc
110 NULL
, // copyFormattingDesc
111 __DeviceOnHoldCopyDescription
// copyDebugDesc
115 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
118 __DeviceOnHoldInitialize(void)
120 __kDeviceOnHoldTypeID
= _CFRuntimeRegisterClass(&__DeviceOnHoldClass
);
125 static DeviceOnHoldPrivateRef
126 __DeviceOnHoldCreatePrivate(CFAllocatorRef allocator
)
128 DeviceOnHoldPrivateRef devicePrivate
;
131 /* initialize runtime */
132 pthread_once(&initialized
, __DeviceOnHoldInitialize
);
134 /* allocate session */
135 size
= sizeof(DeviceOnHoldPrivate
) - sizeof(CFRuntimeBase
);
136 devicePrivate
= (DeviceOnHoldPrivateRef
)_CFRuntimeCreateInstance(allocator
,
137 __kDeviceOnHoldTypeID
,
140 if (!devicePrivate
) {
144 devicePrivate
->name
= NULL
;
145 devicePrivate
->sock
= -1;
147 return devicePrivate
;
152 DeviceOnHoldGetTypeID(void) {
153 pthread_once(&initialized
, __DeviceOnHoldInitialize
); /* initialize runtime */
154 return __kDeviceOnHoldTypeID
;
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.
166 IsDeviceOnHoldSupported(CFStringRef deviceName
, // "modem"
167 CFDictionaryRef options
)
169 CFMutableDictionaryRef deviceToMatch
;
170 uint32_t deviceSupportsHoldValue
;
172 mach_port_t masterPort
;
173 io_iterator_t matchingServices
;
175 CFMutableDictionaryRef properties
;
176 Boolean result
= FALSE
;
177 io_service_t service
;
179 if (CFStringCompare(deviceName
, CFSTR("modem"), NULL
) == kCFCompareEqualTo
) {
180 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
181 if (kr
!= KERN_SUCCESS
) {
185 deviceToMatch
= IOServiceMatching("InternalModemSupport");
186 if (!deviceToMatch
) {
190 kr
= IOServiceGetMatchingServices(masterPort
, deviceToMatch
, &matchingServices
);
191 if (kr
!= KERN_SUCCESS
) {
195 for ( ; (service
= IOIteratorNext(matchingServices
)) ; IOObjectRelease(service
)) {
198 kr
= IORegistryEntryGetPath(service
, kIOServicePlane
, path
);
199 assert( kr
== KERN_SUCCESS
);
201 // grab a copy of the properties
202 kr
= IORegistryEntryCreateCFProperties(service
, &properties
, kCFAllocatorDefault
, kNilOptions
);
203 assert( kr
== KERN_SUCCESS
);
205 num
= CFDictionaryGetValue(properties
, CFSTR(kIODeviceSupportsHoldKey
));
206 if (isA_CFNumber(num
)) {
207 CFNumberGetValue(num
, kCFNumberSInt32Type
, &deviceSupportsHoldValue
);
208 if (deviceSupportsHoldValue
== 1) {
213 CFRelease(properties
);
216 IOObjectRelease(matchingServices
);
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.
233 DeviceOnHoldCreate(CFAllocatorRef allocator
,
234 CFStringRef deviceName
, // "modem"
235 CFDictionaryRef options
)
237 DeviceOnHoldPrivateRef devicePrivate
;
240 if (CFStringCompare(deviceName
, CFSTR("modem"), NULL
) != kCFCompareEqualTo
) {
244 devicePrivate
= __DeviceOnHoldCreatePrivate(allocator
);
245 if (!devicePrivate
) {
249 status
= MOHInit(&devicePrivate
->sock
, deviceName
);
251 CFRelease(devicePrivate
);
255 devicePrivate
->name
= CFStringCreateCopy(NULL
, deviceName
);
257 return (DeviceOnHoldRef
)devicePrivate
;
263 DeviceOnHoldGetStatus(DeviceOnHoldRef device
)
265 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
276 if (devicePrivate
->sock
== -1) {
280 err
= MOHExec(devicePrivate
->sock
,
282 MOH_SESSION_GET_STATUS
,
292 if (replyBufLen
== sizeof(result
)) {
293 result
= *(int32_t *)replyBuf
;
296 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
302 DeviceOnHoldSuspend(DeviceOnHoldRef device
)
304 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
309 Boolean result
= FALSE
;
315 if (devicePrivate
->sock
== -1) {
319 err
= MOHExec(devicePrivate
->sock
,
321 MOH_PUT_SESSION_ON_HOLD
,
331 if (replyBufLen
== sizeof(result
)) {
332 result
= (*(int32_t *)replyBuf
) ? TRUE
: FALSE
;
335 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
341 DeviceOnHoldResume(DeviceOnHoldRef device
)
343 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
348 Boolean result
= FALSE
;
354 if (devicePrivate
->sock
== -1) {
358 err
= MOHExec(devicePrivate
->sock
,
360 MOH_RESUME_SESSION_ON_HOLD
,NULL
,
369 if (replyBufLen
== sizeof(result
)) {
370 result
= (*(int32_t *)replyBuf
) ? TRUE
: FALSE
;
373 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);