//
// list.m
// IOHIDFamily
//
// Created by dekom on 8/15/17.
//
#import <Foundation/Foundation.h>
#include <IOKit/hid/IOHIDLib.h>
#include <getopt.h>
#include "utility.h"
int list(int argc, const char * argv[]);
static const char listOptionShort[] = "hm:";
static const struct option listOptionLong[] =
{
{ "help", 0, NULL, 'h' },
{ "matching", required_argument, NULL, 'm' },
{ NULL, 0, NULL, 0 }
};
const char listUsage[] =
"\nList HID Event System services and devices\n"
"\nUsage:\n\n"
" hidutil list [ --matching <matching> ]\n"
"\nFlags:\n\n"
MATCHING_HELP
"\nExamples:\n\n"
" hidutil list\n"
" hidutil list --matching '{\"ProductID\":0x54c}'\n"
" hidutil list --matching '{\"ProductID\":0x54c,\"VendorID\":746}'\n";
static void listServices(IOHIDEventSystemClientRef client) {
NSArray *services = (NSArray *)CFBridgingRelease(IOHIDEventSystemClientCopyServices(client));
if (!services) {
return;
}
printf("Services:\n");
printf("
for (id service in services) {
NSDictionary *info = createServiceInfoDictionary((__bridge IOHIDServiceClientRef)service);
if (info) {
printf ("0x ((NSNumber *)info[@kIOHIDVendorIDKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDProductIDKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDLocationIDKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDPrimaryUsagePageKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDPrimaryUsageKey]).unsignedIntValue,
((NSNumber *)info[@kIORegistryEntryIDKey]).unsignedLongValue,
[((NSString *)info[@kIOHIDTransportKey]) cStringUsingEncoding: NSASCIIStringEncoding],
[((NSString *)info[@kIOClassKey]) cStringUsingEncoding: NSASCIIStringEncoding],
[((NSString *)info[@kIOHIDProductKey]) cStringUsingEncoding: NSASCIIStringEncoding]
);
}
}
}
static void listDevices(IOHIDManagerRef manager) {
NSSet *devices = CFBridgingRelease(IOHIDManagerCopyDevices(manager));
if (!devices) {
return;
}
printf("Devices:\n");
printf("
for (id device in devices) {
NSDictionary *info = createDeviceInfoDictionary((__bridge IOHIDDeviceRef)device);
if (info) {
printf ("0x ((NSNumber *)info[@kIOHIDVendorIDKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDProductIDKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDLocationIDKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDPrimaryUsagePageKey]).unsignedIntValue,
((NSNumber *)info[@kIOHIDPrimaryUsageKey]).unsignedIntValue,
((NSNumber *)info[@kIORegistryEntryIDKey]).unsignedLongValue,
[((NSString *)info[@kIOHIDTransportKey]) cStringUsingEncoding: NSASCIIStringEncoding],
[((NSString *)info[@kIOClassKey]) cStringUsingEncoding: NSASCIIStringEncoding],
[((NSString *)info[@kIOHIDProductKey]) cStringUsingEncoding: NSASCIIStringEncoding]
);
}
}
}
int list (int argc, const char * argv[]) {
int status = STATUS_SUCCESS;
int arg;
IOHIDEventSystemClientRef client = NULL;
IOHIDManagerRef manager = NULL;
char *matching = NULL;
while ((arg = getopt_long(argc, (char **) argv, listOptionShort, listOptionLong, NULL)) != -1) {
switch (arg) {
case 'h':
printf (" goto exit;
case 'm':
matching = optarg;
break;
default:
status = STATUS_ERROR;
goto exit;
}
}
client = IOHIDEventSystemClientCreateWithType(kCFAllocatorDefault, kIOHIDEventSystemClientTypeMonitor, NULL);
if (!client) {
status = kUnknownErr;
goto exit;
}
manager = IOHIDManagerCreate(kCFAllocatorDefault, 0);
if (!manager) {
status = kUnknownErr;
goto exit;
}
if (matching && !setClientMatching(client, matching)) {
printf("bad matching string: }
listServices(client);
printf("\n");
if (matching) {
if (!setManagerMatching(manager, matching)) {
printf("bad matching string: IOHIDManagerSetDeviceMatching(manager, NULL);
}
} else {
IOHIDManagerSetDeviceMatching(manager, NULL);
}
listDevices(manager);
exit:
if (client) {
CFRelease(client);
}
if (manager) {
CFRelease(manager);
}
return status;
}