Files
vphone-cli/scripts/vphoned/vphoned_hid.m

73 lines
2.4 KiB
Objective-C

#import "vphoned_hid.h"
#include <dlfcn.h>
#include <mach/mach_time.h>
#include <unistd.h>
typedef void *IOHIDEventSystemClientRef;
typedef void *IOHIDEventRef;
static IOHIDEventSystemClientRef (*pCreate)(CFAllocatorRef);
static IOHIDEventRef (*pKeyboard)(CFAllocatorRef, uint64_t,
uint32_t, uint32_t, int, int);
static void (*pSetSender)(IOHIDEventRef, uint64_t);
static void (*pDispatch)(IOHIDEventSystemClientRef, IOHIDEventRef);
static IOHIDEventSystemClientRef gClient;
static dispatch_queue_t gHIDQueue;
BOOL vp_hid_load(void) {
void *h = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW);
if (!h) { NSLog(@"vphoned: dlopen IOKit failed"); return NO; }
pCreate = dlsym(h, "IOHIDEventSystemClientCreate");
pKeyboard = dlsym(h, "IOHIDEventCreateKeyboardEvent");
pSetSender = dlsym(h, "IOHIDEventSetSenderID");
pDispatch = dlsym(h, "IOHIDEventSystemClientDispatchEvent");
if (!pCreate || !pKeyboard || !pSetSender || !pDispatch) {
NSLog(@"vphoned: missing IOKit symbols");
return NO;
}
gClient = pCreate(kCFAllocatorDefault);
if (!gClient) { NSLog(@"vphoned: IOHIDEventSystemClientCreate returned NULL"); return NO; }
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(
DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, 0);
gHIDQueue = dispatch_queue_create("com.vphone.vphoned.hid", attr);
NSLog(@"vphoned: IOKit loaded");
return YES;
}
static void send_hid_event(IOHIDEventRef event) {
IOHIDEventRef strong = (IOHIDEventRef)CFRetain(event);
dispatch_async(gHIDQueue, ^{
pSetSender(strong, 0x8000000817319372);
pDispatch(gClient, strong);
CFRelease(strong);
});
}
void vp_hid_press(uint32_t page, uint32_t usage) {
IOHIDEventRef down = pKeyboard(kCFAllocatorDefault, mach_absolute_time(),
page, usage, 1, 0);
if (!down) return;
send_hid_event(down);
CFRelease(down);
usleep(100000);
IOHIDEventRef up = pKeyboard(kCFAllocatorDefault, mach_absolute_time(),
page, usage, 0, 0);
if (!up) return;
send_hid_event(up);
CFRelease(up);
}
void vp_hid_key(uint32_t page, uint32_t usage, BOOL down) {
IOHIDEventRef ev = pKeyboard(kCFAllocatorDefault, mach_absolute_time(),
page, usage, down ? 1 : 0, 0);
if (ev) { send_hid_event(ev); CFRelease(ev); }
}