AppleUSBMergeNub.cpp [plain text]
#include "AppleUSBMergeNub.h"
#include <IOKit/usb/IOUSBController.h>
#include <IOKit/usb/IOUSBLog.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IOService.h>
#include <libkern/c++/OSNumber.h>
#define super IOService
OSDefineMetaClassAndStructors(AppleUSBMergeNub, IOService)
static bool haveCreatedRef = false;
IOService *
AppleUSBMergeNub::probe(IOService *provider, SInt32 *score)
{
const IORegistryPlane * usbPlane = getPlane(kIOUSBPlane);
IOUSBDevice *device = OSDynamicCast(IOUSBDevice, provider);
if (device && usbPlane)
{
IOUSBNub *parentNub = OSDynamicCast(IOUSBNub, device->getParentEntry(usbPlane));
if (parentNub)
{
OSDictionary *providerDict = (OSDictionary*)getProperty("IOProviderParentUSBNubMergeProperties");
if (providerDict)
{
MergeDictionaryIntoProvider( parentNub, providerDict);
}
}
}
OSDictionary *providerDict = (OSDictionary*)getProperty("IOProviderMergeProperties");
if (providerDict)
{
MergeDictionaryIntoProvider( provider, providerDict);
}
return NULL; }
bool
AppleUSBMergeNub::MergeDictionaryIntoProvider(IOService * provider, OSDictionary * dictionaryToMerge)
{
const OSSymbol * dictionaryEntry = NULL;
OSCollectionIterator * iter = NULL;
bool result = false;
USBLog(6,"+%s[%p]::MergeDictionary(%p)IntoProvider(%p)", getName(), this, dictionaryToMerge, provider);
if (!provider || !dictionaryToMerge)
return false;
if (haveCreatedRef == false)
{
haveCreatedRef = true;
getMetaClass()->instanceConstructed();
}
iter = OSCollectionIterator::withCollection((OSDictionary *)dictionaryToMerge);
if ( iter != NULL )
{
while ( NULL != (dictionaryEntry = (const OSSymbol *)iter->getNextObject()) )
{
const char * str = NULL;
OSDictionary * sourceDictionary = NULL;
OSDictionary * providerDictionary = NULL;
OSObject * providerProperty = NULL;
str = dictionaryEntry->getCStringNoCopy();
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider merging \"%s\"", getName(), this, str);
providerProperty = provider->getProperty(dictionaryEntry);
if ( providerProperty )
{
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider provider already had property %s", getName(), this, str);
providerDictionary = OSDynamicCast(OSDictionary, providerProperty);
if ( providerDictionary )
{
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider provider's %s is also a dictionary (%p)", getName(), this, str, providerDictionary);
}
}
sourceDictionary = OSDynamicCast(OSDictionary, dictionaryToMerge->getObject(dictionaryEntry));
if ( sourceDictionary )
{
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider source dictionary had %s as a dictionary (%p)", getName(), this, str, sourceDictionary);
}
if ( providerDictionary && sourceDictionary )
{
OSDictionary * localCopyOfProvidersDictionary;
UInt32 providerSize;
UInt32 providerSizeAfterMerge;
localCopyOfProvidersDictionary = OSDictionary::withDictionary( providerDictionary, 0);
if ( localCopyOfProvidersDictionary == NULL )
{
USBError(1,"%s[%p]::MergeDictionaryIntoProvider could not copy our provider's dictionary",getName(), this);
break;
}
providerSize = providerDictionary->getCapacity();
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider Created a local copy(%p) of dictionary (%p), size %d", getName(), this, localCopyOfProvidersDictionary, providerDictionary, providerSize);
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider need to merge a dictionary (%s)", getName(), this, str);
result = MergeDictionaryIntoDictionary( sourceDictionary, localCopyOfProvidersDictionary);
if ( result )
{
providerSizeAfterMerge = providerDictionary->getCapacity();
if ( providerSizeAfterMerge != providerSize )
{
USBError(1,"%s[%p]::MergeDictionaryIntoProvider our provider's dictionary size changed (%d,%d)",getName(), this, providerSize, providerSizeAfterMerge);
}
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider setting property %s from merged dictionary (%p)", getName(), this, str, providerDictionary);
result = provider->setProperty( dictionaryEntry, localCopyOfProvidersDictionary );
if ( !result )
{
USBLog(3,"%s[%p]::MergeDictionaryIntoProvider setProperty %s , returned false", getName(), this, str);
break;
}
}
else
{
USBLog(3,"%s[%p]::MergeDictionaryIntoProvider MergeDictionaryIntoDictionary(%p,%p) returned false", getName(), this, sourceDictionary, providerDictionary);
break;
}
}
else
{
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider setting property %s", getName(), this, str);
result = provider->setProperty(dictionaryEntry, dictionaryToMerge->getObject(dictionaryEntry));
if ( !result )
{
USBLog(3,"%s[%p]::MergeDictionaryIntoProvider setProperty %s, returned false", getName(), this, str);
break;
}
}
}
iter->release();
}
USBLog(6,"-%s[%p]::MergeDictionaryIntoProvider(%p, %p) result %d", getName(), this, provider, dictionaryToMerge, result);
return result;
}
bool
AppleUSBMergeNub::MergeDictionaryIntoDictionary(OSDictionary * parentSourceDictionary, OSDictionary * parentTargetDictionary)
{
OSCollectionIterator* srcIterator = NULL;
OSSymbol* keyObject = NULL ;
OSObject* targetObject = NULL ;
bool result = false;
USBLog(3,"+%s[%p]::MergeDictionaryIntoDictionary(%p => %p)", getName(), this, parentSourceDictionary, parentTargetDictionary);
if (!parentSourceDictionary || !parentTargetDictionary)
return false ;
srcIterator = OSCollectionIterator::withCollection(parentSourceDictionary) ;
while (NULL != (keyObject = OSDynamicCast(OSSymbol, srcIterator->getNextObject())))
{
const char * str;
OSDictionary * childSourceDictionary = NULL;
OSDictionary * childTargetDictionary = NULL;
OSObject * childTargetObject = NULL;
str = keyObject->getCStringNoCopy();
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary merging \"%s\"", getName(), this, str);
childTargetObject = parentTargetDictionary->getObject(keyObject);
if ( childTargetObject )
{
childTargetDictionary = OSDynamicCast(OSDictionary, childTargetObject);
if ( childTargetDictionary )
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary target object %s is a dictionary (%p)", getName(), this, str, childTargetDictionary);
}
childSourceDictionary = OSDynamicCast(OSDictionary, parentSourceDictionary->getObject(keyObject));
if ( childSourceDictionary )
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary source dictionary had %s as a dictionary (%p)", getName(), this, str, childSourceDictionary);
}
if ( childTargetDictionary && childSourceDictionary)
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary recursing(%p,%p)", getName(), this, childSourceDictionary, childTargetDictionary);
result = MergeDictionaryIntoDictionary(childSourceDictionary, childTargetDictionary) ;
if ( !result )
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary recursing (%p,%p) failed", getName(), this, childSourceDictionary, childTargetDictionary);
break;
}
}
else
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary setting object %s into dictionary %p", getName(), this, str, parentTargetDictionary);
result = parentTargetDictionary->setObject(keyObject, parentSourceDictionary->getObject(keyObject)) ;
if ( !result )
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary setObject %s, returned false", getName(), this, str);
break;
}
}
}
srcIterator->release();
USBLog(3,"-%s[%p]::MergeDictionaryIntoDictionary(%p=>(%p) result %d", getName(), this, parentSourceDictionary, parentTargetDictionary, result);
return result;
}