/* * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #import "IORegistryClass.h" static Node *ioregRootNode = nil; const UInt32 kIORegFlagShowBold = (1 << 0); // (-b option) const UInt32 kIORegFlagShowProperties = (1 << 1); // (-l option) const UInt32 kIORegFlagShowState = (1 << 2); // (-s option) mach_port_t iokitPort; kern_return_t kernResult = KERN_SUCCESS; io_iterator_t intfIterator; struct Options options; /////////////////////////////////////////////////////////////////////////// @implementation IORegistryClass + (Node *)ioregRootNode { return ioregRootNode; } + (void)doIOReg:(int)plane // 0==IOUSB plane, 1==IOService plane { NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; [ioregRootNode clearNode]; [ioregRootNode setItemName: NULL]; [ioregRootNode setItemValue: @"IORegistry"]; // Obtain the command-line arguments. options.class = 0; options.flags = 0; options.name = 0; options.plane = kIOServicePlane; options.width = 132; kernResult = IOMasterPort(bootstrap_port, &iokitPort); switch (plane) { case 0: options.plane = "IOUSB"; kernResult = [self DumpIOUSBPlane:iokitPort options:options]; break; default: //kernResult = FindUSBPCIDevice(iokitPort, &intfIterator); kernResult = FindUSBPCIDevice(iokitPort, &intfIterator); if (KERN_SUCCESS != kernResult) printf("FindUSBNode returned 0x%08x\n", kernResult); else { //kernResult = ScanUSBDevices(intfIterator, options); kernResult = [self ScanUSBDevices:intfIterator options:options]; if (KERN_SUCCESS != kernResult) printf("GetMACAddress returned 0x%08x\n", kernResult); } IOObjectRelease(intfIterator); break; } [pool release]; } + (kern_return_t)DumpIOUSBPlane:(mach_port_t)iokitPort options:(Options)options { io_object_t service; // Obtain the I/O Kit root service. service = IORegistryGetRootEntry(iokitPort); //assertion(service, "can't obtain I/O Kit's root service"); [self scan:service serviceHasMoreSiblings:FALSE serviceDepth:0 stackOfBits:0 options:options]; // scan( service, /* service */ // FALSE, /* serviceHasMoreSiblings */ // 0, /* serviceDepth */ // 0, /* stackOfBits */ // options /* options */ // ); return KERN_SUCCESS; } + (void)scan:(io_registry_entry_t)service serviceHasMoreSiblings:(Boolean)serviceHasMoreSiblings serviceDepth:(UInt32)serviceDepth stackOfBits:(UInt64)stackOfBits options:(Options)options { io_registry_entry_t child = 0; // (needs release) io_registry_entry_t childUpNext = 0; // (don't release) io_iterator_t children = 0; // (needs release) kern_return_t status = KERN_SUCCESS; status = IORegistryEntryGetChildIterator(service, options.plane, &children); childUpNext = IOIteratorNext(children); if (serviceHasMoreSiblings) stackOfBits |= (1 << serviceDepth); else stackOfBits &= ~(1 << serviceDepth); if (childUpNext) stackOfBits |= (2 << serviceDepth); else stackOfBits &= ~(2 << serviceDepth); [self show:service serviceDepth:serviceDepth stackOfBits:stackOfBits options:options]; //show(service, serviceDepth, stackOfBits, options); while (childUpNext) { child = childUpNext; childUpNext = IOIteratorNext(children); [self scan:child serviceHasMoreSiblings:((childUpNext) ? TRUE : FALSE) serviceDepth:(serviceDepth + 1) stackOfBits:stackOfBits options:options]; // scan( /* service */ child, // /* serviceHasMoreSiblings */ (childUpNext) ? TRUE : FALSE, // /* serviceDepth */ serviceDepth + 1, // /* stackOfBits */ stackOfBits, // /* options */ options ); IOObjectRelease(child); child = 0; } IOObjectRelease(children); children = 0; } + (void)show:(io_registry_entry_t)service serviceDepth:(UInt32)serviceDepth stackOfBits:(UInt64)stackOfBits options:(Options)options { io_name_t class; // (don't release) //struct context context = { serviceDepth, stackOfBits }; int integer = 0; // (don't release) io_name_t name; // (don't release) //CFDictionaryRef properties = 0; // (needs release) kern_return_t status = KERN_SUCCESS; io_name_t location; // (don't release) static char buf[350], tempbuf[350]; // printf out the name of the service. status = IORegistryEntryGetNameInPlane(service, options.plane, name); //indent(TRUE, serviceDepth, stackOfBits); //[self indent:TRUE depth:serviceDepth stackOfBits:stackOfBits]; sprintf((char *)tempbuf, (char *)name); strcat(buf,tempbuf); status = IORegistryEntryGetLocationInPlane(service, options.plane, location); if (status == KERN_SUCCESS) { sprintf((char *)tempbuf, "@%s", location); strcat(buf,tempbuf); } status = IOObjectGetClass(service, class); sprintf((char *)tempbuf, " "); strcat(buf,tempbuf); [self PrintVal:buf atDepth:serviceDepth forNode:ioregRootNode]; tempbuf[0]=0; buf[0]=0; } + (kern_return_t)ScanUSBDevices:(io_iterator_t)intfIterator options:(Options)options { io_object_t intfService; kern_return_t kernResult = KERN_FAILURE; while ( (intfService = IOIteratorNext(intfIterator)) ) { io_name_t deviceName; CFMutableDictionaryRef properties = 0; // (needs release) CFDataRef asciiClass = 0; // (don't release) const UInt8 * bytes; CFIndex length; UInt32 classCode = 0; // Obtain the service's properties. kernResult = IORegistryEntryCreateCFProperties(intfService, &properties, kCFAllocatorDefault, kNilOptions); asciiClass = (CFDataRef) CFDictionaryGetValue( properties, CFSTR( "class-code" ) ); if ( asciiClass && (CFGetTypeID(asciiClass) == CFDataGetTypeID()) ) { length = CFDataGetLength(asciiClass); bytes = CFDataGetBytePtr(asciiClass); if ( length == 4 ) classCode = * ((UInt32 *) bytes); } CFRelease(properties); // Get the service name to see if it's "usb" // kernResult = IORegistryEntryGetName(intfService, deviceName); if (KERN_SUCCESS != kernResult) { deviceName[0] = '\0'; } //if ( !strcmp( deviceName, "usb") ) if ( (classCode == 0x000c0310) || (classCode == 0x000c0320) ) { [self scan:intfService serviceHasMoreSiblings:FALSE serviceDepth:0 stackOfBits:0 options:options]; } } return KERN_SUCCESS; } kern_return_t FindUSBPCIDevice(mach_port_t masterPort, io_iterator_t *matchingServices) { kern_return_t kernResult; CFMutableDictionaryRef classesToMatch; // USB controllers are of type IOPCIDevice // classesToMatch = IOServiceMatching("IOPCIDevice"); if (classesToMatch == NULL) printf("IOServiceMatching returned a NULL dictionary.\n"); kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, &intfIterator); if (KERN_SUCCESS != kernResult) printf("IOServiceGetMatchingServices returned %d\n", kernResult); return kernResult; } + (void)indent:(Boolean)isNode depth:(UInt32)depth stackOfBits:(UInt64)stackOfBits { // stackOfBits representation, given current zero-based depth is n: // bit n+1 = does depth n have children? 1=yes, 0=no // bit [n, .. i .., 0] = does depth i have more siblings? 1=yes, 0=no UInt32 index; if (isNode) { for (index = 0; index < depth; index++) printf( (stackOfBits & (1 << index)) ? "| " : " " ); printf("+-o "); } else // if (!isNode) { for (index = 0; index <= depth + 1; index++) printf( (stackOfBits & (1 << index)) ? "| " : " " ); } } - init { [super init]; ioregRootNode = [[Node alloc] init]; return self; } - (id)outlineView:(NSOutlineView *)ov child:(int)index ofItem:(id)item { if (item) return [item childAtIndex:index]; else return ioregRootNode; } - (BOOL)outlineView:(NSOutlineView *)ov isItemExpandable:(id)item { return [item expandable]; } - (int)outlineView:(NSOutlineView *)ov numberOfChildrenOfItem:(id)item { if (item == nil) { return 1; } return [item childrenCount]; } - (id)outlineView:(NSOutlineView *)ov objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { return [item itemValue]; } - (void)dealloc { [ioregRootNode release]; [super dealloc]; } @end