99import IOKit
1010
1111class HapticFeedback {
12- private var correctDeviceId : UInt64 ?
12+ static let shared = HapticFeedback ( )
1313
1414 // Here we have list of possible IDs for Haptic Generator Device. They are not constant
1515 // To find deviceID, you will need IORegistryExplorer app from Additional Tools for Xcode dmg
@@ -20,16 +20,11 @@ class HapticFeedback {
2020 0x200_0000_0100_0000 , // MacBook Pro 2016/2017
2121 0x300000080500000 // MacBook Pro 2019 (possibly 2018 as well)
2222 ]
23+ private var correctDeviceID : UInt64 ?
24+ private var actuatorRef : CFTypeRef ?
2325
2426 init ( ) {
25- // Let's find our Haptic device
26- possibleDeviceIDs. forEach { ( deviceID) in
27- guard correctDeviceId == nil else { return }
28- let actuatorRef : CFTypeRef ? = MTActuatorCreateFromDeviceID ( deviceID) . takeRetainedValue ( )
29- if actuatorRef != nil {
30- correctDeviceId = deviceID
31- }
32- }
27+ recreateDevice ( )
3328 }
3429
3530 // Don't know how to do strong is enum one of
@@ -44,15 +39,8 @@ class HapticFeedback {
4439 // you can get a plist `otool -s __TEXT __tpad_act_plist /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/Current/MultitouchSupport|tail -n +3|awk -F'\t' '{print $2}'|xxd -r -p`
4540
4641 func tap( strong: Int32 ) {
47- guard correctDeviceId != nil else {
48- print ( " guard correctDeviceId == nil (no haptic device found?) " )
49- return
50- }
51-
52- let actuatorRef : CFTypeRef ? = MTActuatorCreateFromDeviceID ( correctDeviceId!) . takeRetainedValue ( )
53-
54- guard actuatorRef != nil else {
55- print ( " guard actuatorRef == nil " )
42+ guard correctDeviceID != nil , actuatorRef != nil else {
43+ print ( " guard actuatorRef == nil (no haptic device found?) " )
5644 return
5745 }
5846
@@ -61,10 +49,11 @@ class HapticFeedback {
6149 result = MTActuatorOpen ( actuatorRef!)
6250 guard result == kIOReturnSuccess else {
6351 print ( " guard MTActuatorOpen " )
52+ recreateDevice ( )
6453 return
6554 }
6655
67- result = MTActuatorActuate ( actuatorRef!, strong, 0 , 0.0 , 0. 0)
56+ result = MTActuatorActuate ( actuatorRef!, strong, 0 , 0 , 0 )
6857 guard result == kIOReturnSuccess else {
6958 print ( " guard MTActuatorActuate " )
7059 return
@@ -76,4 +65,25 @@ class HapticFeedback {
7665 return
7766 }
7867 }
68+
69+ private func recreateDevice( ) {
70+ if let actuatorRef = actuatorRef {
71+ MTActuatorClose ( actuatorRef)
72+ self . actuatorRef = nil // just in case %)
73+ }
74+
75+ if let correctDeviceID = correctDeviceID {
76+ actuatorRef = MTActuatorCreateFromDeviceID ( correctDeviceID) . takeRetainedValue ( )
77+ } else {
78+ // Let's find our Haptic device
79+ possibleDeviceIDs. forEach { ( deviceID) in
80+ guard correctDeviceID == nil else { return }
81+ actuatorRef = MTActuatorCreateFromDeviceID ( deviceID) . takeRetainedValue ( )
82+
83+ if actuatorRef != nil {
84+ correctDeviceID = deviceID
85+ }
86+ }
87+ }
88+ }
7989}
0 commit comments