1#include <CoreFoundation/CoreFoundation.h>
2#include <IOKit/hid/IOHIDLib.h>
3
4static bool     gReport         = TRUE;
5static bool     gValue          = FALSE;
6static bool     gSend           = FALSE;
7
8static char * getReportTypeString(IOHIDReportType type)
9{
10    switch ( type ) {
11        case kIOHIDReportTypeInput:
12            return "INPUT";
13        case kIOHIDReportTypeOutput:
14            return "OUTPUT";
15        case kIOHIDReportTypeFeature:
16            return "FEATURE";
17        default:
18            return "DUH";
19    }
20}
21
22static void __deviceReportCallback(void * context, IOReturn result, void * sender, IOHIDReportType type, uint32_t reportID, uint8_t * report, CFIndex reportLength)
23{
24    int index;
25
26    printf("IOHIDDeviceRef[%p]: reportType=%s reportID=%d reportLength=%ld: ", sender, getReportTypeString(type), reportID, reportLength);
27    for (index=0; index<reportLength; index++)
28        printf("%02x ", report[index]);
29    printf("\n");
30
31    // toggle a report
32    if ( gSend ) {
33        static uint8_t value = 0;
34        IOReturn ret = IOHIDDeviceSetReport((IOHIDDeviceRef)sender, kIOHIDReportTypeOutput, 0, &(value), 1);
35        value = value+1 % 2;
36        printf("Attempt to send data byte. Ret = %d\n", ret);
37    }
38}
39
40void __deviceValueCallback (void * context, IOReturn result, void * sender, IOHIDValueRef value)
41{
42    IOHIDElementRef element = IOHIDValueGetElement(value);
43
44    printf("IOHIDDeviceRef[%p]: value=%p timestamp=%lld cookie=%d usagePage=0x%02X usage=0x%02X intValue=%ld\n", sender, value, IOHIDValueGetTimeStamp(value), (uint32_t)IOHIDElementGetCookie(element), IOHIDElementGetUsagePage(element), IOHIDElementGetUsage(element), IOHIDValueGetIntegerValue(value));
45}
46
47
48static void __deviceCallback(void * context, IOReturn result, void * sender, IOHIDDeviceRef device)
49{
50    printf("IOHIDDeviceRef[%p] %s\n", device, context!=0 ? "matched" : "terminated");
51}
52
53int main (int argc, const char * argv[]) {
54
55    IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, 0);
56    int a;
57    for (a=1; a<argc; a++) {
58        if ( 0 == strcmp("-v", argv[a]) ) {
59            gValue = TRUE;
60            printf("Print values supported\n");
61        }
62        else if ( 0 == strcmp("-s", argv[a]) ) {
63            gSend = TRUE;
64            printf("Send response out data supported\n");
65        }
66        else if ( 0 == strcmp("-nr", argv[a]) ) {
67            gReport = FALSE;
68            printf("Input report data suppressed\n");
69        }
70    }
71
72
73
74    IOHIDManagerRegisterDeviceMatchingCallback(manager, __deviceCallback, (void*)TRUE);
75    IOHIDManagerRegisterDeviceRemovalCallback(manager, __deviceCallback, (void*)FALSE);
76
77    if ( gReport )
78        IOHIDManagerRegisterInputReportCallback(manager, __deviceReportCallback, NULL);
79    if ( gValue )
80        IOHIDManagerRegisterInputValueCallback(manager, __deviceValueCallback, NULL);
81
82    IOHIDManagerScheduleWithRunLoop(manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
83    IOHIDManagerSetDeviceMatching(manager, NULL);
84    IOHIDManagerOpen(manager, 0);
85
86    CFRunLoopRun();
87
88    return 0;
89}
90