|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * 12 Nov 98 sdouglas created. ! 27: * ! 28: */ ! 29: ! 30: #include <IOKit/IORegistryEntry.h> ! 31: #include <libkern/c++/OSContainers.h> ! 32: #include <IOKit/IOService.h> ! 33: #include <IOKit/IOKitKeys.h> ! 34: ! 35: #include <IOKit/IOLib.h> ! 36: ! 37: #include <IOKit/assert.h> ! 38: ! 39: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 40: ! 41: #define super OSObject ! 42: ! 43: OSDefineMetaClassAndStructors(IORegistryEntry, OSObject) ! 44: ! 45: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 46: ! 47: static IORegistryEntry * gRegistryRoot; ! 48: static OSDictionary * gIORegistryPlanes; ! 49: ! 50: const OSSymbol * gIONameKey; ! 51: const OSSymbol * gIOLocationKey; ! 52: ! 53: enum { ! 54: kParentSetIndex = 0, ! 55: kChildSetIndex = 1, ! 56: kNumSetIndex ! 57: }; ! 58: enum { ! 59: kIOMaxPlaneName = 32 ! 60: }; ! 61: ! 62: class IORegistryPlane : public OSObject { ! 63: ! 64: friend IORegistryEntry; ! 65: ! 66: OSDeclareAbstractStructors(IORegistryPlane) ! 67: ! 68: const OSSymbol * nameKey; ! 69: const OSSymbol * keys[ kNumSetIndex ]; ! 70: const OSSymbol * pathNameKey; ! 71: const OSSymbol * pathLocationKey; ! 72: int reserved[2]; ! 73: ! 74: public: ! 75: virtual bool serialize(OSSerialize *s) const; ! 76: }; ! 77: ! 78: OSDefineMetaClassAndStructors(IORegistryPlane, OSObject) ! 79: ! 80: ! 81: static lock_t * gIORegistryLock; ! 82: static IORecursiveLock * gPropertiesLock; ! 83: static SInt32 gIORegistryGenerationCount; ! 84: ! 85: #define UNLOCK lock_done( gIORegistryLock ) ! 86: #define RLOCK lock_read( gIORegistryLock ) ! 87: #define WLOCK lock_write( gIORegistryLock ); \ ! 88: gIORegistryGenerationCount++ ! 89: // make atomic ! 90: ! 91: #define PUNLOCK IORecursiveLockUnlock( gPropertiesLock ) ! 92: #define PLOCK IORecursiveLockLock( gPropertiesLock ) ! 93: ! 94: #define IOREGSPLITTABLES ! 95: ! 96: #ifdef IOREGSPLITTABLES ! 97: #define registryTable() fRegistryTable ! 98: #else ! 99: #define registryTable() fPropertyTable ! 100: #endif ! 101: ! 102: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 103: ! 104: IORegistryEntry * IORegistryEntry::initialize( void ) ! 105: { ! 106: bool ok; ! 107: ! 108: if( !gRegistryRoot) { ! 109: ! 110: gRegistryRoot = new IORegistryEntry; ! 111: gIORegistryLock = lock_alloc(true, NULL, NULL); ! 112: gPropertiesLock = IORecursiveLockAlloc(); ! 113: gIORegistryPlanes = OSDictionary::withCapacity( 1 ); ! 114: ! 115: assert( gRegistryRoot && gIORegistryLock && gPropertiesLock ! 116: && gIORegistryPlanes ); ! 117: ok = gRegistryRoot->init(); ! 118: ! 119: gIONameKey = OSSymbol::withCStringNoCopy( "IOName" ); ! 120: gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" ); ! 121: ! 122: assert( ok && gIONameKey && gIOLocationKey ); ! 123: ! 124: gRegistryRoot->setName( "Root" ); ! 125: gRegistryRoot->setProperty( kIORegistryPlanesKey, gIORegistryPlanes ); ! 126: } ! 127: ! 128: return( gRegistryRoot ); ! 129: } ! 130: ! 131: IORegistryEntry * IORegistryEntry::getRegistryRoot( void ) ! 132: { ! 133: return( gRegistryRoot ); ! 134: } ! 135: ! 136: SInt32 IORegistryEntry::getGenerationCount( void ) ! 137: { ! 138: return( gIORegistryGenerationCount ); ! 139: } ! 140: ! 141: ! 142: const IORegistryPlane * IORegistryEntry::makePlane( const char * name ) ! 143: { ! 144: IORegistryPlane * plane; ! 145: const OSSymbol * nameKey; ! 146: const OSSymbol * parentKey; ! 147: const OSSymbol * childKey; ! 148: const OSSymbol * pathNameKey; ! 149: const OSSymbol * pathLocationKey; ! 150: char key[ kIOMaxPlaneName + 16 ]; ! 151: char * end; ! 152: ! 153: strncpy( key, name, kIOMaxPlaneName ); ! 154: key[ kIOMaxPlaneName ] = 0; ! 155: end = key + strlen( name ); ! 156: ! 157: nameKey = OSSymbol::withCString( key); ! 158: ! 159: strcpy( end, "ParentLinks" ); ! 160: parentKey = OSSymbol::withCString( key); ! 161: ! 162: strcpy( end, "ChildLinks" ); ! 163: childKey = OSSymbol::withCString( key); ! 164: ! 165: strcpy( end, "Name" ); ! 166: pathNameKey = OSSymbol::withCString( key); ! 167: ! 168: strcpy( end, "Location" ); ! 169: pathLocationKey = OSSymbol::withCString( key); ! 170: ! 171: plane = new IORegistryPlane; ! 172: ! 173: if( plane && plane->init() ! 174: && nameKey && parentKey && childKey ! 175: && pathNameKey && pathLocationKey ) { ! 176: ! 177: plane->nameKey = nameKey; ! 178: plane->keys[ kParentSetIndex ] = parentKey; ! 179: plane->keys[ kChildSetIndex ] = childKey; ! 180: plane->pathNameKey = pathNameKey; ! 181: plane->pathLocationKey = pathLocationKey; ! 182: ! 183: WLOCK; ! 184: gIORegistryPlanes->setObject( nameKey, plane ); ! 185: UNLOCK; ! 186: ! 187: } else { ! 188: ! 189: if( plane) ! 190: plane->release(); ! 191: if( pathLocationKey) ! 192: pathLocationKey->release(); ! 193: if( pathNameKey) ! 194: pathNameKey->release(); ! 195: if( parentKey) ! 196: parentKey->release(); ! 197: if( childKey) ! 198: childKey->release(); ! 199: if( nameKey) ! 200: nameKey->release(); ! 201: plane = 0; ! 202: } ! 203: ! 204: return( plane); ! 205: } ! 206: ! 207: const IORegistryPlane * IORegistryEntry::getPlane( const char * name ) ! 208: { ! 209: const IORegistryPlane * plane; ! 210: ! 211: RLOCK; ! 212: plane = (const IORegistryPlane *) gIORegistryPlanes->getObject( name ); ! 213: UNLOCK; ! 214: ! 215: return( plane ); ! 216: } ! 217: ! 218: bool IORegistryPlane::serialize(OSSerialize *s) const ! 219: { ! 220: return( nameKey->serialize(s) ); ! 221: } ! 222: ! 223: enum { kIORegCapacityIncrement = 4 }; ! 224: ! 225: bool IORegistryEntry::init( OSDictionary * dict = 0 ) ! 226: { ! 227: OSString * prop; ! 228: ! 229: if( !super::init()) ! 230: return( false); ! 231: ! 232: if( dict) { ! 233: dict->retain(); ! 234: fPropertyTable = dict; ! 235: ! 236: } else { ! 237: fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement ); ! 238: if( fPropertyTable) ! 239: fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement ); ! 240: } ! 241: ! 242: if( !fPropertyTable) ! 243: return( false); ! 244: ! 245: #ifdef IOREGSPLITTABLES ! 246: fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement ); ! 247: if( fRegistryTable) ! 248: fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement ); ! 249: ! 250: if( (prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) { ! 251: OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop); ! 252: // ok for OSSymbol too ! 253: setName( sym); ! 254: sym->release(); ! 255: } ! 256: ! 257: #endif /* IOREGSPLITTABLES */ ! 258: ! 259: return( true); ! 260: } ! 261: ! 262: bool IORegistryEntry::init( IORegistryEntry * old, ! 263: const IORegistryPlane * plane ) ! 264: { ! 265: OSArray * all; ! 266: IORegistryEntry * next; ! 267: unsigned int index; ! 268: ! 269: if( !super::init()) ! 270: return( false); ! 271: ! 272: WLOCK; ! 273: ! 274: fPropertyTable = old->getPropertyTable(); ! 275: old->fPropertyTable = 0; ! 276: #ifdef IOREGSPLITTABLES ! 277: fRegistryTable = old->fRegistryTable; ! 278: old->fRegistryTable = 0; ! 279: #endif /* IOREGSPLITTABLES */ ! 280: ! 281: all = getParentSetReference( plane ); ! 282: if( all) for( index = 0; ! 283: (next = (IORegistryEntry *) all->getObject(index)); ! 284: index++ ) { ! 285: next->makeLink( this, kChildSetIndex, plane ); ! 286: next->breakLink( old, kChildSetIndex, plane ); ! 287: } ! 288: ! 289: all = getChildSetReference( plane ); ! 290: if( all) for( index = 0; ! 291: (next = (IORegistryEntry *) all->getObject(index)); ! 292: index++ ) { ! 293: next->makeLink( this, kParentSetIndex, plane ); ! 294: next->breakLink( old, kParentSetIndex, plane ); ! 295: } ! 296: ! 297: UNLOCK; ! 298: ! 299: return( true ); ! 300: } ! 301: ! 302: void IORegistryEntry::free( void ) ! 303: { ! 304: ! 305: #ifdef DEBUG ! 306: OSArray * links; ! 307: const OSSymbol * key; ! 308: const IORegistryPlane * plane; ! 309: OSCollectionIterator * iter; ! 310: ! 311: if( registryTable()) { ! 312: iter = OSCollectionIterator::withCollection( gIORegistryPlanes ); ! 313: if( iter) { ! 314: while( (key = (const OSSymbol *) iter->getNextObject())) { ! 315: if( 0 == (plane = (const IORegistryPlane *) ! 316: OSDynamicCast( IORegistryPlane, ! 317: gIORegistryPlanes->getObject( key )))) ! 318: continue; ! 319: if( (links = getParentSetReference( plane )) ! 320: || (links = getChildSetReference( plane )) ) { ! 321: ! 322: IOLog("%s: Still attached in %s at free()\n", ! 323: getName(), plane->nameKey->getCStringNoCopy()); ! 324: } ! 325: } ! 326: iter->release(); ! 327: } ! 328: } ! 329: #endif ! 330: ! 331: if( getPropertyTable()) ! 332: getPropertyTable()->release(); ! 333: ! 334: #ifdef IOREGSPLITTABLES ! 335: if( registryTable()) ! 336: registryTable()->release(); ! 337: #endif /* IOREGSPLITTABLES */ ! 338: ! 339: super::free(); ! 340: } ! 341: ! 342: void IORegistryEntry::setPropertyTable( OSDictionary * dict ) ! 343: { ! 344: if( fPropertyTable) ! 345: fPropertyTable->release(); ! 346: if( dict) ! 347: dict->retain(); ! 348: fPropertyTable = dict; ! 349: } ! 350: ! 351: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 352: ! 353: /* Wrappers to synchronize property table */ ! 354: ! 355: #define wrap1(func,type,constant) \ ! 356: OSObject * \ ! 357: IORegistryEntry::func ## Property( type * aKey) constant \ ! 358: { \ ! 359: OSObject * obj; \ ! 360: \ ! 361: PLOCK; \ ! 362: obj = getPropertyTable()->func ## Object( aKey ); \ ! 363: PUNLOCK; \ ! 364: \ ! 365: return( obj ); \ ! 366: } ! 367: ! 368: #define wrap2(func,type) \ ! 369: OSObject * \ ! 370: IORegistryEntry::func ## Object( OSObject * anObject, type * aKey) \ ! 371: { \ ! 372: OSObject * obj; \ ! 373: \ ! 374: PLOCK; \ ! 375: obj = getPropertyTable()->func ## Object( anObject, aKey ); \ ! 376: PUNLOCK; \ ! 377: \ ! 378: return( obj ); \ ! 379: } ! 380: ! 381: #define wrap3(func,type,constant) \ ! 382: void \ ! 383: IORegistryEntry::func ## Property( type * aKey) constant \ ! 384: { \ ! 385: PLOCK; \ ! 386: getPropertyTable()->func ## Object( aKey ); \ ! 387: PUNLOCK; \ ! 388: } ! 389: ! 390: bool IORegistryEntry::serializeProperties( OSSerialize * s ) const ! 391: { ! 392: bool ok; ! 393: ! 394: // setProperty( getRetainCount(), 32, "__retain" ); ! 395: ! 396: PLOCK; ! 397: ok = getPropertyTable()->serialize( s ); ! 398: PUNLOCK; ! 399: ! 400: return( ok ); ! 401: } ! 402: ! 403: OSDictionary * IORegistryEntry::dictionaryWithProperties( void ) const ! 404: { ! 405: OSDictionary * dict; ! 406: ! 407: PLOCK; ! 408: dict = OSDictionary::withDictionary( getPropertyTable(), ! 409: getPropertyTable()->getCapacity() ); ! 410: PUNLOCK; ! 411: ! 412: return( dict ); ! 413: } ! 414: ! 415: IOReturn IORegistryEntry::setProperties( OSObject * properties ) ! 416: { ! 417: return( kIOReturnUnsupported ); ! 418: } ! 419: ! 420: wrap1(get, const OSSymbol, const) // getProperty() definition ! 421: wrap1(get, const OSString, const) // getProperty() definition ! 422: wrap1(get, const char, const) // getProperty() definition ! 423: ! 424: wrap3(remove, const OSSymbol,) // removeProperty() definition ! 425: wrap3(remove, const OSString,) // removeProperty() definition ! 426: wrap3(remove, const char,) // removeProperty() definition ! 427: ! 428: bool ! 429: IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject) ! 430: { ! 431: bool ret = false; ! 432: PLOCK; ! 433: ret = getPropertyTable()->setObject( aKey, anObject ); ! 434: PUNLOCK; ! 435: ! 436: return ret; ! 437: } ! 438: ! 439: bool ! 440: IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject) ! 441: { ! 442: bool ret = false; ! 443: PLOCK; ! 444: ret = getPropertyTable()->setObject( aKey, anObject ); ! 445: PUNLOCK; ! 446: ! 447: return ret; ! 448: } ! 449: ! 450: bool ! 451: IORegistryEntry::setProperty( const char * aKey, OSObject * anObject) ! 452: { ! 453: bool ret = false; ! 454: PLOCK; ! 455: ret = getPropertyTable()->setObject( aKey, anObject ); ! 456: PUNLOCK; ! 457: ! 458: return ret; ! 459: } ! 460: ! 461: bool ! 462: IORegistryEntry::setProperty(const char * aKey, const char * aString) ! 463: { ! 464: bool ret = false; ! 465: OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString ); ! 466: ! 467: if( aSymbol) { ! 468: PLOCK; ! 469: ret = getPropertyTable()->setObject( aKey, aSymbol ); ! 470: PUNLOCK; ! 471: aSymbol->release(); ! 472: } ! 473: return( ret ); ! 474: } ! 475: ! 476: bool ! 477: IORegistryEntry::setProperty(const char * aKey, bool aBoolean) ! 478: { ! 479: bool ret = false; ! 480: OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean ); ! 481: ! 482: if( aBooleanObj) { ! 483: PLOCK; ! 484: ret = getPropertyTable()->setObject( aKey, aBooleanObj ); ! 485: PUNLOCK; ! 486: aBooleanObj->release(); ! 487: } ! 488: return( ret ); ! 489: } ! 490: ! 491: bool ! 492: IORegistryEntry::setProperty( const char * aKey, ! 493: unsigned long long aValue, ! 494: unsigned int aNumberOfBits) ! 495: { ! 496: bool ret = false; ! 497: OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits ); ! 498: ! 499: if( anOffset) { ! 500: PLOCK; ! 501: ret = getPropertyTable()->setObject( aKey, anOffset ); ! 502: PUNLOCK; ! 503: anOffset->release(); ! 504: } ! 505: return( ret ); ! 506: } ! 507: ! 508: bool ! 509: IORegistryEntry::setProperty( const char * aKey, ! 510: void * bytes, ! 511: unsigned int length) ! 512: { ! 513: bool ret = false; ! 514: OSData * data = OSData::withBytes( bytes, length ); ! 515: ! 516: if( data) { ! 517: PLOCK; ! 518: ret = getPropertyTable()->setObject( aKey, data ); ! 519: PUNLOCK; ! 520: data->release(); ! 521: } ! 522: return( ret ); ! 523: } ! 524: ! 525: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 526: ! 527: /* Name, location, paths */ ! 528: ! 529: const char * IORegistryEntry::getName( const IORegistryPlane * plane = 0 ) const ! 530: { ! 531: OSSymbol * sym = 0; ! 532: ! 533: RLOCK; ! 534: if( plane) ! 535: sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey ); ! 536: if( !sym) ! 537: sym = (OSSymbol *) registryTable()->getObject( gIONameKey ); ! 538: UNLOCK; ! 539: ! 540: if( sym) ! 541: return( sym->getCStringNoCopy()); ! 542: else ! 543: return( (getMetaClass())->getClassName()); ! 544: } ! 545: ! 546: const OSSymbol * IORegistryEntry::copyName( ! 547: const IORegistryPlane * plane = 0 ) const ! 548: { ! 549: OSSymbol * sym = 0; ! 550: ! 551: RLOCK; ! 552: if( plane) ! 553: sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey ); ! 554: if( !sym) ! 555: sym = (OSSymbol *) registryTable()->getObject( gIONameKey ); ! 556: if( sym) ! 557: sym->retain(); ! 558: UNLOCK; ! 559: ! 560: if( sym) ! 561: return( sym ); ! 562: else ! 563: return( OSSymbol::withCString((getMetaClass())->getClassName()) ); ! 564: } ! 565: ! 566: const OSSymbol * IORegistryEntry::copyLocation( ! 567: const IORegistryPlane * plane = 0 ) const ! 568: { ! 569: OSSymbol * sym = 0; ! 570: ! 571: RLOCK; ! 572: if( plane) ! 573: sym = (OSSymbol *) registryTable()->getObject( plane->pathLocationKey ); ! 574: if( !sym) ! 575: sym = (OSSymbol *) registryTable()->getObject( gIOLocationKey ); ! 576: if( sym) ! 577: sym->retain(); ! 578: UNLOCK; ! 579: ! 580: return( sym ); ! 581: } ! 582: ! 583: const char * IORegistryEntry::getLocation( const IORegistryPlane * plane = 0 ) const ! 584: { ! 585: const OSSymbol * sym = copyLocation( plane ); ! 586: const char * result = 0; ! 587: ! 588: if( sym) { ! 589: result = sym->getCStringNoCopy(); ! 590: sym->release(); ! 591: } ! 592: ! 593: return( result ); ! 594: } ! 595: ! 596: void IORegistryEntry::setName( const OSSymbol * name, ! 597: const IORegistryPlane * plane = 0 ) ! 598: { ! 599: const OSSymbol * key; ! 600: ! 601: if( name) { ! 602: if( plane) ! 603: key = plane->pathNameKey; ! 604: else ! 605: key = gIONameKey; ! 606: ! 607: WLOCK; ! 608: registryTable()->setObject( key, (OSObject *) name); ! 609: UNLOCK; ! 610: } ! 611: } ! 612: ! 613: void IORegistryEntry::setName( const char * name, ! 614: const IORegistryPlane * plane = 0 ) ! 615: { ! 616: OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name ); ! 617: if ( sym ) { ! 618: setName( sym, plane ); ! 619: sym->release(); ! 620: } ! 621: } ! 622: ! 623: void IORegistryEntry::setLocation( const OSSymbol * location, ! 624: const IORegistryPlane * plane = 0 ) ! 625: { ! 626: const OSSymbol * key; ! 627: ! 628: if( location) { ! 629: if( plane) ! 630: key = plane->pathLocationKey; ! 631: else ! 632: key = gIOLocationKey; ! 633: ! 634: WLOCK; ! 635: registryTable()->setObject( key, (OSObject *) location); ! 636: UNLOCK; ! 637: } ! 638: } ! 639: ! 640: void IORegistryEntry::setLocation( const char * location, ! 641: const IORegistryPlane * plane = 0 ) ! 642: { ! 643: OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location ); ! 644: if ( sym ) { ! 645: setLocation( sym, plane ); ! 646: sym->release(); ! 647: } ! 648: } ! 649: ! 650: bool ! 651: IORegistryEntry::compareName( OSString * name, OSString ** matched = 0 ) const ! 652: { ! 653: const OSSymbol * sym = copyName(); ! 654: bool isEqual; ! 655: ! 656: isEqual = sym->isEqualTo( name ); ! 657: ! 658: if( isEqual && matched) { ! 659: name->retain(); ! 660: *matched = name; ! 661: } ! 662: ! 663: if( sym) ! 664: sym->release(); ! 665: ! 666: return( isEqual ); ! 667: } ! 668: ! 669: bool ! 670: IORegistryEntry::compareNames( OSObject * names, OSString ** matched = 0 ) const ! 671: { ! 672: OSString * string; ! 673: OSCollection * collection; ! 674: OSIterator * iter = 0; ! 675: bool result = false; ! 676: ! 677: if( (collection = OSDynamicCast( OSCollection, names))) { ! 678: iter = OSCollectionIterator::withCollection( collection ); ! 679: string = 0; ! 680: } else ! 681: string = OSDynamicCast( OSString, names); ! 682: ! 683: do { ! 684: if( string) ! 685: result = compareName( string, matched ); ! 686: ! 687: } while( (false == result) ! 688: && iter && (string = OSDynamicCast( OSString, iter->getNextObject()))); ! 689: ! 690: if( iter) ! 691: iter->release(); ! 692: ! 693: return( result); ! 694: } ! 695: ! 696: ! 697: bool IORegistryEntry::getPath( char * path, int * length, ! 698: const IORegistryPlane * plane ) const ! 699: { ! 700: OSArray * stack; ! 701: IORegistryEntry * root; ! 702: const IORegistryEntry * entry; ! 703: IORegistryEntry * parent; ! 704: const OSSymbol * alias; ! 705: int index; ! 706: int len, maxLength, compLen; ! 707: char * nextComp; ! 708: bool ok; ! 709: ! 710: if( !path || !length || !plane) ! 711: return( false); ! 712: ! 713: len = 0; ! 714: maxLength = *length - 2; ! 715: nextComp = path; ! 716: ! 717: len = plane->nameKey->getLength(); ! 718: if( len >= maxLength) ! 719: return( false); ! 720: strcpy( nextComp, plane->nameKey->getCStringNoCopy()); ! 721: nextComp[ len++ ] = ':'; ! 722: nextComp += len; ! 723: ! 724: if( (alias = hasAlias( plane ))) { ! 725: len += alias->getLength(); ! 726: ok = (maxLength > len); ! 727: *length = len; ! 728: if( ok) ! 729: strcpy( nextComp, alias->getCStringNoCopy()); ! 730: return( ok ); ! 731: } ! 732: ! 733: entry = this; ! 734: parent = entry->getParentEntry( plane ); ! 735: if( !parent) ! 736: // Error if not attached in plane ! 737: return( false); ! 738: ! 739: stack = OSArray::withCapacity( getDepth( plane )); ! 740: if( !stack) ! 741: return( false); ! 742: ! 743: RLOCK; ! 744: ! 745: root = gRegistryRoot->getChildEntry( plane ); ! 746: while( parent && (entry != root)) { ! 747: // stop below root ! 748: stack->setObject( (OSObject *) entry ); ! 749: entry = parent; ! 750: parent = entry->getParentEntry( plane ); ! 751: } ! 752: ! 753: index = stack->getCount(); ! 754: ok = true; ! 755: ! 756: if( 0 == index) { ! 757: ! 758: *nextComp++ = '/'; ! 759: *nextComp = 0; ! 760: len++; ! 761: ! 762: } else while( ok && ((--index) >= 0)) { ! 763: ! 764: entry = (IORegistryEntry *) stack->getObject((unsigned int) index ); ! 765: assert( entry ); ! 766: ! 767: compLen = maxLength - len; ! 768: ok = entry->getPathComponent( nextComp + 1, &compLen, plane ); ! 769: ! 770: if( ok && compLen) { ! 771: compLen++; ! 772: *nextComp = '/'; ! 773: len += compLen; ! 774: nextComp += compLen; ! 775: } ! 776: } ! 777: *length = len; ! 778: ! 779: UNLOCK; ! 780: ! 781: stack->release(); ! 782: ! 783: return( ok ); ! 784: } ! 785: ! 786: bool IORegistryEntry::getPathComponent( char * path, int * length, ! 787: const IORegistryPlane * plane ) const ! 788: { ! 789: int len, locLen, maxLength; ! 790: const char * compName; ! 791: const char * loc; ! 792: bool ok; ! 793: ! 794: maxLength = *length; ! 795: ! 796: compName = getName( plane ); ! 797: len = strlen( compName ); ! 798: if( (loc = getLocation( plane ))) ! 799: locLen = 1 + strlen( loc ); ! 800: else ! 801: locLen = 0; ! 802: ! 803: ok = ((len + locLen) < maxLength); ! 804: if( ok) { ! 805: strcpy( path, compName ); ! 806: if( loc) { ! 807: path += len; ! 808: len += locLen; ! 809: *path++ = '@'; ! 810: strcpy( path, loc ); ! 811: } ! 812: *length = len; ! 813: } ! 814: ! 815: return( ok ); ! 816: } ! 817: ! 818: const char * IORegistryEntry::matchPathLocation( const char * cmp, ! 819: const IORegistryPlane * plane ) ! 820: { ! 821: const char * str; ! 822: const char * result = 0; ! 823: int num1, num2; ! 824: char c1, c2; ! 825: ! 826: str = getLocation( plane ); ! 827: if( str) { ! 828: c2 = str[0]; ! 829: do { ! 830: num1 = strtoul( cmp, (char **) &cmp, 16 ); ! 831: if( c2) { ! 832: num2 = strtoul( str, (char **) &str, 16 ); ! 833: c2 = str[0]; ! 834: } else ! 835: num2 = 0; ! 836: ! 837: if( num1 != num2) ! 838: break; ! 839: ! 840: c1 = *cmp++; ! 841: if( ',' != c1) { ! 842: result = cmp - 1; ! 843: break; ! 844: } ! 845: ! 846: if( c2) { ! 847: if( c2 != ',') ! 848: break; ! 849: str++; ! 850: } ! 851: ! 852: } while( true); ! 853: } ! 854: ! 855: return( result ); ! 856: } ! 857: ! 858: IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath, ! 859: const IORegistryPlane * plane ) ! 860: { ! 861: IORegistryEntry * entry = 0; ! 862: OSArray * set; ! 863: unsigned int index; ! 864: const char * path; ! 865: const char * cmp = 0; ! 866: size_t len; ! 867: const char * str; ! 868: ! 869: set = getChildSetReference( plane ); ! 870: if( set) { ! 871: ! 872: path = *opath; ! 873: ! 874: for( index = 0; ! 875: (entry = (IORegistryEntry *) set->getObject(index)); ! 876: index++ ) { ! 877: ! 878: cmp = path; ! 879: ! 880: if( *cmp != '@') { ! 881: str = entry->getName( plane ); ! 882: len = strlen( str ); ! 883: if( strncmp( str, cmp, len )) ! 884: continue; ! 885: cmp += len; ! 886: if( *cmp != '@' ) ! 887: break; ! 888: } ! 889: cmp++; ! 890: if( (cmp = entry->matchPathLocation( cmp, plane ))) ! 891: break; ! 892: } ! 893: if( entry) ! 894: *opath = cmp; ! 895: } ! 896: ! 897: return( entry ); ! 898: } ! 899: ! 900: const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane, ! 901: char * opath = 0, int * length = 0 ) const ! 902: { ! 903: IORegistryEntry * entry; ! 904: IORegistryEntry * entry2; ! 905: const OSSymbol * key; ! 906: const OSSymbol * bestKey = 0; ! 907: OSIterator * iter; ! 908: OSData * data; ! 909: const char * path = "/aliases"; ! 910: ! 911: entry = IORegistryEntry::fromPath( path, plane ); ! 912: if( entry) { ! 913: RLOCK; ! 914: if( (iter = OSCollectionIterator::withCollection( ! 915: entry->getPropertyTable() ))) { ! 916: ! 917: while( (key = (OSSymbol *) iter->getNextObject())) { ! 918: ! 919: data = (OSData *) entry->getProperty( key ); ! 920: path = (const char *) data->getBytesNoCopy(); ! 921: if( (entry2 = IORegistryEntry::fromPath( path, plane, ! 922: opath, length ))) { ! 923: if( this == entry2) { ! 924: if( !bestKey ! 925: || (bestKey->getLength() > key->getLength())) ! 926: // pick the smallest alias ! 927: bestKey = key; ! 928: } ! 929: entry2->release(); ! 930: } ! 931: } ! 932: iter->release(); ! 933: } ! 934: entry->release(); ! 935: UNLOCK; ! 936: } ! 937: return( bestKey ); ! 938: } ! 939: ! 940: const char * IORegistryEntry::dealiasPath( ! 941: const char ** opath, ! 942: const IORegistryPlane * plane ) ! 943: { ! 944: IORegistryEntry * entry; ! 945: OSData * data; ! 946: const char * path = *opath; ! 947: const char * rpath = 0; ! 948: const char * end; ! 949: char c; ! 950: char temp[ kIOMaxPlaneName + 1 ]; ! 951: ! 952: if( path[0] == '/') ! 953: return( rpath ); ! 954: ! 955: // check for alias ! 956: end = path; ! 957: while( (c = *end++) && (c != '/') && (c != ':')) ! 958: {} ! 959: end--; ! 960: if( (end - path) < kIOMaxPlaneName) { ! 961: strncpy( temp, path, end - path ); ! 962: temp[ end - path ] = 0; ! 963: ! 964: RLOCK; ! 965: entry = IORegistryEntry::fromPath( "/aliases", plane ); ! 966: if( entry) { ! 967: data = (OSData *) entry->getProperty( temp ); ! 968: if( data ) { ! 969: rpath = (const char *) data->getBytesNoCopy(); ! 970: if( rpath) ! 971: *opath = end; ! 972: } ! 973: entry->release(); ! 974: } ! 975: UNLOCK; ! 976: } ! 977: ! 978: return( rpath ); ! 979: } ! 980: ! 981: IORegistryEntry * IORegistryEntry::fromPath( ! 982: const char * path, ! 983: const IORegistryPlane * plane = 0, ! 984: char * opath = 0, ! 985: int * length = 0, ! 986: IORegistryEntry * fromEntry = 0 ) ! 987: { ! 988: IORegistryEntry * where = 0; ! 989: IORegistryEntry * next; ! 990: const char * alias; ! 991: const char * end; ! 992: int len = 0; ! 993: int len2; ! 994: char c; ! 995: char temp[ kIOMaxPlaneName + 1 ]; ! 996: ! 997: if( 0 == path) ! 998: return( 0 ); ! 999: ! 1000: if( 0 == plane) { ! 1001: // get plane name ! 1002: end = strchr( path, ':' ); ! 1003: if( end && ((end - path) < kIOMaxPlaneName)) { ! 1004: strncpy( temp, path, end - path ); ! 1005: temp[ end - path ] = 0; ! 1006: plane = getPlane( temp ); ! 1007: path = end + 1; ! 1008: } ! 1009: } ! 1010: if( 0 == plane) ! 1011: return( 0 ); ! 1012: ! 1013: // check for alias ! 1014: end = path; ! 1015: if( (alias = dealiasPath( &end, plane))) { ! 1016: if( length) ! 1017: len = *length; ! 1018: where = IORegistryEntry::fromPath( alias, plane, ! 1019: opath, &len, fromEntry ); ! 1020: if( where) ! 1021: path = end; ! 1022: else ! 1023: len = 0; ! 1024: } ! 1025: ! 1026: RLOCK; ! 1027: ! 1028: do { ! 1029: if( 0 == where) { ! 1030: if( (0 == fromEntry) && (*path++ == '/')) ! 1031: fromEntry = gRegistryRoot->getChildEntry( plane ); ! 1032: where = fromEntry; ! 1033: if( 0 == where) ! 1034: break; ! 1035: } else { ! 1036: c = *path++; ! 1037: if( c != '/') { ! 1038: if( c && (c != ':')) // check valid terminator ! 1039: where = 0; ! 1040: break; ! 1041: } ! 1042: } ! 1043: next = where->getChildFromComponent( &path, plane ); ! 1044: if( next) ! 1045: where = next; ! 1046: } while( next ); ! 1047: ! 1048: if( where) { ! 1049: // check residual path ! 1050: if( where != fromEntry) ! 1051: path--; ! 1052: ! 1053: if( opath && length) { ! 1054: // copy out residual path ! 1055: len2 = len + strlen( path ); ! 1056: if( len2 < *length) ! 1057: strcpy( opath + len, path ); ! 1058: *length = len2; ! 1059: ! 1060: } else if( path[0]) ! 1061: // no residual path => must be no tail for success ! 1062: where = 0; ! 1063: } ! 1064: ! 1065: if( where) ! 1066: where->retain(); ! 1067: ! 1068: UNLOCK; ! 1069: ! 1070: return( where ); ! 1071: } ! 1072: ! 1073: IORegistryEntry * IORegistryEntry::childFromPath( ! 1074: const char * path, ! 1075: const IORegistryPlane * plane = 0, ! 1076: char * opath = 0, ! 1077: int * len = 0 ) ! 1078: { ! 1079: return( IORegistryEntry::fromPath( path, plane, opath, len, this )); ! 1080: } ! 1081: ! 1082: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 1083: ! 1084: #define IOLinkIterator OSCollectionIterator ! 1085: ! 1086: #undef super ! 1087: #define super OSObject ! 1088: ! 1089: inline bool IORegistryEntry::arrayMember( OSArray * set, ! 1090: const IORegistryEntry * member, ! 1091: unsigned int * index = 0 ) const ! 1092: { ! 1093: int i; ! 1094: OSObject * probeObject; ! 1095: ! 1096: for( i = 0; (probeObject = set->getObject(i)); i++) { ! 1097: if (probeObject == (OSObject *) member) { ! 1098: if( index) ! 1099: *index = i; ! 1100: return( true ); ! 1101: } ! 1102: } ! 1103: return( false ); ! 1104: } ! 1105: ! 1106: bool IORegistryEntry::makeLink( IORegistryEntry * to, ! 1107: unsigned int relation, ! 1108: const IORegistryPlane * plane ) const ! 1109: { ! 1110: OSArray * links; ! 1111: bool result = false; ! 1112: ! 1113: if( (links = (OSArray *) ! 1114: registryTable()->getObject( plane->keys[ relation ] ))) { ! 1115: ! 1116: result = arrayMember( links, to ); ! 1117: if( !result) ! 1118: result = links->setObject( to ); ! 1119: ! 1120: } else { ! 1121: ! 1122: links = OSArray::withObjects( (OSObject **) &to, 1, 1 ); ! 1123: result = (links != 0); ! 1124: if( result) { ! 1125: result = registryTable()->setObject( plane->keys[ relation ], ! 1126: links ); ! 1127: links->release(); ! 1128: } ! 1129: } ! 1130: ! 1131: return( result); ! 1132: } ! 1133: ! 1134: void IORegistryEntry::breakLink( IORegistryEntry * to, ! 1135: unsigned int relation, ! 1136: const IORegistryPlane * plane ) const ! 1137: { ! 1138: OSArray * links; ! 1139: unsigned int index; ! 1140: ! 1141: if( (links = (OSArray *) ! 1142: registryTable()->getObject( plane->keys[ relation ]))) { ! 1143: ! 1144: if( arrayMember( links, to, &index )) { ! 1145: links->removeObject( index ); ! 1146: if( 0 == links->getCount()) ! 1147: registryTable()->removeObject( plane->keys[ relation ]); ! 1148: } ! 1149: } ! 1150: } ! 1151: ! 1152: ! 1153: OSArray * IORegistryEntry::getParentSetReference( ! 1154: const IORegistryPlane * plane ) const ! 1155: { ! 1156: if( plane) ! 1157: return( (OSArray *) registryTable()->getObject( ! 1158: plane->keys[ kParentSetIndex ])); ! 1159: else ! 1160: return( 0 ); ! 1161: } ! 1162: ! 1163: OSIterator * IORegistryEntry::getParentIterator( ! 1164: const IORegistryPlane * plane ) const ! 1165: { ! 1166: OSArray * links; ! 1167: OSIterator * iter; ! 1168: ! 1169: if( !plane) ! 1170: return( 0 ); ! 1171: ! 1172: RLOCK; ! 1173: links = getParentSetReference( plane ); ! 1174: if( 0 == links) ! 1175: links = OSArray::withCapacity( 1 ); ! 1176: else ! 1177: links = OSArray::withArray( links, links->getCount() ); ! 1178: UNLOCK; ! 1179: ! 1180: iter = IOLinkIterator::withCollection( links ); ! 1181: ! 1182: if( links) ! 1183: links->release(); ! 1184: ! 1185: return( iter ); ! 1186: } ! 1187: ! 1188: IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const ! 1189: { ! 1190: IORegistryEntry * entry = 0; ! 1191: OSArray * links; ! 1192: ! 1193: RLOCK; ! 1194: ! 1195: if( (links = getParentSetReference( plane ))) ! 1196: entry = (IORegistryEntry *) links->getObject( 0 ); ! 1197: ! 1198: UNLOCK; ! 1199: ! 1200: return( entry); ! 1201: } ! 1202: ! 1203: OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const ! 1204: { ! 1205: if( plane) ! 1206: return( (OSArray *) registryTable()->getObject( ! 1207: plane->keys[ kChildSetIndex ])); ! 1208: else ! 1209: return( 0 ); ! 1210: } ! 1211: ! 1212: OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const ! 1213: { ! 1214: OSArray * links; ! 1215: OSIterator * iter; ! 1216: ! 1217: if( !plane) ! 1218: return( 0 ); ! 1219: ! 1220: RLOCK; ! 1221: links = getChildSetReference( plane ); ! 1222: if( 0 == links) ! 1223: links = OSArray::withCapacity( 1 ); ! 1224: else ! 1225: links = OSArray::withArray( links, links->getCount() ); ! 1226: UNLOCK; ! 1227: ! 1228: iter = IOLinkIterator::withCollection( links ); ! 1229: ! 1230: if( links) ! 1231: links->release(); ! 1232: ! 1233: return( iter ); ! 1234: } ! 1235: ! 1236: ! 1237: IORegistryEntry * IORegistryEntry::getChildEntry( ! 1238: const IORegistryPlane * plane ) const ! 1239: { ! 1240: IORegistryEntry * entry = 0; ! 1241: OSArray * links; ! 1242: ! 1243: RLOCK; ! 1244: ! 1245: if( (links = getChildSetReference( plane ))) ! 1246: entry = (IORegistryEntry *) links->getObject( 0 ); ! 1247: ! 1248: UNLOCK; ! 1249: ! 1250: return( entry); ! 1251: } ! 1252: ! 1253: void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier, ! 1254: void * context, ! 1255: const IORegistryPlane * plane ) const ! 1256: { ! 1257: OSArray * array; ! 1258: unsigned int index; ! 1259: IORegistryEntry * next; ! 1260: ! 1261: if( !plane) ! 1262: return; ! 1263: ! 1264: RLOCK; ! 1265: array = OSArray::withArray( getChildSetReference( plane )); ! 1266: UNLOCK; ! 1267: if( array) { ! 1268: for( index = 0; ! 1269: (next = (IORegistryEntry *) array->getObject( index )); ! 1270: index++) ! 1271: (*applier)(next, context); ! 1272: array->release(); ! 1273: } ! 1274: } ! 1275: ! 1276: void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier, ! 1277: void * context, ! 1278: const IORegistryPlane * plane ) const ! 1279: { ! 1280: OSArray * array; ! 1281: unsigned int index; ! 1282: IORegistryEntry * next; ! 1283: ! 1284: if( !plane) ! 1285: return; ! 1286: ! 1287: RLOCK; ! 1288: array = OSArray::withArray( getParentSetReference( plane )); ! 1289: UNLOCK; ! 1290: if( array) { ! 1291: for( index = 0; ! 1292: (next = (IORegistryEntry *) array->getObject( index )); ! 1293: index++) ! 1294: (*applier)(next, context); ! 1295: array->release(); ! 1296: } ! 1297: } ! 1298: ! 1299: bool IORegistryEntry::isChild( IORegistryEntry * child, ! 1300: const IORegistryPlane * plane, ! 1301: bool onlyChild = false ) const ! 1302: { ! 1303: OSArray * links; ! 1304: bool ret = false; ! 1305: ! 1306: RLOCK; ! 1307: ! 1308: if( (links = getChildSetReference( plane ))) { ! 1309: if( (!onlyChild) || (1 == links->getCount())) ! 1310: ret = arrayMember( links, child ); ! 1311: } ! 1312: if( ret && (links = child->getParentSetReference( plane ))) ! 1313: ret = arrayMember( links, this ); ! 1314: ! 1315: UNLOCK; ! 1316: ! 1317: return( ret); ! 1318: } ! 1319: ! 1320: bool IORegistryEntry::isParent( IORegistryEntry * parent, ! 1321: const IORegistryPlane * plane, ! 1322: bool onlyParent = false ) const ! 1323: ! 1324: { ! 1325: OSArray * links; ! 1326: bool ret = false; ! 1327: ! 1328: RLOCK; ! 1329: ! 1330: if( (links = getParentSetReference( plane ))) { ! 1331: if( (!onlyParent) || (1 == links->getCount())) ! 1332: ret = arrayMember( links, parent ); ! 1333: } ! 1334: if( ret && (links = parent->getChildSetReference( plane ))) ! 1335: ret = arrayMember( links, this ); ! 1336: ! 1337: UNLOCK; ! 1338: ! 1339: return( ret); ! 1340: } ! 1341: ! 1342: bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const ! 1343: { ! 1344: bool ret; ! 1345: ! 1346: RLOCK; ! 1347: ! 1348: ret = (0 != getParentSetReference( plane )); ! 1349: ! 1350: UNLOCK; ! 1351: ! 1352: return( ret ); ! 1353: } ! 1354: ! 1355: bool IORegistryEntry::attachToParent( IORegistryEntry * parent, ! 1356: const IORegistryPlane * plane ) ! 1357: { ! 1358: OSArray * links; ! 1359: bool ret; ! 1360: bool needParent; ! 1361: ! 1362: if( this == parent) ! 1363: return( false ); ! 1364: ! 1365: WLOCK; ! 1366: ! 1367: ret = makeLink( parent, kParentSetIndex, plane ); ! 1368: ! 1369: if( (links = parent->getChildSetReference( plane ))) ! 1370: needParent = (false == arrayMember( links, this )); ! 1371: else ! 1372: needParent = true; ! 1373: ! 1374: // ret &= parent->makeLink( this, kChildSetIndex, plane ); ! 1375: ! 1376: UNLOCK; ! 1377: ! 1378: if( needParent) ! 1379: ret &= parent->attachToChild( this, plane ); ! 1380: ! 1381: return( ret ); ! 1382: } ! 1383: ! 1384: bool IORegistryEntry::attachToChild( IORegistryEntry * child, ! 1385: const IORegistryPlane * plane ) ! 1386: { ! 1387: OSArray * links; ! 1388: bool ret; ! 1389: bool needChild; ! 1390: ! 1391: if( this == child) ! 1392: return( false ); ! 1393: ! 1394: WLOCK; ! 1395: ! 1396: ret = makeLink( child, kChildSetIndex, plane ); ! 1397: ! 1398: if( (links = child->getParentSetReference( plane ))) ! 1399: needChild = (false == arrayMember( links, this )); ! 1400: else ! 1401: needChild = true; ! 1402: ! 1403: UNLOCK; ! 1404: ! 1405: if( needChild) ! 1406: ret &= child->attachToParent( this, plane ); ! 1407: ! 1408: return( ret ); ! 1409: } ! 1410: ! 1411: void IORegistryEntry::detachFromParent( IORegistryEntry * parent, ! 1412: const IORegistryPlane * plane ) ! 1413: { ! 1414: OSArray * links; ! 1415: bool needParent; ! 1416: ! 1417: WLOCK; ! 1418: ! 1419: parent->retain(); ! 1420: ! 1421: breakLink( parent, kParentSetIndex, plane ); ! 1422: ! 1423: if( (links = parent->getChildSetReference( plane ))) ! 1424: needParent = arrayMember( links, this ); ! 1425: else ! 1426: needParent = false; ! 1427: ! 1428: // parent->breakLink( this, kChildSetIndex, plane ); ! 1429: ! 1430: UNLOCK; ! 1431: ! 1432: if( needParent) ! 1433: parent->detachFromChild( this, plane ); ! 1434: ! 1435: parent->release(); ! 1436: } ! 1437: ! 1438: void IORegistryEntry::detachFromChild( IORegistryEntry * child, ! 1439: const IORegistryPlane * plane ) ! 1440: { ! 1441: OSArray * links; ! 1442: bool needChild; ! 1443: ! 1444: WLOCK; ! 1445: ! 1446: child->retain(); ! 1447: ! 1448: breakLink( child, kChildSetIndex, plane ); ! 1449: ! 1450: if( (links = child->getParentSetReference( plane ))) ! 1451: needChild = arrayMember( links, this ); ! 1452: else ! 1453: needChild = false; ! 1454: ! 1455: UNLOCK; ! 1456: ! 1457: if( needChild) ! 1458: child->detachFromParent( this, plane ); ! 1459: ! 1460: child->release(); ! 1461: } ! 1462: ! 1463: void IORegistryEntry::detachAbove( const IORegistryPlane * plane ) ! 1464: { ! 1465: IORegistryEntry * parent; ! 1466: ! 1467: retain(); ! 1468: while( (parent = getParentEntry( plane ))) ! 1469: detachFromParent( parent, plane ); ! 1470: release(); ! 1471: } ! 1472: ! 1473: void IORegistryEntry::detachAll( const IORegistryPlane * plane ) ! 1474: { ! 1475: OSOrderedSet * all; ! 1476: IORegistryEntry * next; ! 1477: IORegistryIterator * regIter; ! 1478: ! 1479: regIter = IORegistryIterator::iterateOver( this, plane, true ); ! 1480: if( 0 == regIter) ! 1481: return; ! 1482: all = regIter->iterateAll(); ! 1483: regIter->release(); ! 1484: ! 1485: detachAbove( plane ); ! 1486: if( all) { ! 1487: while( (next = (IORegistryEntry *) all->getLastObject())) { ! 1488: ! 1489: next->retain(); ! 1490: all->removeObject(next); ! 1491: ! 1492: next->detachAbove( plane ); ! 1493: next->release(); ! 1494: } ! 1495: all->release(); ! 1496: } ! 1497: } ! 1498: ! 1499: unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const ! 1500: { ! 1501: unsigned int depth = 1; ! 1502: OSArray * parents; ! 1503: unsigned int oneDepth, maxParentDepth, count; ! 1504: IORegistryEntry * one; ! 1505: const IORegistryEntry * next; ! 1506: unsigned int index; ! 1507: ! 1508: RLOCK; ! 1509: ! 1510: next = this; ! 1511: while( (parents = next->getParentSetReference( plane ))) { ! 1512: ! 1513: count = parents->getCount(); ! 1514: if( 0 == count) ! 1515: break; ! 1516: if( 1 == count) { ! 1517: depth++; ! 1518: next = (IORegistryEntry *) parents->getObject( 0 ); ! 1519: } else { ! 1520: // painful ! 1521: maxParentDepth = 0; ! 1522: for( index = 0; ! 1523: (one = (IORegistryEntry *) parents->getObject( index )); ! 1524: index++ ) { ! 1525: oneDepth = one->getDepth( plane ); ! 1526: if( oneDepth > maxParentDepth) ! 1527: maxParentDepth = oneDepth; ! 1528: } ! 1529: depth += maxParentDepth; ! 1530: break; ! 1531: } ! 1532: } ! 1533: ! 1534: UNLOCK; ! 1535: ! 1536: return( depth); ! 1537: } ! 1538: ! 1539: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 1540: ! 1541: #undef super ! 1542: #define super OSIterator ! 1543: ! 1544: OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator) ! 1545: ! 1546: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 1547: ! 1548: IORegistryIterator * ! 1549: IORegistryIterator::iterateOver( IORegistryEntry * root, ! 1550: const IORegistryPlane * plane, ! 1551: IOOptionBits options = 0 ) ! 1552: { ! 1553: IORegistryIterator * create; ! 1554: ! 1555: if( 0 == root) ! 1556: return( 0); ! 1557: if( 0 == plane) ! 1558: return( 0); ! 1559: ! 1560: create = new IORegistryIterator; ! 1561: if( create) { ! 1562: if( create->init()) { ! 1563: ! 1564: root->retain(); ! 1565: create->root = root; ! 1566: create->where = &create->start; ! 1567: create->start.current = root; ! 1568: create->plane = plane; ! 1569: create->options = options; ! 1570: ! 1571: } else { ! 1572: create->release(); ! 1573: create = 0; ! 1574: } ! 1575: } ! 1576: return( create); ! 1577: } ! 1578: ! 1579: IORegistryIterator * ! 1580: IORegistryIterator::iterateOver( const IORegistryPlane * plane, ! 1581: IOOptionBits options = 0 ) ! 1582: { ! 1583: return( iterateOver( gRegistryRoot, plane, options )); ! 1584: } ! 1585: ! 1586: bool IORegistryIterator::isValid( void ) ! 1587: { ! 1588: bool ok; ! 1589: IORegCursor * next; ! 1590: ! 1591: ok = true; ! 1592: next = where; ! 1593: ! 1594: RLOCK; ! 1595: while( ok && next) { ! 1596: if( where->iter) ! 1597: ok = where->iter->isValid(); ! 1598: next = next->next; ! 1599: } ! 1600: UNLOCK; ! 1601: ! 1602: return( ok); ! 1603: } ! 1604: ! 1605: void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane ) ! 1606: { ! 1607: IORegCursor * prev; ! 1608: ! 1609: prev = where; ! 1610: where = (IORegCursor *) IOMalloc( sizeof( IORegCursor)); ! 1611: assert( where); ! 1612: ! 1613: if( where) { ! 1614: where->iter = 0; ! 1615: where->next = prev; ! 1616: where->current = prev->current; ! 1617: plane = enterPlane; ! 1618: } ! 1619: } ! 1620: ! 1621: void IORegistryIterator::enterEntry( void ) ! 1622: { ! 1623: enterEntry( plane ); ! 1624: } ! 1625: ! 1626: bool IORegistryIterator::exitEntry( void ) ! 1627: { ! 1628: IORegCursor * gone; ! 1629: ! 1630: if( where->iter) { ! 1631: where->iter->release(); ! 1632: where->iter = 0; ! 1633: if( where->current)// && (where != &start)) ! 1634: where->current->release(); ! 1635: } ! 1636: ! 1637: if( where != &start) { ! 1638: gone = where; ! 1639: where = gone->next; ! 1640: IOFree( gone, sizeof( IORegCursor)); ! 1641: return( true); ! 1642: ! 1643: } else ! 1644: return( false); ! 1645: } ! 1646: ! 1647: void IORegistryIterator::reset( void ) ! 1648: { ! 1649: while( exitEntry()) ! 1650: {} ! 1651: ! 1652: if( done) { ! 1653: done->release(); ! 1654: done = 0; ! 1655: } ! 1656: ! 1657: where->current = root; ! 1658: } ! 1659: ! 1660: void IORegistryIterator::free( void ) ! 1661: { ! 1662: reset(); ! 1663: ! 1664: if( root) ! 1665: root->release(); ! 1666: ! 1667: super::free(); ! 1668: } ! 1669: ! 1670: ! 1671: IORegistryEntry * IORegistryIterator::getNextObjectFlat( void ) ! 1672: { ! 1673: IORegistryEntry * next = 0; ! 1674: OSArray * links = 0; ! 1675: ! 1676: RLOCK; ! 1677: ! 1678: if( (0 == where->iter)) { ! 1679: // just entered - create new iter ! 1680: if( isValid() ! 1681: && where->current ! 1682: && (links = ( (options & kIORegistryIterateParents) ? ! 1683: where->current->getParentSetReference( plane ) : ! 1684: where->current->getChildSetReference( plane ) )) ) ! 1685: ! 1686: where->iter = OSCollectionIterator::withCollection( links ); ! 1687: ! 1688: } else ! 1689: // next sibling - release current ! 1690: if( where->current) ! 1691: where->current->release(); ! 1692: ! 1693: if( where->iter) ! 1694: next = (IORegistryEntry *) where->iter->getNextObject(); ! 1695: ! 1696: if( next) ! 1697: next->retain(); ! 1698: ! 1699: where->current = next; ! 1700: ! 1701: UNLOCK; ! 1702: ! 1703: return( next); ! 1704: } ! 1705: ! 1706: IORegistryEntry * IORegistryIterator::getNextObjectRecursive( void ) ! 1707: { ! 1708: IORegistryEntry * next; ! 1709: ! 1710: do ! 1711: next = getNextObjectFlat(); ! 1712: while( (0 == next) && exitEntry()); ! 1713: ! 1714: if( next) { ! 1715: if( 0 == done) ! 1716: done = OSOrderedSet::withCapacity( 10 ); ! 1717: if( done->setObject((OSObject *) next)) { ! 1718: // done set didn't contain this one, so recurse ! 1719: enterEntry(); ! 1720: } ! 1721: } ! 1722: return( next); ! 1723: } ! 1724: ! 1725: IORegistryEntry * IORegistryIterator::getNextObject( void ) ! 1726: { ! 1727: if( options & kIORegistryIterateRecursively) ! 1728: return( getNextObjectRecursive()); ! 1729: else ! 1730: return( getNextObjectFlat()); ! 1731: } ! 1732: ! 1733: IORegistryEntry * IORegistryIterator::getCurrentEntry( void ) ! 1734: { ! 1735: if( isValid()) ! 1736: return( where->current); ! 1737: else ! 1738: return( 0); ! 1739: } ! 1740: ! 1741: OSOrderedSet * IORegistryIterator::iterateAll( void ) ! 1742: { ! 1743: reset(); ! 1744: while( getNextObjectRecursive()) ! 1745: {} ! 1746: if( done) ! 1747: done->retain(); ! 1748: return( done); ! 1749: } ! 1750: ! 1751:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.