IOHIDProviderPropertyMerger.cpp [plain text]
#include <AssertMacros.h>
#include <libkern/OSAtomic.h>
#include <libkern/c++/OSDictionary.h>
#include <IOKit/IOLib.h>
#include "IOHIDProviderPropertyMerger.h"
#define super IOService
OSDefineMetaClassAndStructors(IOHIDProviderPropertyMerger, IOService);
bool IOHIDProviderPropertyMerger::start(IOService* provider)
{
OSObject * properties = NULL;
properties = copyProperty("IOProviderMergeProperties");
mergeProperties(provider, OSDynamicCast(OSDictionary, properties));
OSSafeReleaseNULL(properties);
return false;
}
bool IOHIDProviderPropertyMerger::mergeProperties(IOService * provider, OSDictionary * properties)
{
const OSSymbol * dictionaryEntry = NULL;
OSCollectionIterator * iterator = NULL;
bool result = false;
require(provider && properties, exit);
iterator = OSCollectionIterator::withCollection(properties);
require(iterator, exit);
while ( (dictionaryEntry = (const OSSymbol *)iterator->getNextObject()) ) {
OSDictionary * sourceDictionary = NULL;
OSObject * providerObject = NULL;
OSDictionary * providerDictionary = NULL;
providerObject = provider->copyProperty(dictionaryEntry);
sourceDictionary = OSDynamicCast(OSDictionary, properties->getObject(dictionaryEntry));
providerDictionary = OSDynamicCast(OSDictionary, providerObject);
if ( providerDictionary && sourceDictionary ) {
OSDictionary * providerDictionaryCopy = NULL;
providerDictionaryCopy = OSDictionary::withDictionary( providerDictionary, 0);
require_action(providerDictionaryCopy, dictionaryExit, result=false);
result = mergeDictionaries(sourceDictionary, providerDictionaryCopy);
require(result, dictionaryExit);
result = provider->setProperty(dictionaryEntry, providerDictionaryCopy);
require(result, dictionaryExit);
dictionaryExit:
if ( providerDictionaryCopy )
providerDictionaryCopy->release();
} else {
if (!providerObject) {
result = provider->setProperty(dictionaryEntry, properties->getObject(dictionaryEntry));
}
}
if ( providerObject )
providerObject->release();
if ( !result )
break;
}
exit:
if ( iterator )
iterator->release();
return result;
}
bool IOHIDProviderPropertyMerger::mergeDictionaries(OSDictionary * source, OSDictionary * target)
{
OSCollectionIterator * srcIterator = NULL;
OSSymbol* keyObject = NULL;
bool result = false;
require(source && target, exit);
srcIterator = OSCollectionIterator::withCollection(source);
require(srcIterator, exit);
while ((keyObject = OSDynamicCast(OSSymbol, srcIterator->getNextObject()))) {
OSDictionary * childSourceDictionary = NULL;
OSDictionary * childTargetDictionary = NULL;
OSObject * childTargetObject = NULL;
childTargetObject = target->getObject(keyObject);
if ( childTargetObject )
childTargetDictionary = OSDynamicCast(OSDictionary, childTargetObject);
childSourceDictionary = OSDynamicCast(OSDictionary, source->getObject(keyObject));
if ( childTargetDictionary && childSourceDictionary) {
result = mergeDictionaries(childSourceDictionary, childTargetDictionary) ;
if ( !result )
break;
} else {
result = target->setObject(keyObject, source->getObject(keyObject)) ;
if ( !result )
break;
}
}
exit:
if ( srcIterator )
srcIterator->release();
return result;
}