Skip to content

Commit

Permalink
SMBus Companion Devices (#63)
Browse files Browse the repository at this point in the history
* Set LIBKERN_RETURN_RETAINED

* Add PS/2 stub driver

* Create companion device in start instead of probe

* Retain/Release companion info dictionary

* Clean up PS2 stub device

* Save OSSymbol in class

* Save symbol in class

* Update copyright
  • Loading branch information
1Revenger1 authored Oct 4, 2024
1 parent 43dac6d commit 4750716
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 42 deletions.
8 changes: 8 additions & 0 deletions VoodooPS2Controller.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
CE8DA1C6251839B7008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA1C4251839B2008C44E8 /* libkmod.a */; };
CE8DA1C7251839B9008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA1C4251839B2008C44E8 /* libkmod.a */; };
CE8DA1CC251839BC008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA1C4251839B2008C44E8 /* libkmod.a */; };
EE914A902C952F0D0023CFE0 /* VoodooPS2SMBusDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE914A8E2C952F0D0023CFE0 /* VoodooPS2SMBusDevice.cpp */; };
EE914A912C952F0D0023CFE0 /* VoodooPS2SMBusDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = EE914A8F2C952F0D0023CFE0 /* VoodooPS2SMBusDevice.h */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -131,6 +133,8 @@
EDD95559208E2B640031D99E /* SSDT-Thinkpad_Clickpad.dsl */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SSDT-Thinkpad_Clickpad.dsl"; sourceTree = "<group>"; };
EDD9555A208E2E7A0031D99E /* SSDT-Thinkpad_Trackpad.dsl */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SSDT-Thinkpad_Trackpad.dsl"; sourceTree = "<group>"; };
EDD970FD1FD0B826004CCFFD /* SSDT-HP-FixLidSleep.dsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "SSDT-HP-FixLidSleep.dsl"; sourceTree = "<group>"; };
EE914A8E2C952F0D0023CFE0 /* VoodooPS2SMBusDevice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooPS2SMBusDevice.cpp; sourceTree = "<group>"; };
EE914A8F2C952F0D0023CFE0 /* VoodooPS2SMBusDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VoodooPS2SMBusDevice.h; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -287,6 +291,8 @@
84833FB0161B62A900845294 /* VoodooPS2SynapticsTouchPad.h */,
84833FAF161B62A900845294 /* VoodooPS2SynapticsTouchPad.cpp */,
4CC27EB2251FBC7700824FE1 /* VoodooPS2TrackpadCommon.h */,
EE914A8F2C952F0D0023CFE0 /* VoodooPS2SMBusDevice.h */,
EE914A8E2C952F0D0023CFE0 /* VoodooPS2SMBusDevice.cpp */,
84167857161B56C4002C60E6 /* Supporting Files */,
);
path = VoodooPS2Trackpad;
Expand Down Expand Up @@ -393,6 +399,7 @@
356B896323007F4F0042F30F /* VoodooInputEvent.h in Headers */,
9828A93024A2B6C200550FAA /* VoodooPS2Elan.h in Headers */,
356B896223007F4F0042F30F /* VoodooInputMessages.h in Headers */,
EE914A912C952F0D0023CFE0 /* VoodooPS2SMBusDevice.h in Headers */,
356B896423007F4F0042F30F /* VoodooInputTransducer.h in Headers */,
84833FB2161B62A900845294 /* VoodooPS2ALPSGlidePoint.h in Headers */,
356B896523007F4F0042F30F /* MultitouchHelpers.h in Headers */,
Expand Down Expand Up @@ -653,6 +660,7 @@
84833FB1161B62A900845294 /* VoodooPS2ALPSGlidePoint.cpp in Sources */,
9828A92F24A2B6C200550FAA /* VoodooPS2Elan.cpp in Sources */,
84833FB3161B62A900845294 /* VoodooPS2SentelicFSP.cpp in Sources */,
EE914A902C952F0D0023CFE0 /* VoodooPS2SMBusDevice.cpp in Sources */,
84833FB5161B62A900845294 /* VoodooPS2SynapticsTouchPad.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
7 changes: 7 additions & 0 deletions VoodooPS2Controller/ApplePS2Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ void ApplePS2Device::dispatchMessage(int message, void *data)

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IOReturn ApplePS2Device::startSMBusCompanion(OSDictionary *companionData, UInt8 smbusAddr)
{
return _controller->startSMBusCompanion(companionData, smbusAddr);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

ApplePS2Controller* ApplePS2Device::getController()
{
return _controller;
Expand Down
6 changes: 3 additions & 3 deletions VoodooPS2Controller/ApplePS2Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,8 @@ typedef void (*PS2PowerControlAction)(void * target, UInt32 whatToDo);
// Published property for devices to express interest in receiving messages
#define kDeliverNotifications "RM,deliverNotifications"

#define kSmbusCompanion "VoodooSMBusCompanionDevice"

// Published property for device nub port location
#define kPortKey "Port Num"

Expand All @@ -532,9 +534,6 @@ enum

kPS2M_resetTouchpad = iokit_vendor_specific_msg(151), // Force touchpad reset (data is int*)

// from trackpad on I2C/SMBus
kPS2M_SMBusStart = iokit_vendor_specific_msg(152), // Reset, disable PS2 comms to not interfere with SMBus comms

// from sensor (such as yoga mode indicator) to keyboard
kPS2K_setKeyboardStatus = iokit_vendor_specific_msg(200), // set disable/enable keyboard (data is bool*)
kPS2K_getKeyboardStatus = iokit_vendor_specific_msg(201), // get disable/enable keyboard (data is bool*)
Expand Down Expand Up @@ -607,6 +606,7 @@ class EXPORT ApplePS2Device : public IOService

// Messaging
virtual void dispatchMessage(int message, void *data);
virtual IOReturn startSMBusCompanion(OSDictionary *companionData, UInt8 smbusAddr);

// Exclusive access (command byte contention)

Expand Down
19 changes: 17 additions & 2 deletions VoodooPS2Controller/VoodooPS2Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ bool ApplePS2Controller::init(OSDictionary* dict)
_deliverNotification = OSSymbol::withCString(kDeliverNotifications);
if (_deliverNotification == NULL)
return false;

_smbusCompanion = OSSymbol::withCString(kSmbusCompanion);
if (_smbusCompanion == NULL)
return false;

queue_init(&_requestQueue);

Expand Down Expand Up @@ -747,6 +751,7 @@ void ApplePS2Controller::stop(IOService * provider)
// Free the RMCF configuration cache
OSSafeReleaseNULL(_rmcfCache);
OSSafeReleaseNULL(_deliverNotification);
OSSafeReleaseNULL(_smbusCompanion);

// Free the request queue lock and empty out the request queue.
if (_requestQueueLock)
Expand Down Expand Up @@ -2126,7 +2131,7 @@ static OSString* getPlatformOverride(IORegistryEntry* reg, const char* sz)
return NULL;
}

static OSString* getPlatformManufacturer(IORegistryEntry* reg)
static LIBKERN_RETURNS_RETAINED OSString* getPlatformManufacturer(IORegistryEntry* reg)
{
// allow override in PS2K ACPI device
OSString* id = getPlatformOverride(reg, "RM,oem-id");
Expand All @@ -2148,7 +2153,7 @@ static OSString* getPlatformManufacturer(IORegistryEntry* reg)
return OSString::withCStringNoCopy(oemID);
}

static OSString* getPlatformProduct(IORegistryEntry* reg)
static LIBKERN_RETURNS_RETAINED OSString* getPlatformProduct(IORegistryEntry* reg)
{
// allow override in PS2K ACPI device
OSString* id = getPlatformOverride(reg, "RM,oem-table-id");
Expand Down Expand Up @@ -2423,3 +2428,13 @@ OSDictionary* ApplePS2Controller::makeConfigurationNode(OSDictionary* list, cons

return result;
}

IOReturn ApplePS2Controller::startSMBusCompanion(OSDictionary *companionData, UInt8 smbusAddr) {
IOReturn ret = callPlatformFunction(_smbusCompanion,
false,
static_cast<void *>(this),
static_cast<void *>(companionData),
reinterpret_cast<void *>(smbusAddr),
nullptr);
return ret;
}
3 changes: 3 additions & 0 deletions VoodooPS2Controller/VoodooPS2Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class EXPORT ApplePS2Controller : public IOService
#endif
OSDictionary* _rmcfCache {nullptr};
const OSSymbol* _deliverNotification {nullptr};
const OSSymbol* _smbusCompanion {nullptr};

int _resetControllerFlag {RESET_CONTROLLER_ON_BOOT | RESET_CONTROLLER_ON_WAKEUP};
bool _kbdOnly {0};
Expand Down Expand Up @@ -371,6 +372,8 @@ class EXPORT ApplePS2Controller : public IOService
OSDictionary* getConfigurationOverride(IOACPIPlatformDevice* acpi, const char* method);
OSObject* translateArray(OSArray* array);
OSObject* translateEntry(OSObject* obj);

IOReturn startSMBusCompanion(OSDictionary *companionData, UInt8 smbusAddr);
};

#endif /* _APPLEPS2CONTROLLER_H */
81 changes: 81 additions & 0 deletions VoodooPS2Trackpad/VoodooPS2SMBusDevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// VoodooPS2SMBusDevice.cpp
// VoodooPS2Trackpad
//
// Created by Avery Black on 9/13/24.
// Copyright © 2024 Acidanthera. All rights reserved.
//

#include "VoodooPS2SMBusDevice.h"

// =============================================================================
// ApplePS2SmbusDevice Class Implementation
//

OSDefineMetaClassAndStructors(ApplePS2SmbusDevice, IOService);

ApplePS2SmbusDevice *ApplePS2SmbusDevice::withReset(bool resetNeeded, OSDictionary *data, uint8_t addr) {
ApplePS2SmbusDevice *dev = OSTypeAlloc(ApplePS2SmbusDevice);

if (dev == nullptr) {
return nullptr;
}

if (!dev->init()) {
OSSafeReleaseNULL(dev);
return nullptr;
}

dev->_resetNeeded = resetNeeded;
dev->_data = data;
dev->_data->retain();
dev->_addr = addr;
return dev;
}

bool ApplePS2SmbusDevice::start(IOService *provider) {
if (!super::start(provider))
return false;

_nub = OSDynamicCast(ApplePS2MouseDevice, provider);
if (_nub == nullptr)
return false;

if (_resetNeeded)
resetDevice();

if (_nub->startSMBusCompanion(_data, _addr) != kIOReturnSuccess) {
return false;
}

_nub->installPowerControlAction(this,
OSMemberFunctionCast(PS2PowerControlAction, this, &ApplePS2SmbusDevice::powerAction));
return true;
}

void ApplePS2SmbusDevice::free() {
OSSafeReleaseNULL(_data);
super::free();
}

void ApplePS2SmbusDevice::powerAction(uint32_t ordinal) {
if (ordinal == kPS2C_EnableDevice && _resetNeeded) {
(void) resetDevice();
}
}

IOReturn ApplePS2SmbusDevice::resetDevice() {
TPS2Request<> request;
request.commands[0].command = kPS2C_SendCommandAndCompareAck;
request.commands[0].inOrOut = kDP_SetDefaultsAndDisable; // F5
request.commandsCount = 1;
_nub->submitRequestAndBlock(&request);

if (request.commandsCount == 1) {
DEBUG_LOG("VoodooPS2Trackpad: sending $FF failed: %d\n", request.commandsCount);
return kIOReturnError;
}

return kIOReturnSuccess;
}

45 changes: 45 additions & 0 deletions VoodooPS2Trackpad/VoodooPS2SMBusDevice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// VoodooPS2SMBusDevice.hpp
// VoodooPS2Trackpad
//
// Created by Avery Black on 9/13/24.
// Copyright © 2024 Acidanthera. All rights reserved.
//

#ifndef VoodooPS2SMBusDevice_hpp
#define VoodooPS2SMBusDevice_hpp


#include "../VoodooPS2Controller/ApplePS2MouseDevice.h"
#include <IOKit/IOCommandGate.h>

#include "VoodooPS2TrackpadCommon.h"

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ApplePS2SmbusDevice Class Declaration
// Synaptics and Elans devices still need resets over PS2. This acts as a
// PS/2 stub driver that attaches in lieu of the full touchpad driver to reset
// on wakeups and sleep. This also prevents other devices attaching and using
// the otherwise unused PS/2 interface
//

class EXPORT ApplePS2SmbusDevice : public IOService {
typedef IOService super;
OSDeclareDefaultStructors(ApplePS2SmbusDevice);
public:
static ApplePS2SmbusDevice *withReset(bool resetNeeded, OSDictionary *data, uint8_t addr);

bool start(IOService *provider) override;
void free() override;

private:
ApplePS2MouseDevice *_nub {nullptr};
bool _resetNeeded {false};
OSDictionary *_data {nullptr};
uint8_t _addr{0};

IOReturn resetDevice();
void powerAction(uint32_t ordinal);
};

#endif /* VoodooPS2SMBusDevice_hpp */
Loading

0 comments on commit 4750716

Please sign in to comment.