1/* 2 * @APPLE_LICENSE_HEADER_START@ 3 * 4 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include "IOHIDFamilyPrivate.h" 25 26#if !TARGET_OS_EMBEDDED 27#include "IOHIDSystem.h" 28#endif 29#include "OSStackRetain.h" 30 31#define kHIDTransport1ScoreIncrement 1000 32#define kHIDTransport2ScoreIncrement 2000 33#define kHIDDeviceUsageScoreBase 1100 34#define kHIDDeviceUsageScoreIncrement 100 35#define kHIDVendor1ScoreIncrement 5000 36#define kHIDVendor2ScoreIncrement 1000 37#define kHIDVendor2ArrayScoreIncrement 975 38#define kHIDVendor2MaskScoreIncrement 950 39#define kHIDVendor2ArrayMaskScoreIncrement 925 40#define kHIDVendor3ScoreIncrement 100 41 42//--------------------------------------------------------------------------- 43// Compare the properties in the supplied table to this object's properties. 44bool CompareProperty( IOService * owner, OSDictionary * matching, const char * key, SInt32 * score, SInt32 increment) 45{ 46 // We return success if we match the key in the dictionary with the key in 47 // the property table, or if the prop isn't present 48 // 49 OSObject * value; 50 OSObject * property; 51 bool matches = true; 52 53 value = matching->getObject( key ); 54 55 if( value) 56 { 57 property = owner->copyProperty( key ); 58 59 if ( property ) 60 { 61 matches = value->isEqualTo( property ); 62 63 if (matches && score) 64 *score += increment; 65 66 property->release(); 67 } 68 else 69 matches = false; 70 } 71 72 return matches; 73} 74 75bool CompareDeviceUsage( IOService * owner, OSDictionary * matching, SInt32 * score, SInt32 increment) 76{ 77 // We return success if we match the key in the dictionary with the key in 78 // the property table, or if the prop isn't present 79 // 80 OSObject * usage; 81 OSObject * usagePage; 82 OSArray * functions; 83 OSDictionary * pair; 84 bool matches = true; 85 int count; 86 87 usage = matching->getObject( kIOHIDDeviceUsageKey ); 88 usagePage = matching->getObject( kIOHIDDeviceUsagePageKey ); 89 functions = OSDynamicCast(OSArray, owner->copyProperty( kIOHIDDeviceUsagePairsKey )); 90 91 if ( functions ) 92 { 93 if ( usagePage || usage ) 94 { 95 count = functions->getCount(); 96 97 for (int i=0; i<count; i++) 98 { 99 if ( !(pair = (OSDictionary *)functions->getObject(i)) ) 100 continue; 101 102 if ( !usagePage || 103 !(matches = usagePage->isEqualTo(pair->getObject(kIOHIDDeviceUsagePageKey))) ) 104 continue; 105 106 if ( score && !usage ) 107 { 108 *score += increment / 2; 109 break; 110 } 111 112 if ( !usage || 113 !(matches = usage->isEqualTo(pair->getObject(kIOHIDDeviceUsageKey))) ) 114 continue; 115 116 if ( score ) 117 *score += increment; 118 119 break; 120 } 121 } 122 123 functions->release(); 124 } else { 125 matches = false; 126 } 127 128 return matches; 129} 130 131bool CompareDeviceUsagePairs( IOService * owner, OSDictionary * matching, SInt32 * score, SInt32 increment) 132{ 133 // We return success if we match the key in the dictionary with the key in 134 // the property table, or if the prop isn't present 135 // 136 OSArray * pairArray; 137 OSDictionary * pair; 138 bool matches = true; 139 int count; 140 141 pairArray = OSDynamicCast(OSArray, matching->getObject( kIOHIDDeviceUsagePairsKey )); 142 143 if (pairArray) 144 { 145 count = pairArray->getCount(); 146 147 for (int i=0; i<count; i++) 148 { 149 if ( !(pair = OSDynamicCast(OSDictionary,pairArray->getObject(i))) ) 150 continue; 151 152 if ( !(matches = CompareDeviceUsage(owner, pair, score, increment)) ) 153 continue; 154 155 break; 156 } 157 } 158 159 return matches; 160} 161 162bool CompareProductID( IOService * owner, OSDictionary * matching, SInt32 * score) 163{ 164 bool pidMatch = false; 165 bool arrayMatch = false; 166 bool maskMatch = false; 167 bool maskArrayMatch = false; 168 169 SInt32 pidScore = 0; 170 SInt32 arrayScore = 0; 171 SInt32 maskScore = 0; 172 SInt32 maskArrayScore = 0; 173 174 // Compare each of the types of productID matching. Then in order of highest score to least 175 // see if we have any hits. Once we find one hit that matches properly then we can return 176 // true after incrementing the score. 177 pidMatch = CompareProperty(owner, matching, kIOHIDProductIDKey, &pidScore, kHIDVendor2ScoreIncrement); 178 arrayMatch = CompareNumberPropertyArray(owner, matching, kIOHIDProductIDArrayKey, kIOHIDProductIDKey, &arrayScore, kHIDVendor2ArrayScoreIncrement); 179 maskMatch = CompareNumberPropertyMask(owner, matching, kIOHIDProductIDKey, kIOHIDProductIDMaskKey, &maskScore, kHIDVendor2MaskScoreIncrement); 180 maskArrayMatch = CompareNumberPropertyArrayWithMask(owner, matching, kIOHIDProductIDArrayKey, kIOHIDProductIDKey, kIOHIDProductIDMaskKey, &maskArrayScore, kHIDVendor2ArrayMaskScoreIncrement); 181 182 if ( pidMatch && pidScore != 0 ) 183 { 184 *score += pidScore; 185 return true; 186 } 187 else if ( arrayMatch && arrayScore != 0 ) 188 { 189 *score += arrayScore; 190 return true; 191 } 192 else if ( maskMatch && maskScore != 0 ) 193 { 194 *score += maskScore; 195 return true; 196 } 197 else if ( maskArrayMatch && maskArrayScore != 0 ) 198 { 199 *score += maskArrayScore; 200 return true; 201 } 202 else 203 { 204 // If any of the matches explicitly failed (the property was present 205 // but none of our values matched the service object, then we should 206 // explicitly fail the matching. This will only return true if the 207 // personality did not define any productID related keys. 208 return pidMatch && arrayMatch && maskMatch && maskArrayMatch; 209 } 210} 211 212 213bool CompareNumberPropertyMask( IOService *owner, OSDictionary *matching, const char *key, const char *maskKey, SInt32 *score, SInt32 increment) 214{ 215 OSNumber * registryProperty; 216 OSNumber * dictionaryProperty; 217 OSNumber * valueMask; 218 219 registryProperty = OSDynamicCast(OSNumber, owner->getProperty(key)); 220 dictionaryProperty = OSDynamicCast(OSNumber, matching->getObject(key)); 221 valueMask = OSDynamicCast(OSNumber, matching->getObject(maskKey)); 222 223 // If the dicitonary or value mask doesn't exist then return true 224 if ( dictionaryProperty && valueMask ) 225 { 226 if ( registryProperty ) 227 { 228 // If all our values are OSNumbers, then get their actual value and do the masking 229 // to see if they are equal 230 // 231 UInt32 registryValue = registryProperty->unsigned32BitValue(); 232 UInt32 dictionaryValue = dictionaryProperty->unsigned32BitValue(); 233 UInt32 mask = valueMask->unsigned32BitValue(); 234 235 if ( (registryValue & mask) == (dictionaryValue & mask) ) 236 { 237 if ( score ) 238 *score += increment; 239 return true; 240 } 241 } 242 } 243 else 244 return true; 245 246 return false; 247} 248 249bool CompareNumberPropertyArray( IOService * owner, OSDictionary * matching, const char * arrayName, const char * key, SInt32 * score, SInt32 increment) 250{ 251 OSNumber *registryProperty = (OSNumber *)owner->copyProperty(key); 252 OSArray *propertyArray = (OSArray *)matching->getObject(arrayName); 253 CONVERT_TO_STACK_RETAIN(registryProperty); 254 255 // If the property in the matching doesn't exist return true 256 if ( OSDynamicCast(OSArray, propertyArray) ) 257 { 258 if ( OSDynamicCast(OSNumber, registryProperty ) ) 259 { 260 OSNumber *propertyFromArray; 261 int i = 0; 262 263 for ( i = 0; i < propertyArray->getCount(); i ++ ) 264 { 265 propertyFromArray = OSDynamicCast(OSNumber, propertyArray->getObject(i)); 266 if ( propertyFromArray && propertyFromArray->isEqualTo(registryProperty) ) 267 { 268 if ( score ) 269 *score += increment; 270 return true; 271 } 272 } 273 } 274 } 275 else 276 return true; 277 278 return false; 279} 280 281bool CompareNumberPropertyArrayWithMask( IOService * owner, OSDictionary * matching, const char * arrayName, const char * key, const char * maskKey, SInt32 * score, SInt32 increment) 282{ 283 OSNumber *registryProperty = (OSNumber *)owner->copyProperty(key); 284 OSArray *propertyArray = (OSArray *)matching->getObject(arrayName); 285 OSNumber *valueMask = (OSNumber *)matching->getObject(maskKey); 286 CONVERT_TO_STACK_RETAIN(registryProperty); 287 288 // If the property array or the value mask doesn't exist then return true 289 if( OSDynamicCast(OSArray, propertyArray) && OSDynamicCast(OSNumber, valueMask) ) 290 { 291 if ( OSDynamicCast(OSNumber, registryProperty) ) 292 { 293 OSNumber *propertyFromArray; 294 UInt32 registryValue = registryProperty->unsigned32BitValue(); 295 UInt32 mask = valueMask->unsigned32BitValue(); 296 297 int i = 0; 298 299 for ( i = 0; i < propertyArray->getCount(); i ++ ) 300 { 301 propertyFromArray = OSDynamicCast(OSNumber, propertyArray->getObject(i)); 302 if ( propertyFromArray ) 303 { 304 UInt32 propertyFromArrayValue = propertyFromArray->unsigned32BitValue(); 305 if( (registryValue & mask) == (propertyFromArrayValue & mask ) ) 306 { 307 if ( score ) 308 *score += increment; 309 return true; 310 311 } 312 } 313 } 314 } 315 } 316 else 317 return true; 318 319 return false; 320} 321 322bool MatchPropertyTable(IOService * owner, OSDictionary * table, SInt32 * score) 323{ 324 bool match = true; 325 SInt32 pUScore = 0; 326 SInt32 pUPScore = 0; 327 SInt32 useScore = 0; 328 SInt32 trans1Score = 0; 329 SInt32 trans2Score = 0; 330 SInt32 ven1Score = 0; 331 SInt32 ven2Score = 0; 332 SInt32 ven3Score = 0; 333 bool pUPMatch = CompareProperty(owner, table, kIOHIDPrimaryUsagePageKey, &pUPScore, kHIDDeviceUsageScoreBase); 334 bool pUMatch = CompareProperty(owner, table, kIOHIDPrimaryUsageKey, &pUScore, kHIDDeviceUsageScoreIncrement); 335 bool useMatch = CompareDeviceUsagePairs(owner, table, &useScore, kHIDDeviceUsageScoreIncrement); 336 bool use2Match = CompareDeviceUsage(owner, table, &useScore, kHIDDeviceUsageScoreIncrement); 337 bool trans1Match = CompareProperty(owner, table, kIOHIDTransportKey, &trans1Score, kHIDTransport1ScoreIncrement); 338 bool trans2Match = CompareProperty(owner, table, kIOHIDLocationIDKey, &trans2Score, kHIDTransport2ScoreIncrement); 339 bool venIDMatch = CompareProperty(owner, table, kIOHIDVendorIDKey, &ven1Score, kHIDVendor1ScoreIncrement); 340 bool prodIDMatch = CompareProductID(owner, table, &ven2Score); 341 bool versNumMatch = CompareProperty(owner, table, kIOHIDVersionNumberKey, &ven3Score, kHIDVendor3ScoreIncrement); 342 bool manMatch = CompareProperty(owner, table, kIOHIDManufacturerKey, &ven3Score, kHIDVendor3ScoreIncrement); 343 bool serialMatch = CompareProperty(owner, table, kIOHIDSerialNumberKey, &ven3Score, kHIDVendor3ScoreIncrement); 344 bool bootPMatch = CompareProperty(owner, table, "BootProtocol", score); 345 346 // Compare properties. 347 if (!pUPMatch || 348 !pUMatch || 349 !useMatch || 350 !use2Match || 351 !trans1Match || 352 !trans2Match || 353 !venIDMatch || 354 !prodIDMatch || 355 !versNumMatch || 356 !manMatch || 357 !serialMatch || 358 !bootPMatch || 359 (table->getObject("HIDDefaultBehavior") && !owner->getProperty("HIDDefaultBehavior"))) 360 { 361 if (score) 362 *score = 0; 363 match = false; 364 } 365 else if ( score ) 366 { 367 if ( trans1Score > 0 ) 368 *score += trans1Score + trans2Score; 369 370 if ( ven1Score > 0 ) 371 *score += ven1Score + ven2Score + ven3Score; 372 373 if ( useScore > 0 ) 374 *score += useScore + kHIDDeviceUsageScoreBase; 375 else if ( pUPScore > 0 ) 376 *score += pUPScore + pUScore; 377 } 378 379 return match; 380} 381 382void IOHIDSystemActivityTickle(SInt32 nxEventType, IOService *sender) 383{ 384#if !TARGET_OS_EMBEDDED 385 IOHIDSystem *ioSys = IOHIDSystem::instance(); 386 if (ioSys) { 387 intptr_t event = nxEventType; 388 ioSys->message(kIOHIDSystemActivityTickle, sender, (void*)event); 389 } 390#endif 391} 392 393