AppleUSBMergeNub.cpp [plain text]
#include <IOKit/IOKitKeys.h>
#include <IOKit/usb/IOUSBLog.h>
#include <IOKit/usb/IOUSBDevice.h>
#include "AppleUSBMergeNub.h"
#ifndef APPLEUSBMERGENUB_USE_KPRINTF
#define APPLEUSBMERGENUB_USE_KPRINTF 0
#endif
#if APPLEUSBMERGENUB_USE_KPRINTF
#undef USBLog
#undef USBError
void kprintf(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#define USBLog( LEVEL, FORMAT, ARGS... ) if ((LEVEL) <= APPLEUSBMERGENUB_USE_KPRINTF) { kprintf( FORMAT "\n", ## ARGS ) ; }
#define USBError( LEVEL, FORMAT, ARGS... ) { kprintf( FORMAT "\n", ## ARGS ) ; }
#endif
#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 )
{
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider merging dictionary(%p) into (%p)", getName(), this, sourceDictionary, providerDictionary);
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, (uint32_t)providerSize);
USBLog(5,"%s[%p]::MergeDictionaryIntoProvider need to merge a dictionary \"%s\" %p into %p", getName(), this, str, sourceDictionary, localCopyOfProvidersDictionary);
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, (uint32_t) providerSize, (uint32_t) 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(7,"-%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)
{
OSDictionary * localCopyOfTargetDictionary;
UInt32 targetSize;
UInt32 targetSizeAfterMerge;
localCopyOfTargetDictionary = OSDictionary::withDictionary( childTargetDictionary, 0);
if ( localCopyOfTargetDictionary == NULL )
{
USBError(1,"%s[%p]::MergeDictionaryIntoDictionary could not copy our target's dictionary",getName(), this);
break;
}
targetSize = childTargetDictionary->getCapacity();
USBLog(5,"%s[%p]::MergeDictionaryIntoDictionary Created a local copy(%p) of dictionary (%p), size %d", getName(), this, localCopyOfTargetDictionary, childTargetDictionary, (uint32_t)targetSize);
USBLog(5,"%s[%p]::MergeDictionaryIntoDictionary recursing to merge a dictionary \"%s\" %p into %p", getName(), this, str, childSourceDictionary, localCopyOfTargetDictionary);
result = MergeDictionaryIntoDictionary(childSourceDictionary, localCopyOfTargetDictionary) ;
if ( result )
{
targetSizeAfterMerge = childTargetDictionary->getCapacity();
if ( targetSizeAfterMerge != targetSize )
{
USBError(1,"%s[%p]::MergeDictionaryIntoDictionary our target's dictionary size changed (%d,%d)",getName(), this, (uint32_t) targetSize, (uint32_t) targetSizeAfterMerge);
}
USBLog(5,"%s[%p]::MergeDictionaryIntoDictionary setting dictionary %s from merged dictionary (%p)", getName(), this, str, localCopyOfTargetDictionary);
result = parentTargetDictionary->setObject(keyObject, localCopyOfTargetDictionary);
if ( !result )
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary setProperty %s , returned false", getName(), this, str);
break;
}
}
else
{
USBLog(3,"%s[%p]::MergeDictionaryIntoDictionary MergeDictionaryIntoDictionary(%p,%p) returned false", getName(), this, childSourceDictionary, localCopyOfTargetDictionary);
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;
}