diff --git a/VoodooRMI/Functions/F01.cpp b/VoodooRMI/Functions/F01.cpp index 16a1c98..f5647de 100644 --- a/VoodooRMI/Functions/F01.cpp +++ b/VoodooRMI/Functions/F01.cpp @@ -373,17 +373,12 @@ int F01::rmi_f01_resume() return error; } -void F01::attention() +void F01::attention([[maybe_unused]] AbsoluteTime time, UInt8 *data[], size_t *size) { - int error; UInt8 device_status = 0; - error = readByte(getDataAddr(), &device_status); - - if (error) { - IOLogError("F01: Failed to read device status: %d", error); + if (!getInputData(&device_status, sizeof(device_status), data, size)) return; - } if (RMI_F01_STATUS_BOOTLOADER(device_status)) IOLogError("Device in bootloader mode, please update firmware"); diff --git a/VoodooRMI/Functions/F01.hpp b/VoodooRMI/Functions/F01.hpp index 98c805e..04bec0b 100644 --- a/VoodooRMI/Functions/F01.hpp +++ b/VoodooRMI/Functions/F01.hpp @@ -125,7 +125,7 @@ class F01 : public RMIFunction { public: bool attach(IOService *provider) override; IOReturn config() override; - void attention() override; + void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override; IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) override; diff --git a/VoodooRMI/Functions/F03.cpp b/VoodooRMI/Functions/F03.cpp index 7b8ff87..116a25d 100644 --- a/VoodooRMI/Functions/F03.cpp +++ b/VoodooRMI/Functions/F03.cpp @@ -155,7 +155,7 @@ int F03::rmi_f03_pt_write(unsigned char val) return error; } -void F03::handlePacket(UInt8 *packet) +void F03::handlePacket(AbsoluteTime time, UInt8 *packet) { RMITrackpointReport report; // Trackpoint isn't initialized! @@ -172,6 +172,7 @@ void F03::handlePacket(UInt8 *packet) timer->enable(); } + report.timestamp = time; report.buttons = (packet[0] & 0x7); report.dx = ((packet[0] & 0x10) ? 0xffffff00 : 0) | packet[1]; report.dy = -(((packet[0] & 0x20) ? 0xffffff00 : 0) | packet[2]); @@ -199,26 +200,21 @@ IOReturn F03::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevi return kIOPMAckImplied; } -void F03::attention() +void F03::attention(AbsoluteTime time, UInt8 *data[], size_t *size) { - const UInt16 data_addr = getDataAddr() + RMI_F03_OB_OFFSET; - const UInt8 ob_len = rx_queue_length * RMI_F03_OB_SIZE; - UInt8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE]; + const UInt8 ob_len = RMI_F03_OB_OFFSET + (rx_queue_length * RMI_F03_OB_SIZE); + UInt8 obs[RMI_F03_OB_OFFSET + (RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE)]; - int error = readBlock(data_addr, obs, ob_len); - if (error) { - IOLogError("F03 - Failed to read output buffers: %d", error); + if (!getInputData(obs, ob_len, data, size)) return; - } - for (int i = 0; i < ob_len; i += RMI_F03_OB_SIZE) { + for (int i = RMI_F03_OB_OFFSET; i < ob_len; i += RMI_F03_OB_SIZE) { UInt8 ob_status = obs[i]; UInt8 ob_data = obs[i + RMI_F03_OB_DATA_OFFSET]; if (!(ob_status & RMI_F03_RX_DATA_OFB)) continue; - IOLogDebug("F03 - Recieved data over PS2: %x", ob_data); if (ob_status & RMI_F03_OB_FLAG_TIMEOUT) { IOLogDebug("F03 Timeout Flag"); @@ -229,7 +225,7 @@ void F03::attention() continue; } - handleByte(ob_data); + handleByte(time, ob_data); } } @@ -296,7 +292,7 @@ void F03::initPS2Interrupt(OSObject *owner, IOTimerEventSource *timer) timer->disable(); } -void F03::handleByte(UInt8 byte) +void F03::handleByte(AbsoluteTime time, UInt8 byte) { if (!cmdcnt && !flags) { // Wait for start of packets @@ -306,7 +302,7 @@ void F03::handleByte(UInt8 byte) databuf[index++] = byte; if (index == 3) - handlePacket(databuf); + handlePacket(time, databuf); return; } diff --git a/VoodooRMI/Functions/F03.hpp b/VoodooRMI/Functions/F03.hpp index 719a5f6..38ad054 100644 --- a/VoodooRMI/Functions/F03.hpp +++ b/VoodooRMI/Functions/F03.hpp @@ -24,7 +24,7 @@ class F03 : public RMITrackpointFunction { bool start(IOService *provider) override; void stop(IOService *provider) override; IOReturn setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) override; - void attention() override; + void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override; private: IOWorkLoop *work_loop {nullptr}; @@ -53,11 +53,11 @@ class F03 : public RMITrackpointFunction { int ps2DoSendbyteGated(UInt8 byte, uint64_t timeout); int ps2CommandGated(UInt8 *param, unsigned int *command); int ps2Command(UInt8 *param, unsigned int command); - void handleByte(UInt8); + void handleByte(AbsoluteTime time, UInt8); void initPS2(); void initPS2Interrupt(OSObject *owner, IOTimerEventSource *timer); - void handlePacket(UInt8 *packet); + void handlePacket(AbsoluteTime time, UInt8 *packet); }; #endif /* F03_hpp */ diff --git a/VoodooRMI/Functions/F11.cpp b/VoodooRMI/Functions/F11.cpp index dcd29ff..eb7c0a0 100644 --- a/VoodooRMI/Functions/F11.cpp +++ b/VoodooRMI/Functions/F11.cpp @@ -40,22 +40,31 @@ void F11::free() super::free(); } -void F11::attention() +void F11::attention(AbsoluteTime time, UInt8 *data[], size_t *size) { int error, abs_size; size_t fingers; UInt8 finger_state; - AbsoluteTime timestamp; - error = readBlock(getDataAddr(), data_pkt, pkt_size); - if (error < 0) { - IOLogError("Could not read F11 attention data: %d", error); - return; + if (data) { + if (*size < attn_size) { + IOLogError("F11 attention larger than remaining data"); + return; + } + + memcpy(data_pkt, *data, attn_size); + (*data) += attn_size; + (*size) -= attn_size; + } else { + error = readBlock(getDataAddr(), data_pkt, pkt_size); + + if (error < 0) { + IOLogError("F11 Could not read attention data: %d", error); + return; + } } - clock_get_uptime(×tamp); - - if (shouldDiscardReport(timestamp)) + if (shouldDiscardReport(time)) return; IOLogDebug("F11 Packet"); @@ -94,7 +103,7 @@ void F11::attention() } } - report.timestamp = timestamp; + report.timestamp = time; report.fingers = fingers; handleReport(&report); diff --git a/VoodooRMI/Functions/F11.hpp b/VoodooRMI/Functions/F11.hpp index 9af8c6f..d706356 100644 --- a/VoodooRMI/Functions/F11.hpp +++ b/VoodooRMI/Functions/F11.hpp @@ -500,7 +500,7 @@ class F11 : public RMITrackpadFunction { public: bool attach(IOService *provider) override; - void attention() override; + void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override; void free() override; IOReturn config() override; diff --git a/VoodooRMI/Functions/F12.cpp b/VoodooRMI/Functions/F12.cpp index 58cbbb0..cf05964 100644 --- a/VoodooRMI/Functions/F12.cpp +++ b/VoodooRMI/Functions/F12.cpp @@ -267,22 +267,30 @@ int F12::rmi_f12_read_sensor_tuning() return 0; } -void F12::attention() +void F12::attention(AbsoluteTime time, UInt8 *data[], size_t *size) { - AbsoluteTime timestamp; - if (!data1) return; - int retval = readBlock(getDataAddr(), data_pkt, pkt_size); - - if (retval < 0) { - IOLogError("F12 - Failed to read object data. Code: %d", retval); - return; + if (data) { + if (*size < attn_size) { + IOLogError("F12 attention larger than remaining data"); + return; + } + + memcpy(data_pkt, *data, attn_size); + (*data) += attn_size; + (*size) -= attn_size; + } else { + IOReturn error = readBlock(getDataAddr(), data_pkt, pkt_size); + + if (error < 0) { + IOLogError("F12 Could not read attention data: %d", error); + return; + } } - clock_get_uptime(×tamp); - if (shouldDiscardReport(timestamp)) + if (shouldDiscardReport(time)) return; IOLogDebug("F12 Packet"); @@ -293,12 +301,12 @@ void F12::attention() #endif // debug int fingers = min (nbr_fingers, 5); - UInt8 *data = &data_pkt[data1_offset]; + UInt8 *fingerData = &data_pkt[data1_offset]; for (int i = 0; i < fingers; i++) { rmi_2d_sensor_abs_object *obj = &report.objs[i]; - switch (data[0]) { + switch (fingerData[0]) { case RMI_F12_OBJECT_FINGER: obj->type = RMI_2D_OBJECT_FINGER; break; @@ -309,16 +317,16 @@ void F12::attention() obj->type = RMI_2D_OBJECT_NONE; } - obj->x = (data[2] << 8) | data[1]; - obj->y = (data[4] << 8) | data[3]; - obj->z = data[5]; - obj->wx = data[6]; - obj->wy = data[7]; + obj->x = (fingerData[2] << 8) | fingerData[1]; + obj->y = (fingerData[4] << 8) | fingerData[3]; + obj->z = fingerData[5]; + obj->wx = fingerData[6]; + obj->wy = fingerData[7]; data += F12_DATA1_BYTES_PER_OBJ; } - report.timestamp = timestamp; + report.timestamp = time; report.fingers = fingers; handleReport(&report); diff --git a/VoodooRMI/Functions/F12.hpp b/VoodooRMI/Functions/F12.hpp index d6d011e..1766c80 100644 --- a/VoodooRMI/Functions/F12.hpp +++ b/VoodooRMI/Functions/F12.hpp @@ -54,7 +54,7 @@ class F12 : public RMITrackpadFunction { public: bool attach(IOService *provider) override; - void attention() override; + void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override; void free() override; IOReturn config() override; diff --git a/VoodooRMI/Functions/F17.cpp b/VoodooRMI/Functions/F17.cpp index d07e68c..e7583e9 100644 --- a/VoodooRMI/Functions/F17.cpp +++ b/VoodooRMI/Functions/F17.cpp @@ -34,7 +34,7 @@ void F17::free() super::free(); } -void F17::attention() +void F17::attention(AbsoluteTime time, UInt8 *data[], size_t *size) { int retval = 0; for (int i = 0; i < f17.query.number_of_sticks + 1 && !retval; i++) @@ -244,8 +244,8 @@ int F17::rmi_f17_process_stick(struct rmi_f17_stick_data *stick) { } else { IOLogDebug("%s: Reporting dx: %d, dy: %d\n", __func__, stick->data.rel.x_delta, stick->data.rel.y_delta); - report.dx = (SInt32)((SInt64)stick->data.rel.x_delta * conf.trackpointMult / DEFAULT_MULT); - report.dy = -(SInt32)((SInt64)stick->data.rel.y_delta * conf.trackpointMult / DEFAULT_MULT); + report.dx = (SInt32)((SInt64)stick->data.rel.x_delta; + report.dy = -(SInt32)((SInt64)stick->data.rel.y_delta; report.buttons = 0; handleReport(&report); diff --git a/VoodooRMI/Functions/F17.hpp b/VoodooRMI/Functions/F17.hpp index cffbf10..c58ec70 100644 --- a/VoodooRMI/Functions/F17.hpp +++ b/VoodooRMI/Functions/F17.hpp @@ -150,7 +150,7 @@ class F17 : public RMITrackpointFunction { public: bool attach(IOService *provider) override; void free() override; - void attention() override; + void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override; IOReturn config() override; private: diff --git a/VoodooRMI/Functions/Input/RMIFunction.cpp b/VoodooRMI/Functions/Input/RMIFunction.cpp index 137c5a5..f51bece 100644 --- a/VoodooRMI/Functions/Input/RMIFunction.cpp +++ b/VoodooRMI/Functions/Input/RMIFunction.cpp @@ -5,6 +5,7 @@ */ #include "RMIFunction.hpp" +#include "RMILogging.h" OSDefineMetaClassAndStructors(RMIFunction, IOService) @@ -39,3 +40,35 @@ bool RMIFunction::start(IOService *provider) { registerService(); return true; } + +bool RMIFunction::getInputData(UInt8 dest[], size_t destSize, UInt8 *srcData[], size_t *srcSize) { + if (srcData) { + if (*srcSize < destSize) { + IOLogError("%s Attention size smaller than expected", getName()); + return false; + } + + memcpy(dest, *srcData, destSize); + (*srcData) += destSize; + (*srcSize) -= destSize; + return true; + } + + if (destSize == 1) { + IOReturn error = readByte(getDataAddr(), dest); + + if (error) { + IOLogError("%s Failed to read device status: %d", getName(), error); + return false; + } + } else { + IOReturn error = readBlock(getDataAddr(), dest, destSize); + + if (error) { + IOLogError("%s Failed to read block data: %d", getName(), error); + return false; + } + } + + return true; +} diff --git a/VoodooRMI/Functions/Input/RMIFunction.hpp b/VoodooRMI/Functions/Input/RMIFunction.hpp index 74e3a94..50dfebf 100644 --- a/VoodooRMI/Functions/Input/RMIFunction.hpp +++ b/VoodooRMI/Functions/Input/RMIFunction.hpp @@ -56,13 +56,15 @@ class RMIFunction : public IOService { virtual IOReturn config() { return kIOReturnSuccess; }; // Attention is called whenever this function has data. Any input data // should be read here. - virtual void attention() { }; + virtual void attention(AbsoluteTime time, UInt8 *data[], size_t *size) { }; private: RmiPdtEntry pdtEntry; RMIBus *bus {nullptr}; protected: + bool getInputData(UInt8 dest[], size_t destSize, UInt8 *srcData[], size_t *srcSize); + // Useful functions to talk to RMI4 devicce inline void sendVoodooInputPacket(UInt32 msg, void *packet) { IOService *vi = bus->getVoodooInput(); diff --git a/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp b/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp index 9f1c2e7..7acb262 100644 --- a/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp +++ b/VoodooRMI/Functions/Input/RMIGPIOFunction.cpp @@ -96,20 +96,16 @@ int RMIGPIOFunction::mapGpios() return 0; } -void RMIGPIOFunction::attention() +void RMIGPIOFunction::attention(AbsoluteTime time, UInt8 *data[], size_t *size) { - int error = readBlock(getDataAddr(), - data_regs, register_count); - - if (error < 0) { - IOLogError("Could not read %s data: %d", getName(), error); - } - + if (!getInputData(data_regs, register_count, data, size)) + return; + if (has_gpio) - reportButton(); + reportButton(time); } -void RMIGPIOFunction::reportButton() +void RMIGPIOFunction::reportButton(AbsoluteTime time) { TrackpointReport relativeEvent {}; unsigned int mask, trackpointBtns = 0, btns = 0; @@ -150,12 +146,9 @@ void RMIGPIOFunction::reportButton() } if (numButtons > 1) { - AbsoluteTime timestamp; - clock_get_uptime(×tamp); - relativeEvent.dx = relativeEvent.dy = 0; relativeEvent.buttons = btns; - relativeEvent.timestamp = timestamp; + relativeEvent.timestamp = time; sendVoodooInputPacket(kIOMessageVoodooTrackpointRelativePointer, &relativeEvent); } diff --git a/VoodooRMI/Functions/Input/RMIGPIOFunction.hpp b/VoodooRMI/Functions/Input/RMIGPIOFunction.hpp index 8c51a36..33d34a8 100644 --- a/VoodooRMI/Functions/Input/RMIGPIOFunction.hpp +++ b/VoodooRMI/Functions/Input/RMIGPIOFunction.hpp @@ -18,7 +18,7 @@ class RMIGPIOFunction : public RMIFunction { public: bool attach(IOService *provider) override; IOReturn config() override; - void attention() override; + void attention(AbsoluteTime time, UInt8 *data[], size_t *size) override; void free() override; protected: @@ -42,7 +42,7 @@ class RMIGPIOFunction : public RMIFunction { virtual inline bool is_valid_button(int button) {return false;}; int mapGpios(); - void reportButton(); + void reportButton(AbsoluteTime time); }; #endif /* RMIGPIOFunction_hpp */ diff --git a/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp b/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp index bafc8f3..f44ec2c 100644 --- a/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp +++ b/VoodooRMI/Functions/Input/RMITrackpointFunction.cpp @@ -9,14 +9,11 @@ OSDefineMetaClassAndStructors(RMITrackpointFunction, RMIFunction) void RMITrackpointFunction::handleReport(RMITrackpointReport *report) { - AbsoluteTime timestamp; - clock_get_uptime(×tamp); - TrackpointReport trackpointReport; + trackpointReport.timestamp = report->timestamp; trackpointReport.dx = report->dx; trackpointReport.dy = report->dy; trackpointReport.buttons = report->buttons | overwrite_buttons; - trackpointReport.timestamp = timestamp; sendVoodooInputPacket(kIOMessageVoodooTrackpointMessage, &trackpointReport); if (report->dx || report->dy) { diff --git a/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp b/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp index 40ebef5..89d53a4 100644 --- a/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp +++ b/VoodooRMI/Functions/Input/RMITrackpointFunction.hpp @@ -9,6 +9,7 @@ #include struct RMITrackpointReport { + AbsoluteTime timestamp; SInt32 dx; SInt32 dy; UInt32 buttons; diff --git a/VoodooRMI/RMIBus.cpp b/VoodooRMI/RMIBus.cpp index b954ef9..9f2ecd8 100644 --- a/VoodooRMI/RMIBus.cpp +++ b/VoodooRMI/RMIBus.cpp @@ -77,7 +77,7 @@ bool RMIBus::start(IOService *provider) { // Ready for interrupts setProperty(RMIBusIdentifier, kOSBooleanTrue); - if (!transport->open(this)) { + if (!transport->open(this, 0, OSMemberFunctionCast(RMIAttentionAction, this, &RMIBus::handleHostNotify))) { IOLogError("Could not open transport"); goto err; } @@ -106,19 +106,21 @@ bool RMIBus::start(IOService *provider) { return false; } -void RMIBus::handleHostNotify() { +void RMIBus::handleHostNotify(AbsoluteTime time, UInt8 *data, size_t size) { UInt32 irqStatus; - if (controlFunction == nullptr) { IOLogError("Interrupt - No F01"); return; } - IOReturn error = controlFunction->readIRQ(irqStatus); - - if (error != kIOReturnSuccess){ - IOLogError("Unable to read IRQ"); - return; + if (data) { + irqStatus = data[0]; + } else { + IOReturn error = controlFunction->readIRQ(irqStatus); + if (error != kIOReturnSuccess){ + IOLogError("Unable to read IRQ"); + return; + } } OSIterator* iter = OSCollectionIterator::withCollection(functions); @@ -127,35 +129,18 @@ void RMIBus::handleHostNotify() { return; } + UInt8 *dataPtr = &data[1]; while(RMIFunction *func = OSDynamicCast(RMIFunction, iter->getNextObject())) { if (func->hasAttnSig(irqStatus)) { - func->attention(); + func->attention(time, &dataPtr, &size); } } OSSafeReleaseNULL(iter); } -void RMIBus::handleHostNotifyLegacy() { - if (controlFunction == nullptr) { - IOLogError("Interrupt - No F01"); - } - - OSIterator* iter = OSCollectionIterator::withCollection(functions); - while(RMIFunction *func = OSDynamicCast(RMIFunction, iter->getNextObject())) - func->attention(); - OSSafeReleaseNULL(iter); -} - IOReturn RMIBus::message(UInt32 type, IOService *provider, void *argument) { switch (type) { - case kIOMessageVoodooI2CHostNotify: - case kIOMessageVoodooSMBusHostNotify: - handleHostNotify(); - break; - case kIOMessageVoodooI2CLegacyHostNotify: - handleHostNotifyLegacy(); - break; case kIOMessageRMI4ResetHandler: rmiEnableSensor(); break; diff --git a/VoodooRMI/RMIBus.hpp b/VoodooRMI/RMIBus.hpp index e8e9217..ab4ee06 100644 --- a/VoodooRMI/RMIBus.hpp +++ b/VoodooRMI/RMIBus.hpp @@ -87,8 +87,7 @@ class RMIBus : public IOService { IOService *trackpointFunction {nullptr}; F01 *controlFunction {nullptr}; - void handleHostNotify(); - void handleHostNotifyLegacy(); + void handleHostNotify(AbsoluteTime time, UInt8 *data, size_t size); // IRQ information UInt8 irqCount {0}; diff --git a/VoodooRMI/Transports/I2C/RMII2C.cpp b/VoodooRMI/Transports/I2C/RMII2C.cpp index d5a6f4c..5da75af 100644 --- a/VoodooRMI/Transports/I2C/RMII2C.cpp +++ b/VoodooRMI/Transports/I2C/RMII2C.cpp @@ -102,6 +102,7 @@ bool RMII2C::start(IOService *provider) { interrupt_source = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &RMII2C::interruptOccured), device_nub, 0); if (interrupt_source) { + interrupt_source->enablePrimaryInterruptTimestamp(true); work_loop->addEventSource(interrupt_source); } else { IOLogInfo("%s::%s Could not get interrupt event source, falling back to polling", getName(), name); @@ -110,10 +111,12 @@ bool RMII2C::start(IOService *provider) { IOLogError("%s::%s Could not get timer event source", getName(), name); goto exit; } - + work_loop->addEventSource(interrupt_simulator); } + inputBuffer = new UInt8[hdesc.wMaxInputLength]; + startInterrupt(); PMinit(); @@ -150,6 +153,10 @@ void RMII2C::releaseResources() { device_nub->close(this); device_nub = nullptr; } + + if (inputBuffer) { + delete inputBuffer; + } OSSafeReleaseNULL(command_gate); OSSafeReleaseNULL(interrupt_source); @@ -278,16 +285,13 @@ int RMII2C::reset() { return retval; }; -bool RMII2C::handleOpen(IOService *forClient, IOOptionBits options, void *arg) { - if (forClient && forClient->getProperty(RMIBusIdentifier)) { - bus = forClient; - bus->retain(); - - startInterrupt(); - return true; +bool RMII2C::open(IOService *client, IOOptionBits options, RMIAttentionAction action) { + if (!super::open(client, options, action)) { + return false; } - - return IOService::handleOpen(forClient, options, arg); + + startInterrupt(); + return true; } int RMII2C::readBlock(UInt16 rmiaddr, UInt8 *databuff, size_t len) { @@ -395,8 +399,20 @@ int RMII2C::blockWrite(UInt16 rmiaddr, UInt8 *buf, size_t len) { void RMII2C::interruptOccured(OSObject *owner, IOInterruptEventSource *src, int intCount) { if (!ready || !bus) return; - - messageClient(reportMode == RMI_MODE_ATTN_REPORTS ? kIOMessageVoodooI2CLegacyHostNotify : kIOMessageVoodooI2CHostNotify, bus); + + if (device_nub->readI2C(inputBuffer, hdesc.wMaxInputLength) != kIOReturnSuccess) { + IOLogError("%s::%s Unable to read interrupt data", getName(), name); + return; + } + + UInt16 size = inputBuffer[0] | (inputBuffer[1] << 8); + UInt8 reportId = inputBuffer[2]; + + if (!size || reportId != RMI_ATTN_REPORT_ID) { + return; + } + + handleAttention(mach_absolute_time(), &inputBuffer[3], size - 3); } void RMII2C::simulateInterrupt(OSObject* owner, IOTimerEventSource* timer) { diff --git a/VoodooRMI/Transports/I2C/RMII2C.hpp b/VoodooRMI/Transports/I2C/RMII2C.hpp index 79719fb..766036e 100644 --- a/VoodooRMI/Transports/I2C/RMII2C.hpp +++ b/VoodooRMI/Transports/I2C/RMII2C.hpp @@ -72,7 +72,7 @@ typedef struct __attribute__((__packed__)) { class RMII2C : public RMITransport { OSDeclareDefaultStructors(RMII2C); - typedef IOService super; + typedef RMITransport super; public: const char* name; @@ -81,7 +81,7 @@ class RMII2C : public RMITransport { bool start(IOService *provider) APPLE_KEXT_OVERRIDE; void stop(IOService *provider) APPLE_KEXT_OVERRIDE; IOReturn setPowerState(unsigned long powerState, IOService *whatDevice) APPLE_KEXT_OVERRIDE; - bool handleOpen(IOService *forClient, IOOptionBits options, void *arg) APPLE_KEXT_OVERRIDE; + bool open(IOService *client, IOOptionBits options, RMIAttentionAction action) APPLE_KEXT_OVERRIDE; int reset() APPLE_KEXT_OVERRIDE; int readBlock(UInt16 rmiaddr, UInt8 *databuff, size_t len) APPLE_KEXT_OVERRIDE; @@ -92,7 +92,8 @@ class RMII2C : public RMITransport { bool ready {false}; unsigned long currentPowerState {1}; int page {0}; - int reportMode {RMI_MODE_NO_PACKED_ATTN_REPORTS}; + int reportMode {RMI_MODE_ATTN_REPORTS}; + UInt8 *inputBuffer {nullptr}; VoodooI2CDeviceNub *device_nub {nullptr}; diff --git a/VoodooRMI/Transports/RMITransport.hpp b/VoodooRMI/Transports/RMITransport.hpp index 78eed9b..4ba6449 100644 --- a/VoodooRMI/Transports/RMITransport.hpp +++ b/VoodooRMI/Transports/RMITransport.hpp @@ -15,14 +15,14 @@ #include #define kIOMessageVoodooSMBusHostNotify iokit_vendor_specific_msg(420) -#define kIOMessageVoodooI2CHostNotify iokit_vendor_specific_msg(421) -#define kIOMessageVoodooI2CLegacyHostNotify iokit_vendor_specific_msg(422) #define kIOMessageRMI4ResetHandler iokit_vendor_specific_msg(423) #define kIOMessageRMI4Sleep iokit_vendor_specific_msg(424) #define kIOMessageRMI4Resume iokit_vendor_specific_msg(425) #define RMIBusIdentifier "Synaptics RMI4 Device" #define RMIBusSupported "RMI4 Supported" +typedef void (*RMIAttentionAction)(OSObject *target, AbsoluteTime timestamp, UInt8 *data, size_t size); + /* * read/write/reset APIs can be used before opening. Opening/Closing is needed to recieve interrupts */ @@ -38,30 +38,35 @@ class RMITransport : public IOService { virtual int reset() { return 0; }; virtual OSDictionary *createConfig() { return nullptr; }; - - /* - * IMPORTANT: These handleClose/handleOpen must be called. These can be overriden, - * but said implementation must call the ones below. - */ - inline virtual void handleClose(IOService *forClient, IOOptionBits options) override { - OSSafeReleaseNULL(bus); - IOService::handleClose(forClient, options); + + virtual bool open(IOService *client, IOOptionBits options, RMIAttentionAction action) { + if (!IOService::open(client, options)) { + return false; + } + + bus = client; + interruptAction = action; + return true; + } + + virtual void close(IOService *client, IOOptionBits options = 0) override { + bus = nullptr; + interruptAction = nullptr; + IOService::close(client); } - inline virtual bool handleOpen(IOService *forClient, IOOptionBits options, void *arg) override { - if (forClient && forClient->getProperty(RMIBusIdentifier) - && IOService::handleOpen(forClient, options, arg)) { - bus = forClient; - bus->retain(); - - return true; + void handleAttention(AbsoluteTime timestamp, UInt8 *data, size_t size) { + if (!interruptAction) { + return; } - return false; + (*interruptAction)(bus, timestamp, data, size); } protected: IOService *bus {nullptr}; +private: + RMIAttentionAction interruptAction {nullptr}; }; #endif // RMITransport_H diff --git a/VoodooRMI/Transports/SMBus/RMISMBus.cpp b/VoodooRMI/Transports/SMBus/RMISMBus.cpp index 99288fe..6e3f984 100644 --- a/VoodooRMI/Transports/SMBus/RMISMBus.cpp +++ b/VoodooRMI/Transports/SMBus/RMISMBus.cpp @@ -268,7 +268,8 @@ IOReturn RMISMBus::message(UInt32 type, IOService *provider, void *argument) { switch (type) { case kIOMessageVoodooSMBusHostNotify: - return messageClient(kIOMessageVoodooSMBusHostNotify, bus); + handleAttention(mach_absolute_time(), nullptr, 0); + return kIOReturnSuccess; default: return IOService::message(type, provider, argument); }