Пример #1
0
// ------------------------------------------------------------
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;
    }
  }
}
Пример #2
0
  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.
  }
Пример #3
0
    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();
    }
Пример #4
0
  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();
  }
Пример #5
0
  // ----------------------------------------------------------------------
  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();
  }
Пример #6
0
    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;
    }
Пример #7
0
    // ======================================================================
    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;
    }
Пример #8
0
  // ----------------------------------------------------------------------
  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();
  }
Пример #9
0
  // ======================================================================
  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();
  }