From e73d53371d97b6c04ae57e2fe73bc10a6010b45c Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 3 Feb 2023 13:12:35 -0800 Subject: [PATCH] Use Trackpoint logic in VoodooInput (#161) --- VoodooRMI/Functions/F11.cpp | 10 +- VoodooRMI/Functions/F11.hpp | 1 - VoodooRMI/Functions/F12.cpp | 10 +- VoodooRMI/Functions/F12.hpp | 1 - VoodooRMI/Functions/Input/RMIFunction.hpp | 8 +- VoodooRMI/Functions/Input/RMIGPIOFunction.cpp | 8 +- .../Functions/Input/RMITrackpadFunction.cpp | 55 ++++------- .../Functions/Input/RMITrackpadFunction.hpp | 49 ++-------- .../Functions/Input/RMITrackpointFunction.cpp | 98 ++----------------- .../Functions/Input/RMITrackpointFunction.hpp | 8 +- VoodooRMI/RMIBus.cpp | 76 ++++++++++++++ VoodooRMI/RMIBus.hpp | 12 ++- VoodooRMI/RMIBusPDT.cpp | 2 +- 13 files changed, 140 insertions(+), 198 deletions(-) diff --git a/VoodooRMI/Functions/F11.cpp b/VoodooRMI/Functions/F11.cpp index cf39f27..dcd29ff 100644 --- a/VoodooRMI/Functions/F11.cpp +++ b/VoodooRMI/Functions/F11.cpp @@ -560,6 +560,7 @@ int F11::rmi_f11_get_query_parameters(f11_2d_sensor_queries *sensor_query, int F11::rmi_f11_initialize() { + struct Rmi2DSensorData sensorSize; UInt8 query_offset, buf; UInt16 query_base_addr, control_base_addr; UInt16 max_x_pos, max_y_pos; @@ -594,8 +595,8 @@ int F11::rmi_f11_initialize() query_offset += rc; if (sens_query.has_physical_props) { - x_mm = sens_query.x_sensor_size_mm; - y_mm = sens_query.y_sensor_size_mm; + sensorSize.sizeX = sens_query.x_sensor_size_mm; + sensorSize.sizeY = sens_query.y_sensor_size_mm; } else { IOLogError("No size data from Device."); return -ENODEV; @@ -620,8 +621,9 @@ int F11::rmi_f11_initialize() return rc; } - max_x = max_x_pos; - max_y = max_y_pos; + sensorSize.maxX = max_x_pos; + sensorSize.maxY = max_y_pos; + setData(sensorSize); rc = f11_2d_construct_data(); if (rc < 0) { diff --git a/VoodooRMI/Functions/F11.hpp b/VoodooRMI/Functions/F11.hpp index a88d802..9af8c6f 100644 --- a/VoodooRMI/Functions/F11.hpp +++ b/VoodooRMI/Functions/F11.hpp @@ -533,7 +533,6 @@ class F11 : public RMITrackpadFunction { size_t attn_size; struct f11_2d_sensor_queries sens_query; struct f11_2d_data data_2d; - struct rmi_2d_sensor_platform_data sensor_pdata; unsigned long *abs_mask; unsigned long *rel_mask; diff --git a/VoodooRMI/Functions/F12.cpp b/VoodooRMI/Functions/F12.cpp index 12edb77..58cbbb0 100644 --- a/VoodooRMI/Functions/F12.cpp +++ b/VoodooRMI/Functions/F12.cpp @@ -191,6 +191,7 @@ IOReturn F12::config() int F12::rmi_f12_read_sensor_tuning() { const rmi_register_desc_item *item; + struct Rmi2DSensorData sensorSize; int ret; int offset; UInt8 buf[15]; @@ -219,8 +220,8 @@ int F12::rmi_f12_read_sensor_tuning() offset = 0; if (rmi_register_desc_has_subpacket(item, 0)) { - max_x = (buf[offset + 1] << 8) | buf[offset]; - max_y = (buf[offset + 3] << 8) | buf[offset + 2]; + sensorSize.maxX = (buf[offset + 1] << 8) | buf[offset]; + sensorSize.maxY = (buf[offset + 3] << 8) | buf[offset + 2]; offset += 4; } else { IOLogError("F12 - No size register"); @@ -259,8 +260,9 @@ int F12::rmi_f12_read_sensor_tuning() if (rmi_register_desc_has_subpacket(item, 4)) offset += 1; - x_mm = (pitch_x * rx_receivers) >> 12; - y_mm = (pitch_y * tx_receivers) >> 12; + sensorSize.sizeX = (pitch_x * rx_receivers) >> 12; + sensorSize.sizeY = (pitch_y * tx_receivers) >> 12; + setData(sensorSize); return 0; } diff --git a/VoodooRMI/Functions/F12.hpp b/VoodooRMI/Functions/F12.hpp index f996b7e..d6d011e 100644 --- a/VoodooRMI/Functions/F12.hpp +++ b/VoodooRMI/Functions/F12.hpp @@ -74,7 +74,6 @@ class F12 : public RMITrackpadFunction { UInt8 *data_pkt; size_t pkt_size; size_t attn_size; - struct rmi_2d_sensor_platform_data sensor_pdata; bool has_dribble; rmi_register_descriptor query_reg_desc; diff --git a/VoodooRMI/Functions/Input/RMIFunction.hpp b/VoodooRMI/Functions/Input/RMIFunction.hpp index 321ab2f..74e3a94 100644 --- a/VoodooRMI/Functions/Input/RMIFunction.hpp +++ b/VoodooRMI/Functions/Input/RMIFunction.hpp @@ -64,8 +64,12 @@ class RMIFunction : public IOService { protected: // Useful functions to talk to RMI4 devicce - inline const IOService *getVoodooInput() const { return bus->getVoodooInput(); } - inline void setVoodooInput(IOService *service) { bus->setVoodooInput(service); } + inline void sendVoodooInputPacket(UInt32 msg, void *packet) { + IOService *vi = bus->getVoodooInput(); + if (vi != nullptr) { + vi->message(msg, bus, packet); + } + } inline const RmiGpioData &getGPIOData() const { return bus->getGPIOData(); } inline const RmiConfiguration &getConfiguration() const { return bus->getConfiguration(); } inline IOReturn readByte(UInt16 addr, UInt8 *buf) const { return bus->read(addr, buf); } diff --git a/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp b/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp index 03bd1dd..9f1c2e7 100644 --- a/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp +++ b/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp @@ -111,7 +111,7 @@ void RMIGPIOFunction::attention() void RMIGPIOFunction::reportButton() { - RelativePointerEvent relativeEvent {}; + TrackpointReport relativeEvent {}; unsigned int mask, trackpointBtns = 0, btns = 0; unsigned int reg_num, bit_num; UInt16 key_code; @@ -149,16 +149,14 @@ void RMIGPIOFunction::reportButton() } } - const IOService *voodooInputInstance = getVoodooInput(); - if (numButtons > 1 && voodooInputInstance) { + if (numButtons > 1) { AbsoluteTime timestamp; clock_get_uptime(×tamp); relativeEvent.dx = relativeEvent.dy = 0; relativeEvent.buttons = btns; relativeEvent.timestamp = timestamp; - - messageClient(kIOMessageVoodooTrackpointRelativePointer, const_cast(voodooInputInstance), &relativeEvent, sizeof(RelativePointerEvent)); + sendVoodooInputPacket(kIOMessageVoodooTrackpointRelativePointer, &relativeEvent); } if (hasTrackpointButtons) { diff --git a/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp b/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp index 4b69e3b..fe704e5 100644 --- a/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp +++ b/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp @@ -29,6 +29,14 @@ static void fillZone (RMI2DSensorZone *zone, int min_x, int min_y, int max_x, in zone->y_max = max_y; } +void RMITrackpadFunction::setData(const Rmi2DSensorData &data) { + this->data = data; +} + +const Rmi2DSensorData &RMITrackpadFunction::getData() const { + return data; +} + bool RMITrackpadFunction::start(IOService *provider) { memset(freeFingerTypes, true, sizeof(freeFingerTypes)); @@ -39,9 +47,9 @@ bool RMITrackpadFunction::start(IOService *provider) } const RmiConfiguration &conf = getConfiguration(); - const int palmRejectWidth = max_x * cfgToPercent(conf.palmRejectionWidth); - const int palmRejectHeight = max_y * cfgToPercent(conf.palmRejectionHeight); - const int trackpointRejectHeight = max_y * cfgToPercent(conf.palmRejectionHeightTrackpoint); + const int palmRejectWidth = data.maxX * cfgToPercent(conf.palmRejectionWidth); + const int palmRejectHeight = data.maxY * cfgToPercent(conf.palmRejectionHeight); + const int trackpointRejectHeight = data.maxY * cfgToPercent(conf.palmRejectionHeightTrackpoint); /* * Calculate reject zones. @@ -56,24 +64,16 @@ bool RMITrackpadFunction::start(IOService *provider) // Top right fillZone(&rejectZones[1], - max_x - palmRejectWidth, 0, - max_x, palmRejectHeight); + data.maxX - palmRejectWidth, 0, + data.maxX, palmRejectHeight); // Top band for trackpoint and buttons fillZone(&rejectZones[2], 0, 0, - max_x, trackpointRejectHeight); - - setProperty(VOODOO_INPUT_LOGICAL_MAX_X_KEY, max_x, 16); - setProperty(VOODOO_INPUT_LOGICAL_MAX_Y_KEY, max_y, 16); - // Need to be in 0.01mm units - setProperty(VOODOO_INPUT_PHYSICAL_MAX_X_KEY, x_mm * 100, 16); - setProperty(VOODOO_INPUT_PHYSICAL_MAX_Y_KEY, y_mm * 100, 16); - setProperty(VOODOO_INPUT_TRANSFORM_KEY, 0ull, 32); + data.maxX, trackpointRejectHeight); // VoodooPS2 keyboard notifs setProperty("RM,deliverNotifications", kOSBooleanTrue); - setProperty("VoodooInputSupported", kOSBooleanTrue); for (int i = 0; i < VOODOO_INPUT_MAX_TRANSDUCERS; i++) { auto& transducer = inputEvent.transducers[i]; @@ -85,27 +85,6 @@ bool RMITrackpadFunction::start(IOService *provider) return super::start(provider); } -bool RMITrackpadFunction::handleOpen(IOService *forClient, IOOptionBits options, void *arg) -{ - if (forClient && forClient->getProperty(VOODOO_INPUT_IDENTIFIER) - && super::handleOpen(forClient, options, arg)) { - voodooInputInstance = forClient; - setVoodooInput(voodooInputInstance); - return true; - } - - return false; -} - -void RMITrackpadFunction::handleClose(IOService *forClient, IOOptionBits options) -{ - if (forClient && forClient == voodooInputInstance) { - setVoodooInput(voodooInputInstance); - voodooInputInstance = nullptr; - super::handleClose(forClient, options); - } -} - IOReturn RMITrackpadFunction::message(UInt32 type, IOService *provider, void *argument) { switch (type) @@ -139,7 +118,7 @@ IOReturn RMITrackpadFunction::message(UInt32 type, IOService *provider, void *ar bool RMITrackpadFunction::shouldDiscardReport(AbsoluteTime timestamp) { - return !trackpadEnable || voodooInputInstance == nullptr; + return !trackpadEnable; } // Returns zone that finger is in (or 0 if not in a zone) @@ -206,7 +185,7 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report) transducer.timestamp = report->timestamp; transducer.currentCoordinates.x = obj.x; - transducer.currentCoordinates.y = max_y - obj.y; + transducer.currentCoordinates.y = data.maxY - obj.y; int deltaWidth = abs(obj.wx - obj.wy); @@ -305,7 +284,7 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report) inputEvent.contact_count = reportIdx; inputEvent.timestamp = report->timestamp; - messageClient(kIOMessageVoodooInputMessage, voodooInputInstance, &inputEvent, sizeof(VoodooInputEvent)); + sendVoodooInputPacket(kIOMessageVoodooInputMessage, &inputEvent); for (int i = 0; i < VOODOO_INPUT_MAX_TRANSDUCERS; i++) { inputEvent.transducers[i].isTransducerActive = false; } diff --git a/VoodooRMI/Functions/Input/RMITrackpadFunction.hpp b/VoodooRMI/Functions/Input/RMITrackpadFunction.hpp index eedb9ab..b3939ec 100644 --- a/VoodooRMI/Functions/Input/RMITrackpadFunction.hpp +++ b/VoodooRMI/Functions/Input/RMITrackpadFunction.hpp @@ -35,36 +35,11 @@ enum finger_state { RMI_FINGER_FORCE_TOUCH, // Force touch }; -/** - * struct rmi_2d_sensor_data - overrides defaults for a 2D sensor. - * @axis_align - provides axis alignment overrides (see above). - * @sensor_type - Forces the driver to treat the sensor as an indirect - * pointing device (trackpad) rather than a direct pointing device - * (touchscreen). This is useful when F11_2D_QUERY14 register is not - * available. - * @disable_report_mask - Force data to not be reported even if it is supported - * by the firware. - * @topbuttonpad - Used with the "5 buttons trackpads" found on the Lenovo 40 - * series - * @kernel_tracking - most moderns RMI f11 firmwares implement Multifinger - * Type B protocol. However, there are some corner cases where the user - * triggers some jumps by tapping with two fingers on the trackpad. - * Use this setting and dmax to filter out these jumps. - * Also, when using an old sensor using MF Type A behavior, set to true to - * report an actual MT protocol B. - * @dmax - the maximum distance (in sensor units) the kernel tracking allows two - * distincts fingers to be considered the same. - */ -struct rmi_2d_sensor_platform_data { - int x_mm; - int y_mm; - int disable_report_mask; - UInt16 rezero_wait; - bool topbuttonpad; - bool kernel_tracking; - int dmax; - int dribble; - int palm_detect; +struct Rmi2DSensorData { + UInt16 sizeX; + UInt16 sizeY; + UInt16 maxX; + UInt16 maxY; }; struct rmi_2d_sensor_abs_object { @@ -102,29 +77,23 @@ class RMITrackpadFunction : public RMIFunction { OSDeclareDefaultStructors(RMITrackpadFunction) public: bool start(IOService *provider) override; - bool handleOpen(IOService *forClient, IOOptionBits options, void *arg) override; - void handleClose(IOService *forClient, IOOptionBits options) override; IOReturn message(UInt32 type, IOService *provider, void *argument = 0) override; -protected: - UInt16 min_x{0}; - UInt16 min_y{0}; - UInt16 max_x; - UInt16 max_y; - UInt8 x_mm; - UInt8 y_mm; + const Rmi2DSensorData &getData() const; +protected: UInt8 report_abs {0}; UInt8 report_rel {0}; UInt8 nbr_fingers; - IOService *voodooInputInstance {nullptr}; void handleReport(RMI2DSensorReport *report); bool shouldDiscardReport(AbsoluteTime timestamp); + void setData(const Rmi2DSensorData &data); private: VoodooInputEvent inputEvent {}; RMI2DSensorZone rejectZones[3]; + Rmi2DSensorData data; bool freeFingerTypes[kMT2FingerTypeCount]; finger_state fingerState[MAX_FINGERS]; diff --git a/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp b/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp index 104bf04..bafc8f3 100644 --- a/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp +++ b/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp @@ -8,104 +8,22 @@ OSDefineMetaClassAndStructors(RMITrackpointFunction, RMIFunction) -#define MIDDLE_MOUSE_MASK 0x04 - -bool RMITrackpointFunction::shouldDiscardReport() { - return getVoodooInput() != nullptr; -} - void RMITrackpointFunction::handleReport(RMITrackpointReport *report) { AbsoluteTime timestamp; clock_get_uptime(×tamp); - SInt32 dx = report->dx; - SInt32 dy = report->dy; - UInt32 buttons = report->buttons | overwrite_buttons; - - const RmiConfiguration &conf = getConfiguration(); + TrackpointReport trackpointReport; + trackpointReport.dx = report->dx; + trackpointReport.dy = report->dy; + trackpointReport.buttons = report->buttons | overwrite_buttons; + trackpointReport.timestamp = timestamp; - // The highest dx/dy is lowered by subtracting by trackpointDeadzone. - // This however does allows values below the deadzone value to still be sent, preserving control in the lower end - - dx -= signum(dx) * min(abs(dx), conf.trackpointDeadzone); - dy -= signum(dy) * min(abs(dy), conf.trackpointDeadzone); - - // For middle button, we do not actually tell macOS it's been pressed until it's been released and we didn't scroll - // We first say that it's been pressed internally - but if we scroll at all, then instead we say we scroll - if (buttons & MIDDLE_MOUSE_MASK && !isScrolling) { - if (dx || dy) { - isScrolling = true; - middlePressed = false; - } else { - middlePressed = true; - } - } - - IOService *voodooInputInstance = const_cast(getVoodooInput()); - - // When middle button is released, if we registered a middle press w/o scrolling, send middle click as a seperate packet - // Otherwise just turn scrolling off and remove middle buttons from packet - if (!(buttons & MIDDLE_MOUSE_MASK)) { - if (middlePressed) { - dispatchPointerEvent(voodooInputInstance, dx, dy, MIDDLE_MOUSE_MASK, timestamp); - } - - middlePressed = false; - isScrolling = false; - } - - buttons &= ~MIDDLE_MOUSE_MASK; - - // Must multiply first then divide so we don't multiply by zero - if (isScrolling) { - SInt32 scrollY = (SInt32)((SInt64)-dy * conf.trackpointScrollYMult / DEFAULT_MULT); - SInt32 scrollX = (SInt32)((SInt64)-dx * conf.trackpointScrollXMult / DEFAULT_MULT); - - dispatchScrollEvent(voodooInputInstance, scrollY, scrollX, timestamp); - } else { - SInt32 mulDx = (SInt32)((SInt64)dx * conf.trackpointMult / DEFAULT_MULT); - SInt32 mulDy = (SInt32)((SInt64)dy * conf.trackpointMult / DEFAULT_MULT); - - dispatchPointerEvent(voodooInputInstance, mulDx, mulDy, buttons, timestamp); - } - - if (dx || dy) { + sendVoodooInputPacket(kIOMessageVoodooTrackpointMessage, &trackpointReport); + if (report->dx || report->dy) { notify(kHandleRMITrackpoint); } - IOLogDebug("Dx: %d Dy : %d, Buttons: %d", dx, dy, buttons); -} - -int RMITrackpointFunction::signum(int value) -{ - if (value > 0) return 1; - if (value < 0) return -1; - return 0; -} - -void RMITrackpointFunction::dispatchScrollEvent(IOService *voodooInputInstance, - short delta1, - short delta2, - AbsoluteTime timestamp) { - scrollEvent.deltaAxis1 = delta1; - scrollEvent.deltaAxis2 = delta2; - scrollEvent.deltaAxis3 = 0; // Never used - scrollEvent.timestamp = timestamp; - - messageClient(kIOMessageVoodooTrackpointScrollWheel, voodooInputInstance, &scrollEvent, sizeof(ScrollWheelEvent)); -} - -void RMITrackpointFunction::dispatchPointerEvent(IOService *voodooInputInstance, - int dx, - int dy, - int buttons, - AbsoluteTime timestamp) { - relativeEvent.dx = dx; - relativeEvent.dy = dy; - relativeEvent.buttons = buttons; - relativeEvent.timestamp = timestamp; - - messageClient(kIOMessageVoodooTrackpointRelativePointer, voodooInputInstance, &relativeEvent, sizeof(RelativePointerEvent)); + IOLogDebug("Dx: %d Dy : %d, Buttons: %d", report->dx, report->dy, report->buttons); } IOReturn RMITrackpointFunction::message(UInt32 type, IOService *provider, void *argument) { diff --git a/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp b/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp index ab3ce94..40ebef5 100644 --- a/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp +++ b/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp @@ -16,16 +16,10 @@ struct RMITrackpointReport { class RMITrackpointFunction : public RMIFunction { OSDeclareDefaultStructors(RMITrackpointFunction) - - bool shouldDiscardReport(); - void handleReport(RMITrackpointReport *report); + void handleReport(RMITrackpointReport *report); IOReturn message(UInt32 type, IOService *provider, void *argument = 0) override; - private: - RelativePointerEvent relativeEvent {}; - ScrollWheelEvent scrollEvent {}; - // Used when sending buttons from other functions RMITrackpointReport emptyReport {}; diff --git a/VoodooRMI/RMIBus.cpp b/VoodooRMI/RMIBus.cpp index a94ebe7..b045bb0 100644 --- a/VoodooRMI/RMIBus.cpp +++ b/VoodooRMI/RMIBus.cpp @@ -6,10 +6,12 @@ #include "RMIBus.hpp" #include "RMIFunction.hpp" +#include "RMITrackpadFunction.hpp" #include "RMIConfiguration.hpp" #include "RMILogging.h" #include "RMIMessages.h" #include "F01.hpp" +#include "VoodooInputMessages.h" OSDefineMetaClassAndStructors(RMIBus, IOService) OSDefineMetaClassAndStructors(RMITransport, IOService) @@ -87,6 +89,7 @@ bool RMIBus::start(IOService *provider) { OSSafeReleaseNULL(config); } + publishVoodooInputProperties(); registerService(); return true; err: @@ -212,6 +215,7 @@ bool RMIBus::willTerminate(IOService *provider, IOOptionBits options) { IOReturn RMIBus::setProperties(OSObject *properties) { commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &RMIBus::updateConfiguration), OSDynamicCast(OSDictionary, properties)); + publishVoodooInputProperties(); return kIOReturnSuccess; } @@ -282,3 +286,75 @@ IOReturn RMIBus::rmiEnableSensor() { OSSafeReleaseNULL(iter); return controlFunction->setIRQs(); } + +// MARK: VoodooInput + +void RMIBus::publishVoodooInputProperties() { + OSNumber *value; + + if (trackpadFunction == nullptr) { + // VoodooInput requires trackpad properties to exist to attach + // Don't bother if there is no trackpad + return; + } + + const Rmi2DSensorData &trackpadData = trackpadFunction->getData(); + + setProperty(VOODOO_INPUT_LOGICAL_MAX_X_KEY, trackpadData.maxX, 16); + setProperty(VOODOO_INPUT_LOGICAL_MAX_Y_KEY, trackpadData.maxY, 16); + // Need to be in 0.01mm units + setProperty(VOODOO_INPUT_PHYSICAL_MAX_X_KEY, trackpadData.sizeX * 100, 16); + setProperty(VOODOO_INPUT_PHYSICAL_MAX_Y_KEY, trackpadData.sizeY * 100, 16); + setProperty(VOODOO_INPUT_TRANSFORM_KEY, 0ull, 32); + + if (trackpointFunction != nullptr) { + OSDictionary *trackpoint = OSDictionary::withCapacity(5); + if (trackpoint == nullptr) + return; + + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_DEADZONE, conf.trackpointDeadzone, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_BTN_CNT, 3, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_MOUSE_MULT_X, conf.trackpointMult, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_MOUSE_MULT_Y, conf.trackpointMult, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_MOUSE_DIV_X, DEFAULT_MULT, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_MOUSE_DIV_Y, DEFAULT_MULT, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_SCROLL_MULT_X, conf.trackpointScrollXMult, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_SCROLL_MULT_Y, conf.trackpointScrollYMult, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_SCROLL_DIV_X, DEFAULT_MULT, 32); + setPropertyNumber(trackpoint, VOODOO_TRACKPOINT_SCROLL_DIV_Y, DEFAULT_MULT, 32); + setProperty(VOODOO_TRACKPOINT_KEY, trackpoint); + OSSafeReleaseNULL(trackpoint); + } + + setProperty("VoodooInputSupported", kOSBooleanTrue); + messageClient(kIOMessageVoodooTrackpointUpdatePropertiesNotification, voodooInputInstance); +} + +bool RMIBus::handleOpen(IOService *forClient, IOOptionBits options, void *arg) { + if (voodooInputInstance != nullptr) { + // Already opened + return false; + } + + if (forClient != nullptr && forClient->getProperty(VOODOO_INPUT_IDENTIFIER)) { + voodooInputInstance = forClient; + voodooInputInstance->retain(); + return true; + } + + return false; +} + +void RMIBus::handleClose(IOService *forClient, IOOptionBits options) { + if (forClient == voodooInputInstance && forClient != nullptr) { + OSSafeReleaseNULL(voodooInputInstance); + } +} + +bool RMIBus::handleIsOpen(const IOService *forClient) const { + if (forClient == nullptr) { + return voodooInputInstance != nullptr; + } else { + return voodooInputInstance == forClient; + } +} diff --git a/VoodooRMI/RMIBus.hpp b/VoodooRMI/RMIBus.hpp index 66eda53..e8e9217 100644 --- a/VoodooRMI/RMIBus.hpp +++ b/VoodooRMI/RMIBus.hpp @@ -21,6 +21,7 @@ struct RmiPdtEntry; class F01; +class RMITrackpadFunction; class RMIBus : public IOService { OSDeclareDefaultStructors(RMIBus); @@ -32,6 +33,10 @@ class RMIBus : public IOService { virtual bool willTerminate(IOService *provider, IOOptionBits options) override; virtual void free() override; + virtual bool handleOpen(IOService *forClient, IOOptionBits options, void *arg) override; + virtual void handleClose(IOService *forClient, IOOptionBits options) override; + virtual bool handleIsOpen(const IOService *forClient) const override; + IOReturn message(UInt32 type, IOService *provider, void *argument = 0) override; IOReturn setProperties(OSObject* properties) override; @@ -56,10 +61,6 @@ class RMIBus : public IOService { return voodooInputInstance; } - inline void setVoodooInput(IOService *service) { - voodooInputInstance = service; - } - inline const RmiGpioData &getGPIOData() const { return gpio; } @@ -75,13 +76,14 @@ class RMIBus : public IOService { IOService *voodooInputInstance {nullptr}; OSSet *functions {nullptr}; + void publishVoodooInputProperties(); void getGPIOData(OSDictionary *dict); void updateConfiguration(OSDictionary *dictionary); RmiConfiguration conf {}; RmiGpioData gpio {}; RMITransport *transport {nullptr}; - IOService *trackpadFunction {nullptr}; + RMITrackpadFunction *trackpadFunction {nullptr}; IOService *trackpointFunction {nullptr}; F01 *controlFunction {nullptr}; diff --git a/VoodooRMI/RMIBusPDT.cpp b/VoodooRMI/RMIBusPDT.cpp index 4aa3a03..43b9151 100644 --- a/VoodooRMI/RMIBusPDT.cpp +++ b/VoodooRMI/RMIBusPDT.cpp @@ -185,7 +185,7 @@ IOReturn RMIBus::rmiHandlePdtEntry(RmiPdtEntry &entry) { } if (OSDynamicCast(RMITrackpadFunction, function)) { - trackpadFunction = function; + trackpadFunction = OSDynamicCast(RMITrackpadFunction, function); } else if (OSDynamicCast(RMITrackpointFunction, function)) { trackpointFunction = function; } else if (entry.function == 0x01) {