IOFireWireUserClientIniter.cpp   [plain text]


/*
 * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 *  IOFireWireUserClientIniter.cpp
 *  IOFireWireFamily
 *
 *  Created by NWG on Wed Jan 24 2001.
 *  Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
 *
 */

#import "IOFireWireUserClientIniter.h"

#import <IOKit/assert.h>
#import <IOKit/IOLib.h>
#import <IOKit/IOService.h>
#import <libkern/OSAtomic.h>

#undef super
#define super IOService

OSDefineMetaClassAndStructors(IOFireWireUserClientIniter, super);
OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 0);
OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 1);
OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 2);
OSMetaClassDefineReservedUnused(IOFireWireUserClientIniter, 3);

// init
//
//

bool
IOFireWireUserClientIniter::init(OSDictionary * propTable)
{
	fPropTable = propTable ;
	fProvider = NULL ;
	
	return super::init(propTable) ;
}

// start
//
//

bool
IOFireWireUserClientIniter::start(
	IOService*	provider)
{
	if( provider == NULL )
	{
		return false;
	}
	
	fProvider = provider ;
	fProvider->retain();

	OSObject*	dictObj = getProperty("IOProviderMergeProperties");
	
	fProviderMergeProperties = OSDynamicCast(OSDictionary, dictObj);
	
	if ( !fProviderMergeProperties )
	{
		fHasUCIniter = false;
		IOLog("%s %u: couldn't get fProviderMergeProperties\n", __FILE__, __LINE__ ) ;
		return false;
	}

	//
	// make sure the user client class object is an OSSymbol
	//
	
	OSObject * userClientClassObject = fProviderMergeProperties->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 )
		{
			fProviderMergeProperties->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
		
		fProviderMergeProperties->removeObject(gIOUserClientClassKey);
	}
	
    OSDictionary*	providerProps = fProvider->getPropertyTable() ;
	if (providerProps)
	{
		mergeProperties(providerProps, fProviderMergeProperties) ;
//		fProviderMergeProperties->flushCollection() ;
	}

    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
//
// recurively merge the properties of two dictionaries

void
IOFireWireUserClientIniter::mergeProperties(OSObject* inDest, OSObject* inSrc)
{
	OSDictionary*	dest = OSDynamicCast(OSDictionary, inDest);
	OSDictionary*	src = OSDynamicCast(OSDictionary, inSrc);

	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);
		
		if (OSDynamicCast(OSDictionary, srcObject))
		{
			srcObject = copyDictionaryProperty((OSDictionary*)srcObject);
			
			// if there's a already a dictionary with the same key as the 
			// srcObject, we need to merge the new properties with that 
			// dictionary, otherwise we can just add the srcObject to the
			// dest dictionary
			
			if( destObject )
				mergeProperties(destObject, srcObject);
			else
				dest->setObject(keyObject, srcObject);
			
			// copyDictionaryProperty creates a new dictionary, so we should release 
			// it after we add it to our dictionary
	
			srcObject->release();
		}
		else
		{
			// if the property is not a dictionary, then we can simply add it to the
			// destination dictionary
			
			dest->setObject(keyObject, srcObject);
		}
	}
	
	// have to release this, or we'll leak.
	srcIterator->release();
}

// copyDictionaryProperty
//
// recursively copy am OSDictionary

OSDictionary*
IOFireWireUserClientIniter::copyDictionaryProperty(
	OSDictionary*	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 = copyDictionaryProperty((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();
		}
	}
	
	return result;
}