Skip to content

Commit b45d75d

Browse files
committed
Use IOServiceGetMatchingServices to find multitouch device
Original fixed list approach is no longer feasible because multitouch ID is now changed per device per macOS versions. Instead, search the I/O Registry to use the build-in actuation supported multitouch device, which should be the trackpad.
1 parent 2a4bbe3 commit b45d75d

1 file changed

Lines changed: 47 additions & 22 deletions

File tree

HapticKey/Sources/HTKMultitouchActuator.m

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,6 @@ - (BOOL)actuateActuationID:(SInt32)actuationID unknown1:(UInt32)unknown1 unknown
6464
return result;
6565
}
6666

67-
// By using IORegistryExplorer, which is in Additional Tools for Xcode,
68-
// Find `AppleMultitouchDevice` which has `Multitouch ID`.
69-
// Probably these are fixed value.
70-
static const UInt64 kKnownAppleMultitouchDeviceMultitouchIDs[] = {
71-
// For MacBook Pro 2016, 2017
72-
0x200000001000000,
73-
// For MacBook Pro 2018
74-
0x300000080500000,
75-
// For MacBook Pro (M1, 2020)
76-
0x200000000000024
77-
};
78-
7967
- (void)_htk_main_openActuator
8068
{
8169
if (_actuatorRef) {
@@ -90,20 +78,57 @@ - (void)_htk_main_openActuator
9078
}
9179
_actuatorRef = actuatorRef;
9280
} else {
93-
const size_t count = sizeof(kKnownAppleMultitouchDeviceMultitouchIDs) / sizeof(UInt64);
94-
for (size_t index = 0; index < count; index++) {
95-
const UInt64 multitouchDeviceMultitouchID = kKnownAppleMultitouchDeviceMultitouchIDs[index];
81+
io_iterator_t itreator = IO_OBJECT_NULL;
82+
// NOTE: `IOServiceGetMatchingServices` will take ownership of `matchingRef`. Do not release it.
83+
const CFMutableDictionaryRef matchingRef = IOServiceMatching("AppleMultitouchDevice");
84+
const kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingRef, &itreator);
85+
if (result != KERN_SUCCESS) {
86+
os_log_info(OS_LOG_DEFAULT, "Failed to get matching services: 0x%x", result);
87+
return;
88+
}
89+
90+
io_service_t service = IO_OBJECT_NULL;
91+
while ((service = IOIteratorNext(itreator)) != IO_OBJECT_NULL) {
92+
CFMutableDictionaryRef propertiesRef = NULL;
93+
const kern_return_t result = IORegistryEntryCreateCFProperties(service, &propertiesRef, CFAllocatorGetDefault(), 0);
94+
if (result != KERN_SUCCESS) {
95+
IOObjectRetain(service);
96+
continue;
97+
}
98+
99+
NSMutableDictionary * const properties = (__bridge_transfer NSMutableDictionary *)propertiesRef;
100+
os_log_debug(OS_LOG_DEFAULT, "Found multitouch device: %{public}@", properties);
101+
102+
// Use first actuation supported build-in, multitouch device, which should be a track pad.
103+
NSString * const productProperty = (NSString *)properties[@"Product"];
104+
NSNumber * const acutuationSupportedProperty = (NSNumber *)properties[@"ActuationSupported"];
105+
NSNumber * const mtBuildInProperty = (NSNumber *)properties[@"MT Built-In"];
106+
if (!(acutuationSupportedProperty.boolValue && mtBuildInProperty.boolValue)) {
107+
os_log_info(OS_LOG_DEFAULT, "Found not applicable multitouch device: %{public}@", productProperty);
108+
IOObjectRetain(service);
109+
continue;
110+
}
111+
112+
NSNumber * const multitouchIDProperty = (NSNumber *)properties[@"Multitouch ID"];
113+
const UInt64 multitouchDeviceMultitouchID = multitouchIDProperty.longLongValue;
96114
const CFTypeRef actuatorRef = MTActuatorCreateFromDeviceID(multitouchDeviceMultitouchID);
97-
if (actuatorRef) {
98-
os_log_info(OS_LOG_DEFAULT, "Use MTActuatorCreateFromDeviceID: 0x%llx", multitouchDeviceMultitouchID);
99-
_actuatorRef = actuatorRef;
100-
self.lastKnownMultitouchDeviceMultitouchID = multitouchDeviceMultitouchID;
101-
break;
115+
if (!actuatorRef) {
116+
os_log_info(OS_LOG_DEFAULT, "Fail to MTActuatorCreateFromDeviceID: 0x%llx multitouich device: %{public}@", multitouchDeviceMultitouchID, productProperty);
117+
IOObjectRetain(service);
118+
continue;
102119
}
103-
os_log_info(OS_LOG_DEFAULT, "Fail to test MTActuatorCreateFromDeviceID: 0x%llx", multitouchDeviceMultitouchID);
120+
121+
os_log_info(OS_LOG_DEFAULT, "Use MTActuatorCreateFromDeviceID: 0x%llx multitouich device: %{public}@", multitouchDeviceMultitouchID, productProperty);
122+
_actuatorRef = actuatorRef;
123+
self.lastKnownMultitouchDeviceMultitouchID = multitouchDeviceMultitouchID;
124+
125+
IOObjectRelease(service);
126+
break;
104127
}
128+
IOObjectRelease(itreator);
129+
105130
if (!_actuatorRef) {
106-
os_log_info(OS_LOG_DEFAULT, "Fail to MTActuatorCreateFromDeviceID");
131+
os_log_info(OS_LOG_DEFAULT, "Fail to any MTActuatorCreateFromDeviceID");
107132
return;
108133
}
109134
}

0 commit comments

Comments
 (0)