IOHIDRemoteSensorSessionFilter.m   [plain text]

//
// IOHIDRemoteSessionFilter.m
// IOHIDRemoteSensorSessionFilter
//
// Created by yg on 3/4/18.
// Copyright © 2018 apple. All rights reserved.
//

#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <IOKit/hid/IOHIDSessionFilterPlugIn.h>
#import <IOKit/hid/IOHIDEventSystemKeys.h>
#import <IOKit/hid/IOHIDSession.h>
#import <RemoteHID/RemoteHID.h>
#import "IOHIDDebug.h"
#import <objc/runtime.h>

void * IOHIDSessionSensorFilterFactory (CFAllocatorRef allocator, CFUUIDRef typeUUID);
static HRESULT _QueryInterface (void *self, REFIID iid, LPVOID *ppv);
static ULONG _AddRef (void *self);
static ULONG _Release (void *self);
static boolean_t _open (void * self, IOHIDSessionRef session, IOOptionBits options);
static void _close (void * self, IOHIDSessionRef session, IOOptionBits options);
static CFTypeRef _getPropertyForClient (void * self, CFStringRef key, CFTypeRef client);

IOHIDSessionFilterPlugInInterface __filter =
{
// Required padding for COM
NULL,
// These three are the required COM functions
_QueryInterface,
_AddRef,
_Release,
// IOHIDSimpleSessionFilterPlugInInterface functions
NULL,
NULL,
NULL,
// IOHIDSessionFilterPlugInInterface functions
_open,
_close,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
_getPropertyForClient,
NULL,
};

@interface HIDSessionFilterWrapper : HIDRemoteDeviceAACPServer {

@public
IOHIDSessionFilterPlugInInterface _filter;
IOHIDSessionFilterPlugInInterface * _filterPrt;
}
-(nullable instancetype) init;
@end

@implementation HIDSessionFilterWrapper

-(nullable instancetype) init;
{
dispatch_queue_t queue = dispatch_queue_create("com.apple.hidrc", DISPATCH_QUEUE_SERIAL);
self = [super initWithQueue:queue];
if (self) {
_filter = __filter;
_filter._reserved = self;
_filterPrt = &_filter;
}
dispatch_release(queue);
return self;
}

@end

static HRESULT _QueryInterface (void *self, REFIID iid, LPVOID *ppv)
{
// Create a CoreFoundation UUIDRef for the requested interface.
CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes( NULL, iid );
// Test the requested ID against the valid interfaces.
if (CFEqual(interfaceID, kIOHIDSessionFilterPlugInInterfaceID)) {
_AddRef(self);
*ppv = self;
CFRelease(interfaceID);
return S_OK;
}
// Requested interface unknown, bail with error.
*ppv = NULL;
CFRelease (interfaceID);
return E_NOINTERFACE;
}

static ULONG _AddRef (void *self)
{
NSObject * obj = (*(IUnknownVTbl **) self)->_reserved;
[obj retain];
return (ULONG) [obj retainCount];
}

static ULONG _Release (void *self)
{
NSObject * obj = (*(IUnknownVTbl **) self)->_reserved;
NSUInteger result = [obj retainCount];
[obj release];
return (ULONG)--result;
}

static CFTypeRef _getPropertyForClient (void * self __unused, CFStringRef key __unused, CFTypeRef client __unused)
{
CFTypeRef result = NULL;
if (CFEqual(key, CFSTR(kIOHIDSessionFilterDebugKey))) {
NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:1];
dict[@"Class"] = @"HIDRemoteAACPServer";
result = (CFTypeRef)dict;
}
return result;
}

static boolean_t _open (void * self, IOHIDSessionRef session __unused, IOOptionBits options __unused)
{
HIDSessionFilterWrapper * obj = (*(IUnknownVTbl **) self)->_reserved;
[obj activate];
return true;
}

static void _close (void * self, IOHIDSessionRef session __unused, IOOptionBits options __unused)
{
HIDSessionFilterWrapper * obj = (*(IUnknownVTbl **) self)->_reserved;
[obj cancel];
}

//------------------------------------------------------------------------------
// IOHIDSessionSensorFilterFactory
//------------------------------------------------------------------------------
// Implementation of the factory function for this type.
void * IOHIDSessionSensorFilterFactory (CFAllocatorRef allocator __unused, CFUUIDRef typeUUID)
{
// If correct type is being requested, allocate an
// instance of TestType and return the IUnknown interface.
if (CFEqual(typeUUID, kIOHIDSessionFilterPlugInTypeID)) {
HIDSessionFilterWrapper * obj;
obj = [[HIDSessionFilterWrapper alloc] init];
if (obj) {
HIDLogInfo ("AACP server object: %@", obj);
return (void *)&obj->_filterPrt;
}

HIDLogError ("Unable to create AACP HID server");

return NULL;
}
// If the requested type is incorrect, return NULL.
return NULL;
}