1/* 2 * Copyright (c) 2008 Apple 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/* 24cc ionotifyCB.c -o /tmp/ion -Wall -Wno-four-char-constants -framework IOKit -undefined warning 25*/ 26 27#include <ctype.h> 28#include <stdlib.h> 29#include <string.h> 30#include <assert.h> 31#include <limits.h> 32 33#include <mach/mach_interface.h> 34#include <IOKit/IOKitLib.h> 35#include <CoreFoundation/CFRunLoop.h> 36 37mach_port_t masterPort; 38mach_port_t notifyPort; 39CFRunLoopSourceRef cfSource; 40 41void ServiceInterestCallback(void * refcon, io_service_t service, 42 natural_t messageType, void * messageArgument ) 43{ 44 io_name_t name; 45 46 assert( refcon == (void *) masterPort ); 47 48 if( KERN_SUCCESS == IORegistryEntryGetName( service, name )) 49 printf(name); 50 else 51 printf("???"); 52 printf(": messageType %08lx, arg %08lx\n", 53 messageType, messageArgument); 54} 55 56void ServiceArrivalCallback( void * refcon, io_iterator_t iter ) 57{ 58 kern_return_t kr; 59 io_object_t obj; 60 io_name_t name; 61 io_string_t path; 62 mach_port_t note; 63 CFDictionaryRef dict; 64 65 IONotificationPortRef notify = (IONotificationPortRef) refcon; 66 67 while( (obj = IOIteratorNext( iter))) { 68 assert( KERN_SUCCESS == ( 69 kr = IORegistryEntryGetName( obj, name ) 70 )); 71 printf("name:%s(%d)\n", name, obj); 72 73 74 dict = IOCreateDisplayInfoDictionary( obj, kNilOptions ); 75 if( dict) { 76 CFShow( dict ); 77 CFRelease( dict ); 78 } 79 80 kr = IORegistryEntryGetPath( obj, kIOServicePlane, path ); 81 if( KERN_SUCCESS == kr) { 82 83 // if the object is detached, getPath will fail 84 printf("path:%s\n", path); 85 86 // as will IOServiceAddInterestNotification 87 if( KERN_SUCCESS != ( 88 kr = IOServiceAddInterestNotification( 89 notify, 90 obj, kIOGeneralInterest, 91 &ServiceInterestCallback, (void *) masterPort, 92 ¬e ) 93 )) printf("IOServiceAddInterestNotification(%lx)\n", kr); 94 // can compare two kernel objects with IOObjectIsEqualTo() if we keep the object, 95 // otherwise, release 96 IOObjectRelease( obj ); 97 } 98 } 99} 100 101void notifyTest( char * arg ) 102{ 103 kern_return_t kr; 104 io_iterator_t note1, note2; 105 io_service_t obj; 106 const char * type; 107 IONotificationPortRef notify; 108 109 assert( 0 != ( 110 notify = IONotificationPortCreate( masterPort ) 111 )); 112 113 type = kIOMatchedNotification;// or kIOPublishNotification; 114 assert( KERN_SUCCESS == ( 115 kr = IOServiceAddMatchingNotification( 116 notify, 117 type, 118 IOServiceMatching( arg ), 119// IOBSDNameMatching( masterPort, 0, arg ), 120 &ServiceArrivalCallback, (void *) notify, 121 ¬e1 ) 122 )); 123 printf("IOServiceAddMatchingNotification: %s: ", type ); 124 // dumping the iterator gives us the current list 125 // and arms the notification for changes 126 ServiceArrivalCallback ( (void *) notify, note1 ); 127 printf("\n"); 128 129 type = kIOBusyInterest; 130 obj = IORegistryEntryFromPath( masterPort, kIOServicePlane ":/"); 131 assert( obj ); 132 assert( KERN_SUCCESS == ( 133 kr = IOServiceAddInterestNotification( 134 notify, 135 obj, type, 136 &ServiceInterestCallback, (void *) masterPort, 137 ¬e2 ) 138 )); 139 140 CFRunLoopAddSource(CFRunLoopGetCurrent(), 141 IONotificationPortGetRunLoopSource(notify), 142 kCFRunLoopDefaultMode); 143 printf("waiting...\n"); 144 CFRunLoopRun(); // Start silly state machine 145 146 IOObjectRelease( note1 ); 147 IOObjectRelease( note2 ); 148} 149 150int 151main(int argc, char **argv) 152{ 153 kern_return_t kr; 154 155 /* 156 * Get master device port 157 */ 158 assert( KERN_SUCCESS == ( 159 kr = IOMasterPort( bootstrap_port, 160 &masterPort) 161 )); 162 163 if( argc > 1) 164 notifyTest( argv[1] ); 165 else 166 printf("%s className\n", argv[0]); 167 168 printf("Exit\n"); 169} 170 171