+bool
+IOPlatformExpert::CheckSubTree(OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
+{
+ unsigned int i;
+ unsigned int numPowerTreeNodes;
+ OSDictionary * entry;
+ OSDictionary * matchingDictionary;
+ OSDictionary * providerDictionary;
+ OSDictionary * deviceDictionary;
+ OSDictionary * nubDictionary;
+ OSArray * children;
+ bool nodeFound = false;
+ bool continueSearch = false;
+ bool deviceMatch = false;
+ bool providerMatch = false;
+ bool multiParentMatch = false;
+
+ if ((NULL == theDevice) || (NULL == inSubTree)) {
+ return false;
+ }
+
+ numPowerTreeNodes = inSubTree->getCount();
+
+ // iterate through the power tree to find a home for this device
+
+ for (i = 0; i < numPowerTreeNodes; i++) {
+ entry = (OSDictionary *) inSubTree->getObject(i);
+
+ matchingDictionary = (OSDictionary *) entry->getObject("device");
+ providerDictionary = (OSDictionary *) entry->getObject("provider");
+
+ deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
+ if (matchingDictionary) {
+ deviceMatch = false;
+ if (NULL != (deviceDictionary = theDevice->dictionaryWithProperties())) {
+ deviceMatch = deviceDictionary->isEqualTo( matchingDictionary, matchingDictionary );
+ deviceDictionary->release();
+ }
+ }
+
+ providerMatch = true; // we indicate a match if there is no nub or provider
+ if (theNub && providerDictionary) {
+ providerMatch = false;
+ if (NULL != (nubDictionary = theNub->dictionaryWithProperties())) {
+ providerMatch = nubDictionary->isEqualTo( providerDictionary, providerDictionary );
+ nubDictionary->release();
+ }
+ }
+
+ multiParentMatch = true; // again we indicate a match if there is no multi-parent node
+ if (deviceMatch && providerMatch) {
+ if (NULL != multipleParentKeyValue) {
+ OSNumber * aNumber = (OSNumber *) entry->getObject("multiple-parent");
+ multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo(aNumber) : false;
+ }
+ }
+
+ nodeFound = (deviceMatch && providerMatch && multiParentMatch);
+
+ // if the power tree specifies a provider dictionary but theNub is
+ // NULL then we cannot match with this entry.
+
+ if (theNub == NULL && providerDictionary != NULL) {
+ nodeFound = false;
+ }
+
+ // if this node is THE ONE...then register the device
+
+ if (nodeFound) {
+ if (RegisterServiceInTree(theDevice, entry, theParent, theNub)) {
+ if (kIOLogPower & gIOKitDebug) {
+ IOLog("PMRegisterDevice/CheckSubTree - service registered!\n");
+ }
+
+ numInstancesRegistered++;
+
+ // determine if we need to search for additional nodes for this item
+ multipleParentKeyValue = (OSNumber *) entry->getObject("multiple-parent");
+ } else {
+ nodeFound = false;
+ }
+ }
+
+ continueSearch = ((false == nodeFound) || (NULL != multipleParentKeyValue));
+
+ if (continueSearch && (NULL != (children = (OSArray *) entry->getObject("children")))) {
+ nodeFound = CheckSubTree( children, theNub, theDevice, entry );
+ continueSearch = ((false == nodeFound) || (NULL != multipleParentKeyValue));
+ }
+
+ if (false == continueSearch) {
+ break;
+ }
+ }
+
+ return nodeFound;
+}
+
+//*********************************************************************************
+// RegisterServiceInTree
+//
+// Register a device at the specified node of our power tree.
+//*********************************************************************************
+
+bool
+IOPlatformExpert::RegisterServiceInTree(IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
+{
+ IOService * aService;
+ bool registered = false;
+ OSArray * children;
+ unsigned int numChildren;
+ OSDictionary * child;
+
+ // make sure someone is not already registered here
+
+ if (NULL == theTreeNode->getObject("service")) {
+ if (theTreeNode->setObject("service", OSDynamicCast( OSObject, theService))) {
+ // 1. CHILDREN ------------------
+
+ // we registered the node in the tree...now if the node has children
+ // registered we must tell this service to add them.
+
+ if (NULL != (children = (OSArray *) theTreeNode->getObject("children"))) {
+ numChildren = children->getCount();
+ for (unsigned int i = 0; i < numChildren; i++) {
+ if (NULL != (child = (OSDictionary *) children->getObject(i))) {
+ if (NULL != (aService = (IOService *) child->getObject("service"))) {
+ theService->addPowerChild(aService);
+ }
+ }
+ }
+ }
+
+ // 2. PARENT --------------------
+
+ // also we must notify the parent of this node (if a registered service
+ // exists there) of a new child.
+
+ if (theTreeParentNode) {
+ if (NULL != (aService = (IOService *) theTreeParentNode->getObject("service"))) {
+ if (aService != theProvider) {
+ aService->addPowerChild(theService);
+ }
+ }
+ }
+
+ registered = true;
+ }
+ }
+
+ return registered;
+}
+
+//*********************************************************************************
+// printDictionaryKeys
+//
+// Print the keys for the given dictionary and selected contents.
+//*********************************************************************************
+void
+printDictionaryKeys(OSDictionary * inDictionary, char * inMsg)