// ------------------------------------------------------------ void org_pqrs_driver_KeyRemap4MacBook_UserClient_kext::handle_synchronized_communication(uint32_t type, uint32_t option, mach_vm_address_t address, mach_vm_size_t size, uint64_t* outputdata) { org_pqrs_KeyRemap4MacBook::IOLockWrapper::ScopedLock lk_eventlock(org_pqrs_KeyRemap4MacBook::CommonData::getEventLock()); *outputdata = BRIDGE_USERCLIENT_SYNCHRONIZED_COMMUNICATION_RETURN_ERROR_GENERIC; switch (type) { case BRIDGE_USERCLIENT_TYPE_SET_REMAPCLASSES_INITIALIZE_VECTOR: { org_pqrs_KeyRemap4MacBook::Config::set_initialized(false); const uint32_t* initialize_vector = reinterpret_cast<uint32_t*>(address); if (initialize_vector) { if (org_pqrs_KeyRemap4MacBook::RemapClassManager::load_remapclasses_initialize_vector(initialize_vector, size)) { *outputdata = BRIDGE_USERCLIENT_SYNCHRONIZED_COMMUNICATION_RETURN_SUCCESS; } } break; } case BRIDGE_USERCLIENT_TYPE_SET_CONFIG: { const int32_t* config = reinterpret_cast<int32_t*>(address); if (config) { if (org_pqrs_KeyRemap4MacBook::RemapClassManager::set_config(config, size)) { org_pqrs_KeyRemap4MacBook::Config::set_initialized(true); *outputdata = BRIDGE_USERCLIENT_SYNCHRONIZED_COMMUNICATION_RETURN_SUCCESS; } } break; } case BRIDGE_USERCLIENT_TYPE_GET_STATUS_MESSAGE: { const char* statusmessage = org_pqrs_KeyRemap4MacBook::CommonData::get_statusmessage(option); char* p = reinterpret_cast<char*>(address); if (statusmessage && p) { strlcpy(p, statusmessage, static_cast<size_t>(size)); *outputdata = BRIDGE_USERCLIENT_SYNCHRONIZED_COMMUNICATION_RETURN_SUCCESS; } break; } case BRIDGE_USERCLIENT_TYPE_SET_WORKSPACEDATA: { if (size != sizeof(BridgeWorkSpaceData)) { IOLOG_ERROR("BRIDGE_USERCLIENT_TYPE_SET_ESSENTIAL_CONFIG wrong 'size' parameter\n"); } else { BridgeWorkSpaceData* p = reinterpret_cast<BridgeWorkSpaceData*>(address); if (p) { org_pqrs_KeyRemap4MacBook::CommonData::setcurrent_workspacedata(*p); *outputdata = BRIDGE_USERCLIENT_SYNCHRONIZED_COMMUNICATION_RETURN_SUCCESS; } } break; } } }
void EventInputQueue::push_UpdateEventFlagsCallback(OSObject* target, unsigned flags, OSObject* sender, void* refcon) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); if (! lk_eventlock) return; IOLockWrapper::ScopedLock lk(timer_.getlock()); if (! lk) return; // ------------------------------------------------------------ Params_UpdateEventFlagsCallback::auto_ptr ptr(Params_UpdateEventFlagsCallback::alloc(flags)); if (! ptr) return; Params_UpdateEventFlagsCallback& params = *ptr; // ------------------------------------------------------------ // update device priority by calling ListHookedKeyboard::instance().get(kbd). { IOLockWrapper::ScopedLock lk_device(ListHookedKeyboard::instance().getListLock()); if (! lk_device) return; IOHIKeyboard* device = OSDynamicCast(IOHIKeyboard, sender); if (! device) return; ListHookedKeyboard::Item* item = static_cast<ListHookedKeyboard::Item*>(ListHookedKeyboard::instance().get_nolock(device)); if (! item) return; } params.log(); // Don't push_back for UpdateEventFlagsCallback. }
void stop(void) { // At first, restoreEventAction for all devices. { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); timer_refresh.terminate(); ListHookedKeyboard::instance().terminate(); ListHookedConsumer::instance().terminate(); ListHookedPointing::instance().terminate(); } // roughly sleep: waiting for finishing queued device events. IOSleep(200); // call terminate { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); Config::sysctl_unregister(); Config::terminate(); RemapClassManager::terminate(); KeyboardRepeat::terminate(); EventInputQueue::terminate(); VirtualKey::terminate(); EventOutputQueue::terminate(); RemapFunc::HoldingKeyToKey::static_terminate(); RemapFunc::KeyOverlaidModifier::static_terminate(); RemapFunc::PointingRelativeToScroll::static_terminate(); ListHookedKeyboard::static_terminate(); if (workLoop) { workLoop->release(); workLoop = NULL; } KeyRemap4MacBook_client::terminate(); EventWatcher::terminate(); PressDownKeys::terminate(); } CommonData::terminate(); }
void EventInputQueue::push_ScrollWheelEventCallback(OSObject* target, short deltaAxis1, short deltaAxis2, short deltaAxis3, IOFixed fixedDelta1, IOFixed fixedDelta2, IOFixed fixedDelta3, SInt32 pointDelta1, SInt32 pointDelta2, SInt32 pointDelta3, SInt32 options, AbsoluteTime ts, OSObject* sender, void* refcon) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); if (! lk_eventlock) return; IOLockWrapper::ScopedLock lk(timer_.getlock()); if (! lk) return; // ------------------------------------------------------------ Params_ScrollWheelEventCallback::auto_ptr ptr(Params_ScrollWheelEventCallback::alloc(deltaAxis1, deltaAxis2, deltaAxis3, fixedDelta1, fixedDelta2, fixedDelta3, pointDelta1, pointDelta2, pointDelta3, options)); if (! ptr) return; Params_ScrollWheelEventCallback& params = *ptr; // ------------------------------------------------------------ DeviceVendor deviceVendor(0); DeviceProduct deviceProduct(0); { IOLockWrapper::ScopedLock lk_device(ListHookedKeyboard::instance().getListLock()); if (! lk_device) return; IOHIPointing* device = OSDynamicCast(IOHIPointing, sender); if (! device) return; ListHookedPointing::Item* item = static_cast<ListHookedPointing::Item*>(ListHookedPointing::instance().get_nolock(device)); if (! item) return; // ------------------------------------------------------------ CommonData::setcurrent_ts(ts); deviceVendor = item->getVendor(); deviceProduct = item->getProduct(); } // ------------------------------------------------------------ bool retainFlagStatusTemporaryCount = Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_general_lazy_modifiers_with_mouse_event); bool updateWorkspaceData = false; enqueue_(params, retainFlagStatusTemporaryCount, updateWorkspaceData, deviceVendor, deviceProduct); setTimer(); }
// ---------------------------------------------------------------------- void EventInputQueue::push_KeyboardSpecialEventCallback(OSObject* target, unsigned int eventType, unsigned int flags, unsigned int key, unsigned int flavor, UInt64 guid, bool repeat, AbsoluteTime ts, OSObject* sender, void* refcon) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); if (! lk_eventlock) return; IOLockWrapper::ScopedLock lk(timer_.getlock()); if (! lk) return; // ------------------------------------------------------------ Params_KeyboardSpecialEventCallback::auto_ptr ptr(Params_KeyboardSpecialEventCallback::alloc(EventType(eventType), Flags(flags), ConsumerKeyCode(key), flavor, guid, repeat)); if (! ptr) return; Params_KeyboardSpecialEventCallback& params = *ptr; // ------------------------------------------------------------ DeviceVendor deviceVendor(0); DeviceProduct deviceProduct(0); { IOLockWrapper::ScopedLock lk_device(ListHookedKeyboard::instance().getListLock()); if (! lk_device) return; IOHIKeyboard* device = OSDynamicCast(IOHIKeyboard, sender); if (! device) return; ListHookedConsumer::Item* item = static_cast<ListHookedConsumer::Item*>(ListHookedConsumer::instance().get_nolock(device)); // ------------------------------------------------------------ CommonData::setcurrent_ts(ts); deviceVendor = item->getVendor(); deviceProduct = item->getProduct(); } // ------------------------------------------------------------ // Because we handle the key repeat ourself, drop the key repeat by hardware. if (repeat) return; // ------------------------------------------------------------ bool retainFlagStatusTemporaryCount = false; bool updateWorkspaceData = params.ex_iskeydown; enqueue_(params, retainFlagStatusTemporaryCount, updateWorkspaceData, deviceVendor, deviceProduct); setTimer(); }
bool notifierfunc_unhookPointing(void* target, void* refCon, IOService* newService, IONotifier* notifier) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); IOLOG_DEBUG("notifierfunc_unhookPointing newService:%p\n", newService); IOHIDevice* device = OSDynamicCast(IOHIPointing, newService); if (! device) return false; ListHookedPointing::instance().erase(device); return true; }
// ====================================================================== bool notifierfunc_hookKeyboard(void* target, void* refCon, IOService* newService, IONotifier* notifier) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); IOLOG_DEBUG("notifierfunc_hookKeyboard newService:%p\n", newService); IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService); if (! device) return false; ListHookedKeyboard::instance().push_back(new ListHookedKeyboard::Item(device)); ListHookedConsumer::instance().push_back(new ListHookedConsumer::Item(device)); return true; }
// ---------------------------------------------------------------------- void EventInputQueue::push_RelativePointerEventCallback(OSObject* target, int buttons_raw, int dx, int dy, AbsoluteTime ts, OSObject* sender, void* refcon) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); if (! lk_eventlock) return; IOLockWrapper::ScopedLock lk(timer_.getlock()); if (! lk) return; // ------------------------------------------------------------ Buttons buttons(buttons_raw); Buttons justPressed; Buttons justReleased; DeviceVendor deviceVendor(0); DeviceProduct deviceProduct(0); { IOLockWrapper::ScopedLock lk_device(ListHookedKeyboard::instance().getListLock()); if (! lk_device) return; IOHIPointing* device = OSDynamicCast(IOHIPointing, sender); if (! device) return; ListHookedPointing::Item* item = static_cast<ListHookedPointing::Item*>(ListHookedPointing::instance().get_nolock(device)); if (! item) return; // ------------------------------------------------------------ CommonData::setcurrent_ts(ts); deviceVendor = item->getVendor(); deviceProduct = item->getProduct(); // ------------------------------------------------------------ justPressed = buttons.justPressed(item->get_previousbuttons()); justReleased = buttons.justReleased(item->get_previousbuttons()); item->set_previousbuttons(buttons); } // ------------------------------------------------------------ // divide an event into button and cursormove events. for (int i = 0; i < ButtonStatus::MAXNUM; ++i) { PointingButton btn(1 << i); if (justPressed.isOn(btn)) { Params_RelativePointerEventCallback::auto_ptr ptr(Params_RelativePointerEventCallback::alloc(buttons, 0, 0, btn, true)); if (! ptr) return; bool retainFlagStatusTemporaryCount = Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_general_lazy_modifiers_with_mouse_event); enqueue_(*ptr, retainFlagStatusTemporaryCount, deviceVendor, deviceProduct); } if (justReleased.isOn(btn)) { Params_RelativePointerEventCallback::auto_ptr ptr(Params_RelativePointerEventCallback::alloc(buttons, 0, 0, btn, false)); if (! ptr) return; bool retainFlagStatusTemporaryCount = Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_general_lazy_modifiers_with_mouse_event); enqueue_(*ptr, retainFlagStatusTemporaryCount, deviceVendor, deviceProduct); } } Params_RelativePointerEventCallback::auto_ptr ptr(Params_RelativePointerEventCallback::alloc(buttons, dx, dy, PointingButton::NONE, false)); if (! ptr) return; bool retainFlagStatusTemporaryCount = true; enqueue_(*ptr, retainFlagStatusTemporaryCount, deviceVendor, deviceProduct); setTimer(); }
// ====================================================================== void EventInputQueue::push_KeyboardEventCallback(OSObject* target, unsigned int eventType, unsigned int flags, unsigned int key, unsigned int charCode, unsigned int charSet, unsigned int origCharCode, unsigned int origCharSet, unsigned int keyboardType, bool repeat, AbsoluteTime ts, OSObject* sender, void* refcon) { IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock()); if (! lk_eventlock) return; IOLockWrapper::ScopedLock lk(timer_.getlock()); if (! lk) return; // ------------------------------------------------------------ KeyboardType newkeyboardtype(keyboardType); RemapClassManager::remap_setkeyboardtype(newkeyboardtype); KeyCode newkey(key); Flags newflags(flags); KeyCode::normalizeKey(newkey, newflags, EventType(eventType), newkeyboardtype); // ------------------------------------------------------------ Params_KeyboardEventCallBack::auto_ptr ptr(Params_KeyboardEventCallBack::alloc(EventType(eventType), newflags, newkey, CharCode(charCode), CharSet(charSet), OrigCharCode(origCharCode), OrigCharSet(origCharSet), newkeyboardtype, repeat)); if (! ptr) return; Params_KeyboardEventCallBack& params = *ptr; // ------------------------------------------------------------ DeviceVendor deviceVendor(0); DeviceProduct deviceProduct(0); { IOLockWrapper::ScopedLock lk_device(ListHookedKeyboard::instance().getListLock()); if (! lk_device) return; IOHIKeyboard* device = OSDynamicCast(IOHIKeyboard, sender); if (! device) return; ListHookedKeyboard::Item* item = static_cast<ListHookedKeyboard::Item*>(ListHookedKeyboard::instance().get_nolock(device)); if (! item) return; // ------------------------------------------------------------ // Logitech Cordless Presenter (LCP) Hack // // When an LCP is first plugged in, it will send a CONTROL_L down event // when the first pageup/pagedown key is pressed without sending a corresponding // up event -- effectively rendering the device (and the Mac) useless until it is // unplugged from the system. // // Similarly, when the volume keys are first pressed, a SHIFT_L down event // is generated, with now up event. // // This code effectively throws these events away if they are received from an LCP. // // *** LCP has 6 keys (Page Up, Page Down, a 'B' key, an 'Esc' key, and volume up / down keys). *** // *** So, we can drop CONTROL_L and SHIFT_L without a problem. *** if (item->isEqualVendorProduct(DeviceVendor::LOGITECH, DeviceProduct::LOGITECH_CORDLESS_PRESENTER)) { if (params.key == KeyCode::CONTROL_L) return; if (params.key == KeyCode::SHIFT_L) return; } // ------------------------------------------------------------ // "ts & keyboardType" are not used in filters like <not>/<only>. // Therefore, we can set current ts and keyboardType here. CommonData::setcurrent_ts(ts); CommonData::setcurrent_keyboardType(params.keyboardType); deviceVendor = item->getVendor(); deviceProduct = item->getProduct(); } // ------------------------------------------------------------ // Because we handle the key repeat ourself, drop the key repeat by hardware. if (repeat) return; // ------------------------------------------------------------ bool retainFlagStatusTemporaryCount = false; bool push_back = true; enqueue_(params, retainFlagStatusTemporaryCount, deviceVendor, deviceProduct, push_back); setTimer(); }