Skip to content

Commit

Permalink
Start on an event driver
Browse files Browse the repository at this point in the history
  • Loading branch information
lazd committed Jan 6, 2020
1 parent d5fbbcf commit baf81bf
Show file tree
Hide file tree
Showing 4 changed files with 300 additions and 1 deletion.
8 changes: 8 additions & 0 deletions VoodooI2CGoodix.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
objects = {

/* Begin PBXBuildFile section */
EE80555023C2AFB20038376B /* VoodooI2CGoodixEventDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE80554E23C2AFB20038376B /* VoodooI2CGoodixEventDriver.cpp */; };
EE80555123C2AFB20038376B /* VoodooI2CGoodixEventDriver.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE80554F23C2AFB20038376B /* VoodooI2CGoodixEventDriver.hpp */; };
F1F613CE2090304000F1B282 /* VoodooI2CGoodixTouchDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1F613CC2090304000F1B282 /* VoodooI2CGoodixTouchDriver.cpp */; };
F1F613CF2090304000F1B282 /* VoodooI2CGoodixTouchDriver.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F1F613CD2090304000F1B282 /* VoodooI2CGoodixTouchDriver.hpp */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
EE80554E23C2AFB20038376B /* VoodooI2CGoodixEventDriver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooI2CGoodixEventDriver.cpp; sourceTree = "<group>"; };
EE80554F23C2AFB20038376B /* VoodooI2CGoodixEventDriver.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooI2CGoodixEventDriver.hpp; sourceTree = "<group>"; };
F1F613BE20902F4C00F1B282 /* VoodooI2CGoodix.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VoodooI2CGoodix.kext; sourceTree = BUILT_PRODUCTS_DIR; };
F1F613C320902F4C00F1B282 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F1F613CB20902FEE00F1B282 /* goodix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = goodix.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -53,6 +57,8 @@
F1F613CB20902FEE00F1B282 /* goodix.h */,
F1F613CC2090304000F1B282 /* VoodooI2CGoodixTouchDriver.cpp */,
F1F613CD2090304000F1B282 /* VoodooI2CGoodixTouchDriver.hpp */,
EE80554E23C2AFB20038376B /* VoodooI2CGoodixEventDriver.cpp */,
EE80554F23C2AFB20038376B /* VoodooI2CGoodixEventDriver.hpp */,
);
path = VoodooI2CGoodix;
sourceTree = "<group>";
Expand All @@ -64,6 +70,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
EE80555123C2AFB20038376B /* VoodooI2CGoodixEventDriver.hpp in Headers */,
F1F613CF2090304000F1B282 /* VoodooI2CGoodixTouchDriver.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -136,6 +143,7 @@
buildActionMask = 2147483647;
files = (
F1F613CE2090304000F1B282 /* VoodooI2CGoodixTouchDriver.cpp in Sources */,
EE80555023C2AFB20038376B /* VoodooI2CGoodixEventDriver.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<key>VoodooI2CGoodix.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>5</integer>
<integer>4</integer>
</dict>
</dict>
</dict>
Expand Down
153 changes: 153 additions & 0 deletions VoodooI2CGoodix/VoodooI2CGoodixEventDriver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//
// VoodooI2CGoodixEventDriver.cpp
// VoodooI2CGoodix
//
// Created by Larry Davis on 1/5/20.
// Copyright © 2020 lazd. All rights reserved.
//

#include "VoodooI2CGoodixEventDriver.hpp"

#include "VoodooI2CGoodixEventDriver.hpp"
#include <IOKit/hid/IOHIDInterface.h>
#include <IOKit/IOLib.h>

#define super IOHIDEventService
OSDefineMetaClassAndStructors(VoodooI2CGoodixEventDriver, IOHIDEventService);

bool VoodooI2CGoodixEventDriver::didTerminate(IOService* provider, IOOptionBits options, bool* defer) {
if (hid_interface)
hid_interface->close(this);
hid_interface = NULL;

return super::didTerminate(provider, options, defer);
}

void VoodooI2CGoodixEventDriver::forwardReport(VoodooI2CMultitouchEvent event, AbsoluteTime timestamp) {
if (multitouch_interface)
multitouch_interface->handleInterruptReport(event, timestamp);
}

const char* VoodooI2CGoodixEventDriver::getProductName() {
return "Goodix HID Device";
}

bool VoodooI2CGoodixEventDriver::handleStart(IOService* provider) {
if(!super::handleStart(provider)) {
return false;
}

hid_interface = OSDynamicCast(IOHIDInterface, provider);

if (!hid_interface)
return false;

name = getProductName();

publishMultitouchInterface();

digitiser.fingers = OSArray::withCapacity(1);

if (!digitiser.fingers)
return false;

digitiser.styluses = OSArray::withCapacity(1);

if (!digitiser.styluses)
return false;

digitiser.transducers = OSArray::withCapacity(1);

if (!digitiser.transducers)
return false;

setDigitizerProperties();

PMinit();
hid_interface->joinPMtree(this);
registerPowerDriver(this, VoodooI2CIOPMPowerStates, kVoodooI2CIOPMNumberPowerStates);

return true;
}

void VoodooI2CGoodixEventDriver::handleStop(IOService* provider) {
OSSafeReleaseNULL(digitiser.transducers);
OSSafeReleaseNULL(digitiser.wrappers);
OSSafeReleaseNULL(digitiser.styluses);
OSSafeReleaseNULL(digitiser.fingers);

OSSafeReleaseNULL(attached_hid_pointer_devices);

if (multitouch_interface) {
multitouch_interface->stop(this);
multitouch_interface->detach(this);
OSSafeReleaseNULL(multitouch_interface);
}

PMstop();
super::handleStop(provider);
}

IOReturn VoodooI2CGoodixEventDriver::publishMultitouchInterface() {
multitouch_interface = OSTypeAlloc(VoodooI2CMultitouchInterface);

if (!multitouch_interface ||
!multitouch_interface->init(NULL) ||
!multitouch_interface->attach(this))
goto exit;

if (!multitouch_interface->start(this)) {
multitouch_interface->detach(this);
goto exit;
}

multitouch_interface->setProperty(kIOHIDVendorIDKey, 0x0416, 32);
multitouch_interface->setProperty(kIOHIDProductIDKey, 0x0416, 32);

// Todo: should this be true?
multitouch_interface->setProperty(kIOHIDDisplayIntegratedKey, kOSBooleanFalse);

multitouch_interface->registerService();

return kIOReturnSuccess;

exit:
OSSafeReleaseNULL(multitouch_interface);
return kIOReturnError;
}

void VoodooI2CGoodixEventDriver::setDigitizerProperties() {
OSDictionary* properties = OSDictionary::withCapacity(4);

if (!properties)
return;

if (!digitiser.transducers)
goto exit;

properties->setObject("Contact Count Element", digitiser.contact_count);
properties->setObject("Input Mode Element", digitiser.input_mode);
properties->setObject("Contact Count Maximum Element", digitiser.contact_count_maximum);
properties->setObject("Button Element", digitiser.button);
properties->setObject("Transducer Count", OSNumber::withNumber(digitiser.transducers->getCount(), 32));

setProperty("Digitizer", properties);

exit:
OSSafeReleaseNULL(properties);
}

IOReturn VoodooI2CGoodixEventDriver::setPowerState(unsigned long whichState, IOService* whatDevice) {
return kIOPMAckImplied;
}

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

attached_hid_pointer_devices = OSSet::withCapacity(1);

setProperty("VoodooI2CServices Supported", kOSBooleanTrue);

return true;
}
138 changes: 138 additions & 0 deletions VoodooI2CGoodix/VoodooI2CGoodixEventDriver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//
// VoodooI2CGoodixEventDriver.hpp
// VoodooI2CGoodix
//
// Created by Larry Davis on 1/5/20.
// Copyright © 2020 lazd. All rights reserved.
//

#ifndef VoodooI2CGoodixEventDriver_hpp
#define VoodooI2CGoodixEventDriver_hpp

// hack to prevent IOHIDEventDriver from loading when
// we include IOHIDEventService

#define _IOKIT_HID_IOHIDEVENTDRIVER_H

#include <libkern/OSBase.h>

#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>

#include <IOKit/hidevent/IOHIDEventService.h>
#include <IOKit/hidsystem/IOHIDTypes.h>

#include "../../../Multitouch Support/VoodooI2CDigitiserStylus.hpp"
#include "../../../Multitouch Support/VoodooI2CMultitouchInterface.hpp"
#include "../../../Multitouch Support/MultitouchHelpers.hpp"

#include "../../../Dependencies/helpers.hpp"

/* Implements an HID Event Driver for HID devices that expose a digitiser usage page.
*
* The members of this class are responsible for parsing, processing and interpreting digitiser-related HID objects.
*/

class EXPORT VoodooI2CGoodixEventDriver : public IOHIDEventService {
OSDeclareDefaultStructors(VoodooI2CGoodixEventDriver);

public:
struct {
OSArray* fingers = NULL;
OSArray* styluses = NULL;

OSArray* wrappers = NULL;
OSArray*
transducers= NULL;

// report level elements

IOHIDElement* contact_count;
IOHIDElement* input_mode;
IOHIDElement* button;

// collection level elements

IOHIDElement* contact_count_maximum;


UInt8 current_contact_count = 1;
UInt8 report_count = 1;
UInt8 current_report = 1;
} digitiser;

/* Notification that a provider has been terminated, sent after recursing up the stack, in leaf-to-root order.
* @options The terminated provider of this object.
* @defer If there is pending I/O that requires this object to persist, and the provider is not opened by this object set defer to true and call the IOService::didTerminate() implementation when the I/O completes. Otherwise, leave defer set to its default value of false.
*
* @return *true*
*/

bool didTerminate(IOService* provider, IOOptionBits options, bool* defer);

const char* getProductName();

/* Called during the start routine to set up the HID Event Driver
* @provider The <IOHIDInterface> object which we have matched against.
*
* This function is reponsible for opening a client connection with the <IOHIDInterface> provider and for publishing
* a multitouch interface into the IOService plane.
*
* @return *true* on successful start, *false* otherwise
*/

bool handleStart(IOService* provider);

/* Publishes a <VoodooI2CMultitouchInterface> into the IOService plane
*
* @return *kIOReturnSuccess* on successful publish, *kIOReturnError* otherwise.
*/

IOReturn publishMultitouchInterface();

/* Publishes some miscellaneous properties to the IOService plane
*/

void setDigitizerProperties();

/* Called by the OS in order to notify the driver that the device should change power state
* @whichState The power state the device is expected to enter represented by either
* *kIOPMPowerOn* or *kIOPMPowerOff*
* @whatDevice The power management policy maker
*
* This function exists to be overriden by inherited classes should they need it.
*
* @return *kIOPMAckImplied* on succesful state change, *kIOReturnError* otherwise
*/

virtual IOReturn setPowerState(unsigned long whichState, IOService* whatDevice);

/* Called during the stop routine to terminate the HID Event Driver
* @provider The <IOHIDInterface> object which we have matched against.
*
* This function is reponsible for releasing the resources allocated in <start>
*/

void handleStop(IOService* provider);

/* Implemented to set a certain property
* @provider The <IOHIDInterface> object which we have matched against.
*/

bool start(IOService* provider);

protected:
const char* name;
bool awake = true;
IOHIDInterface* hid_interface;
VoodooI2CMultitouchInterface* multitouch_interface;

virtual void forwardReport(VoodooI2CMultitouchEvent event, AbsoluteTime timestamp);

private:
OSSet* attached_hid_pointer_devices;
};


#endif /* VoodooI2CGoodixEventDriver_hpp */

0 comments on commit baf81bf

Please sign in to comment.