/* * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This 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 OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * IOFireWireUserClientIniter.cpp * IOFireWireFamily * * Created by NWG on Wed Jan 24 2001. * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. * */ #import "IOFireWireUserClientIniter.h" #import #import #import #import #undef super #define super IOService IORecursiveLock * IOFireWireUserClientIniter::sIniterLock = NULL; OSDefineMetaClassAndStructors(IOFireWireUserClientIniter, super); OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 0); OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 1); OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 2); OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 3); // init // // bool IOFireWireUserClientIniter::init(OSDictionary * propTable) { fProvider = NULL ; if( sIniterLock == NULL ) { IORecursiveLock * lock = IORecursiveLockAlloc(); //IOLog( "IOFireWireUserClientIniter<0x%08lx>::init - IORecursiveLockAlloc = 0x%08lx\n", this, lock ); bool result = false; while( sIniterLock == NULL && result == false ) { result = OSCompareAndSwap( NULL, (UInt32)lock, (UInt32*)&sIniterLock ); } if( result == false ) { //IOLog( "IOFireWireUserClientIniter<0x%08lx>::init - IORecursiveLockFree = 0x%08lx\n", this, lock ); IORecursiveLockFree( lock ); } } //IOLog( "IOFireWireUserClientIniter<0x%08lx>::init - sIniterLock = 0x%08lx\n", this, sIniterLock ); return super::init(propTable) ; } // start // // bool IOFireWireUserClientIniter::start( IOService* provider) { //IOLog( "IOFireWireUserClientIniter<0x%08lx>::start - provider = 0x%08lx\n", this, provider ); if( provider == NULL ) { return false; } fProvider = provider ; fProvider->retain(); OSObject* dictObj = getProperty("IOProviderMergeProperties"); OSDictionary * merge_properties = OSDynamicCast(OSDictionary, dictObj); if( merge_properties != NULL ) { merge_properties = dictionaryDeepCopy( merge_properties ); } if ( !merge_properties ) { IOLog("%s %u: couldn't get merge_properties\n", __FILE__, __LINE__ ) ; return false; } // // make sure the user client class object is an OSSymbol // OSObject * userClientClassObject = merge_properties->getObject( gIOUserClientClassKey ); if( OSDynamicCast(OSString, userClientClassObject) != NULL ) { // if the the user client class object is an OSString, turn it into an OSSymbol const OSSymbol * userClientClassSymbol = OSSymbol::withString((const OSString *) userClientClassObject); if( userClientClassSymbol != NULL ) { merge_properties->setObject(gIOUserClientClassKey, (OSObject *) userClientClassSymbol); userClientClassSymbol->release(); } } else if( OSDynamicCast(OSSymbol, userClientClassObject) == NULL ) { // if its not an OSString or an OSymbol remove it from the merge properties merge_properties->removeObject(gIOUserClientClassKey); } // serialize all firwire user client initers IORecursiveLockLock( sIniterLock ); mergeProperties( fProvider, merge_properties ); IORecursiveLockUnlock( sIniterLock ); merge_properties->release(); //IOLog( "IOFireWireUserClientIniter<0x%08lx>::start - return\n", this ); return true ; } // stop // // void IOFireWireUserClientIniter::stop(IOService* provider) { IOService::stop(provider) ; } // free // // void IOFireWireUserClientIniter::free() { if( fProvider != NULL ) { fProvider->release(); fProvider = NULL; } IOService::free(); } // mergeProperties // // recursively merge a dictionaries into a registry entry void IOFireWireUserClientIniter::mergeProperties( IORegistryEntry * dest, OSDictionary * src ) { //IOLog( "IOFireWireUserClientIniter<0x%08lx>::mergeProperties - dest = 0x%08lx, src = 0x%08lx\n", this, dest, src ); if( !dest || !src ) return; OSCollectionIterator* srcIterator = OSCollectionIterator::withCollection( src ); OSSymbol* keyObject = NULL; OSObject* destObject = NULL; OSObject* srcObject = NULL; while( NULL != (keyObject = OSDynamicCast(OSSymbol, srcIterator->getNextObject())) ) { srcObject = src->getObject(keyObject); destObject = dest->getProperty(keyObject); OSDictionary * destDictionary = OSDynamicCast( OSDictionary, destObject ); OSDictionary * srcDictionary = OSDynamicCast( OSDictionary, srcObject ); if( destDictionary && srcDictionary ) { // if there's already already a property defined in the destination // and the source and destination are dictionaries, we need to do // a recursive merge // shallow copy the destination directory destDictionary = OSDictionary::withDictionary( destDictionary ); // recurse mergeDictionaries( destDictionary, srcDictionary ); // set the property dest->setProperty( keyObject, destDictionary ); destDictionary->release(); } else { // if the property is not already in destination dictionary // or both source a destination are not dictionaries // then we can set the property without merging // any dictionaries in the source should already // have been deep copied before we began merging dest->setProperty( keyObject, srcObject ); } } // have to release this, or we'll leak. srcIterator->release(); //IOLog( "IOFireWireUserClientIniter<0x%08lx>::mergeProperties - return\n", this ); } // mergeDictionaries // // recursively merge two dictionaries void IOFireWireUserClientIniter::mergeDictionaries( OSDictionary * dest, OSDictionary * src ) { //IOLog( "IOFireWireUserClientIniter<0x%08lx>::mergeDictionaries - dest = 0x%08lx, src = 0x%08lx\n", this, dest, src ); if( !src || !dest ) return; OSCollectionIterator* srcIterator = OSCollectionIterator::withCollection(src); OSSymbol* keyObject = NULL; OSObject* destObject = NULL; OSObject* srcObject = NULL; while( NULL != (keyObject = OSDynamicCast(OSSymbol, srcIterator->getNextObject())) ) { srcObject = src->getObject(keyObject); destObject = dest->getObject(keyObject); OSDictionary * destDictionary = OSDynamicCast( OSDictionary, destObject ); OSDictionary * srcDictionary = OSDynamicCast( OSDictionary, srcObject ); if( destDictionary && srcDictionary ) { // if there's already already a property defined in the destination // and the source and destination are dictionaries, we need to do // a recursive merge // shallow copy the destination directory destDictionary = OSDictionary::withDictionary( destDictionary); // recurse mergeDictionaries( destDictionary, srcDictionary ); // set the property dest->setObject( keyObject, destDictionary ); destDictionary->release(); } else { // if the property is not already in destination dictionary // or both source a destination are not dictionaries // then we can set the property without merging // any dictionaries in the source should already // have been deep copied before we began merging dest->setObject( keyObject, srcObject ); } } // have to release this, or we'll leak. srcIterator->release(); //IOLog( "IOFireWireUserClientIniter<0x%08lx>::mergeDictionaries - return\n", this ); } // dictionaryDeepCopy // // recursively copy an OSDictionary OSDictionary* IOFireWireUserClientIniter::dictionaryDeepCopy( OSDictionary* srcDictionary) { //IOLog( "IOFireWireUserClientIniter<0x%08lx>::dictionaryDeepCopy - srcDictionary = 0x%08lx\n", this, srcDictionary ); OSDictionary* result = NULL; OSObject* srcObject = NULL; OSCollectionIterator* srcIterator = NULL; OSSymbol* keyObject = NULL; result = OSDictionary::withCapacity(srcDictionary->getCount()); if (result) { srcIterator = OSCollectionIterator::withCollection(srcDictionary); if (srcIterator) { while ( (keyObject = OSDynamicCast(OSSymbol, srcIterator->getNextObject())) ) { srcObject = srcDictionary->getObject(keyObject); if (OSDynamicCast(OSDictionary, srcObject)) { srcObject = dictionaryDeepCopy((OSDictionary*)srcObject); result->setObject(keyObject, srcObject); // copyDictionaryProperty creates a new dictionary, so we should release // it after we add it to our dictionary srcObject->release(); } else { result->setObject(keyObject, srcObject); } } srcIterator->release(); } } //IOLog( "IOFireWireUserClientIniter<0x%08lx>::dictionaryDeepCopy - return\n", this ); return result; }