bool ListHookedPointing::Item::restoreEventAction(void) {
  if (!device_) return false;

  IOHIPointing* pointing = OSDynamicCast(IOHIPointing, device_);
  if (!pointing) return false;

  bool result = false;

  // ----------------------------------------
  {
    RelativePointerEventCallback callback = reinterpret_cast<RelativePointerEventCallback>(pointing->_relativePointerEventAction);
    if (callback == EventInputQueue::push_RelativePointerEventCallback) {
      IOLOG_DEBUG("HookedPointing::restoreEventAction (RelativePointerEventCallback) device_:%p (%p -> %p)\n",
                  device_, callback, orig_relativePointerEventAction_);

      pointing->_relativePointerEventAction = reinterpret_cast<RelativePointerEventAction>(orig_relativePointerEventAction_);

      result = true;
    }
  }
  {
    ScrollWheelEventCallback callback = reinterpret_cast<ScrollWheelEventCallback>(pointing->_scrollWheelEventAction);
    if (callback == EventInputQueue::push_ScrollWheelEventCallback) {
      IOLOG_DEBUG("HookedPointing::restoreEventAction (ScrollWheelEventCallback) device_:%p (%p -> %p)\n",
                  device_, callback, orig_scrollWheelEventTarget_);

      pointing->_scrollWheelEventAction = reinterpret_cast<ScrollWheelEventAction>(orig_scrollWheelEventAction_);

      result = true;
    }
  }

  orig_relativePointerEventAction_ = nullptr;
  orig_scrollWheelEventAction_ = nullptr;
  orig_relativePointerEventTarget_ = nullptr;
  orig_scrollWheelEventTarget_ = nullptr;

  return result;
}
Esempio n. 2
0
bool IOHIKeyboard_gIOTerminatedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
  if (!device) return false;

  ListHookedKeyboard::instance().erase(device);
  ListHookedConsumer::instance().erase(device);
  return true;
}
Esempio n. 3
0
bool
IOHIPointing_gIOMatchedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier)
{
    GlobalLock::ScopedLock lk;
    if (! lk) return false;

    IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

    IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
    if (! device) return false;

    ListHookedPointing::instance().push_back(new ListHookedPointing::Item(device));
    return true;
}
Esempio n. 4
0
    bool
    notifierfunc_unhookKeyboard(void* target, void* refCon, IOService* newService, IONotifier* notifier)
    {
      IOLockWrapper::ScopedLock lk_eventlock(CommonData::getEventLock());

      IOLOG_DEBUG("notifierfunc_unhookKeyboard newService:%p\n", newService);

      IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
      if (! device) return false;

      ListHookedKeyboard::instance().erase(device);
      ListHookedConsumer::instance().erase(device);
      return true;
    }
  void
  ListHookedDevice::Item::setVendorProduct(void)
  {
    if (! device_) return;

    IORegistryEntry* dev = device_;

    while (dev) {
      const OSNumber* vid = NULL;
      vid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDVendorIDKey));

      const OSNumber* pid = NULL;
      pid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDProductIDKey));

      if (vid && pid) {
        vendor_ = vid->unsigned32BitValue();
        product_ = pid->unsigned32BitValue();

        goto finish;

      } else {
        // ApplePS2Keyboard does not have ProductID,
        // so we check for Manufacturer and Product strings
        const char* name = dev->getName();

        if (name && strcmp(name, "ApplePS2Keyboard") == 0) {
          // kIOHIDManufacturerKey == "Manufacturer"
          // kIOHIDProductKey == "Product"
          const OSString* manufacturer = OSDynamicCast(OSString, dev->getProperty(kIOHIDManufacturerKey));
          const OSString* product      = OSDynamicCast(OSString, dev->getProperty(kIOHIDProductKey));

          if (manufacturer && product) {
            if (manufacturer->isEqualTo("Apple") &&
                product->isEqualTo("Keyboard")) {
              vendor_ = DeviceVendor::APPLE_COMPUTER;
              product_ = DeviceProduct::APPLE_INTERNAL_KEYBOARD_TRACKPAD_0x0218;
              goto finish;
            }
          }
        }
      }

      // check parent property.
      dev = dev->getParentEntry(IORegistryEntry::getPlane(kIOServicePlane));
    }

  finish:
    IOLOG_DEBUG("HookedDevice::setVendorProduct device_:%p, vendor_:0x%04x, product_:0x%04x\n", device_, vendor_.get(), product_.get());
  }
  bool
  ListHookedConsumer::Item::replaceEventAction(void)
  {
    if (! device_) return false;

    IOHIKeyboard* kbd = OSDynamicCast(IOHIKeyboard, device_);
    if (! kbd) return false;

    KeyboardSpecialEventCallback callback = reinterpret_cast<KeyboardSpecialEventCallback>(kbd->_keyboardSpecialEventAction);
    if (callback == EventInputQueue::push_KeyboardSpecialEventCallback) return false;

    // ------------------------------------------------------------
    IOLOG_DEBUG("HookedConsumer::replaceEventAction device_:%p\n", device_);

    orig_keyboardSpecialEventAction_ = callback;
    orig_keyboardSpecialEventTarget_ = kbd->_keyboardSpecialEventTarget;

    kbd->_keyboardSpecialEventAction = reinterpret_cast<KeyboardSpecialEventAction>(EventInputQueue::push_KeyboardSpecialEventCallback);

    return true;
  }
  bool
  ListHookedConsumer::Item::restoreEventAction(void)
  {
    IOLockWrapper::ScopedLock lk(replacerestore_lock_);
    if (! lk) return false;

    if (! device_) return false;

    IOHIKeyboard* kbd = OSDynamicCast(IOHIKeyboard, device_);
    if (! kbd) return false;

    KeyboardSpecialEventCallback callback = reinterpret_cast<KeyboardSpecialEventCallback>(kbd->_keyboardSpecialEventAction);
    if (callback != EventInputQueue::push_KeyboardSpecialEventCallback) return false;

    // ----------------------------------------
    IOLOG_DEBUG("HookedConsumer::restoreEventAction device_:%p\n", device_);

    kbd->_keyboardSpecialEventAction = reinterpret_cast<KeyboardSpecialEventAction>(orig_keyboardSpecialEventAction_);

    orig_keyboardSpecialEventAction_ = NULL;
    orig_keyboardSpecialEventTarget_ = NULL;

    return true;
  }
Esempio n. 8
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) {
  GlobalLock::ScopedLock lk;
  if (!lk) return;

  Params_KeyboardEventCallBack::log(true, EventType(eventType), Flags(flags), KeyCode(key), KeyboardType(keyboardType), repeat);

  // ------------------------------------------------------------
  // Ignore unknown modifiers
  //
  // You can confirm an unknown modifier by setting key code to 255 on Seil.
  // This event also will be sent by Fn key on Leopold FC660M.
  //
  //   KeyboardEventCallback [ caught]: eventType 12, flags 0x80000000, key 0x00ff, kbdType  43, repeat = 0
  //
  // This key sends the same event at key pressing and key releasing.
  // Therefore, we cannot recognize whether key is pressed or key is released.
  // So, we have to ignore this key for PressingPhysicalKeys.
  //
  if (EventType::MODIFY == EventType(eventType)) {
    if (KeyCode(key).getModifierFlag() == ModifierFlag::ZERO) {
      IOLOG_DEBUG("An unknown modifier is pressed (KeyCode:0x%x, Flags:0x%x). Ignore it.\n", key, flags);
      return;
    }
  }

  // ------------------------------------------------------------
  KeyboardType newkeyboardtype(keyboardType);
  RemapClassManager::remap_setkeyboardtype(newkeyboardtype);

  KeyCode newkey(key);
  Flags newflags(flags);
  KeyCode::normalizeKey(newkey, newflags, EventType(eventType), newkeyboardtype);

  // ------------------------------------------------------------
  Params_KeyboardEventCallBack params(EventType(eventType),
                                      newflags,
                                      newkey,
                                      CharCode(charCode),
                                      CharSet(charSet),
                                      OrigCharCode(origCharCode),
                                      OrigCharSet(origCharSet),
                                      newkeyboardtype,
                                      repeat);

  // ------------------------------------------------------------
  IOHIKeyboard* device = OSDynamicCast(IOHIKeyboard, sender);
  if (!device) return;

  ListHookedKeyboard::Item* item = static_cast<ListHookedKeyboard::Item*>(ListHookedKeyboard::instance().get(device));
  if (!item) return;

  // ------------------------------------------------------------
  // Device Hacks

  // Drop events if "Disable an internal keyboard while external keyboards are connected" is enabled.
  if (Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_general_disable_internal_keyboard_if_external_keyboard_exsits)) {
    if (item->isInternalDevice() &&
        ListHookedKeyboard::instance().isExternalDevicesConnected()) {
      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->getDeviceIdentifier()).isEqualVendorProduct(DeviceVendor::LOGITECH, DeviceProduct::LOGITECH_CORDLESS_PRESENTER)) {
    if (params.key == KeyCode::CONTROL_L) return;
    if (params.key == KeyCode::SHIFT_L) return;
  }

  // ------------------------------------------------------------
  // NumLock Hacks
  //
  // As for some keypads, NumLock is off when it was connected.
  // We need to call setAlphaLock(true) to activate a device.
  RemapClassManager::remap_forcenumlockon(item);

  // ------------------------------------------------------------
  CommonData::setcurrent_ts(ts);

  // ------------------------------------------------------------
  // Because we handle the key repeat ourself, drop the key repeat by hardware.
  if (repeat) return;

  // ------------------------------------------------------------
  bool retainFlagStatusTemporaryCount = false;
  bool push_back = true;
  bool isSimultaneousKeyPressesTarget = true;
  enqueue_(params, retainFlagStatusTemporaryCount, item->getDeviceIdentifier(), push_back, isSimultaneousKeyPressesTarget);

  setTimer();
}
Esempio n. 9
0
void ListHookedDevice::Item::setDeviceType(void) {
  if (!device_) return;

  const char* name = nullptr;

  name = device_->getName();
  if (!name) goto finish;

  // Apple device
  if (strcmp(name, "IOHIDKeyboard") == 0 ||
      strcmp(name, "AppleADBKeyboard") == 0 ||
      strcmp(name, "IOHIDConsumer") == 0 ||
      strcmp(name, "IOHIDPointing") == 0 ||
      strcmp(name, "ApplePS2Mouse") == 0 ||
      strcmp(name, "ApplePS2Trackpad") == 0 ||
      strcmp(name, "AppleUSBGrIIITrackpad") == 0 ||
      strcmp(name, "AppleADBMouseType4") == 0) {

    deviceType_ = DeviceType::APPLE_EXTERNAL;

    // ------------------------------------------------------------
    // Judge internal device or external device.
    //
    // We judge it from a product name whether it is internal device.
    // At keyboard, we cannot use the KeyboardType,
    // because some external keyboard has the same KeyboardType as Apple internal keyboard.
    const OSString* productname = nullptr;
    productname = OSDynamicCast(OSString, device_->getProperty(kIOHIDProductKey));
    if (productname) {
      const char* pname = productname->getCStringNoCopy();
      if (pname) {
        const char* internalname = "Apple Internal ";
        if (strncmp(internalname, pname, strlen(internalname)) == 0) {
          deviceType_ = DeviceType::APPLE_INTERNAL;
        }

        const char* mikeyname = "Apple Mikey HID Driver";
        if (strcmp(mikeyname, pname) == 0) {
          deviceType_ = DeviceType::APPLE_MIKEY_HID_DRIVER;
        }
      }
    }

    goto finish;
  }

  if (strcmp(name, "ApplePS2Keyboard") == 0) {
    deviceType_ = DeviceType::APPLE_INTERNAL;
    goto finish;
  }

  // USB Overdrive
  if (strcmp(name, "OverdriveHIDKeyboard") == 0 ||
      strcmp(name, "OverdriveHIDPointer") == 0) {
    deviceType_ = DeviceType::USB_OVERDRIVE;
    goto finish;
  }

finish:
  IOLOG_DEBUG("HookedDevice::setDeviceType device_:%p, name:%s, deviceType_:%d\n",
              device_,
              name ? name : "null",
              deviceType_);
}
 ListHookedConsumer::Item::~Item(void)
 {
   IOLOG_DEBUG("ListHookedConsumer::Item::~Item()\n");
   restoreEventAction();
 }
Esempio n. 11
0
 // ----------------------------------------
 static void log(bool isCaught, Flags flags) {
   IOLOG_DEBUG("UpdateEventFlagsCallback [%7s]: flags 0x%08x\n",
               isCaught ? "caught" : "sending",
               flags.get());
 }
Esempio n. 12
0
 // ----------------------------------------
 static void log(bool isCaught, EventType eventType, Flags flags, KeyCode key, KeyboardType keyboardType, bool repeat) {
   IOLOG_DEBUG("KeyboardEventCallback [%7s]: eventType %2d, flags 0x%08x, key 0x%04x, kbdType %3d, repeat = %d\n",
               isCaught ? "caught" : "sending",
               eventType.get(), flags.get(), key.get(), keyboardType.get(), repeat);
 }
Esempio n. 13
0
 // ----------------------------------------
 static void log(bool isCaught, EventType eventType, Flags flags, ConsumerKeyCode key, unsigned int flavor, UInt64 guid, bool repeat) {
   IOLOG_DEBUG("KeyboardSpecialEventCallBack [%7s]: eventType %2d, flags 0x%08x, key 0x%04x, flavor %4d, guid %lld, repeat = %d\n",
               isCaught ? "caught" : "sending",
               eventType.get(), flags.get(), key.get(), flavor, guid, repeat);
 }
Esempio n. 14
0
ListHookedKeyboard::Item::~Item(void) {
  IOLOG_DEBUG("ListHookedKeyboard::Item::~Item()\n");
  restoreEventAction();
}
 ListHookedConsumer::Item::~Item(void)
 {
   IOLOG_DEBUG("ListHookedConsumer::Item::~Item()\n");
   restoreEventAction();
   IOLockWrapper::free(replacerestore_lock_);
 }
 ListHookedPointing::Item::~Item(void)
 {
   IOLOG_DEBUG("ListHookedPointing::Item::~Item()\n");
   restoreEventAction();
 }