1/* 2 * Copyright (c) 2000 Apple Computer, 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 ionotify.c -o notify -Wall -Wno-four-char-constants -framework IOKit 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 36mach_port_t masterPort; 37 38void dumpIter( io_iterator_t iter, mach_port_t recvPort ) 39{ 40 kern_return_t kr; 41 io_object_t obj; 42 io_name_t name; 43 io_string_t path; 44 mach_port_t iter3; 45 46 while( (obj = IOIteratorNext( iter))) { 47 assert( KERN_SUCCESS == ( 48 kr = IORegistryEntryGetName( obj, name ) 49 )); 50 printf("name:%s(%d)\n", name, obj); 51 kr = IORegistryEntryGetPath( obj, kIOServicePlane, path ); 52 if( KERN_SUCCESS == kr) { 53 54 // if the object is detached, getPath will fail 55 printf("path:%s\n", path); 56 57 // as will IOServiceAddInterestNotification 58 if( KERN_SUCCESS != ( 59 kr = IOServiceAddInterestNotificationMsg( obj, kIOGeneralInterest, 60 recvPort, (unsigned int) obj, &iter3) 61 )) printf("IOServiceAddInterestNotification(%lx)\n", kr); 62 // can compare two kernel objects with IOObjectIsEqualTo() if we keep the object, 63 // otherwise, release 64 IOObjectRelease( obj ); 65 } 66 } 67} 68 69 70void notifyTest( char * arg ) 71{ 72 kern_return_t kr; 73 io_iterator_t iter1, iter2, iter3; 74 mach_port_t port; 75 io_service_t obj; 76 io_name_t name; 77 const char * type; 78 IOServiceInterestContent * content; 79 vm_size_t size; 80 unsigned long int notifyType; 81 unsigned long int ref; 82 struct { 83 mach_msg_header_t msgHdr; 84 OSNotificationHeader notifyHeader; 85 IOServiceInterestContent content; 86 mach_msg_trailer_t trailer; 87 } msg; 88 89 assert( KERN_SUCCESS == ( 90 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port) 91 )); 92 93 type = kIOMatchedNotification;// or kIOPublishNotification; 94 assert( KERN_SUCCESS == ( 95 kr = IOServiceAddNotification( masterPort, type, 96 IOServiceMatching( arg ), 97// IOBSDNameMatching( masterPort, 0, arg ), 98 port, (unsigned int) type, &iter2 ) 99 )); 100 printf("IOServiceAddNotification: %s: ", type ); 101 // dumping the iterator gives us the current list 102 // and arms the notification for changes 103 dumpIter( iter2, port ); 104 printf("\n"); 105 106 type = kIOTerminatedNotification; 107 assert( KERN_SUCCESS == ( 108 kr = IOServiceAddNotification( masterPort, type, 109 IOServiceMatching( arg ), 110 port, (unsigned int) type, &iter1 ) 111 )); 112 printf("IOServiceAddNotification: %s: ", type ); 113 dumpIter( iter1, port ); 114 printf("\n"); 115 116 type = kIOBusyInterest; 117 obj = IORegistryEntryFromPath( masterPort, kIOServicePlane ":/"); 118 assert( obj ); 119 assert( KERN_SUCCESS == ( 120 kr = IOServiceAddInterestNotificationMsg( obj, type, 121 port, (unsigned int) obj, &iter3) 122 )); 123 124 printf("ports: iter1=%d, iter2=%d, rcv=%d\n", iter1, iter2, port); 125 126 do { 127 printf("waiting...\n"); 128 assert( KERN_SUCCESS == ( 129 kr = mach_msg(&msg.msgHdr, MACH_RCV_MSG, 130 0, sizeof(msg), port, 0, MACH_PORT_NULL) 131 )); 132 133 assert( KERN_SUCCESS == ( 134 kr = OSGetNotificationFromMessage( &msg.msgHdr, 0, ¬ifyType, &ref, 135 (void **) &content, &size ) 136 )); 137 138 // we passed a string for the refcon 139 printf("got notification, type=%d, local=%d, remote=%d\n", notifyType, 140 msg.msgHdr.msgh_local_port, msg.msgHdr.msgh_remote_port ); 141 if( notifyType == kIOServiceMessageNotificationType) { 142 obj = ref; 143 if( KERN_SUCCESS == ( 144 kr = IORegistryEntryGetName( obj, name ) 145 )) printf(name); else printf("???"); 146 printf(": messageType %08lx, arg %08lx\n", 147 content->messageType, content->messageArgument[0]); 148 } else { 149 printf("%s: ", ref ); 150 // remote port is the notification (an iterator_t) that fired 151 dumpIter( msg.msgHdr.msgh_remote_port, port ); 152 } 153 154 } while( TRUE ); 155 156 IOObjectRelease( iter1 ); 157 IOObjectRelease( iter2 ); 158 IOObjectRelease( iter3 ); 159} 160 161int 162main(int argc, char **argv) 163{ 164 kern_return_t kr; 165 166 /* 167 * Get master device port 168 */ 169 assert( KERN_SUCCESS == ( 170 kr = IOMasterPort( bootstrap_port, 171 &masterPort) 172 )); 173 174 if( argc > 1) 175 notifyTest( argv[1] ); 176 else 177 printf("%s className\n", argv[0]); 178 179 printf("Exit\n"); 180} 181 182