Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trackpoint #75

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions VoodooI2CHID.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
ACE41BFE22FE5BCF00F75673 /* VoodooI2CHIDSYNA3602Device.hpp in Headers */ = {isa = PBXBuildFile; fileRef = ACE41BFC22FE5BCF00F75673 /* VoodooI2CHIDSYNA3602Device.hpp */; };
ACF66526201A762F00D211EA /* VoodooI2CSensorHubEnabler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ACF66524201A762F00D211EA /* VoodooI2CSensorHubEnabler.cpp */; };
ACF66527201A762F00D211EA /* VoodooI2CSensorHubEnabler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = ACF66525201A762F00D211EA /* VoodooI2CSensorHubEnabler.hpp */; };
EE3DD2D72C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE3DD2D52C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.cpp */; };
EE3DD2D82C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE3DD2D62C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.hpp */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -67,6 +69,8 @@
ACE41BFC22FE5BCF00F75673 /* VoodooI2CHIDSYNA3602Device.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooI2CHIDSYNA3602Device.hpp; sourceTree = "<group>"; };
ACF66524201A762F00D211EA /* VoodooI2CSensorHubEnabler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VoodooI2CSensorHubEnabler.cpp; path = Sensors/VoodooI2CSensorHubEnabler.cpp; sourceTree = "<group>"; };
ACF66525201A762F00D211EA /* VoodooI2CSensorHubEnabler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = VoodooI2CSensorHubEnabler.hpp; path = Sensors/VoodooI2CSensorHubEnabler.hpp; sourceTree = "<group>"; };
EE3DD2D52C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooI2CHIDTrackpointWrapper.cpp; sourceTree = "<group>"; };
EE3DD2D62C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooI2CHIDTrackpointWrapper.hpp; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -124,6 +128,8 @@
AC0B0C541FFB08600039AC33 /* VoodooI2CHIDTransducerWrapper.hpp */,
AC0ADA322017C2DC004DB693 /* VoodooI2CStylusHIDEventDriver.cpp */,
AC0ADA332017C2DC004DB693 /* VoodooI2CStylusHIDEventDriver.hpp */,
EE3DD2D52C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.cpp */,
EE3DD2D62C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.hpp */,
);
path = VoodooI2CHID;
sourceTree = "<group>";
Expand Down Expand Up @@ -166,6 +172,7 @@
files = (
ACCFCF241F69C1DC003E4131 /* VoodooI2CMultitouchHIDEventDriver.hpp in Headers */,
ACE41BFA22FE565000F75673 /* VoodooI2CHIDDeviceOverride.hpp in Headers */,
EE3DD2D82C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.hpp in Headers */,
ACF66527201A762F00D211EA /* VoodooI2CSensorHubEnabler.hpp in Headers */,
AC05569A1F7333FB00ABFD91 /* VoodooI2CPrecisionTouchpadHIDEventDriver.hpp in Headers */,
AC6388CD201B8E9F005E1341 /* VoodooI2CDeviceOrientationSensor.hpp in Headers */,
Expand Down Expand Up @@ -254,6 +261,7 @@
AC0E628B201A629A00A31157 /* VoodooI2CSensorHubEventDriver.cpp in Sources */,
4E9F1E831F8AFECD00E91849 /* VoodooI2CTouchscreenHIDEventDriver.cpp in Sources */,
AC01EE9C201E2B7D005A2988 /* VoodooI2CAccelerometerSensor.cpp in Sources */,
EE3DD2D72C0AC1A100C2873F /* VoodooI2CHIDTrackpointWrapper.cpp in Sources */,
ACCFCF231F69C1DC003E4131 /* VoodooI2CMultitouchHIDEventDriver.cpp in Sources */,
ACF66526201A762F00D211EA /* VoodooI2CSensorHubEnabler.cpp in Sources */,
ACE41BFD22FE5BCF00F75673 /* VoodooI2CHIDSYNA3602Device.cpp in Sources */,
Expand Down
40 changes: 40 additions & 0 deletions VoodooI2CHID/VoodooI2CHIDTrackpointWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// VoodooI2CHIDTrackpointWrapper.cpp
// VoodooI2CHID
//
// Created by Avery Black on 5/31/24.
// Copyright © 2024 Alexandre Daoud. All rights reserved.
//

#include "VoodooI2CHIDTrackpointWrapper.hpp"

#define super OSObject
OSDefineMetaClassAndStructors(VoodooI2CHIDTrackpointWrapper, OSObject);

VoodooI2CHIDTrackpointWrapper* VoodooI2CHIDTrackpointWrapper::wrapper() {
auto *tp = OSTypeAlloc(VoodooI2CHIDTrackpointWrapper);
if (tp == nullptr) {
return nullptr;
}

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

return tp;
}

bool VoodooI2CHIDTrackpointWrapper::init() {
if (!super::init()) {
return false;
}

buttons = OSArray::withCapacity(1);
return buttons != nullptr;
}

void VoodooI2CHIDTrackpointWrapper::free() {
OSSafeReleaseNULL(buttons);
super::free();
}
28 changes: 28 additions & 0 deletions VoodooI2CHID/VoodooI2CHIDTrackpointWrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// VoodooI2CHIDTrackpointWrapper.hpp
// VoodooI2CHID
//
// Created by Avery Black on 5/31/24.
// Copyright © 2024 Alexandre Daoud. All rights reserved.
//

#ifndef VoodooI2CHIDTrackpointWrapper_hpp
#define VoodooI2CHIDTrackpointWrapper_hpp

#include <IOKit/hid/IOHIDElement.h>

class VoodooI2CHIDTrackpointWrapper : public OSObject {
OSDeclareDefaultStructors(VoodooI2CHIDTrackpointWrapper);
public:
static VoodooI2CHIDTrackpointWrapper* wrapper();

bool init() override;
void free() override;

UInt8 report_id = 0;
IOHIDElement* dx = nullptr;
IOHIDElement* dy = nullptr;
OSArray* buttons = nullptr;
};

#endif /* VoodooI2CHIDTrackpointWrapper_hpp */
88 changes: 84 additions & 4 deletions VoodooI2CHID/VoodooI2CMultitouchHIDEventDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,31 @@ void VoodooI2CMultitouchHIDEventDriver::handleInterruptReport(AbsoluteTime times
uint64_t now_ns;
absolutetime_to_nanoseconds(now_abs, &now_ns);

for (int index = 0; index < trackpointReports->getCount(); index++) {
VoodooI2CHIDTrackpointWrapper* tp = OSDynamicCast(VoodooI2CHIDTrackpointWrapper, trackpointReports->getObject(index));

if (tp == nullptr || tp->report_id != report_id) {
continue;
}

UInt8 button_bitmap = 0;
for (int btn_idx = 0; btn_idx < tp->buttons->getCount(); btn_idx++) {
IOHIDElement* elem = OSDynamicCast(IOHIDElement, tp->buttons->getObject(btn_idx));
if (elem->getValue()) {
button_bitmap |= BIT(elem->getUsage() - 1);
}
}

VoodooI2CTrackpointEvent event;
UInt32 dx = tp->dx->getValue();
UInt32 dy = tp->dy->getValue();
event.dx = *reinterpret_cast<SInt32 *>(&dx);
event.dy = *reinterpret_cast<SInt32 *>(&dy);
event.buttons = button_bitmap;
multitouch_interface->handleTrackpointReport(event, timestamp);
return;
}

if (report_type == kIOHIDReportTypeInput && readyForReports())
clock_get_uptime(&last_multi_touch_event);

Expand Down Expand Up @@ -207,6 +232,7 @@ void VoodooI2CMultitouchHIDEventDriver::handleDigitizerReport(AbsoluteTime times
void VoodooI2CMultitouchHIDEventDriver::handleDigitizerTransducerReport(VoodooI2CDigitiserTransducer* transducer, AbsoluteTime timestamp, UInt32 report_id) {
bool handled = false;
bool has_confidence = false;
bool has_valid = false;
UInt32 element_index = 0;
UInt32 element_count = 0;

Expand Down Expand Up @@ -297,6 +323,12 @@ void VoodooI2CMultitouchHIDEventDriver::handleDigitizerTransducerReport(VoodooI2
transducer->in_range = value != 0;
handled |= element_is_current;
break;
case kHIDUsage_Dig_Confidence:
case kHIDUsage_Dig_Quality:
transducer->confidence.update(element->getValue(), timestamp);
handled |= element_is_current;
has_confidence = true;
break;
case kHIDUsage_Dig_TipPressure:
case kHIDUsage_Dig_SecondaryTipSwitch:
{
Expand Down Expand Up @@ -334,13 +366,11 @@ void VoodooI2CMultitouchHIDEventDriver::handleDigitizerTransducerReport(VoodooI2
handled |= element_is_current;
break;
case kHIDUsage_Dig_DataValid:
case kHIDUsage_Dig_TouchValid:
case kHIDUsage_Dig_Quality:
if (value)
transducer->is_valid = true;
else
transducer->is_valid = false;
has_confidence = true;
has_valid = true;
handled |= element_is_current;
break;
case kHIDUsage_Dig_BarrelPressure:
Expand Down Expand Up @@ -382,6 +412,9 @@ void VoodooI2CMultitouchHIDEventDriver::handleDigitizerTransducerReport(VoodooI2
}

if (!has_confidence)
transducer->confidence.update(1, timestamp);

if (!has_valid)
transducer->is_valid = true;

if (!handled)
Expand Down Expand Up @@ -440,6 +473,10 @@ bool VoodooI2CMultitouchHIDEventDriver::handleStart(IOService* provider) {

if (!digitiser.transducers)
return false;

trackpointReports = OSArray::withCapacity(1);
if (!trackpointReports)
return false;

if (parseElements(kHIDUsage_Dig_Any) != kIOReturnSuccess) {
IOLog("%s::%s Could not parse multitouch elements\n", getName(), name);
Expand Down Expand Up @@ -475,7 +512,7 @@ void VoodooI2CMultitouchHIDEventDriver::handleStop(IOService* provider) {

OSSafeReleaseNULL(work_loop);


OSSafeReleaseNULL(trackpointReports);
OSSafeReleaseNULL(digitiser.transducers);
OSSafeReleaseNULL(digitiser.wrappers);
OSSafeReleaseNULL(digitiser.styluses);
Expand Down Expand Up @@ -607,6 +644,43 @@ IOReturn VoodooI2CMultitouchHIDEventDriver::parseDigitizerElement(IOHIDElement*

return kIOReturnSuccess;
}

IOReturn VoodooI2CMultitouchHIDEventDriver::parseTrackpointElement(IOHIDElement* element) {
auto* tp = VoodooI2CHIDTrackpointWrapper::wrapper();
if (tp == nullptr) {
return kIOReturnNoMemory;
}

const auto* collections = element->getChildElements();
IOHIDElement* collection = OSDynamicCast(IOHIDElement, collections->getObject(0));
if (collection == nullptr ||
!collection->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_Pointer)) {
OSSafeReleaseNULL(tp);
return kIOReturnSuccess;
}

OSArray* elements = collection->getChildElements();
for (int index = 0; index < elements->getCount(); index++) {
IOHIDElement* element = OSDynamicCast(IOHIDElement, elements->getObject(index));
if (element == nullptr) {
continue;
}

if (element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_X)) {
tp->dx = element;
tp->report_id = element->getReportID();
} else if (element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_Y)) {
tp->dy = element;
} else if (element->conformsTo(kHIDPage_Button)) {
tp->buttons->setObject(element);
}
}

trackpointReports->setObject(tp);
OSSafeReleaseNULL(tp);

return kIOReturnError;
}

IOReturn VoodooI2CMultitouchHIDEventDriver::parseElements(UInt32 usage) {
int index, count;
Expand All @@ -626,6 +700,11 @@ IOReturn VoodooI2CMultitouchHIDEventDriver::parseElements(UInt32 usage) {
if (element->getUsage() == 0)
continue;

/* Trackpoint devices */
if (element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse)) {
parseTrackpointElement(element);
}

/*
* Parse digitzer elements depending on which Event Driver is attaching.
* Precision/TouchScreen are specifically looking for kHIDUsage_Dig_TouchPad/TouchScreen respectively.
Expand Down Expand Up @@ -776,6 +855,7 @@ void VoodooI2CMultitouchHIDEventDriver::setDigitizerProperties() {
setOSDictionaryNumber(properties, "Transducer Count", digitiser.transducers->getCount());

setProperty("Digitizer", properties);
setProperty("Trackpoints", trackpointReports->getCount(), 32);

OSSafeReleaseNULL(properties);
}
Expand Down
14 changes: 13 additions & 1 deletion VoodooI2CHID/VoodooI2CMultitouchHIDEventDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "VoodooI2CHIDDevice.hpp"
#include "VoodooI2CHIDTransducerWrapper.hpp"
#include "VoodooI2CHIDTrackpointWrapper.hpp"

#include "../../../Multitouch Support/VoodooI2CDigitiserStylus.hpp"
#include "../../../Multitouch Support/VoodooI2CMultitouchInterface.hpp"
Expand Down Expand Up @@ -63,6 +64,7 @@ class EXPORT VoodooI2CMultitouchHIDEventDriver : public IOHIDEventService {
OSDeclareDefaultStructors(VoodooI2CMultitouchHIDEventDriver);

public:

struct {
OSArray* fingers = NULL;
OSArray* styluses = NULL;
Expand Down Expand Up @@ -179,7 +181,16 @@ class EXPORT VoodooI2CMultitouchHIDEventDriver : public IOHIDEventService {
*/

IOReturn parseDigitizerTransducerElement(IOHIDElement* element, IOHIDElement* parent);


/* Parses a mouse usage page element
* @element The element to parse
*
* This function is reponsible for adding a new mouse report.
*
* @return *kIOReturnSuccess* on successful parse, *kIOReturnDeviceError*, *kIOReturnError* or *kIOReturnNoDevice* if the mouse element is not supported
*/

IOReturn parseTrackpointElement(IOHIDElement* element);

/* Postprocessing of digitizer elements
*
Expand Down Expand Up @@ -260,6 +271,7 @@ class EXPORT VoodooI2CMultitouchHIDEventDriver : public IOHIDEventService {
IOHIDDevice* hid_device;
VoodooI2CMultitouchInterface* multitouch_interface;
bool should_have_interface = true;
OSArray* trackpointReports = nullptr;

virtual void forwardReport(VoodooI2CMultitouchEvent event, AbsoluteTime timestamp);

Expand Down
2 changes: 1 addition & 1 deletion VoodooI2CHID/VoodooI2CTouchscreenHIDEventDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ bool VoodooI2CTouchscreenHIDEventDriver::handleStart(IOService* provider) {
if (active_framebuffer) {
active_framebuffer->retain();
}

return true;
}

Expand Down