IOHIDTestConnectionFilter.m [plain text]
//
// IOHIDTestConnectionFilter.m
// IOHIDTestConnectionFilter
//
// Created by Abhishek Nayyar on 3/30/18.
//
#include "IOHIDTestConnectionFilter.h"
#include <IOKit/hid/IOHIDEventTypes.h>
#include "AppleHIDUsageTables.h"
#include <IOKit/hid/IOHIDServiceKeys.h>
#include <os/log.h>
#define kUsages "Usages"
#define kUsagePage "UsagePage"
@implementation HIDTestConnectionFilter {
NSMutableDictionary *_filterUsages;
//debug
//Usage-UsagePage (Keyboard Events Only)
// This is just example, user can add debug info accordingly
NSMutableArray *_droppedEvents;
}
-(nullable instancetype) init
{
self = [super init];
if (!self) {
return nil;
}
_filterUsages = [[NSMutableDictionary alloc] init];
_droppedEvents = [[NSMutableArray alloc] init];
return self;
}
-(bool) setProperty:(NSString*)key property:(id)property
{
//Property (UsagePage-Usage)
if (_filterUsages && [key isEqualToString:@(kIOHIDServiceDeviceDebugUsageFilter)]) {
NSArray *usages = NULL;
NSNumber *usagePage = NULL;
for (NSDictionary *propertyValue in property) {
if ([propertyValue objectForKey:@kUsagePage]) {
//Usage Page Filter
// add last usage page enteries
if (usages && usagePage) {
_filterUsages[usagePage] = usages;
}
usagePage = propertyValue[@kUsagePage];
} else if ([propertyValue objectForKey:@kUsages]) {
//Usage Filter For Usage Page
usages = propertyValue[@kUsages];
} else {
usagePage = NULL;
usages = NULL;
}
}
//last slot
if (usages && usagePage) {
_filterUsages[usagePage] = usages;
}
return [_filterUsages count] > 0 ? true : false;
}
return false;
}
-(id) copyProperty:(NSString*)key
{
NSArray *result = NULL;
//return set of all usage key/ usagePage array for which we need to set filter
if (_filterUsages && [key isEqualToString:@(kIOHIDServiceDeviceDebugUsageFilter)]) {
NSMutableArray *ret = [[NSMutableArray alloc] init];
for (NSNumber *usagePage in _filterUsages) {
NSDictionary *propertyUsagePage = @{@kUsagePage : usagePage};
[ret addObject:propertyUsagePage];
NSDictionary *propertyUsages = @{@kUsages : _filterUsages[usagePage]};
[ret addObject:propertyUsages];
}
result = ret;
} else if ([key isEqualToString:@(kIOHIDConnectionPluginDebugKey)]) {
result = _droppedEvents;
}
return result;
}
-(IOHIDEventRef) filter:(IOHIDEventRef) event
{
IOHIDEventRef res = NULL;
//Filters keyboard events
if (!event || IOHIDEventGetType(event) != kIOHIDEventTypeKeyboard) {
//If user has enabled plugin for connection, it will not recieve events other than
// keyboard event, change as per requirement
// return event : if user want to filter only keyboard event and return other event as such
return res;
}
//Filter for given keyboard usage
UInt32 usage;
UInt32 usagePage;
usage = (UInt32)IOHIDEventGetIntegerValue(event, kIOHIDEventFieldKeyboardUsage);
usagePage = (UInt32)IOHIDEventGetIntegerValue(event, kIOHIDEventFieldKeyboardUsagePage);
//We can filer events based on usage page/usage pair.
//Verify if usage page is valid and then if it;s valid uage in given usage page
os_log_debug(OS_LOG_DEFAULT,"HIDTestConnectionFilter : Usage 0x
if ([_filterUsages count] == 0) {
res = event;
} else if ([_filterUsages objectForKey:@(usagePage)]) {
for (NSNumber *usg in _filterUsages[@(usagePage)]) {
if (usage == [usg intValue]) {
res = event;
break;
}
}
}
if (!res) {
//dropped event
//tracking only keyboard events
[_droppedEvents addObject:@{@usagePage : @usage}];
}
return res;
}
@end