2 * Copyright (c) 2002-2003 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 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("__DeviceOnHoldDeallocate:"));
87 /* release resources */
88 if (DeviceOnHoldPrivate
->name
) CFRelease(DeviceOnHoldPrivate
->name
);
89 if (DeviceOnHoldPrivate
->sock
!= -1) {
97 static CFTypeID __kDeviceOnHoldTypeID
= _kCFRuntimeNotATypeID
;
100 static const CFRuntimeClass __DeviceOnHoldClass
= {
102 "DeviceOnHold", // className
105 __DeviceOnHoldDeallocate
, // dealloc
108 NULL
, // copyFormattingDesc
109 __DeviceOnHoldCopyDescription
// copyDebugDesc
113 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
116 __DeviceOnHoldInitialize(void)
118 __kDeviceOnHoldTypeID
= _CFRuntimeRegisterClass(&__DeviceOnHoldClass
);
123 static DeviceOnHoldPrivateRef
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 devicePrivate
;
150 DeviceOnHoldGetTypeID(void) {
151 pthread_once(&initialized
, __DeviceOnHoldInitialize
); /* initialize runtime */
152 return __kDeviceOnHoldTypeID
;
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.
164 IsDeviceOnHoldSupported(CFStringRef deviceName
, // "modem"
165 CFDictionaryRef options
)
167 CFMutableDictionaryRef deviceToMatch
;
168 uint32_t deviceSupportsHoldValue
;
170 mach_port_t masterPort
;
171 io_iterator_t matchingServices
;
173 CFMutableDictionaryRef properties
;
174 Boolean result
= FALSE
;
175 io_service_t service
;
177 if (CFStringCompare(deviceName
, CFSTR("modem"), NULL
) == kCFCompareEqualTo
) {
178 kr
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
179 if (kr
!= KERN_SUCCESS
) {
183 deviceToMatch
= IOServiceMatching("InternalModemSupport");
184 if (!deviceToMatch
) {
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.
231 DeviceOnHoldCreate(CFAllocatorRef allocator
,
232 CFStringRef deviceName
, // "modem"
233 CFDictionaryRef options
)
235 DeviceOnHoldPrivateRef devicePrivate
;
238 if (CFStringCompare(deviceName
, CFSTR("modem"), NULL
) != kCFCompareEqualTo
) {
242 devicePrivate
= __DeviceOnHoldCreatePrivate(allocator
);
243 if (!devicePrivate
) {
247 status
= MOHInit(&devicePrivate
->sock
, deviceName
);
249 CFRelease(devicePrivate
);
253 devicePrivate
->name
= CFStringCreateCopy(NULL
, deviceName
);
255 return (DeviceOnHoldRef
)devicePrivate
;
261 DeviceOnHoldGetStatus(DeviceOnHoldRef device
)
263 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
274 if (devicePrivate
->sock
== -1) {
278 err
= MOHExec(devicePrivate
->sock
,
280 MOH_SESSION_GET_STATUS
,
290 if (replyBufLen
== sizeof(result
)) {
291 result
= *(int32_t *)replyBuf
;
294 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
300 DeviceOnHoldSuspend(DeviceOnHoldRef device
)
302 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
307 Boolean result
= FALSE
;
313 if (devicePrivate
->sock
== -1) {
317 err
= MOHExec(devicePrivate
->sock
,
319 MOH_PUT_SESSION_ON_HOLD
,
329 if (replyBufLen
== sizeof(result
)) {
330 result
= (*(int32_t *)replyBuf
) ? TRUE
: FALSE
;
333 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);
339 DeviceOnHoldResume(DeviceOnHoldRef device
)
341 DeviceOnHoldPrivateRef devicePrivate
= (DeviceOnHoldPrivateRef
)device
;
346 Boolean result
= FALSE
;
352 if (devicePrivate
->sock
== -1) {
356 err
= MOHExec(devicePrivate
->sock
,
358 MOH_RESUME_SESSION_ON_HOLD
,NULL
,
367 if (replyBufLen
== sizeof(result
)) {
368 result
= (*(int32_t *)replyBuf
) ? TRUE
: FALSE
;
371 if (replyBuf
) CFAllocatorDeallocate(NULL
, replyBuf
);