IOHIDFamilyPrivate.cpp [plain text]
#include "IOHIDFamilyPrivate.h"
#if !TARGET_OS_EMBEDDED
#include "IOHIDSystem.h"
#endif
#include "OSStackRetain.h"
#define kHIDTransport1ScoreIncrement 1000
#define kHIDTransport2ScoreIncrement 2000
#define kHIDDeviceUsageScoreBase 1100
#define kHIDDeviceUsageScoreIncrement 100
#define kHIDVendor1ScoreIncrement 5000
#define kHIDVendor2ScoreIncrement 1000
#define kHIDVendor2ArrayScoreIncrement 975
#define kHIDVendor2MaskScoreIncrement 950
#define kHIDVendor2ArrayMaskScoreIncrement 925
#define kHIDVendor3ScoreIncrement 100
bool CompareProperty( IOService * owner, OSDictionary * matching, const char * key, SInt32 * score, SInt32 increment)
{
OSObject * value;
OSObject * property;
bool matches = true;
value = matching->getObject( key );
if( value)
{
property = owner->copyProperty( key );
if ( property )
{
matches = value->isEqualTo( property );
if (matches && score)
*score += increment;
property->release();
}
else
matches = false;
}
return matches;
}
bool CompareDeviceUsage( IOService * owner, OSDictionary * matching, SInt32 * score, SInt32 increment)
{
OSObject * usage;
OSObject * usagePage;
OSArray * functions;
OSDictionary * pair;
bool matches = true;
int count;
usage = matching->getObject( kIOHIDDeviceUsageKey );
usagePage = matching->getObject( kIOHIDDeviceUsagePageKey );
functions = OSDynamicCast(OSArray, owner->copyProperty( kIOHIDDeviceUsagePairsKey ));
if ( functions )
{
if ( usagePage || usage )
{
count = functions->getCount();
for (int i=0; i<count; i++)
{
if ( !(pair = (OSDictionary *)functions->getObject(i)) )
continue;
if ( !usagePage ||
!(matches = usagePage->isEqualTo(pair->getObject(kIOHIDDeviceUsagePageKey))) )
continue;
if ( score && !usage )
{
*score += increment / 2;
break;
}
if ( !usage ||
!(matches = usage->isEqualTo(pair->getObject(kIOHIDDeviceUsageKey))) )
continue;
if ( score )
*score += increment;
break;
}
}
functions->release();
} else {
matches = false;
}
return matches;
}
bool CompareDeviceUsagePairs( IOService * owner, OSDictionary * matching, SInt32 * score, SInt32 increment)
{
OSArray * pairArray;
OSDictionary * pair;
bool matches = true;
int count;
pairArray = OSDynamicCast(OSArray, matching->getObject( kIOHIDDeviceUsagePairsKey ));
if (pairArray)
{
count = pairArray->getCount();
for (int i=0; i<count; i++)
{
if ( !(pair = OSDynamicCast(OSDictionary,pairArray->getObject(i))) )
continue;
if ( !(matches = CompareDeviceUsage(owner, pair, score, increment)) )
continue;
break;
}
}
return matches;
}
bool CompareProductID( IOService * owner, OSDictionary * matching, SInt32 * score)
{
bool pidMatch = false;
bool arrayMatch = false;
bool maskMatch = false;
bool maskArrayMatch = false;
SInt32 pidScore = 0;
SInt32 arrayScore = 0;
SInt32 maskScore = 0;
SInt32 maskArrayScore = 0;
pidMatch = CompareProperty(owner, matching, kIOHIDProductIDKey, &pidScore, kHIDVendor2ScoreIncrement);
arrayMatch = CompareNumberPropertyArray(owner, matching, kIOHIDProductIDArrayKey, kIOHIDProductIDKey, &arrayScore, kHIDVendor2ArrayScoreIncrement);
maskMatch = CompareNumberPropertyMask(owner, matching, kIOHIDProductIDKey, kIOHIDProductIDMaskKey, &maskScore, kHIDVendor2MaskScoreIncrement);
maskArrayMatch = CompareNumberPropertyArrayWithMask(owner, matching, kIOHIDProductIDArrayKey, kIOHIDProductIDKey, kIOHIDProductIDMaskKey, &maskArrayScore, kHIDVendor2ArrayMaskScoreIncrement);
if ( pidMatch && pidScore != 0 )
{
*score += pidScore;
return true;
}
else if ( arrayMatch && arrayScore != 0 )
{
*score += arrayScore;
return true;
}
else if ( maskMatch && maskScore != 0 )
{
*score += maskScore;
return true;
}
else if ( maskArrayMatch && maskArrayScore != 0 )
{
*score += maskArrayScore;
return true;
}
else
{
return pidMatch && arrayMatch && maskMatch && maskArrayMatch;
}
}
bool CompareNumberPropertyMask( IOService *owner, OSDictionary *matching, const char *key, const char *maskKey, SInt32 *score, SInt32 increment)
{
OSNumber * registryProperty;
OSNumber * dictionaryProperty;
OSNumber * valueMask;
registryProperty = OSDynamicCast(OSNumber, owner->getProperty(key));
dictionaryProperty = OSDynamicCast(OSNumber, matching->getObject(key));
valueMask = OSDynamicCast(OSNumber, matching->getObject(maskKey));
if ( dictionaryProperty && valueMask )
{
if ( registryProperty )
{
UInt32 registryValue = registryProperty->unsigned32BitValue();
UInt32 dictionaryValue = dictionaryProperty->unsigned32BitValue();
UInt32 mask = valueMask->unsigned32BitValue();
if ( (registryValue & mask) == (dictionaryValue & mask) )
{
if ( score )
*score += increment;
return true;
}
}
}
else
return true;
return false;
}
bool CompareNumberPropertyArray( IOService * owner, OSDictionary * matching, const char * arrayName, const char * key, SInt32 * score, SInt32 increment)
{
OSNumber *registryProperty = (OSNumber *)owner->copyProperty(key);
OSArray *propertyArray = (OSArray *)matching->getObject(arrayName);
CONVERT_TO_STACK_RETAIN(registryProperty);
if ( OSDynamicCast(OSArray, propertyArray) )
{
if ( OSDynamicCast(OSNumber, registryProperty ) )
{
OSNumber *propertyFromArray;
int i = 0;
for ( i = 0; i < propertyArray->getCount(); i ++ )
{
propertyFromArray = OSDynamicCast(OSNumber, propertyArray->getObject(i));
if ( propertyFromArray && propertyFromArray->isEqualTo(registryProperty) )
{
if ( score )
*score += increment;
return true;
}
}
}
}
else
return true;
return false;
}
bool CompareNumberPropertyArrayWithMask( IOService * owner, OSDictionary * matching, const char * arrayName, const char * key, const char * maskKey, SInt32 * score, SInt32 increment)
{
OSNumber *registryProperty = (OSNumber *)owner->copyProperty(key);
OSArray *propertyArray = (OSArray *)matching->getObject(arrayName);
OSNumber *valueMask = (OSNumber *)matching->getObject(maskKey);
CONVERT_TO_STACK_RETAIN(registryProperty);
if( OSDynamicCast(OSArray, propertyArray) && OSDynamicCast(OSNumber, valueMask) )
{
if ( OSDynamicCast(OSNumber, registryProperty) )
{
OSNumber *propertyFromArray;
UInt32 registryValue = registryProperty->unsigned32BitValue();
UInt32 mask = valueMask->unsigned32BitValue();
int i = 0;
for ( i = 0; i < propertyArray->getCount(); i ++ )
{
propertyFromArray = OSDynamicCast(OSNumber, propertyArray->getObject(i));
if ( propertyFromArray )
{
UInt32 propertyFromArrayValue = propertyFromArray->unsigned32BitValue();
if( (registryValue & mask) == (propertyFromArrayValue & mask ) )
{
if ( score )
*score += increment;
return true;
}
}
}
}
}
else
return true;
return false;
}
bool MatchPropertyTable(IOService * owner, OSDictionary * table, SInt32 * score)
{
bool match = true;
SInt32 pUScore = 0;
SInt32 pUPScore = 0;
SInt32 useScore = 0;
SInt32 trans1Score = 0;
SInt32 trans2Score = 0;
SInt32 ven1Score = 0;
SInt32 ven2Score = 0;
SInt32 ven3Score = 0;
bool pUPMatch = CompareProperty(owner, table, kIOHIDPrimaryUsagePageKey, &pUPScore, kHIDDeviceUsageScoreBase);
bool pUMatch = CompareProperty(owner, table, kIOHIDPrimaryUsageKey, &pUScore, kHIDDeviceUsageScoreIncrement);
bool useMatch = CompareDeviceUsagePairs(owner, table, &useScore, kHIDDeviceUsageScoreIncrement);
bool use2Match = CompareDeviceUsage(owner, table, &useScore, kHIDDeviceUsageScoreIncrement);
bool trans1Match = CompareProperty(owner, table, kIOHIDTransportKey, &trans1Score, kHIDTransport1ScoreIncrement);
bool trans2Match = CompareProperty(owner, table, kIOHIDLocationIDKey, &trans2Score, kHIDTransport2ScoreIncrement);
bool venIDMatch = CompareProperty(owner, table, kIOHIDVendorIDKey, &ven1Score, kHIDVendor1ScoreIncrement);
bool prodIDMatch = CompareProductID(owner, table, &ven2Score);
bool versNumMatch = CompareProperty(owner, table, kIOHIDVersionNumberKey, &ven3Score, kHIDVendor3ScoreIncrement);
bool manMatch = CompareProperty(owner, table, kIOHIDManufacturerKey, &ven3Score, kHIDVendor3ScoreIncrement);
bool serialMatch = CompareProperty(owner, table, kIOHIDSerialNumberKey, &ven3Score, kHIDVendor3ScoreIncrement);
bool bootPMatch = CompareProperty(owner, table, "BootProtocol", score);
if (!pUPMatch ||
!pUMatch ||
!useMatch ||
!use2Match ||
!trans1Match ||
!trans2Match ||
!venIDMatch ||
!prodIDMatch ||
!versNumMatch ||
!manMatch ||
!serialMatch ||
!bootPMatch ||
(table->getObject("HIDDefaultBehavior") && !owner->getProperty("HIDDefaultBehavior")))
{
if (score)
*score = 0;
match = false;
}
else if ( score )
{
if ( trans1Score > 0 )
*score += trans1Score + trans2Score;
if ( ven1Score > 0 )
*score += ven1Score + ven2Score + ven3Score;
if ( useScore > 0 )
*score += useScore + kHIDDeviceUsageScoreBase;
else if ( pUPScore > 0 )
*score += pUPScore + pUScore;
}
return match;
}
void IOHIDSystemActivityTickle(SInt32 nxEventType, IOService *sender)
{
#if !TARGET_OS_EMBEDDED
IOHIDSystem *ioSys = IOHIDSystem::instance();
if (ioSys) {
intptr_t event = nxEventType;
ioSys->message(kIOHIDSystemActivityTickle, sender, (void*)event);
}
#endif
}