Skip to content

Instantly share code, notes, and snippets.

@heiner
Last active February 11, 2021 14:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heiner/ca5b66b673d5514e520ad8099a9c905e to your computer and use it in GitHub Desktop.
Save heiner/ca5b66b673d5514e520ad8099a9c905e to your computer and use it in GitHub Desktop.
cmake_minimum_required(VERSION 3.10)
project(cppgen VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(remapping remapping.cc)
target_link_libraries(remapping stdc++ "-framework Foundation" "-framework IOKit" objc)
# See https://developer.apple.com/library/archive/technotes/tn2450/_index.html
# and
# https://www.nanoant.com/mac/macos-function-key-remapping-with-hidutil
# https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=56
# https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1090.260.23/IOHIDEventSystemPlugIns/
# https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1090.260.23/IOHIDFamily/IOHIDUsageTables.h.auto.html
import os
TABLE = {
"Keyboard a and A": 0x04,
"Keyboard 5 and %": 0x22,
"Keyboard F7": 0x40,
"Keypad 6 and Right Arrow": 0x5E,
"Keyboard b and B": 0x05,
"Keyboard 6 and ^": 0x23,
"Keyboard F8": 0x41,
"Keypad 7 and Home": 0x5F,
"Keyboard c and C": 0x06,
"Keyboard 7 and&": 0x24,
"Keyboard F9": 0x42,
"Keypad 8 and Up Arrow": 0x60,
"Keyboard d and D": 0x07,
"Keyboard 8 and *": 0x25,
"Keyboard F10": 0x43,
"Keypad 9 and Page Up": 0x61,
"Keyboard e and E": 0x08,
"Keyboard 9 and (": 0x26,
"Keyboard F11": 0x44,
"Keypad 0 and Insert": 0x62,
"Keyboard f and F": 0x09,
"Keyboard 0 and )": 0x27,
"Keyboard F12": 0x45,
"Keypad . and Delete": 0x63,
"Keyboard g and G": 0x0A,
"Keyboard Return (Enter)": 0x28,
"Keyboard Print Screen": 0x46,
"Keyboard Non-US \\ and |": 0x64,
"Keyboard h and H": 0x0B,
"Keyboard Escape": 0x29,
"Keyboard Scroll Lock": 0x47,
"Keyboard Application": 0x65,
"Keyboard i and I": 0x0C,
"Keyboard Delete (Backspace)": 0x2A,
"Keyboard Pause": 0x48,
"Keyboard Power": 0x66,
"Keyboard j and J": 0x0D,
"Keyboard Tab": 0x2B,
"Keyboard Insert": 0x49,
"Keypad =": 0x67,
"Keyboard k and K": 0x0E,
"Keyboard Spacebar": 0x2C,
"Keyboard Home": 0x4A,
"Keyboard F13": 0x68,
"Keyboard l and L": 0x0F,
"Keyboard - and _": 0x2D,
"Keyboard Page Up": 0x4B,
"Keyboard F14": 0x69,
"Keyboard m and M": 0x10,
"Keyboard = and +": 0x2E,
"Keyboard Delete Forward": 0x4C,
"Keyboard F15": 0x6A,
"Keyboard n and N": 0x11,
"Keyboard [ and {": 0x2F,
"Keyboard End": 0x4D,
"Keyboard F16": 0x6B,
"Keyboard o and O": 0x12,
"Keyboard ] and }": 0x30,
"Keyboard Page Down": 0x4E,
"Keyboard F17": 0x6C,
"Keyboard p and P": 0x13,
"Keyboard \\ and |": 0x31,
"Keyboard Right Arrow": 0x4F,
"Keyboard F18": 0x6D,
"Keyboard q and Q": 0x14,
"Keyboard Non-US # and ~": 0x32,
"Keyboard Left Arrow": 0x50,
"Keyboard F19": 0x6E,
"Keyboard r and R": 0x15,
"Keyboard ; and :": 0x33,
"Keyboard Down Arrow": 0x51,
"Keyboard F20": 0x6F,
"Keyboard s and S": 0x16,
"Keyboard ' and \"": 0x34,
"Keyboard Up Arrow": 0x52,
"Keyboard F21": 0x70,
"Keyboard t and T": 0x17,
"Keyboard Grave Accent and Tilde": 0x35,
"Keypad Num Lock and Clear": 0x53,
"Keyboard F22": 0x71,
"Keyboard u and U": 0x18,
'Keyboard , and "<"': 0x36,
"Keypad /": 0x54,
"Keyboard F23": 0x72,
"Keyboard v and V": 0x19,
'Keyboard . and ">"': 0x37,
"Keypad *": 0x55,
"Keyboard F24": 0x73,
"Keyboard w and W": 0x1A,
"Keyboard / and ?": 0x38,
"Keypad -": 0x56,
"Keyboard Left Control": 0xE0,
"Keyboard x and X": 0x1B,
"Keyboard Caps Lock": 0x39,
"Keypad +": 0x57,
"Keyboard Left Shift": 0xE1,
"Keyboard y and Y": 0x1C,
"Keyboard F1": 0x3A,
"Keypad Enter": 0x58,
"Keyboard Left Alt": 0xE2,
"Keyboard z and Z": 0x1D,
"Keyboard F2": 0x3B,
"Keypad 1 and End": 0x59,
"Keyboard Left GUI": 0xE3,
"Keyboard 1 and !": 0x1E,
"Keyboard F3": 0x3C,
"Keypad 2 and Down Arrow": 0x5A,
"Keyboard Right Control": 0xE4,
"Keyboard 2 and @": 0x1F,
"Keyboard F4": 0x3D,
"Keypad 3 and Page Down": 0x5B,
"Keyboard Right Shift": 0xE5,
"Keyboard 3 and #": 0x20,
"Keyboard F5": 0x3E,
"Keypad 4 and Left Arrow": 0x5C,
"Keyboard Right Alt": 0xE6,
"Keyboard 4 and $": 0x21,
"Keyboard F6": 0x3F,
"Keypad 5": 0x5D,
"Keyboard Right GUI": 0xE7,
}
def key2hex(k):
return 0x700000000 | TABLE[k]
def fromto(fromk, tok):
return {
"HIDKeyboardModifierMappingSrc": key2hex(fromk),
"HIDKeyboardModifierMappingDst": key2hex(tok),
}
def user_key_mapping(mapping):
"""Hex version of return str({"UserKeyMapping": mapping})."""
m = []
for d in mapping:
m.append("{%s}" % ",".join('"%s":%s' % (k, hex(d[k])) for k in d))
return '{"UserKeyMapping":[%s]}' % ",".join(m)
def main():
# Settings for Razer Huntsman Tournament Edition Keyboard.
# (ioreg -lw0 | less).
matching = {"ProductID": 579, "VendorID": 5426}
mapping = [
fromto("Keyboard Left Alt", "Keyboard Left GUI"),
fromto("Keyboard Left GUI", "Keyboard Left Alt"),
fromto("Keyboard Right Alt", "Keyboard Right GUI"),
fromto("Keyboard Application", "Keyboard Right Alt"),
]
command = "hidutil property --matching '%s' --set '%s'" % (
str(matching).replace("'", '"'),
user_key_mapping(mapping),
)
print(command)
os.system(command)
if __name__ == "__main__":
main()
// Cf.
// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1090.260.23/tools/hidutil/property.m.auto.html
// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1090.260.23/IOHIDFamily/IOHIDUsageTables.h.auto.html
#include <iostream>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/hid/IOHIDUsageTables.h>
#include <IOKit/hidsystem/IOHIDEventSystemClient.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
#include <IOKit/hidsystem/IOHIDServiceClient.h>
int main(int argc, char *argv[]) {
uint64_t aKey = 0x700000004;
uint64_t bKey = 0x700000005;
CFStringRef keys[2] = {CFSTR(kIOHIDKeyboardModifierMappingSrcKey),
CFSTR(kIOHIDKeyboardModifierMappingDstKey)};
CFNumberRef values[2] = {
CFNumberCreate(NULL, kCFNumberSInt64Type, &aKey),
CFNumberCreate(NULL, kCFNumberSInt64Type, &bKey),
};
CFDictionaryRef dicts[2];
dicts[0] = CFDictionaryCreate(
NULL, (const void **)keys, (const void **)values, 2,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFArrayRef map =
CFArrayCreate(NULL, (const void **)dicts, 1, &kCFTypeArrayCallBacks);
int product = 579;
int vendor = 5426;
CFStringRef keys2[2] = {CFSTR(kIOHIDProductIDKey), CFSTR(kIOHIDVendorIDKey)};
CFNumberRef values2[2] = {
CFNumberCreate(NULL, kCFNumberSInt64Type, &product),
CFNumberCreate(NULL, kCFNumberSInt64Type, &vendor),
};
dicts[1] = CFDictionaryCreate(
NULL, (const void **)keys2, (const void **)values2, 2,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
IOHIDEventSystemClientRef system =
IOHIDEventSystemClientCreateSimpleClient(kCFAllocatorDefault);
// IOHIDEventSystemClientSetMatchingMultiple(system, dicts[1]);
CFArrayRef services = IOHIDEventSystemClientCopyServices(system);
for (CFIndex i = 0; i < CFArrayGetCount(services); i++) {
IOHIDServiceClientRef service =
(IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, i);
if (IOHIDServiceClientConformsTo(service, kHIDPage_GenericDesktop,
kHIDUsage_GD_Keyboard)) {
CFTypeRef product_ref =
IOHIDServiceClientCopyProperty(service, CFSTR(kIOHIDProductIDKey));
CFShow(product_ref);
int64_t value = 0;
CFNumberGetValue((CFNumberRef)product_ref, kCFNumberSInt64Type, &value);
std::cout << value << std::endl;
/*IOHIDServiceClientSetProperty(service, CFSTR(kIOHIDUserKeyUsageMapKey),
map);
*/
}
}
CFRelease(services);
CFRelease(system);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment