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 iodisplayregistry.c -o iodisplayregistry -framework IOKit -Wall 25*/ 26 27 28#include <assert.h> 29 30#include <CoreFoundation/CoreFoundation.h> 31 32#include <IOKit/IOKitLib.h> 33#include <IOKit/IOCFSerialize.h> 34 35static mach_port_t masterPort; 36 37static void indent(Boolean node, int depth, UInt64 stackOfBits); 38static void properties(io_registry_entry_t service, 39 int depth, 40 UInt64 stackOfBits); 41static void traverse(unsigned int options, 42 io_name_t plane, io_iterator_t services, 43 io_registry_entry_t first, 44 int depth, UInt64 stackOfBits); 45 46enum { 47 kDoPropsOption = 1, 48 kDoRootOption = 2 49}; 50 51int main(int argc, char **argv) 52{ 53 io_registry_entry_t root; 54 char * plane; 55 unsigned int options; 56 kern_return_t status; ///na 57 int arg; 58 59 // Parse args 60 61 plane = kIOServicePlane; 62 options = kDoPropsOption; 63 for(arg = 1; arg < argc; arg++) 64 { 65 if ('-' == argv[arg][0]) switch(argv[arg][1]) 66 { 67 case 'h': 68 printf("%s [-p] [-r] [-h] [plane]\n", argv[0]); 69 exit(0); 70 break; 71 case 'p': 72 options &= ~kDoPropsOption; 73 break; 74 case 'r': 75 options |= kDoRootOption; 76 break; 77 } 78 else 79 { 80 plane = argv[arg]; 81 } 82 } 83 84 // Obtain the I/O Kit communication handle. 85 86// status = IOGetMasterPort(&masterPort); 87 status = IOMasterPort(bootstrap_port, &masterPort); 88 assert(status == KERN_SUCCESS); 89 90 // Obtain the registry root entry. 91 92 root = IORegistryGetRootEntry(masterPort); 93 assert(root); 94 95 // Traverse below the root in the plane. 96 97 traverse(options, plane, 0, root, 0, 0); 98 99 // Quit. 100 101 exit(0); 102} 103 104void traverse(unsigned int options, 105 io_name_t plane, io_iterator_t services, 106 io_registry_entry_t serviceUpNext, 107 int depth, UInt64 stackOfBits) 108{ 109 io_registry_entry_t service; ///ok 110 Boolean doProps; 111 112 // We loop for every service in the list of services provided. 113 114 while ( (service = serviceUpNext) ) 115 { 116 io_iterator_t children; 117 Boolean hasChildren; 118 io_name_t name; 119 kern_return_t status; 120 io_registry_entry_t child; 121 int busy; 122 123 // Obtain the next service entry, if any. 124 125 serviceUpNext = IOIteratorNext(services); 126 127 // Obtain the current service entry's children, if any. 128 129 status = IORegistryEntryGetChildIterator(service, 130 plane, 131 &children); 132 assert(status == KERN_SUCCESS); 133 134 child = IOIteratorNext(children); ///ok 135 hasChildren = child ? true : false; 136 137 // Save has-more-siblings state into stackOfBits for this depth. 138 139 if (serviceUpNext) 140 stackOfBits |= (1 << depth); 141 else 142 stackOfBits &= ~(1 << depth); 143 144 // Save has-children state into stackOfBits for this depth. 145 146 if (hasChildren) 147 stackOfBits |= (2 << depth); 148 else 149 stackOfBits &= ~(2 << depth); 150 151 indent(true, depth, stackOfBits); 152 153 // Print out the name of the service. 154 155 status = IORegistryEntryGetName(service, name); 156 assert(status == KERN_SUCCESS); 157 158 printf("%s", name); 159 160 if (strcmp("Root", name)) 161 doProps = (options & kDoPropsOption) != 0; 162 else 163 doProps = (options & kDoRootOption) != 0; 164 165 // Print out the class of the service. 166 167 status = IOObjectGetClass(service, name); 168 assert(status == KERN_SUCCESS); 169 printf(" <class %s", name); 170 171 status = IOServiceGetBusyState(service, &busy); 172 if(status == KERN_SUCCESS) 173 printf(", busy %d", busy); 174 175 // Print out the retain count of the service. 176 177 printf(", retain count %d>\n", IOObjectGetRetainCount(service)); 178 179 // Print out the properties of the service. 180 181 if (doProps) 182 properties(service, depth, stackOfBits); 183 184 // Recurse down. 185 186 traverse(options, plane, children, child, depth + 1, stackOfBits); 187 188 // Release resources. 189 190 IOObjectRelease(children); children = 0; 191 IOObjectRelease(service); service = 0; 192 } 193} 194 195struct indent_ctxt { 196 int depth; 197 UInt64 stackOfBits; 198}; 199 200static void printCFString(CFStringRef string) 201{ 202 CFIndex len; 203 char * buffer; 204 205 len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), 206 CFStringGetSystemEncoding()) + sizeof('\0'); 207 buffer = malloc(len); 208 if (buffer && CFStringGetCString(string, buffer, len, 209 CFStringGetSystemEncoding()) ) 210 printf(buffer); 211 212 if (buffer) 213 free(buffer); 214} 215 216static void printEntry(const void *key, const void *value, void *context) 217{ 218 struct indent_ctxt * ctxt = context; 219 220#if 1 221 // IOKit pretty 222 CFDataRef data; 223 224 indent(false, ctxt->depth, ctxt->stackOfBits); 225 printf(" "); 226 printCFString( (CFStringRef)key ); 227 printf(" = "); 228 229 data = IOCFSerialize((CFStringRef)value, kNilOptions); 230 if( data) { 231 if( 10000 > CFDataGetLength(data)) 232 printf(CFDataGetBytePtr(data)); 233 else 234 printf("<is BIG>"); 235 CFRelease(data); 236 } else 237 printf("<IOCFSerialize failed>"); 238 printf("\n"); 239 240#else 241 // CF ugly 242 CFStringRef keyStr = (CFStringRef) key; 243 CFStringRef valueStr = CFCopyDescription((CFTypeRef) val); 244 CFStringRef outStr; 245 246 indent(false, ctxt->depth, ctxt->stackOfBits); 247 outStr = CFStringCreateWithFormat(kCFAllocatorDefault, 0, 248 CFSTR(" %@ = %@\n"), keyStr, valueStr); 249 assert(outStr); 250 printCFString(outStr); 251 CFRelease(valueStr); 252 CFRelease(outStr); 253#endif 254} 255 256static void properties(io_registry_entry_t service, 257 int depth, 258 UInt64 stackOfBits) 259{ 260 CFDictionaryRef dictionary; ///ok 261 kern_return_t status; ///na 262 struct indent_ctxt context; 263 264 context.depth = depth; 265 context.stackOfBits = stackOfBits; 266 267 // Prepare to print out the service's properties. 268 indent(false, context.depth, context.stackOfBits); 269 printf("{\n"); 270 271 // Obtain the service's properties. 272 273 status = IORegistryEntryCreateCFProperties(service, 274 (CFTypeRef *) &dictionary, 275 kCFAllocatorDefault, kNilOptions); 276 assert( KERN_SUCCESS == status ); 277 assert( CFDictionaryGetTypeID() == CFGetTypeID(dictionary)); 278 279 CFDictionaryApplyFunction(dictionary, 280 (CFDictionaryApplierFunction) printEntry, &context); 281 282 CFRelease(dictionary); 283 284 indent(false, context.depth, context.stackOfBits); 285 printf("}\n"); 286 indent(false, context.depth, context.stackOfBits); 287 printf("\n"); 288 289} 290 291void indent(Boolean node, int depth, UInt64 stackOfBits) 292{ 293 int i; 294 295 // stackOfBits representation, given current depth is n: 296 // bit n+1 = does depth n have children? 1=yes, 0=no 297 // bit [n, .. i .., 0] = does depth i have more siblings? 1=yes, 0=no 298 299 if (node) 300 { 301 for (i = 0; i < depth; i++) 302 printf( (stackOfBits & (1 << i)) ? "| " : " " ); 303 304 printf("+-o "); 305 } 306 else // if (!node) 307 { 308 for (i = 0; i <= depth + 1; i++) 309 printf( (stackOfBits & (1 << i)) ? "| " : " " ); 310 } 311} 312