property.m   [plain text]

//
// property.m
// IOHIDFamily
//
// Created by YG on 4/14/16.
//
//

#import <Foundation/Foundation.h>
#include <IOKit/hid/IOHIDEventSystemKeys.h>
#include "hdutil.h"
#include <getopt.h>
#include "utility.h"

int property (int argc __unused, const char * argv[] __unused);
int propertySetOnEventSystem (IOHIDEventSystemClientRef client, NSDictionary * propertiesDicitonary);
int propertySetOnServices (IOHIDEventSystemClientRef client, NSDictionary * propertiesDicitonary);
int propertyGetEventSystemProperty (IOHIDEventSystemClientRef client, NSString* key);
int propertyGetServicesProperty (IOHIDEventSystemClientRef client, NSString* key);
void propertyPrint (NSString *str);

static const char propertyOptionShort[] = "hm:g:s:";
static const struct option propertyOptionLong[] =
{
{ "help", 0 , NULL, 'h' },
{ "matching", required_argument, NULL, 'm' },
{ "get", required_argument, NULL, 'g' },
{ "set", required_argument, NULL, 's' },
{ NULL, 0, NULL, 0 }
};

const char propertyUsage[] =
"\nRead/Write HID Event System property\n"
"\nUsage:\n\n"
" hidutil property [ --matching <matching> ][ --get <key> ][ --set <key> ]\n"
"\nFlags:\n\n"
" -g --get...................Get property with key (where key is string value)\n"
" -s --set...................Set property (key/value pair JSON style dictionary)\n"
MATCHING_HELP
"\nExamples:\n\n"
" hidutil property --matching '{\"ProductID\":0x54c}' --get \"HIDPointerAcceleration\"\n"
" hidutil property --matching '{\"ProductID\":0x54c,\"VendorID\":746}' --set '{\"HIDPointerAcceleration\":0}'\n"
" hidutil property --get \"HIDPointerAcceleration\"\n";

void propertyPrint (NSString *str) {
const char * c_str = [str UTF8String];
if (c_str) {
printf ("%s" , [str UTF8String]);
}
}

int propertySetOnEventSystem (IOHIDEventSystemClientRef client, NSDictionary * propertiesDicitonary) {

[propertiesDicitonary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop __unused) {
propertyPrint ([NSString stringWithFormat:@"%@:%@\n", key, value]);
IOHIDEventSystemClientSetProperty (client, (__bridge CFStringRef) key, (__bridge CFStringRef) value);
}];
return STATUS_SUCCESS;
}

int propertySetOnServices (IOHIDEventSystemClientRef client, NSDictionary * propertiesDicitonary) {

NSArray *services = (NSArray *)CFBridgingRelease(IOHIDEventSystemClientCopyServices(client));
if (services) {
printf ("%-8s %-20s %s\n", "RegistryID", "Key", "Value");
for (id service in services) {
NSNumber *regID = (__bridge NSNumber *)IOHIDServiceClientGetRegistryID((__bridge IOHIDServiceClientRef)service);
[propertiesDicitonary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop __unused) {
propertyPrint ([NSString stringWithFormat:@"%-8lx %-20@ %@\n", regID.unsignedLongValue, key, value]);
IOHIDServiceClientSetProperty ((__bridge IOHIDServiceClientRef)service, (__bridge CFStringRef) key, (__bridge CFStringRef) value);
}];
}
}

return STATUS_SUCCESS;
}

int propertyGetEventSystemProperty (IOHIDEventSystemClientRef client, NSString* key) {
id value = CFBridgingRelease(IOHIDEventSystemClientCopyProperty (client, (__bridge CFStringRef) key));
propertyPrint ([NSString stringWithFormat:@"%@\n",value]);
return STATUS_SUCCESS;
}

int propertyGetServicesProperty (IOHIDEventSystemClientRef client, NSString* key) {
NSArray *services = (NSArray *)CFBridgingRelease(IOHIDEventSystemClientCopyServices(client));
if (services) {
printf ("%-8s %-20s %s\n", "RegistryID", "Key", "Value");
for (id service in services) {
id value = CFBridgingRelease(IOHIDServiceClientCopyProperty ((__bridge IOHIDServiceClientRef)service, (__bridge CFStringRef) key));
NSNumber *regID = (__bridge NSNumber *)IOHIDServiceClientGetRegistryID((__bridge IOHIDServiceClientRef)service);
propertyPrint ([NSString stringWithFormat:@"%-8lx %-20@ %@\n", regID.unsignedLongValue, key, value]);
}
}
return STATUS_SUCCESS;
}

int property (int argc, const char * argv[]) {
int arg;
int status = STATUS_SUCCESS;
IOHIDEventSystemClientRef client = NULL;
id propertyDicitonary = NULL;
NSString *propertyKey = NULL;
bool matching = false;

#ifdef INTERNAL
client = IOHIDEventSystemClientCreateWithType(kCFAllocatorDefault, kIOHIDEventSystemClientTypeMonitor, NULL);
#else
client = IOHIDEventSystemClientCreateWithType(kCFAllocatorDefault, kIOHIDEventSystemClientTypeSimple, NULL);
#endif
if (!client) {
status = STATUS_ERROR;
goto exit;
}

while ((arg = getopt_long(argc, (char **) argv, propertyOptionShort, propertyOptionLong, NULL)) != -1) {
switch (arg) {
case 'h':
printf ("%s", propertyUsage);
goto exit;
case 'm':
matching = setClientMatching(client, optarg);
if (!matching) {
printf ("bad matching string: %s\n", optarg);
}
break;
case 's':
propertyDicitonary = createPropertiesDicitonary (createPropertiesString(optarg));
if (propertyDicitonary == NULL || ![propertyDicitonary isKindOfClass:[NSDictionary class]]) {
printf ("\nERROR!!!! Unable to create property object for \'%s\'\n", optarg);
}
break;
case 'g':
propertyKey = [NSString stringWithUTF8String:optarg];
break;
default:
status = STATUS_ERROR;
goto exit;
}
}

if ((!propertyKey && !propertyDicitonary) ||
(propertyKey && propertyDicitonary)) {
status = STATUS_ERROR;
goto exit;
}

if (propertyDicitonary) {
if (matching) {
status = propertySetOnServices (client, propertyDicitonary);
} else {
status = propertySetOnEventSystem (client, propertyDicitonary);
}
} else {
if (!matching) {
status = propertyGetEventSystemProperty (client, propertyKey);
} else {
status = propertyGetServicesProperty (client, propertyKey);
}
}

exit:
if (client) {
CFRelease (client);
}
return status;
}