#include <libkern/c++/OSCollectionIterator.h>
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/hidsystem/IOHIDevice.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
#include "IOHIDevicePrivateKeys.h"
#include "IOHIDEventService.h"
#define super IOService
OSDefineMetaClassAndStructors(IOHIDevice, IOService);
bool IOHIDevice::init(OSDictionary * properties)
{
if (!super::init(properties)) return false;
return true;
}
void IOHIDevice::free()
{
super::free();
}
bool IOHIDevice::start(IOService * provider)
{
if (!super::start(provider))
return false;
if (!getProperty(kIOHIDVirtualHIDevice)) {
OSObject * prop;
while (provider) {
prop = provider->copyProperty(kIOHIDVirtualHIDevice);
if ( OSDynamicCast(OSBoolean, prop) ) {
setProperty(kIOHIDVirtualHIDevice, prop);
break;
}
else if ( provider == getResourceService() || OSDynamicCast(IOHIDevice, provider) ) {
setProperty(kIOHIDVirtualHIDevice, kOSBooleanTrue);
break;
}
provider = provider->getProvider();
OSSafeReleaseNULL(prop);
}
OSSafeReleaseNULL(prop);
if ( !provider )
setProperty(kIOHIDVirtualHIDevice, kOSBooleanFalse);
}
updateProperties();
return true;
}
bool IOHIDevice::open(IOService * forClient,
IOOptionBits options,
void * arg)
{
if(forClient == this) return true;
return super::open(forClient, options, arg);
}
IOHIDKind IOHIDevice::hidKind()
{
return kHIUnknownDevice;
}
UInt32 IOHIDevice::interfaceID()
{
return 0;
}
UInt32 IOHIDevice::deviceType()
{
return 0;
}
UInt64 IOHIDevice::getGUID()
{
return(0xffffffffffffffffULL);
}
SInt32 IOHIDevice::GenerateKey(OSObject *object)
{
if ( !object )
return NULL;
IORegistryEntry* temp = (IORegistryEntry*)(object);
return (SInt32)temp->getRegistryEntryID(); }
bool IOHIDevice::updateProperties( void )
{
bool ok;
ok = setProperty( kIOHIDKindKey, hidKind(), 32 )
& setProperty( kIOHIDInterfaceIDKey, interfaceID(), 32 )
& setProperty( kIOHIDDeviceEventIDKey, IOHIDevice::GenerateKey(this), 32 )
& setProperty( kIOHIDSubinterfaceIDKey, deviceType(), 32 );
return( ok );
}
IOReturn IOHIDevice::setProperties( OSObject * properties )
{
OSDictionary * propertyDict = OSDynamicCast(OSDictionary, properties);
IOReturn ret = kIOReturnBadArgument;
if ( propertyDict ) {
if (propertyDict->setOptions(0, 0) & OSDictionary::kImmutable) {
OSDictionary * temp = propertyDict;
propertyDict = OSDynamicCast(OSDictionary, temp->copyCollection());
}
else {
propertyDict->retain();
}
propertyDict->setObject(kIOHIDDeviceParametersKey, kOSBooleanTrue);
ret = setParamProperties( propertyDict );
propertyDict->removeObject(kIOHIDDeviceParametersKey);
propertyDict->release();
}
return ret;
}
IOReturn IOHIDevice::setParamProperties( OSDictionary * dict )
{
IOHIDEventService * eventService = NULL;
if ( dict->getObject(kIOHIDEventServicePropertiesKey) == NULL ) {
IOService * service = getProvider();
if ( service )
eventService = OSDynamicCast(IOHIDEventService, service);
}
if ( dict->getObject(kIOHIDDeviceParametersKey) == kOSBooleanTrue ) {
OSDictionary * deviceParameters = OSDynamicCast(OSDictionary, copyProperty(kIOHIDParametersKey));
if ( !deviceParameters ) {
deviceParameters = OSDictionary::withCapacity(4);
}
else {
if (deviceParameters->setOptions(0, 0) & OSDictionary::kImmutable) {
OSDictionary * temp = deviceParameters;
deviceParameters = OSDynamicCast(OSDictionary, temp->copyCollection());
temp->release();
}
else {
}
}
if ( deviceParameters ) {
OSCollectionIterator * iterator = OSCollectionIterator::withCollection(dict);
if ( iterator ) {
OSSymbol * key;
while ( ( key = (OSSymbol *)iterator->getNextObject() ) )
if ( !key->isEqualTo(kIOHIDResetKeyboardKey) &&
!key->isEqualTo(kIOHIDResetPointerKey) &&
!key->isEqualTo(kIOHIDScrollResetKey) &&
!key->isEqualTo(kIOHIDDeviceParametersKey) &&
!key->isEqualTo(kIOHIDResetLEDsKey) &&
!key->isEqualTo(kIOUserClientClassKey)) {
OSObject * value = dict->getObject(key);
deviceParameters->setObject(key, value);
setProperty(key, value);
}
iterator->release();
}
setProperty(kIOHIDParametersKey, deviceParameters);
deviceParameters->release();
if ( eventService )
eventService->setSystemProperties(dict);
}
else {
return kIOReturnNoMemory;
}
}
return( kIOReturnSuccess );
}