8 #define IS_NUMPAD(scancode) ((scancode) >= kVK_ANSI_KeypadDecimal && (scancode) <= kVK_ANSI_Keypad9 && (scancode) != kVK_ANSI_KeypadClear && (scancode) != kVK_ANSI_KeypadEnter) 
   10 pthread_mutex_t _euid_guard = PTHREAD_MUTEX_INITIALIZER;
 
   13 static void postevent(io_connect_t event, UInt32 type, NXEventData* ev, IOOptionBits flags, IOOptionBits options, 
int silence_errors){
 
   22     if(!stat(
"/dev/console", &file)){
 
   27     IOGPoint location = {0, 0};
 
   28     if((options & kIOHIDSetRelativeCursorPosition) && type != NX_MOUSEMOVED){
 
   31         CGEventRef cge = CGEventCreate(nil);
 
   32         CGPoint loc = CGEventGetLocation(cge);
 
   34         location.x = floor(loc.x + ev->mouseMove.dx);
 
   35         location.y = floor(loc.y + ev->mouseMove.dy);
 
   36         options = (options & ~kIOHIDSetRelativeCursorPosition) | kIOHIDSetCursorPosition;
 
   45     kern_return_t res = IOHIDPostEvent(event, type, location, ev, kNXEventDataVersion, flags | NX_NONCOALSESCEDMASK, options);
 
   46     if(res != kIOReturnSuccess && !silence_errors)
 
   47         ckb_warn(
"Post event failed: %x\n", res);
 
   57 #define aux_key_data(scancode, down, is_repeat) ((scancode) << 16 | ((down) ? 0x0a00 : 0x0b00) | !!(is_repeat)) 
   58 static void postevent_kp(io_connect_t event, 
int kbflags, 
int scancode, 
int down, 
int is_flags, 
int is_repeat){
 
   60     memset(&kp, 0, 
sizeof(kp));
 
   62     IOOptionBits flags = kbflags;
 
   63     IOOptionBits options = 0;
 
   64     if(scancode == KEY_CAPSLOCK){
 
   66         kp.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
 
   67         kp.compound.misc.L[0] = aux_key_data(NX_KEYTYPE_CAPS_LOCK, down, is_repeat);
 
   68         postevent(event, NX_SYSDEFINED, &kp, flags, options, 1);
 
   71         memset(&kp, 0, 
sizeof(kp));
 
   73     if(IS_MEDIA(scancode)){
 
   74         kp.compound.subType = (scancode != KEY_POWER ? NX_SUBTYPE_AUX_CONTROL_BUTTONS : NX_SUBTYPE_POWER_KEY);
 
   75         kp.compound.misc.L[0] = aux_key_data(scancode - KEY_MEDIA, down, is_repeat);
 
   80             type = NX_FLAGSCHANGED;
 
   81             options = kIOHIDSetGlobalEventFlags;
 
   84             type = down ? NX_KEYDOWN : NX_KEYUP;
 
   85         kp.key.repeat = is_repeat;
 
   86         kp.key.keyCode = scancode;
 
   87         kp.key.origCharSet = kp.key.charSet = NX_ASCIISET;
 
   88         if(IS_NUMPAD(scancode))
 
   89             flags |= NX_NUMERICPADMASK;
 
   90         else if(scancode == kVK_Help)
 
   93     postevent(event, type, &kp, flags, options, !down || is_repeat);
 
   98 static void postevent_mb(io_connect_t event, 
int button, 
int down){
 
  100     memset(&mb, 0, 
sizeof(mb));
 
  101     mb.compound.subType = NX_SUBTYPE_AUX_MOUSE_BUTTONS;
 
  102     mb.compound.misc.L[0] = (1 << button);
 
  103     mb.compound.misc.L[1] = down ? (1 << button) : 0;
 
  104     postevent(event, NX_SYSDEFINED, &mb, 0, 0, !down);
 
  106     memset(&mb, 0, 
sizeof(mb));
 
  108     mb.mouse.buttonNumber = button;
 
  111         type = down ? NX_LMOUSEDOWN : NX_LMOUSEUP;
 
  114         type = down ? NX_RMOUSEDOWN : NX_RMOUSEUP;
 
  117         type = down ? NX_OMOUSEDOWN : NX_OMOUSEUP;
 
  120         mb.mouse.pressure = 255;
 
  121     postevent(event, type, &mb, 0, 0, 1);
 
  125 extern void wheel_accel(io_connect_t event, 
int* deltaAxis1, SInt32* fixedDeltaAxis1, SInt32* pointDeltaAxis1);
 
  126 extern void mouse_accel(io_connect_t event, 
int* x, 
int* y);
 
  129 static void postevent_wheel(io_connect_t event, 
int scroll_rate, 
int value){
 
  131     memset(&mm, 0, 
sizeof(mm));
 
  133         wheel_accel(event, &value, &mm.scrollWheel.fixedDeltaAxis1, &mm.scrollWheel.pointDeltaAxis1);
 
  134         mm.scrollWheel.deltaAxis1 = value;
 
  137         mm.scrollWheel.deltaAxis1 = value * scroll_rate;
 
  139     postevent(event, NX_SCROLLWHEELMOVED, &mm, 0, 0, 0);
 
  143 static void postevent_mm(io_connect_t event, 
int x, 
int y, 
int use_accel, 
uchar buttons){
 
  145     memset(&mm, 0, 
sizeof(mm));
 
  146     UInt32 type = NX_MOUSEMOVED;
 
  148         mouse_accel(event, &x, &y);
 
  154             type = NX_LMOUSEDRAGGED;
 
  156             type = NX_RMOUSEDRAGGED;
 
  158             type = NX_OMOUSEDRAGGED;
 
  161         while(!(buttons & 1)){
 
  165         mm.mouse.pressure = 255;
 
  166         mm.mouse.buttonNumber = button;
 
  168     postevent(event, type, &mm, 0, kIOHIDSetRelativeCursorPosition, 1);
 
  172 long repeattime(io_connect_t event, 
int first){
 
  174     IOByteCount actualSize = 0;
 
  175     if(IOHIDGetParameter(event, first ? CFSTR(kIOHIDInitialKeyRepeatKey) : CFSTR(kIOHIDKeyRepeatKey), 
sizeof(
long), &delay, &actualSize) != KERN_SUCCESS || actualSize == 0)
 
  186         postevent_kp(kb->event, 0, scan, 0, 0, 0);
 
  191 static int open_iohid(io_connect_t* connection){
 
  193     io_service_t service;
 
  195     static mach_port_t master = 0;
 
  197     if(!master && (res = IOMasterPort(bootstrap_port, &master)) != kIOReturnSuccess){
 
  199         ckb_err(
"Unable to open master port: 0x%08x\n", res);
 
  203     if((res = IOServiceGetMatchingServices(master, IOServiceMatching(kIOHIDSystemClass), &iter)) != kIOReturnSuccess)
 
  205     service = IOIteratorNext(iter);
 
  207         res = kIOReturnNotOpen;
 
  208         goto failure_release_iter;
 
  210     if((res = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, connection)) != kIOReturnSuccess){
 
  212         goto failure_release_iter;
 
  215     IOObjectRelease(service);
 
  216     failure_release_iter:
 
  217     IOObjectRelease(iter);
 
  225     while((res = open_iohid(&kb->event)) != kIOReturnSuccess){
 
  226         if(res != kIOReturnNotOpen){
 
  228             ckb_err(
"Unable to open HID system: 0x%08x\n", res);
 
  242         IOServiceClose(kb->event);
 
  250         CFRunLoopRemoveTimer(kb->input_loop, kb->krtimer, kCFRunLoopCommonModes);
 
  252         CFRunLoopAddTimer(kb->input_loop, kb->krtimer, kCFRunLoopCommonModes);
 
  256 static void _keyretrigger(
usbdevice* kb){
 
  257     int scancode = kb->lastkeypress;
 
  258     postevent_kp(kb->event, kb->modifiers, scancode, 1, 0, 1);
 
  260     long repeat = repeattime(kb->event, 0);
 
  267 void keyretrigger(CFRunLoopTimerRef timer, 
void* info){
 
  270     struct timespec time;
 
  271     clock_gettime(CLOCK_MONOTONIC, &time);
 
  280 static void* indicator_update(
void* context){
 
  282     pthread_mutex_lock(
dmutex(kb));
 
  284         pthread_mutex_lock(
imutex(kb));
 
  285         IOOptionBits modifiers = kb->modifiers;
 
  288         pthread_mutex_unlock(
imutex(kb));
 
  290         uchar ileds = 1 | !!(modifiers & NX_ALPHASHIFTMASK) << 1;
 
  292         kb->
vtable->updateindicators(kb, 0);
 
  294     pthread_mutex_unlock(
dmutex(kb));
 
  300     keyretrigger(NULL, kb);
 
  305                 postevent_wheel(kb->event, kb->scroll_rate, 1);
 
  309                 postevent_wheel(kb->event, kb->scroll_rate, -1);
 
  312         int button = scancode & ~SCAN_MOUSE;
 
  315         if(IOHIDGetMouseButtonMode(kb->event, &mode) == kIOReturnSuccess){
 
  316             if(mode == kIOHIDButtonMode_ReverseLeftRightClicks && button == 0)
 
  318             else if(mode != kIOHIDButtonMode_EnableRightClick && button == 1)
 
  321         postevent_mb(kb->event, button, down);
 
  323             kb->mousestate |= (1 << button);
 
  325             kb->mousestate &= ~(1 << button);
 
  333         else if(scancode == KEY_BACKSLASH)
 
  337         scancode = KEY_BACKSLASH;
 
  340         if(scancode == KEY_GRAVE)
 
  341             scancode = KEY_102ND;
 
  342         else if(scancode == KEY_102ND)
 
  343             scancode = KEY_GRAVE;
 
  347     IOOptionBits mod = 0;
 
  348     if(scancode == KEY_CAPSLOCK){
 
  350             kb->modifiers ^= NX_ALPHASHIFTMASK;
 
  353         if(!kb->indicthread){
 
  357             if(!pthread_create(&kb->indicthread, 0, indicator_update, kb))
 
  358                 pthread_detach(kb->indicthread);
 
  361     else if(scancode == KEY_LEFTSHIFT) mod = NX_DEVICELSHIFTKEYMASK;
 
  362     else if(scancode == KEY_RIGHTSHIFT) mod = NX_DEVICERSHIFTKEYMASK;
 
  363     else if(scancode == KEY_LEFTCTRL) mod = NX_DEVICELCTLKEYMASK;
 
  364     else if(scancode == KEY_RIGHTCTRL) mod = NX_DEVICERCTLKEYMASK;
 
  365     else if(scancode == KEY_LEFTMETA) mod = NX_DEVICELCMDKEYMASK;
 
  366     else if(scancode == KEY_RIGHTMETA) mod = NX_DEVICERCMDKEYMASK;
 
  367     else if(scancode == KEY_LEFTALT) mod = NX_DEVICELALTKEYMASK;
 
  368     else if(scancode == KEY_RIGHTALT) mod = NX_DEVICERALTKEYMASK;
 
  369     else if(scancode == KEY_FN) mod = NX_SECONDARYFNMASK;
 
  373             mod |= kb->modifiers;
 
  375             mod = kb->modifiers & ~mod;
 
  376         if((mod & NX_DEVICELSHIFTKEYMASK) || (mod & NX_DEVICERSHIFTKEYMASK)) mod |= NX_SHIFTMASK; 
else mod &= ~NX_SHIFTMASK;
 
  377         if((mod & NX_DEVICELCTLKEYMASK) || (mod & NX_DEVICERCTLKEYMASK)) mod |= NX_CONTROLMASK; 
else mod &= ~NX_CONTROLMASK;
 
  378         if((mod & NX_DEVICELCMDKEYMASK) || (mod & NX_DEVICERCMDKEYMASK)) mod |= NX_COMMANDMASK; 
else mod &= ~NX_COMMANDMASK;
 
  379         if((mod & NX_DEVICELALTKEYMASK) || (mod & NX_DEVICERALTKEYMASK)) mod |= NX_ALTERNATEMASK; 
else mod &= ~NX_ALTERNATEMASK;
 
  386             long repeat = repeattime(kb->event, 1);
 
  388                 kb->lastkeypress = scancode;
 
  389                 clock_gettime(CLOCK_MONOTONIC, &kb->keyrepeat);
 
  397     postevent_kp(kb->event, kb->modifiers, scancode, down, isMod, 0);
 
#define SCROLL_ACCELERATED
 
#define ckb_err(fmt, args...)
 
#define KEY_BACKSLASH_ISO
 
long gid
Group ID for the control nodes. -1 to give read/write access to everybody. 
 
#define ckb_warn(fmt, args...)
 
#define timespec_ge(left, right)
 
const union devcmd * vtable
 
#define HAS_ANY_FEATURE(kb, feat)
 
#define HAS_FEATURES(kb, feat)
 
const key keymap[(((152+3+12)+25)+11)]
 
void timespec_add(struct timespec *timespec, long nanoseconds)