|
|
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.