Skip to content

Instantly share code, notes, and snippets.

@felixgr
Created May 27, 2017 07:37
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save felixgr/a55aa42a4398f15f13c7fb58b11e70c5 to your computer and use it in GitHub Desktop.
Save felixgr/a55aa42a4398f15f13c7fb58b11e70c5 to your computer and use it in GitHub Desktop.
Remove Caps Delay MBP15 Touchbar Late 2016
// Build:
// clang hidnative.c -o hidnative -framework IOKit -framework CoreFoundation
//
// Run:
// sudo ./hidnative
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <stdlib.h>
static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
{
CFTypeRef ref;
int32_t value;
ref = IOHIDDeviceGetProperty(device, key);
if (ref) {
if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value);
return value;
}
}
return 0;
}
int dump(const char* target_device, int max_report_id) {
IOHIDManagerRef hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
CFIndex num_devices = CFSetGetCount(device_set);
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
CFSetGetValues(device_set, (const void **) device_array);
char *keyboard_path = NULL;
for (int i = 0; i < num_devices; i++) {
IOHIDDeviceRef dev = device_array[i];
if (!dev) {
continue;
}
int32_t vendor = get_int_property(dev, CFSTR(kIOHIDVendorIDKey));
int32_t product = get_int_property(dev, CFSTR(kIOHIDProductIDKey));
io_object_t iokit_dev = IOHIDDeviceGetService(dev);
io_string_t path;
kern_return_t res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
// printf("device %d %x %x\n%s\n", i, vendor, product, path);
if (strstr(path, target_device)) {
keyboard_path = strdup(path);
}
}
free(device_array);
CFRelease(device_set);
if (keyboard_path == NULL) {
printf("keyboard not found\n");
goto cleanup;
}
printf("using keyboard: '%s'\n\n", keyboard_path);
io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, keyboard_path);
if (entry == MACH_PORT_NULL) {
printf("device not found\n");
goto cleanup;
}
IOHIDDeviceRef device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry);
if (device_handle == NULL) {
printf("unable to create device\n");
goto cleanup;
}
IOReturn ret = IOHIDDeviceOpen(device_handle, kIOHIDOptionsTypeSeizeDevice);
if (ret != kIOReturnSuccess) {
printf("unable to open device\n");
goto cleanup;
}
//CFStringRef str = IOHIDDeviceGetProperty(device_handle, CFSTR(kIOHIDProductKey));
//if (!str) {
// printf("unable to get product key\n");
// goto cleanup;
//}
//printf("got productkey %s\n\n", CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
int setreport_sent = 0;
unsigned char buf[256];
CFIndex len = sizeof(buf);
getreport:
for (int reportID = 0; reportID < max_report_id; reportID++) {
memset(buf, 0x00, sizeof(buf));
len = sizeof(buf);
printf("'%s' reportID %d: ", target_device, reportID);
ret = IOHIDDeviceGetReport(device_handle, kIOHIDReportTypeFeature, reportID, buf, &len);
if (ret != kIOReturnSuccess) {
printf("no report\n");
continue;
}
for (int i = 0; i < len; i++) {
printf(" %02x", buf[i]);
}
printf("\n");
}
// read only, remove to set 09 00 00 00 magic
// remove next line to send the setreport and remove
goto cleanup;
setreport:
if (setreport_sent) {
goto cleanup;
}
buf[0] = 0x9;
buf[1] = 0x0;
buf[2] = 0x0;
buf[3] = 0x0;
len = 4;
ret = IOHIDDeviceSetReport(device_handle, kIOHIDReportTypeFeature, 0x09, buf, len);
if (ret != kIOReturnSuccess) {
printf("unable to set report\n");
} else {
printf("report set\n");
}
setreport_sent = 1;
goto getreport;
cleanup:
printf("\n\n\ncleanup\n");
if (device_handle != NULL) CFRelease(device_handle);
if (entry != MACH_PORT_NULL) IOObjectRelease(entry);
return 0;
}
int main() {
dump("Keyboard / Boot", 40);
//dump("Trackpad / Boot", 40);
//dump("Actuator", 50);
//dump("Device Management", 50);
//dump("Accelerometer", 10);
return 0;
}
@aoenth
Copy link

aoenth commented Dec 4, 2019

I'm getting "unable to set report". I have the MacBook 13" Early 2015 (MacBook 12,1). Please help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment