1/* 2 * @APPLE_LICENSE_HEADER_START@ 3 * 4 * Copyright (c) 1999-2009 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#include <libkern/c++/OSCollectionIterator.h> 24#include <IOKit/assert.h> 25#include <IOKit/IOLib.h> 26#include <IOKit/IOService.h> 27#include <IOKit/hidsystem/IOHIDevice.h> 28#include <IOKit/hidsystem/IOHIDParameter.h> 29#include "IOHIDevicePrivateKeys.h" 30#include "IOHIDEventService.h" 31 32#define super IOService 33OSDefineMetaClassAndStructors(IOHIDevice, IOService); 34 35bool IOHIDevice::init(OSDictionary * properties) 36{ 37 if (!super::init(properties)) return false; 38 39 /* 40 * Initialize minimal state. 41 */ 42 43 return true; 44} 45 46void IOHIDevice::free() 47{ 48 super::free(); 49} 50 51bool IOHIDevice::start(IOService * provider) 52{ 53 if (!super::start(provider)) 54 return false; 55 56 // RY: If the kIOHIDVirtualHIDevice property isn't 57 // set scan the up provider chain to determine if 58 // this is a resource or if the provider is another 59 // IOHIDevice. Also propegate value is property 60 // was already set in provider. 61 if (!getProperty(kIOHIDVirtualHIDevice)) { 62 OSObject * prop; 63 64 while (provider) { 65 prop = provider->copyProperty(kIOHIDVirtualHIDevice); 66 if ( OSDynamicCast(OSBoolean, prop) ) { 67 setProperty(kIOHIDVirtualHIDevice, prop); 68 break; 69 } 70 else if ( provider == getResourceService() || OSDynamicCast(IOHIDevice, provider) ) { 71 setProperty(kIOHIDVirtualHIDevice, kOSBooleanTrue); 72 break; 73 } 74 75 provider = provider->getProvider(); 76 OSSafeReleaseNULL(prop); 77 } 78 OSSafeReleaseNULL(prop); 79 80 if ( !provider ) 81 setProperty(kIOHIDVirtualHIDevice, kOSBooleanFalse); 82 } 83 84 updateProperties(); 85 86 return true; 87} 88 89bool IOHIDevice::open(IOService * forClient, 90 IOOptionBits options, 91 void * arg) 92{ 93 if(forClient == this) return true; 94 95 return super::open(forClient, options, arg); 96} 97 98 99IOHIDKind IOHIDevice::hidKind() 100{ 101 return kHIUnknownDevice; 102} 103 104UInt32 IOHIDevice::interfaceID() 105{ 106 return 0; 107} 108 109UInt32 IOHIDevice::deviceType() 110{ 111 return 0; 112} 113 114UInt64 IOHIDevice::getGUID() 115{ 116 return(0xffffffffffffffffULL); 117} 118 119SInt32 IOHIDevice::GenerateKey(OSObject *object) 120{ 121 SInt32 key = 0; 122#if __LP64__ 123 UInt64 temp = (UInt64)object; 124 temp -= 0xffffff8000111000; // Subtract out the kernel base address 125 temp >>= 4; // Assume that objects can't be closer than 16 bytes apart 126 key = (SInt32)temp; 127#else 128 key = (SInt32)object; 129#endif 130 return key; 131} 132 133bool IOHIDevice::updateProperties( void ) 134{ 135 bool ok; 136 137 ok = setProperty( kIOHIDKindKey, hidKind(), 32 ) 138 & setProperty( kIOHIDInterfaceIDKey, interfaceID(), 32 ) 139 & setProperty( kIOHIDDeviceEventIDKey, IOHIDevice::GenerateKey(this), 32 ) 140 & setProperty( kIOHIDSubinterfaceIDKey, deviceType(), 32 ); 141 142 return( ok ); 143} 144 145// RY: Override IORegistryEntry::setProperties(). This will allow properties 146// to be set per device, instead of globally via setParamProperties. 147IOReturn IOHIDevice::setProperties( OSObject * properties ) 148{ 149 OSDictionary * propertyDict = OSDynamicCast(OSDictionary, properties); 150 IOReturn ret = kIOReturnBadArgument; 151 152 if ( propertyDict ) { 153 if (propertyDict->setOptions(0, 0) & OSDictionary::kImmutable) { 154 OSDictionary * temp = propertyDict; 155 propertyDict = OSDynamicCast(OSDictionary, temp->copyCollection()); 156 } 157 else { 158 propertyDict->retain(); 159 } 160 propertyDict->setObject(kIOHIDDeviceParametersKey, kOSBooleanTrue); 161 ret = setParamProperties( propertyDict ); 162 propertyDict->removeObject(kIOHIDDeviceParametersKey); 163 propertyDict->release(); 164 } 165 166 return ret; 167} 168 169 170IOReturn IOHIDevice::setParamProperties( OSDictionary * dict ) 171{ 172 IOHIDEventService * eventService = NULL; 173 174 if ( dict->getObject(kIOHIDEventServicePropertiesKey) == NULL ) { 175 IOService * service = getProvider(); 176 if ( service ) 177 eventService = OSDynamicCast(IOHIDEventService, service); 178 } 179 180 if ( dict->getObject(kIOHIDDeviceParametersKey) == kOSBooleanTrue ) { 181 OSDictionary * deviceParameters = OSDynamicCast(OSDictionary, copyProperty(kIOHIDParametersKey)); 182 183 if ( !deviceParameters ) { 184 deviceParameters = OSDictionary::withCapacity(4); 185 } 186 else { 187 if (deviceParameters->setOptions(0, 0) & OSDictionary::kImmutable) { 188 OSDictionary * temp = deviceParameters; 189 deviceParameters = OSDynamicCast(OSDictionary, temp->copyCollection()); 190 temp->release(); 191 } 192 else { 193 // do nothing 194 } 195 } 196 197 if ( deviceParameters ) { 198 // RY: Because K&M Prefs and Admin still expect device props to be 199 // top level, let's continue to set them via setProperty. When we get 200 // Max to migrate over, we can remove the interator code and use: 201 // deviceParameters->merge(dict); 202 // deviceParameters->removeObject(kIOHIDResetKeyboardKey); 203 // deviceParameters->removeObject(kIOHIDResetPointerKey); 204 // setProperty(kIOHIDParametersKey, deviceParameters); 205 // deviceParameters->release(); 206 207 OSCollectionIterator * iterator = OSCollectionIterator::withCollection(dict); 208 if ( iterator ) { 209 OSSymbol * key; 210 211 while ( ( key = (OSSymbol *)iterator->getNextObject() ) ) 212 if ( !key->isEqualTo(kIOHIDResetKeyboardKey) && 213 !key->isEqualTo(kIOHIDResetPointerKey) && 214 !key->isEqualTo(kIOHIDScrollResetKey) && 215 !key->isEqualTo(kIOHIDDeviceParametersKey) && 216 !key->isEqualTo(kIOHIDResetLEDsKey)) { 217 OSObject * value = dict->getObject(key); 218 219 deviceParameters->setObject(key, value); 220 setProperty(key, value); 221 } 222 223 iterator->release(); 224 } 225 226 setProperty(kIOHIDParametersKey, deviceParameters); 227 deviceParameters->release(); 228 229 // RY: Propogate up to IOHIDEventService level 230 if ( eventService ) 231 eventService->setSystemProperties(dict); 232 233 } 234 else { 235 return kIOReturnNoMemory; 236 } 237 } 238 239 return( kIOReturnSuccess ); 240} 241 242 243