void org_pqrs_driver_NoEjectDelay::stop(IOService* provider) { IOLOG_INFO("stop\n"); // ---------------------------------------- org_pqrs_NoEjectDelay::GlobalLock::terminate(); // ---------------------------------------- if (timerEventSource_) { if (workLoop_) { workLoop_->removeEventSource(timerEventSource_); } timerEventSource_->release(); timerEventSource_ = NULL; } if (workLoop_) { workLoop_->release(); workLoop_ = NULL; } // ---------------------------------------- if (notifier_hookKeyboard_) { notifier_hookKeyboard_->remove(); } if (notifier_unhookKeyboard_) { notifier_unhookKeyboard_->remove(); } if (notifier_hookEventService_) { notifier_hookEventService_->remove(); } if (notifier_unhookEventService_) { notifier_unhookEventService_->remove(); } super::stop(provider); }
// ---------------------------------------- bool org_pqrs_driver_NoEjectDelay::IOHIKeyboard_gIOMatchedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) { org_pqrs_NoEjectDelay::GlobalLock::ScopedLock lk; if (!lk) return false; // ---------------------------------------- org_pqrs_driver_NoEjectDelay* self = reinterpret_cast<org_pqrs_driver_NoEjectDelay*>(target); if (!self) return false; if (!newService) return false; // ---------------------------------------- const char* name = newService->getName(); const char* pname = getProductPropertyCStringNoCopy(newService); if (name && pname) { IOLOG_INFO("device: %s (%s)\n", pname, name); } // ---------------------------------------- for (int i = 0; i < MAXNUM_DEVICES; ++i) { if (!self->devices_[i]) { self->devices_[i] = newService; return true; } } IOLOG_WARN("There is no space for the new device. Please increase MAXNUM_DEVICES.\n"); return true; }
bool org_pqrs_driver_Seil::start(IOService* provider) { IOLOG_INFO("start\n"); bool res = super::start(provider); if (!res) { return res; } org_pqrs_Seil::GlobalLock::initialize(); notifier_hookKeyboard_ = addMatchingNotification(gIOMatchedNotification, serviceMatching("IOHIKeyboard"), org_pqrs_driver_Seil::IOHIKeyboard_gIOMatchedNotification_callback, this, nullptr, 0); if (notifier_hookKeyboard_ == nullptr) { IOLOG_ERROR("initialize_notification notifier_hookKeyboard_ == nullptr\n"); return false; } notifier_unhookKeyboard_ = addMatchingNotification(gIOTerminatedNotification, serviceMatching("IOHIKeyboard"), org_pqrs_driver_Seil::IOHIKeyboard_gIOTerminatedNotification_callback, this, nullptr, 0); if (notifier_unhookKeyboard_ == nullptr) { IOLOG_ERROR("initialize_notification notifier_unhookKeyboard_ == nullptr\n"); return false; } // Publish ourselves so clients can find us registerService(); return res; }
bool org_pqrs_driver_NoEjectDelay::start(IOService* provider) { IOLOG_INFO("start\n"); bool res = super::start(provider); if (!res) { return res; } // ---------------------------------------- org_pqrs_NoEjectDelay::GlobalLock::initialize(); // ---------------------------------------- notifier_hookKeyboard_ = addMatchingNotification(gIOMatchedNotification, serviceMatching("IOHIKeyboard"), org_pqrs_driver_NoEjectDelay::IOHIKeyboard_gIOMatchedNotification_callback, this, NULL, 0); if (notifier_hookKeyboard_ == NULL) { IOLOG_ERROR("initialize_notification notifier_hookKeyboard_ == NULL\n"); return false; } notifier_unhookKeyboard_ = addMatchingNotification(gIOTerminatedNotification, serviceMatching("IOHIKeyboard"), org_pqrs_driver_NoEjectDelay::IOHIKeyboard_gIOTerminatedNotification_callback, this, NULL, 0); if (notifier_unhookKeyboard_ == NULL) { IOLOG_ERROR("initialize_notification notifier_unhookKeyboard_ == NULL\n"); return false; } notifier_hookEventService_ = addMatchingNotification(gIOMatchedNotification, serviceMatching("IOHIDEventService"), org_pqrs_driver_NoEjectDelay::IOHIKeyboard_gIOMatchedNotification_callback, this, NULL, 0); if (notifier_hookEventService_ == NULL) { IOLOG_ERROR("initialize_notification notifier_hookEventService_ == NULL\n"); return false; } notifier_unhookEventService_ = addMatchingNotification(gIOTerminatedNotification, serviceMatching("IOHIDEventService"), org_pqrs_driver_NoEjectDelay::IOHIKeyboard_gIOTerminatedNotification_callback, this, NULL, 0); if (notifier_unhookEventService_ == NULL) { IOLOG_ERROR("initialize_notification notifier_unhookEventService_ == NULL\n"); return false; } // ---------------------------------------- workLoop_ = IOWorkLoop::workLoop(); if (!workLoop_) return false; timerEventSource_ = IOTimerEventSource::timerEventSource(this, timer_callback); if (!timerEventSource_) return false; if (workLoop_->addEventSource(timerEventSource_) != kIOReturnSuccess) return false; timerEventSource_->setTimeoutMS(TIMER_INTERVAL_MS); // ---------------------------------------- return res; }
// ---------------------------------------------------------------------- bool org_pqrs_driver_Karabiner::init(OSDictionary* dict) { IOLOG_INFO("init\n"); bool res = super::init(dict); return res; }
void org_pqrs_driver_NoEjectDelay::timer_callback(OSObject* target, IOTimerEventSource* sender) { org_pqrs_NoEjectDelay::GlobalLock::ScopedLock lk; if (! lk) return; // ---------------------------------------- org_pqrs_driver_NoEjectDelay* self = OSDynamicCast(org_pqrs_driver_NoEjectDelay, target); if (! self) return; // ---------------------------------------- // supportsF12Eject becomes true when user logged in even if supportsF12Eject is false. // Therefore, we need to overwrite this value from timer. for (int i = 0; i < MAXNUM_DEVICES; ++i) { if (! self->devices_[i]) continue; // set Eject delay. { { IOHIDConsumer* consumer = OSDynamicCast(IOHIDConsumer, self->devices_[i]); if (consumer) { // We are using private header of IOHIDConsumer. // So, we need to check "consumer->_provider is IOHIDEventService" by OSDynamicCast. IOHIDEventService* service = OSDynamicCast(IOHIDEventService, consumer->_provider); setEjectDelayMS(service); } } { IOHIDKeyboard* keyboard = OSDynamicCast(IOHIDKeyboard, self->devices_[i]); if (keyboard) { // Like above, we need to check _provider. IOHIDEventService* service = OSDynamicCast(IOHIDEventService, keyboard->_provider); setEjectDelayMS(service); } } } // disable F12Eject { IOHIKeyboard* keyboard = OSDynamicCast(IOHIKeyboard, self->devices_[i]); if (keyboard) { IOHIKeyboardMapper* mapper = OSDynamicCast(IOHIKeyboardMapper, keyboard->_keyMap); if (mapper && mapper->_reserved && mapper->_reserved->supportsF12Eject != 0) { IOLOG_INFO("Unset supportsF12Eject\n"); mapper->_reserved->supportsF12Eject = 0; } } } } if (sender) { sender->setTimeoutMS(TIMER_INTERVAL_MS); } }
// ---------------------------------------------------------------------- bool org_pqrs_driver_Seil::init(OSDictionary* dict) { IOLOG_INFO("init %s\n", ostype); bool res = super::init(dict); memset(&configuration_, 0, sizeof(configuration_)); return res; }
void RemapClass::log_allocation_count(void) { IOLOG_INFO("RemapClass::allocation_count_ %d/%d (memory usage: %d%% of %dKB)\n", allocation_count_, MAX_ALLOCATION_COUNT, allocation_count_ * 100 / MAX_ALLOCATION_COUNT, static_cast<int>(MAX_ALLOCATION_COUNT * sizeof(uint32_t) / 1024)); }
void org_pqrs_driver_NoEjectDelay::setEjectDelayMS(IOHIDEventService* service) { if (!service) return; if (!service->_reserved) return; const int DELAY = 5; if ((service->_reserved->keyboard).eject.delayMS != DELAY) { IOLOG_INFO("Set eject.delayMS\n"); (service->_reserved->keyboard).eject.delayMS = DELAY; } }
void org_pqrs_driver_Karabiner::stop(IOService* provider) { IOLOG_INFO("stop\n"); terminate_notification(); org_pqrs_Karabiner::Core::stop(); super::stop(provider); }
// ---------------------------------------------------------------------- bool org_pqrs_driver_Seil::init(OSDictionary* dict) { IOLOG_INFO("init %s\n", ostype); bool res = super::init(dict); memset(&configuration_, 0, sizeof(configuration_)); notifier_hookKeyboard_ = nullptr; notifier_unhookKeyboard_ = nullptr; return res; }
// ---------------------------------------------------------------------- bool org_pqrs_driver_NoEjectDelay::init(OSDictionary* dict) { IOLOG_INFO("init %s\n", NoEjectDelay_version); notifier_hookKeyboard_ = NULL; notifier_unhookKeyboard_ = NULL; workLoop_ = NULL; timerEventSource_ = NULL; for (int i = 0; i < MAXNUM_DEVICES; ++i) { devices_[i] = NULL; } return super::init(dict); }
void org_pqrs_driver_Seil::stop(IOService* provider) { IOLOG_INFO("stop\n"); for (int i = 0; i < MAXNUM_KEYBOARD; ++i) { hookedKeyboard_[i].terminate(); } if (notifier_hookKeyboard_) notifier_hookKeyboard_->remove(); if (notifier_unhookKeyboard_) notifier_unhookKeyboard_->remove(); org_pqrs_Seil::GlobalLock::terminate(); super::stop(provider); }
bool org_pqrs_driver_Karabiner::start(IOService* provider) { IOLOG_INFO("start\n"); bool res = super::start(provider); if (! res) return res; org_pqrs_Karabiner::Core::start(); if (! initialize_notification()) return false; // Publish ourselves so clients can find us registerService(); return res; }
// ---------------------------------------------------------------------- bool org_pqrs_driver_Seil::isTargetDevice(IOHIKeyboard* kbd) { if (!kbd) return false; // ------------------------------------------------------------ uint32_t vendorID = 0; uint32_t productID = 0; IORegistryEntry* dev = kbd; while (dev) { const OSNumber* vid = nullptr; vid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDVendorIDKey)); const OSNumber* pid = nullptr; pid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDProductIDKey)); if (vid && pid) { vendorID = vid->unsigned32BitValue(); productID = pid->unsigned32BitValue(); goto finish; } // check parent property. dev = dev->getParentEntry(IORegistryEntry::getPlane(kIOServicePlane)); } finish: enum { VENDOR_LOGITECH = 0x046d, PRODUCT_LOGITECH_G700_LASER_MOUSE = 0xc06b, }; if (vendorID == VENDOR_LOGITECH && productID == PRODUCT_LOGITECH_G700_LASER_MOUSE) { IOLOG_INFO("vendorID:0x%04x, productID:0x%04x (skipped)\n", vendorID, productID); return false; } return true; }
// ---------------------------------------------------------------------- void org_pqrs_driver_Seil::HookedKeyboard::initialize(IOHIKeyboard* p) { IOHIDKeyboard* hid = OSDynamicCast(IOHIDKeyboard, p); if (hid) { kbd_ = p; for (int i = 0; i < BRIDGE_KEY_INDEX__END__; ++i) { KeyMapIndex::Value idx = KeyMapIndex::bridgeKeyindexToValue(i); if (idx != KeyMapIndex::NONE) { originalKeyCode_[i] = hid->_usb_2_adb_keymap[idx]; } } #if 0 // Dump _usb_2_adb_keymap for (size_t i = 0; i < sizeof(hid->_usb_2_adb_keymap) / sizeof(hid->_usb_2_adb_keymap[0]); ++i) { IOLOG_INFO("%d = %d\n", static_cast<int>(i), hid->_usb_2_adb_keymap[i]); } #endif } refresh(); }
void org_pqrs_driver_NoEjectDelay::free(void) { IOLOG_INFO("free\n"); super::free(); }
void org_pqrs_driver_Karabiner::free(void) { IOLOG_INFO("free\n"); super::free(); }
void RemapClass::log_allocation_count(void) { IOLOG_INFO("RemapClass::allocation_count_ %d/%d (capacity %d%%)\n", allocation_count_, MAX_ALLOCATION_COUNT, allocation_count_ * 100 / MAX_ALLOCATION_COUNT); }
RemapClass::RemapClass(const unsigned int* initialize_vector, bool enabledvalue) : statusmessage_(NULL), enabled_(enabledvalue), is_simultaneouskeypresses_(false) { // ------------------------------------------------------------ // check parameters. // #define CHECK_INITIALIZE_VECTOR { \ if (! initialize_vector) { \ IOLOG_ERROR("RemapClass::RemapClass invalid parameter.\n"); \ return; \ } \ } CHECK_INITIALIZE_VECTOR; // -------------------- // check version unsigned int version = initialize_vector[0]; ++initialize_vector; CHECK_INITIALIZE_VECTOR; if (version != BRIDGE_REMAPCLASS_INITIALIZE_VECTOR_FORMAT_VERSION) { IOLOG_INFO("RemapClass::RemapClass version mismatch.\n"); return; } // ------------------------------------------------------------ // initialize items_ from vector unsigned int total_length = initialize_vector[0]; ++initialize_vector; CHECK_INITIALIZE_VECTOR; if (total_length == 0) return; if (allocation_count_ + total_length > MAX_ALLOCATION_COUNT) { IOLOG_ERROR("RemapClass::RemapClass too many allocation_count_.\n"); return; } allocation_count_ += total_length; // -------------------- unsigned int total_tmp = 0; for (;;) { unsigned int size = initialize_vector[0]; ++initialize_vector; ++total_tmp; CHECK_INITIALIZE_VECTOR; // ---------------------------------------- if (size > 0) { unsigned int type = initialize_vector[0]; if (BRIDGE_REMAPTYPE_NONE < type && type < BRIDGE_REMAPTYPE_END) { Item* newp = new Item(initialize_vector, size); items_.push_back(newp); if (type == BRIDGE_REMAPTYPE_SIMULTANEOUSKEYPRESSES) { is_simultaneouskeypresses_ = true; } } else if (BRIDGE_FILTERTYPE_NONE < type && type < BRIDGE_FILTERTYPE_END) { if (items_.size() == 0) { IOLOG_ERROR("RemapClass::RemapClass invalid filter (%d).\n", type); return; } Item* p = items_.back(); if (p) { p->append_filter(initialize_vector, size); } } else if (type == BRIDGE_STATUSMESSAGE) { if (statusmessage_) { delete[] statusmessage_; } statusmessage_ = new char[size]; if (statusmessage_) { for (size_t i = 0; i < size - 1; ++i) { statusmessage_[i] = initialize_vector[i + 1]; } statusmessage_[size - 1] = '\0'; } } else if (type == BRIDGE_VK_CONFIG) { if (size == 5) { unsigned int keycode_toggle = initialize_vector[1]; unsigned int keycode_force_on = initialize_vector[2]; unsigned int keycode_force_off = initialize_vector[3]; unsigned int keycode_sync_keydownup = initialize_vector[4]; Handle_VK_CONFIG::add_item(this, keycode_toggle, keycode_force_on, keycode_force_off, keycode_sync_keydownup); } } else { IOLOG_ERROR("RemapClass::RemapClass unknown type:%d.\n", type); return; } initialize_vector += size; total_tmp += size; CHECK_INITIALIZE_VECTOR; } // ---------------------------------------- if (total_tmp == total_length) return; if (total_tmp > total_length) { IOLOG_ERROR("RemapClass::RemapClass invalid initialize_vector. (total_length:%d, total_tmp:%d)\n", total_length, total_tmp); return; } } }
// ====================================================================== void EventInputQueue::fire_timer_callback(OSObject* /*notuse_owner*/, IOTimerEventSource* /*notuse_sender*/) { // IOLOG_DEVEL("EventInputQueue::fire queue_.size = %d\n", static_cast<int>(queue_.size())); // ------------------------------------------------------------ // Ignore key bouncing (chattering). if (Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_general_ignore_bouncing_events)) { retry: for (Item* p = static_cast<Item*>(queue_.safe_front()); p; p = static_cast<Item*>(p->getnext())) { // Search key up, key down event. bool iskeydown; if (p->getParamsBase().iskeydown(iskeydown) && !iskeydown) { Item* keyUpEvent = p; FromEvent fromEvent(p->getParamsBase()); for (Item* q = static_cast<Item*>(p->getnext()); q; q = static_cast<Item*>(q->getnext())) { if (fromEvent.isTargetUpEvent(q->getParamsBase())) { break; } else if (fromEvent.isTargetDownEvent(q->getParamsBase())) { Item* keyDownEvent = q; uint32_t ms1 = (keyUpEvent->ic).getmillisec(); uint32_t ms2 = (keyDownEvent->ic).getmillisec(); uint32_t interval = ms1 - ms2; uint32_t threshold = 0; switch (fromEvent.getType()) { case FromEvent::Type::KEY: case FromEvent::Type::CONSUMER_KEY: threshold = Config::get_ignore_bouncing_threshold_for_keyboard(); break; case FromEvent::Type::POINTING_BUTTON: threshold = Config::get_ignore_bouncing_threshold_for_mice(); break; case FromEvent::Type::NONE: break; } if (interval < threshold) { IOLOG_INFO("Bouncing events are removed. (interval: %d, threshold: %d)\n", interval, threshold); queue_.erase_and_delete(keyUpEvent); queue_.erase_and_delete(keyDownEvent); goto retry; } else { IOLOG_INFO("Bouncing events? (interval: %d, threshold: %d)\n", interval, threshold); } } } } } } // ------------------------------------------------------------ // handle SimultaneousKeyPresses while (true) { Item* front = static_cast<Item*>(queue_.safe_front()); if (!front) return; // ------------------------------------------------------------ // clear temporary_count_ // // Don't call FlagStatus::set(key, flags) here. // If SimultaneousKeyPresses is enabled, keys may be dropped. // For example, Shift_L+Shift_R to Space is enabled, Shift_L and Shift_R may be dropped. // If we call FlagStatus::set(key, flags) here, dropped keys are kept as pushed status. // So, call FlagStatus::set(key, flags) after EventInputQueue. // ------------------------------------------------------------ if (!front->retainFlagStatusTemporaryCount) { FlagStatus::globalFlagStatus().set(); } CommonData::setcurrent_deviceIdentifier(front->deviceIdentifier); { auto params = (front->getParamsBase()).get_Params_KeyboardEventCallBack(); if (params) { CommonData::setcurrent_keyboardType(params->keyboardType); } } bool iskeydown = false; if (!(front->getParamsBase()).iskeydown(iskeydown)) { iskeydown = true; } if (!RemapClassManager::remap_simultaneouskeypresses(iskeydown)) { break; } } // ------------------------------------------------------------ // handle BlockUntilKeyUp // // Note: // We need to handle BlockUntilKeyUp after SimultaneousKeyPresses // in order to avoid unintended modification by SimultaneousKeyPresses. bool needToFire = BlockUntilKeyUpHander::doBlockUntilKeyUp(); if (needToFire) { doFire(); } setTimer(); }
void org_pqrs_driver_Seil::free(void) { IOLOG_INFO("free\n"); super::free(); }