├── .github └── workflows │ └── main.yml ├── .gitignore ├── Changelog.md ├── Docs ├── ACPI │ ├── SSDT-AlternateSwipes.dsl │ ├── SSDT-DisableDeepSleep.dsl │ ├── SSDT-DisableElanWakeDelay.dsl │ ├── SSDT-DisableTrackpadProbe.dsl │ ├── SSDT-HP-FixLidSleep.dsl │ ├── SSDT-KEY-DELL-WN09.dsl │ ├── SSDT-NumLockOnAtBoot.dsl │ ├── SSDT-NumLockSupport.dsl │ ├── SSDT-PrtSc-Remap.dsl │ ├── SSDT-Swap-CommandOption.dsl │ ├── SSDT-Swap-LeftControlCapsLock.dsl │ ├── SSDT-Swap-LeftControlCommand.dsl │ ├── SSDT-Thinkpad_Clickpad.dsl │ └── SSDT-Thinkpad_Trackpad.dsl ├── SynapticsRevB.pdf ├── force_touch.png └── voodoops2ioio.sh ├── LICENSE.md ├── README.md ├── VoodooPS2Controller.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── VoodooPS2Controller.xcscheme │ ├── VoodooPS2Keyboard.xcscheme │ ├── VoodooPS2Mouse.xcscheme │ └── VoodooPS2Trackpad.xcscheme ├── VoodooPS2Controller ├── AppleACPIPS2Nub.cpp ├── AppleACPIPS2Nub.h ├── ApplePS2Device.cpp ├── ApplePS2Device.h ├── ApplePS2KeyboardDevice.cpp ├── ApplePS2KeyboardDevice.h ├── ApplePS2MouseDevice.cpp ├── ApplePS2MouseDevice.h ├── VoodooPS2Controller-Info.plist ├── VoodooPS2Controller.cpp ├── VoodooPS2Controller.h └── en.lproj │ └── InfoPlist.strings ├── VoodooPS2Keyboard ├── ApplePS2ToADBMap.h ├── VoodooPS2Keyboard-Breakless-Info.plist ├── VoodooPS2Keyboard-Info.plist ├── VoodooPS2Keyboard-RemapFN-Info.plist ├── VoodooPS2Keyboard.cpp ├── VoodooPS2Keyboard.h └── en.lproj │ └── InfoPlist.strings ├── VoodooPS2Mouse ├── VoodooPS2Mouse-Info.plist ├── VoodooPS2Mouse.cpp ├── VoodooPS2Mouse.h └── en.lproj │ └── InfoPlist.strings └── VoodooPS2Trackpad ├── VoodooPS2ALPSGlidePoint.cpp ├── VoodooPS2ALPSGlidePoint.h ├── VoodooPS2Elan.cpp ├── VoodooPS2Elan.h ├── VoodooPS2SMBusDevice.cpp ├── VoodooPS2SMBusDevice.h ├── VoodooPS2SentelicFSP.cpp ├── VoodooPS2SentelicFSP.h ├── VoodooPS2SynapticsTouchPad.cpp ├── VoodooPS2SynapticsTouchPad.h ├── VoodooPS2Trackpad-Info.plist ├── VoodooPS2TrackpadCommon.h └── en.lproj └── InfoPlist.strings /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | release: 8 | types: [published] 9 | 10 | env: 11 | PROJECT_TYPE: KEXT 12 | 13 | jobs: 14 | build: 15 | name: Build 16 | runs-on: macos-latest 17 | env: 18 | JOB_TYPE: BUILD 19 | steps: 20 | - uses: actions/checkout@v3 21 | - uses: actions/checkout@v3 22 | with: 23 | repository: acidanthera/MacKernelSDK 24 | path: MacKernelSDK 25 | - name: CI Bootstrap 26 | run: | 27 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1 28 | - name: VoodooInput Bootstrap 29 | run: | 30 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/VoodooInput/master/VoodooInput/Scripts/bootstrap.sh) && eval "$src" || exit 1 31 | 32 | - run: xcodebuild -jobs 1 -configuration Debug 33 | - run: xcodebuild -jobs 1 -configuration Release 34 | 35 | - name: Upload to Artifacts 36 | uses: actions/upload-artifact@v3 37 | with: 38 | name: Artifacts 39 | path: build/*/*/*.zip 40 | - name: Upload to Release 41 | if: github.event_name == 'release' 42 | uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d 43 | with: 44 | repo_token: ${{ secrets.GITHUB_TOKEN }} 45 | file: build/*/*/*.zip 46 | tag: ${{ github.ref }} 47 | file_glob: true 48 | 49 | analyze-clang: 50 | name: Analyze Clang 51 | runs-on: macos-latest 52 | env: 53 | JOB_TYPE: ANALYZE 54 | steps: 55 | - uses: actions/checkout@v3 56 | - uses: actions/checkout@v3 57 | with: 58 | repository: acidanthera/MacKernelSDK 59 | path: MacKernelSDK 60 | - name: CI Bootstrap 61 | run: | 62 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1 63 | - name: VoodooInput Bootstrap 64 | run: | 65 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/VoodooInput/master/VoodooInput/Scripts/bootstrap.sh) && eval "$src" || exit 1 66 | 67 | - run: xcodebuild analyze -quiet -scheme VoodooPS2Controller -configuration Debug CLANG_ANALYZER_OUTPUT=plist-html CLANG_ANALYZER_OUTPUT_DIR="$(pwd)/clang-analyze" && [ "$(find clang-analyze -name "*.html")" = "" ] 68 | - run: xcodebuild analyze -quiet -scheme VoodooPS2Controller -configuration Release CLANG_ANALYZER_OUTPUT=plist-html CLANG_ANALYZER_OUTPUT_DIR="$(pwd)/clang-analyze" && [ "$(find clang-analyze -name "*.html")" = "" ] 69 | 70 | analyze-coverity: 71 | name: Analyze Coverity 72 | runs-on: macos-latest 73 | env: 74 | JOB_TYPE: COVERITY 75 | if: github.repository_owner == 'acidanthera' && github.event_name != 'pull_request' 76 | steps: 77 | - uses: actions/checkout@v3 78 | - uses: actions/checkout@v3 79 | with: 80 | repository: acidanthera/MacKernelSDK 81 | path: MacKernelSDK 82 | - name: CI Bootstrap 83 | run: | 84 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1 85 | - name: Run Coverity 86 | run: | 87 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/coverity/covstrap.sh) && eval "$src" || exit 1 88 | env: 89 | COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 90 | COVERITY_SCAN_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }} 91 | COVERITY_BUILD_COMMAND: xcodebuild -configuration Release 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Build 2 | DerivedData 3 | Distribute 4 | *.xccheckout 5 | .DS_Store 6 | xcuserdata 7 | xcshareddata 8 | project.xcworkspace 9 | VoodooInput 10 | /MacKernelSDK 11 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | VoodooPS2 Changelog 2 | ============================ 3 | #### v2.3.7 4 | - Fixed multiple PS2/SMBus devices attaching 5 | - Fixed eratic pointer in bootpicker by disabling SMBus/PS2 devices on shutdown 6 | 7 | #### v2.3.6 8 | - Lowered macOS requirements to 10.10 9 | - Added PS/2 stub driver for better VoodooRMI compatibility 10 | - Removed old external reset interface originally used by VoodooRMI 11 | 12 | #### v2.3.5 13 | - Removed actAsTrackpad and related logic 14 | - Fix Trackpoints connected to Elan Touchpads 15 | - Use VoodooInput Trackpoint logic for Elan Touchpads 16 | 17 | #### v2.3.4 18 | - Fixed device count detection when `ps2rst=0` is set 19 | - Fixed handleClose not being called by VoodooInput 20 | 21 | #### v2.3.3 22 | - Fixed rapidly opening pages in browsers while scrolling with the trackpoint 23 | - Fixed buttons on various trackpads (especially those without trackpoints attached) 24 | - Fixed DynamicEWMode problem on Lenovo ThinkPad Laptops (acidanthera/bugtracker#890) 25 | 26 | #### v2.3.2 27 | - Added `ps2kbdonly=1` argument not to disable touchpad line on reboot, thx @Kethen 28 | 29 | #### v2.3.1 30 | - Fixed disabled keyboard after reboot 31 | 32 | #### v2.3.0 33 | - Fixed variable shadowing 34 | 35 | #### v2.2.9 36 | - Improved stability of ALPS touchpads 37 | - V8 touchpads can pass all four fingers to VoodooInput natively 38 | - Fixed unpressing during 3 fingers gesture on ALPS V7 39 | - Use VoodooTrackpoint for trackstick and non-MT ALPS touchpads 40 | 41 | #### v2.2.8 42 | - Added ALPS touchpad support 43 | - Fixed ELAN trackpoint scrolling in the wrong direction 44 | 45 | #### v2.2.7 46 | - Fixed kernel panic after S3 47 | 48 | #### v2.2.6 49 | - Fixed some touchpads not waking after S3 50 | 51 | #### v2.2.5 52 | - Added support for touchpads with multiplexors 53 | 54 | #### v2.2.4 55 | - Fixed incorrect command gate initialization causing panics 56 | 57 | #### v2.2.3 58 | - Added `DisableDeepSleep` to workaround ACPI S3 wakes on some Synaptics touchpads 59 | 60 | #### v2.2.2 61 | - Added NumLockSupport & NumLockOnAtBoot 62 | 63 | #### v2.2.1 64 | - Fix issue with registering of services matched by property name "RM,deliverNotifications". It solves issue with broadcasting timestamp for the last pressed key and handling of QuietTimeAfterTyping [see bug #1415](https://github.com/acidanthera/bugtracker/issues/1415) 65 | 66 | #### v2.2.0 67 | - Added VoodooRmi compatibility to allow external touchpad resets 68 | 69 | #### v2.1.9 70 | - Disabled PrntScr remap by default, see `SSDT-PrtSc-Remap.dsl` for example to re-enable it 71 | - Disabled Command and Option remap by default, see `SSDT-Swap-CommandOption.dsl` for example to re-enable it 72 | 73 | #### v2.1.8 74 | - Added support for receiving input form other kexts 75 | - Fixed dynamic coordinate refresh for ELAN v3 touchpads 76 | 77 | #### v2.1.7 78 | - Initial MacKernelSDK and Xcode 12 compatibility 79 | - Added support for select ELAN touchpads by BAndysc and hieplpvip 80 | - Added constants for 11.0 support 81 | 82 | #### v2.1.6 83 | - Upgraded to VoodooInput 1.0.7 84 | - Fixed swiping desktops when holding a dragged item by improving thumb detection 85 | - Fixed keyboard timeout error on some laptop configurations 86 | - Fix Command key being pressed after disabling the keyboard and trackpad with Command-PrtScr key combo 87 | - Added a message to allow other kexts to disable the keyboard 88 | 89 | #### v2.1.5 90 | - Upgraded to VoodooInput 1.0.6 91 | - Added logo + print scr hotkey to disable trackpad 92 | 93 | #### v2.1.4 94 | - Upgraded to VoodooInput 1.0.5 95 | - Improved Smart Zoom and four finger gestures 96 | - Enabled Extended W mode on all trackpads that support it 97 | - Added ability for one special key to block trackpad longer than other keys 98 | - Added a new Force Touch emulation mode 99 | 100 | #### v2.1.3 101 | - Added `ps2rst=0` boot-arg for select CFL laptop compatibility 102 | - Added compatibility with VoodooInput 1.0.4 103 | - VoodooInput is now bundled with VoodooPS2 104 | 105 | #### v2.1.2 106 | - Fixed initialisation race conditions causing kernel panics 107 | 108 | #### v2.1.1 109 | - Fixed kext unloading causing kernel panics 110 | - Fixed Caps Lock LED issues (thx @Goshin) 111 | 112 | #### v2.1.0 113 | - Improved reliability of three-finger dragging 114 | - Improved reliability of finger renumbering algorithm 115 | - Support for four-finger swipes 116 | - Experimental support for four-finger pinch and spread gestures (very unstable) 117 | - Magic Trackpad 2 simulation moved to VoodooInput project 118 | 119 | #### v2.0.4 120 | - Patched CapsLock workaround for Mojave 121 | 122 | #### v2.0.3 123 | - Use touchpad sleep mode during mainboard sleep 124 | - Improve physical and trackpad button support 125 | 126 | #### v2.0.2 127 | - Unified release archive names 128 | - Initial workaround to rare kernel panics 129 | - Rebranding and conflict resolution with other drivers 130 | - Improve reliability of edge swipe gestures 131 | - Support macOS 10.11 to 10.15 beta 132 | - Support Xcode 11 beta 133 | - Support clicking with multiple fingers 134 | - Fix bugs in finger renumbering algorithm 135 | - Ignore hovering above the touchpad 136 | - \[Temporary\] Support overriding touchpad dimensions for old touchpads that don't report minimum coordinates 137 | 138 | Change of earlier versions may be tracked in [commits](https://github.com/acidanthera/VoodooPS2/commits/master) and [releases](https://github.com/acidanthera/VoodooPS2/releases). 139 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-AlternateSwipes.dsl: -------------------------------------------------------------------------------- 1 | // This sample shows how to remap the the default swipes to Option+Arrows, 2 | // instead of the Ctrl+Option+Arrows 3 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 4 | { 5 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 6 | 7 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 8 | { 9 | "Keyboard", Package() 10 | { 11 | "ActionSwipeUp", "37 d, 7e d, 7e u, 37 u", 12 | "ActionSwipeDown", "37 d, 7d d, 7d u, 37 u", 13 | "ActionSwipeLeft", "37 d, 7b d, 7b u, 37 u", 14 | "ActionSwipeRight", "37 d, 7c d, 7c u, 37 u", 15 | }, 16 | }) 17 | } 18 | //EOF 19 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-DisableDeepSleep.dsl: -------------------------------------------------------------------------------- 1 | // For computers with Synaptics touchpad that wake immediately after 2 | // going to sleep deeper touchpad sleep can be disabled. 3 | // 4 | // This will cause the touchpad to consume more power in ACPI S3. 5 | DefinitionBlock("", "SSDT", 2, "ACDT", "ps2", 0) 6 | { 7 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 8 | 9 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 10 | { 11 | "Synaptics TouchPad", Package() 12 | { 13 | "DisableDeepSleep", ">y", 14 | } 15 | }) 16 | } 17 | //EOF 18 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-DisableElanWakeDelay.dsl: -------------------------------------------------------------------------------- 1 | // For some computers wake delay needs to be shorter 2 | // for ELAN touchpad to work after wakeup. 3 | 4 | DefinitionBlock("", "SSDT", 2, "ACDT", "ps2", 0) 5 | { 6 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 7 | 8 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 9 | { 10 | "Elantech TouchPad", Package() 11 | { 12 | "WakeDelay", 0, 13 | }, 14 | }) 15 | } 16 | //EOF 17 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-DisableTrackpadProbe.dsl: -------------------------------------------------------------------------------- 1 | // For computers that either have no trackpad (eg. desktop with PS2 mouse) 2 | // or laptops without any support by VoodooPS2Trackpad.kext, you can disable 3 | // each of the trackpad drivers, such that they don't probe. 4 | // 5 | // This can improve the reliability of VoodooPS2Mouse.kext and is more efficient as well. 6 | DefinitionBlock("", "SSDT", 2, "ACDT", "ps2", 0) 7 | { 8 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 9 | 10 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 11 | { 12 | "Synaptics TouchPad", Package() 13 | { 14 | "DisableDevice", ">y", 15 | }, 16 | "ALPS GlidePoint", Package() 17 | { 18 | "DisableDevice", ">y", 19 | }, 20 | "Sentelic FSP", Package() 21 | { 22 | "DisableDevice", ">y", 23 | }, 24 | }) 25 | } 26 | //EOF 27 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-HP-FixLidSleep.dsl: -------------------------------------------------------------------------------- 1 | // SSDT-HP-FixLidSleep.dsl 2 | // Fix for LID sleep on certain HP computers. 3 | // Make sure you verify _SB.PCI0.LPCB.PS2K ACPI path. 4 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 5 | { 6 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 7 | 8 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 9 | { 10 | "Keyboard", Package() 11 | { 12 | "Custom PS2 Map", Package() 13 | { 14 | Package(){}, 15 | "e005=0", // nullify ps2 code 'e0 05' to prevent keygen at lid close 16 | }, 17 | }, 18 | }) 19 | } 20 | //EOF 21 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-KEY-DELL-WN09.dsl: -------------------------------------------------------------------------------- 1 | // Fix for Dell breakless PS2 keys 2 | // This SSDT selects the Dell profile in the Info.plist for VoodooPS2Keyboard.kext 3 | 4 | // Note: the path to your ACPI keyboard object must match as specified in the SSDT 5 | // This example assumes _SB.PCI0.LPCB.PS2K 6 | // Other common paths are _SB.PCI0.LPCB.KBC, _SB.PCI0.LPC.KBD, etc. 7 | 8 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2dell", 0) 9 | { 10 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 11 | 12 | // Select Dell specific keyboard map in VoodooPS2Keyboard.kext 13 | Method(_SB.PCI0.LPCB.PS2K._DSM, 4) 14 | { 15 | If (!Arg2) { Return (Buffer() { 0x03 } ) } 16 | Return (Package() 17 | { 18 | "RM,oem-id", "DELL", 19 | "RM,oem-table-id", "WN09", 20 | }) 21 | } 22 | } 23 | // EOF 24 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-NumLockOnAtBoot.dsl: -------------------------------------------------------------------------------- 1 | // Set NumLock state to ON at Bootup 2 | 3 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 4 | { 5 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 6 | 7 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 8 | { 9 | "Keyboard", Package() 10 | { 11 | "NumLockOnAtBoot", ">y", 12 | }, 13 | }) 14 | } 15 | //EOF 16 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-NumLockSupport.dsl: -------------------------------------------------------------------------------- 1 | // Add Support for Num Lock key 2 | // By Default Voodoo maps Num Lock to Clear key because of the following 3 | // 1) On USB keyboards Num Lock is translated to the Clear key 4 | // 2) On Apple keyboards there is no Num Lock key 5 | 6 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 7 | { 8 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 9 | 10 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 11 | { 12 | "Keyboard", Package() 13 | { 14 | "NumLockSupport", ">y", 15 | }, 16 | }) 17 | } 18 | //EOF 19 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-PrtSc-Remap.dsl: -------------------------------------------------------------------------------- 1 | // Remap PrntScr to disable touchpad/keyboard 2 | // Supported Voodoo PrntScr Key combinations: 3 | 4 | // PrntScr Enable/Disable touchpad 5 | // Windows+PrntScr Enable/Disable touchpad+keyboard 6 | // Ctrl+Alt+PrntScr Reset and enable touchpad 7 | // Shift+PrntScr Send SysRq scancode to the kernel 8 | 9 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 10 | { 11 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 12 | 13 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 14 | { 15 | "Keyboard", Package() 16 | { 17 | "RemapPrntScr", ">y", 18 | }, 19 | }) 20 | } 21 | //EOF 22 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-Swap-CommandOption.dsl: -------------------------------------------------------------------------------- 1 | // This sample shows how to remap the Command and Option. 2 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 3 | { 4 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 5 | 6 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 7 | { 8 | "Keyboard", Package() 9 | { 10 | "Swap command and option", ">y", 11 | } 12 | }) 13 | } 14 | //EOF 15 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-Swap-LeftControlCapsLock.dsl: -------------------------------------------------------------------------------- 1 | // This sample shows how to remap the Left Control to CapsLock, 2 | // and CapsLock to Left Control. 3 | // Be sure to specify the correct path to your device, followed by ".RMCF" 4 | // For example, a Lenovo x1 Carbon 5th Gen would be "_SB.PCI0.LPCB.KBD.RMCF" 5 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 6 | { 7 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 8 | 9 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 10 | { 11 | "Keyboard", Package() 12 | { 13 | "Custom ADB Map", Package() 14 | { 15 | Package(){}, 16 | "3a=3b", // 3a is PS2 for capslock, 3b is ADB for left control (normal map is 3a=39) 17 | "1d=39", // 1d is PS2 for left control, 39 is ADB for caps lock (normal map is 1d=3b) 18 | }, 19 | }, 20 | }) 21 | } 22 | //EOF 23 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-Swap-LeftControlCommand.dsl: -------------------------------------------------------------------------------- 1 | // This sample shows how to remap the Left Control to Command, 2 | // and Command (left Alt) to Left Control. 3 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 4 | { 5 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) 6 | 7 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 8 | { 9 | "Keyboard", Package() 10 | { 11 | "Custom ADB Map", Package() 12 | { 13 | Package(){}, 14 | "1d=3a", // 1d is PS2 for left control, 3a is ADB for command 15 | "38=3b", // 38 is PS2 for left alt, 3b is ADB for left control 16 | }, 17 | }, 18 | }) 19 | } 20 | //EOF 21 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-Thinkpad_Clickpad.dsl: -------------------------------------------------------------------------------- 1 | // Example overrides for Thinkpad models with ClickPad 2 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 3 | { 4 | // Change _SB.PCI0.LPC.KBD if your PS2 keyboard is at a different ACPI path 5 | External(_SB.PCI0.LPC.KBD, DeviceObj) 6 | Scope(_SB.PCI0.LPC.KBD) 7 | { 8 | // Select specific configuration in VoodooPS2Trackpad.kext 9 | Method(_DSM, 4) 10 | { 11 | If (!Arg2) { Return (Buffer() { 0x03 } ) } 12 | Return (Package() 13 | { 14 | "RM,oem-id", "LENOVO", 15 | "RM,oem-table-id", "Thinkpad_ClickPad", 16 | }) 17 | } 18 | // Overrides (the example data here is default in the Info.plist) 19 | Name(RMCF, Package() 20 | { 21 | "Synaptics TouchPad", Package() 22 | { 23 | "HWResetOnStart", ">y", 24 | "QuietTimeAfterTyping", 500000000, 25 | "FingerZ", 30, 26 | "MouseMultiplierX", 2, 27 | "MouseMultiplierY", 2, 28 | "MouseDivisorX", 1, 29 | "MouseDivisorY", 1, 30 | // Change multipliers to 0xFFFE in order to inverse the scroll direction 31 | // of the Trackpoint when holding the middle mouse button. 32 | "TrackpointScrollXMultiplier", 2, 33 | "TrackpointScrollYMultiplier", 2, 34 | "TrackpointScrollXDivisor", 1, 35 | "TrackpointScrollYDivisor", 1 36 | }, 37 | }) 38 | } 39 | } 40 | //EOF 41 | -------------------------------------------------------------------------------- /Docs/ACPI/SSDT-Thinkpad_Trackpad.dsl: -------------------------------------------------------------------------------- 1 | // Example overrides for Thinkpad models with TrackPad 2 | DefinitionBlock ("", "SSDT", 2, "ACDT", "ps2", 0) 3 | { 4 | External(_SB_.PCI0.LPCB.PS2K, DeviceObj) 5 | // Change _SB.PCI0.LPC.KBD if your PS2 keyboard is at a different ACPI path 6 | External(_SB_.PCI0.LPC.KBD, DeviceObj) 7 | Scope(_SB.PCI0.LPC.KBD) 8 | { 9 | // Select specific configuration in VoodooPS2Trackpad.kext 10 | Method(_SB.PCI0.LPCB.PS2K._DSM, 4) 11 | { 12 | If (!Arg2) { Return (Buffer() { 0x03 } ) } 13 | Return (Package() 14 | { 15 | "RM,oem-id", "LENOVO", 16 | "RM,oem-table-id", "Thinkpad_TrackPad", 17 | }) 18 | } 19 | // Overrides (the example data here is default in the Info.plist) 20 | Name(_SB.PCI0.LPCB.PS2K.RMCF, Package() 21 | { 22 | "Synaptics TouchPad", Package() 23 | { 24 | "HWResetOnStart", ">y", 25 | "PalmNoAction When Typing", ">y", 26 | "FingerZ", 47, 27 | "MouseMultiplierX", 8, 28 | "MouseMultiplierY", 8, 29 | "MouseDivisorX", 1, 30 | "MouseDivisorY", 1, 31 | // Change multipliers to 0xFFFE in order to inverse the scroll direction 32 | // of the Trackpoint when holding the middle mouse button. 33 | "TrackpointScrollXMultiplier", 2, 34 | "TrackpointScrollYMultiplier", 2, 35 | "TrackpointScrollXDivisor", 1, 36 | "TrackpointScrollYDivisor", 1 37 | }, 38 | }) 39 | } 40 | } 41 | //EOF 42 | -------------------------------------------------------------------------------- /Docs/SynapticsRevB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidanthera/VoodooPS2/b6713c37b9919bd95c3b7f4d484bd049371bcfc1/Docs/SynapticsRevB.pdf -------------------------------------------------------------------------------- /Docs/force_touch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidanthera/VoodooPS2/b6713c37b9919bd95c3b7f4d484bd049371bcfc1/Docs/force_touch.png -------------------------------------------------------------------------------- /Docs/voodoops2ioio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ioio=/usr/local/bin/ioio 4 | 5 | $ioio -s ApplePS2SynapticsTouchPad Dragging 1 6 | $ioio -s ApplePS2SynapticsTouchPad DragExitDelayTime 500000000 7 | # $ioio -s ApplePS2SynapticsTouchPad DragExitDelayTime 250000000 8 | $ioio -s ApplePS2Keyboard "Swap command and option" true 9 | 10 | #3 finger gestures are disabled when three-finger drag is on 11 | # avoid using with three finger drag 12 | $ioio -s ApplePS2Keyboard Action3FingersSpread :"" 13 | $ioio -s ApplePS2Keyboard Action3FingersPinch :"" 14 | 15 | # cmd-left/right 16 | $ioio -s ApplePS2Keyboard ActionSwipeLeft :"" #37 d, 1e d, 1e u, 37 u" 17 | $ioio -s ApplePS2Keyboard ActionSwipeRight :"" #37 d, 21 d, 21 u, 37 u" 18 | $ioio -s ApplePS2Keyboard ActionSwipeUp :"" 19 | $ioio -s ApplePS2Keyboard ActionSwipeDown :"" 20 | 21 | # ctrl-right/left/up/down 22 | $ioio -s ApplePS2Keyboard ActionSwipe4FingersLeft :"3b d, 7c d, 7c u, 3b u" 23 | $ioio -s ApplePS2Keyboard ActionSwipe4FingersRight :"3b d, 7b d, 7b u, 3b u" 24 | $ioio -s ApplePS2Keyboard ActionSwipe4FingersUp :"3b d, 7e d, 7e u, 3b u" 25 | $ioio -s ApplePS2Keyboard ActionSwipe4FingersDown :"3b d, 7d d, 7d u, 3b u" 26 | 27 | # not ready 28 | $ioio -s ApplePS2Keyboard Action4FingersSpread :"" 29 | $ioio -s ApplePS2Keyboard Action4FingersPinch :"" 30 | 31 | # cmd-space 32 | $ioio -s ApplePS2Keyboard Action2FingersTap :"" # implementation not ready 33 | $ioio -s ApplePS2Keyboard Action3FingersTap :"" #37 d, 31 d, 31 u, 37 u" 34 | $ioio -s ApplePS2Keyboard Action4FingersTap :"37 d, 31 d, 31 u, 37 u" 35 | 36 | $ioio -s ApplePS2SynapticsTouchPad TrackpadRightClick 1 37 | $ioio -s ApplePS2SynapticsTouchPad TrackpadMiddleClick 1 38 | 39 | $ioio -s ApplePS2SynapticsTouchPad TrackpadThreeFingerDrag 1 40 | 41 | $ioio -s ApplePS2Keyboard LogScanCodes 0 42 | 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## APPLE PUBLIC SOURCE LICENSE 2 | ## Version 2.0 - August 6, 2003 3 | 4 | Please read this License carefully before downloading this software. By downloading or using this software, you are agreeing to be bound by the terms of this License. If you do not or cannot agree to the terms of this License, please do not download or use the software. 5 | 6 | 1\. General; Definitions. This License applies to any program or other work which Apple Computer, Inc. ("Apple") makes publicly available and which contains a notice placed by Apple identifying such program or work as "Original Code" and stating that it is subject to the terms of this Apple Public Source License version 2.0 ("License"). As used in this License: 7 | 8 | 1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to Apple and (ii) that cover subject matter contained in the Original Code, but only to the extent necessary to use, reproduce and/or distribute the Original Code without infringement; and (b) in the case where You are the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to You and (ii) that cover subject matter in Your Modifications, taken alone or in combination with Original Code. 9 | 10 | 1.2 "Contributor" means any person or entity that creates or contributes to the creation of Modifications. 11 | 12 | 1.3 "Covered Code" means the Original Code, Modifications, the combination of Original Code and any Modifications, and/or any respective portions thereof. 13 | 14 | 1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise make Covered Code available, directly or indirectly, to anyone other than You; and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way to provide a service, including but not limited to delivery of content, through electronic communication with a client other than You. 15 | 16 | 1.5 "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 17 | 18 | 1.6 "Modifications" mean any addition to, deletion from, and/or change to, the substance and/or structure of the Original Code, any previous Modifications, the combination of Original Code and any previous Modifications, and/or any respective portions thereof. When code is released as a series of files, a Modification is: (a) any addition to or deletion from the contents of a file containing Covered Code; and/or (b) any new file or other representation of computer program statements that contains any part of Covered Code. 19 | 20 | 1.7 "Original Code" means (a) the Source Code of a program or other work as originally made available by Apple under this License, including the Source Code of any updates or upgrades to such programs or works made available by Apple under this License, and that has been expressly identified by Apple as such in the header file(s) of such work; and (b) the object code compiled from such Source Code and originally made available by Apple under this License. 21 | 22 | 1.8 "Source Code" means the human readable form of a program or other work that is suitable for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an executable (object code). 23 | 24 | 1.9 "You" or "Your" means an individual or a legal entity exercising rights under this License. For legal entities, "You" or "Your" includes any entity which controls, is controlled by, or is under common control with, You, where "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. 25 | 26 | 2\. Permitted Uses; Conditions & Restrictions. Subject to the terms and conditions of this License, Apple hereby grants You, effective on the date You accept this License and download the Original Code, a world-wide, royalty-free, non-exclusive license, to the extent of Apple's Applicable Patent Rights and copyrights covering the Original Code, to do the following: 27 | 28 | 2.1 Unmodified Code. You may use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy verbatim, unmodified copies of the Original Code, for commercial or non-commercial purposes, provided that in each instance: 29 | 30 | (a) You must retain and reproduce in all copies of Original Code the copyright and other proprietary notices and disclaimers of Apple as they appear in the Original Code, and keep intact all notices in the Original Code that refer to this License; and 31 | 32 | (b) You must include a copy of this License with every copy of Source Code of Covered Code and documentation You distribute or Externally Deploy, and You may not offer or impose any terms on such Source Code that alter or restrict this License or the recipients' rights hereunder, except as permitted under Section 6. 33 | 34 | 2.2 Modified Code. You may modify Covered Code and use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy Your Modifications and Covered Code, for commercial or non-commercial purposes, provided that in each instance You also meet all of these conditions: 35 | 36 | (a) You must satisfy all the conditions of Section 2.1 with respect to the Source Code of the Covered Code; 37 | 38 | (b) You must duplicate, to the extent it does not already exist, the notice in Exhibit A in each file of the Source Code of all Your Modifications, and cause the modified files to carry prominent notices stating that You changed the files and the date of any change; and 39 | 40 | (c) If You Externally Deploy Your Modifications, You must make Source Code of all Your Externally Deployed Modifications either available to those to whom You have Externally Deployed Your Modifications, or publicly available. Source Code of Your Externally Deployed Modifications must be released under the terms set forth in this License, including the license grants set forth in Section 3 below, for as long as you Externally Deploy the Covered Code or twelve (12) months from the date of initial External Deployment, whichever is longer. You should preferably distribute the Source Code of Your Externally Deployed Modifications electronically (e.g. download from a web site). 41 | 42 | 2.3 Distribution of Executable Versions. In addition, if You Externally Deploy Covered Code (Original Code and/or Modifications) in object code, executable form only, You must include a prominent notice, in the code itself as well as in related documentation, stating that Source Code of the Covered Code is available under the terms of this License with information on how and where to obtain such Source Code. 43 | 44 | 2.4 Third Party Rights. You expressly acknowledge and agree that although Apple and each Contributor grants the licenses to their respective portions of the Covered Code set forth herein, no assurances are provided by Apple or any Contributor that the Covered Code does not infringe the patent or other intellectual property rights of any other entity. Apple and each Contributor disclaim any liability to You for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, You hereby assume sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow You to distribute the Covered Code, it is Your responsibility to acquire that license before distributing the Covered Code. 45 | 46 | 3\. Your Grants. In consideration of, and as a condition to, the licenses granted to You under this License, You hereby grant to any person or entity receiving or distributing Covered Code under this License a non-exclusive, royalty-free, perpetual, irrevocable license, under Your Applicable Patent Rights and other intellectual property rights (other than patent) owned or controlled by You, to use, reproduce, display, perform, modify, sublicense, distribute and Externally Deploy Your Modifications of the same scope and extent as Apple's licenses under Sections 2.1 and 2.2 above. 47 | 48 | 4\. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In each such instance, You must make sure the requirements of this License are fulfilled for the Covered Code or any portion thereof. 49 | 50 | 5\. Limitations on Patent License. Except as expressly stated in Section 2, no other patent rights, express or implied, are granted by Apple herein. Modifications and/or Larger Works may require additional patent licenses from Apple which Apple may grant in its sole discretion. 51 | 52 | 6\. Additional Terms. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations and/or other rights consistent with the scope of the license granted herein ("Additional Terms") to one or more recipients of Covered Code. However, You may do so only on Your own behalf and as Your sole responsibility, and not on behalf of Apple or any Contributor. You must obtain the recipient's agreement that any such Additional Terms are offered by You alone, and You hereby agree to indemnify, defend and hold Apple and every Contributor harmless for any liability incurred by or claims asserted against Apple or such Contributor by reason of any such Additional Terms. 53 | 54 | 7\. Versions of the License. Apple may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Once Original Code has been published under a particular version of this License, You may continue to use it under the terms of that version. You may also choose to use such Original Code under the terms of any subsequent version of this License published by Apple. No one other than Apple has the right to modify the terms applicable to Covered Code created under this License. 55 | 56 | 8\. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in part pre-release, untested, or not fully tested works. The Covered Code may contain errors that could cause failures or loss of data, and may be incomplete or contain inaccuracies. You expressly acknowledge and agree that use of the Covered Code, or any portion thereof, is at Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge that the Covered Code is not intended for use in the operation of nuclear facilities, aircraft navigation, communication systems, or air traffic control machines in which case the failure of the Covered Code could lead to death, personal injury, or severe physical or environmental damage. 57 | 58 | 9\. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to You for all damages (other than as may be required by applicable law) under this License exceed the amount of fifty dollars ($50.00). 59 | 60 | 10\. Trademarks. This License does not grant any rights to use the trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", "QuickTime", "QuickTime Streaming Server" or any other trademarks, service marks, logos or trade names belonging to Apple (collectively "Apple Marks") or to any trademark, service mark, logo or trade name belonging to any Contributor. You agree not to use any Apple Marks in or as part of the name of products derived from the Original Code or to endorse or promote products derived from the Original Code other than as expressly permitted by and in strict compliance at all times with Apple's third party trademark usage guidelines which are posted at http://www.apple.com/legal/guidelinesfor3rdparties.html. 61 | 62 | 11\. Ownership. Subject to the licenses granted under this License, each Contributor retains all rights, title and interest in and to any Modifications made by such Contributor. Apple retains all rights, title and interest in and to the Original Code and any Modifications made by or on behalf of Apple ("Apple Modifications"), and such Apple Modifications will not be automatically subject to this License. Apple may, at its sole discretion, choose to license such Apple Modifications under this License, or on different terms from those contained in this License or may choose not to license them at all. 63 | 64 | 12\. Termination. 65 | 66 | 12.1 Termination. This License and the rights granted hereunder will terminate: 67 | 68 | (a) automatically without notice from Apple if You fail to comply with any term(s) of this License and fail to cure such breach within 30 days of becoming aware of such breach; 69 | 70 | (b) immediately in the event of the circumstances described in Section 13.5(b); or 71 | 72 | (c) automatically without notice from Apple if You, at any time during the term of this License, commence an action for patent infringement against Apple; provided that Apple did not first commence an action for patent infringement against You in that instance. 73 | 74 | 12.2 Effect of Termination. Upon termination, You agree to immediately stop any further use, reproduction, modification, sublicensing and distribution of the Covered Code. All sublicenses to the Covered Code which have been properly granted prior to termination shall survive any termination of this License. Provisions which, by their nature, should remain in effect beyond the termination of this License shall survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other for compensation, indemnity or damages of any sort solely as a result of terminating this License in accordance with its terms, and termination of this License will be without prejudice to any other right or remedy of any party. 75 | 76 | 13\. Miscellaneous. 77 | 78 | 13.1 Government End Users. The Covered Code is a "commercial item" as defined in FAR 2.101. Government software and technical data rights in the Covered Code include only those rights customarily provided to the public as defined in this License. This customary commercial license in technical data and software is provided in accordance with FAR 12.211 (Technical Data) and 12.212 (Computer Software) and, for Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in Commercial Computer Software or Computer Software Documentation). Accordingly, all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 79 | 80 | 13.2 Relationship of Parties. This License will not be construed as creating an agency, partnership, joint venture or any other form of legal association between or among You, Apple or any Contributor, and You will not represent to the contrary, whether expressly, by implication, appearance or otherwise. 81 | 82 | 13.3 Independent Development. Nothing in this License will impair Apple's right to acquire, license, develop, have others develop for it, market and/or distribute technology or products that perform the same or similar functions as, or otherwise compete with, Modifications, Larger Works, technology or products that You may develop, produce, market or distribute. 83 | 84 | 13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce any provision of this License will not be deemed a waiver of future enforcement of that or any other provision. Any law or regulation which provides that the language of a contract shall be construed against the drafter will not apply to this License. 85 | 86 | 13.5 Severability. (a) If for any reason a court of competent jurisdiction finds any provision of this License, or portion thereof, to be unenforceable, that provision of the License will be enforced to the maximum extent permissible so as to effect the economic benefits and intent of the parties, and the remainder of this License will continue in full force and effect. (b) Notwithstanding the foregoing, if applicable law prohibits or restricts You from fully and/or specifically complying with Sections 2 and/or 3 or prevents the enforceability of either of those Sections, this License will immediately terminate and You must immediately discontinue any use of the Covered Code and destroy all copies of it that are in your possession or control. 87 | 88 | 13.6 Dispute Resolution. Any litigation or other dispute resolution between You and Apple relating to this License shall take place in the Northern District of California, and You and Apple hereby consent to the personal jurisdiction of, and venue in, the state and federal courts within that District with respect to this License. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. 89 | 90 | 13.7 Entire Agreement; Governing Law. This License constitutes the entire agreement between the parties with respect to the subject matter hereof. This License shall be governed by the laws of the United States and the State of California, except that body of California law concerning conflicts of law. 91 | 92 | Where You are located in the province of Quebec, Canada, the following clause applies: The parties hereby confirm that they have requested that this License and all related documents be drafted in English. Les parties ont exige que le present contrat et tous les documents connexes soient rediges en anglais. 93 | 94 | EXHIBIT A. 95 | 96 | "Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 97 | 98 | This file contains Original Code and/or Modifications of Original Code as defined in and that are subject to the Apple Public Source License Version 2.0 (the 'License'). You may not use this file except in compliance with the License. Please obtain a copy of the License at http://www.opensource.apple.com/apsl/ and read it before using this file. 99 | 100 | The Original Code and all software distributed under the License are distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the specific language governing rights and limitations under the License." 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VoodooPS2 2 | ========= 3 | 4 | [![Build Status](https://github.com/acidanthera/VoodooPS2/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/acidanthera/VoodooPS2/actions) [![Scan Status](https://scan.coverity.com/projects/22190/badge.svg?flat=1)](https://scan.coverity.com/projects/22190) 5 | 6 | New **VoodooPS2Trackpad** uses VoodooInput's Magic Trackpad II emulation in order to use macOS native driver instead of handling all gestures itself. This enables the use of any from one to four finger gestures defined by Apple including: 7 | * Look up & data detectors 8 | * Secondary click (*with two fingers, in bottom left corner\*, in bottom right corner\**) 9 | * Tap to click 10 | * Scrolling 11 | * Zoom in or out 12 | * Smart zoom 13 | * Rotate 14 | * Swipe between pages 15 | * Swipe between full-screen apps (*with three or four fingers*) 16 | * Notification Centre 17 | * Mission Control (*with three or four fingers*) 18 | * App Exposé (*with three or four fingers*) 19 | * Dragging with or without drag lock (*configured in 'Accessibility'/'Universal Access' prefpane*) 20 | * Three finger drag (*configured in 'Accessibility'/'Universal Access' prefpane, may work unreliably\*\**) 21 | * Launchpad (*may work unreliably*) 22 | * Show Desktop (*may work unreliably*) 23 | * Screen zoom (*configured in 'Accessibility'/'Universal Access' -> Zoom -> Advanced -> Controls -> Use trackpad gesture to zoom*) 24 | 25 | It also supports **BetterTouchTool**. 26 | 27 | In addition this kext supports **Force Touch** emulation (*configured in `Info.plist`*): 28 | * **Mode 0** – Force Touch emulation is disabled (*you can also disable it in **System Preferences** without setting the mode*). 29 | * **Mode 1** – Force Touch emulation using a physical button: on ClickPads (touchpads which have the whole surface clickable (the physical button is inside the laptop under the bottom of touchpad)), the physical button can be remapped to Force Touch. In such mode a tap is a regular click, if **Tap to click** gesture is enabled in **System Preferences**, and a click is a Force Touch. This mode is convenient for people who usually tap on the touchpad, not click. 30 | * **Mode 2** – *'wide tap'*: for Force Touch one needs to increase the area of a finger touching the touchpad\*\*\*. The necessary width can be set in `Info.plist`. 31 | * **Mode 3** – pressure value is passed to the system as is; this mode shouldn't be used. 32 | * **Mode 4** (*by @Tarik02*) – pressure is passed to the system using the following formula: ![formula](Docs/force_touch.png) 33 | The parameters in the formula are configured using `ForceTouchCustomUpThreshold`, `ForceTouchCustomDownThreshold` and `ForceTouchCustomPower` keys in `Info.plist` or configuration SSDT. Note that `ForceTouchCustomDownThreshold` is the *upper* limit on the pressure value and vice versa, because it corresponds to the touchpad being fully pressed *down*. 34 | 35 | For Elan touchpad, only mode 0 and mode 1 are supported. 36 | 37 | For ALPS touchpads, V1, V2 and V6 do not support Force Touch. V3, V4 and V5 only support mode 0, 2, 3 and 4. V7 only supports mode 0 and 1. V8 supports all modes. 38 | 39 | ## Installation and compilation 40 | 41 | For VoodooPS2Trackpad.kext to work multitouch interface engine, named VoodooInput.kext, is required. 42 | 43 | - For released binaries a compatible version of VoodooInput.kext is already included in the PlugIns directory. 44 | - For custom compiled versions VoodooInput.kext bootstrapping is required prior to compilation. 45 | By default Xcode project will do this automatically. If you prefer to have your own control over the 46 | process execute the following command in the project directory to have VoodooInput bootstrapped: 47 | 48 | ``` 49 | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/VoodooInput/master/VoodooInput/Scripts/bootstrap.sh) && eval "$src" || exit 1 50 | ``` 51 | 52 | ## Touchpad and Keyboard Input Toggle 53 | 54 | This kext supports disabling touch input by pressing the Printscreen key on your keyboard, or the touchpad disable key on many laptops. Simply press the key to toggle touchpad input off and again to toggle it back on. 55 | 56 | In addition, for 2-in-1 systems that do not support disabling the keyboard in hardware while in tablet mode you may toggle keyboard input off and on by holding option(Windows) and pressing the Printscreen key. Repeat the keypress to re-enable keyboard input. These settings are runtime only and do not persist across a reboot. 57 | 58 | ## Credits: 59 | * VoodooPS2Controller etc. – turbo, mackerintel, @RehabMan, nhand42, phb, Chunnan, jape, bumby (see RehabMan's repository). 60 | * Magic Trackpad 2 reverse engineering and implementation – https://github.com/alexandred/VoodooI2C project team. 61 | * VoodooPS2Trackpad integration – @kprinssu. 62 | * Force Touch emulation and finger renumbering algorithm** – @usr-sse2. 63 | * Elan touchpad driver – linux kernel contributors, @kprinssu, @BAndysc and @hieplpvip 64 | 65 | \* On my touchpad this gesture was practically impossible to perform with the old VoodooPS2Trackpad. Now it works well. 66 | 67 | \*\* Due to the limitations of PS/2 bus, Synaptics touchpad reports only the number of fingers and coordinates of two of them to the computer. When there are two fingers on the touchpad and third finger is added, a 'jump' may happen, because the coordinates of one of the fingers are replaced with the coordinates of the added finger. Finger renumbering algorithm estimates the distance from old coordinates to new ones in order to hide this 'jump' from the OS ~~and to calculate approximate position of the 'hidden' finger, in assumption that fingers move together in parallel to each other~~. Now third and fourth fingers are reported at the same position as one of the first two fingers. It allows Launchpad/Show desktop gesture to work more reliably. 68 | 69 | \*\*\* The touchpad reports both finger width (ranged from 4 to 15) and pressure (ranged from 0 to 255), but in practice the measured width is almost always 4, and the reported pressure depends more on actual touch width than on actual pressure. 70 | -------------------------------------------------------------------------------- /VoodooPS2Controller.xcodeproj/xcshareddata/xcschemes/VoodooPS2Controller.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 57 | 63 | 64 | 65 | 71 | 77 | 78 | 79 | 85 | 91 | 92 | 93 | 94 | 95 | 100 | 101 | 107 | 108 | 109 | 110 | 111 | 112 | 122 | 123 | 129 | 130 | 131 | 132 | 138 | 139 | 145 | 146 | 147 | 148 | 150 | 151 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /VoodooPS2Controller.xcodeproj/xcshareddata/xcschemes/VoodooPS2Keyboard.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /VoodooPS2Controller.xcodeproj/xcshareddata/xcschemes/VoodooPS2Mouse.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /VoodooPS2Controller.xcodeproj/xcshareddata/xcschemes/VoodooPS2Trackpad.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /VoodooPS2Controller/AppleACPIPS2Nub.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /*! @file AppleACPIPS2Nub.cpp 24 | @abstract AppleACPIPS2Nub class implementation 25 | @discussion 26 | Implements the ACPI PS/2 nub for ApplePS2Controller.kext. 27 | Reverse-engineered from the Darwin 8 binary ACPI kext. 28 | Copyright 2007 David Elliott 29 | */ 30 | 31 | #include "AppleACPIPS2Nub.h" 32 | 33 | #if 0 34 | #define DEBUG_LOG(args...) 35 | #else 36 | #undef DEBUG_LOG 37 | #define DEBUG_LOG(args...) 38 | #endif 39 | 40 | static IOPMPowerState myTwoStates[2] = { 41 | {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42 | {1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0} 43 | }; 44 | 45 | OSDefineMetaClassAndStructors(AppleACPIPS2Nub, IOPlatformDevice); 46 | 47 | // We could simply ask for the PE rather than importing the global 48 | // from AppleACPIPlatformExpert.kext 49 | // extern IOPlatformExpert *gAppleACPIPlatformExpert; 50 | 51 | bool AppleACPIPS2Nub::start(IOService *provider) 52 | { 53 | if (!super::start(provider)) 54 | return false; 55 | 56 | DEBUG_LOG("AppleACPIPS2Nub::start: provider=%p\n", provider); 57 | 58 | /* Initialize our interrupt controller/specifier i-vars */ 59 | m_interruptControllers = OSArray::withCapacity(2); 60 | m_interruptSpecifiers = OSArray::withCapacity(2); 61 | if(m_interruptControllers == NULL || m_interruptSpecifiers == NULL) 62 | return false; 63 | 64 | /* Merge in the keyboard (primary) provider interrupt properties */ 65 | mergeInterruptProperties(provider, LEGACY_KEYBOARD_IRQ); 66 | 67 | /* Initialize and register our power management properties */ 68 | PMinit(); 69 | registerPowerDriver(this, myTwoStates, 2); 70 | provider->joinPMtree(this); 71 | 72 | /* Find the mouse provider */ 73 | m_mouseProvider = findMouseDevice(); 74 | if(m_mouseProvider != NULL) 75 | { 76 | DEBUG_LOG("AppleACPIPS2Nub::start: Found mouse PNP device\n"); 77 | if(attach(m_mouseProvider)) 78 | { 79 | mergeInterruptProperties(m_mouseProvider, LEGACY_MOUSE_IRQ); 80 | if(m_mouseProvider->inPlane(gIOPowerPlane)) 81 | { 82 | m_mouseProvider->joinPMtree(this); 83 | } 84 | } 85 | } 86 | 87 | /* Set our interrupt properties in the IO registry */ 88 | if(m_interruptControllers->getCount() != 0 && m_interruptSpecifiers->getCount() != 0) 89 | { 90 | setProperty(gIOInterruptControllersKey, m_interruptControllers); 91 | setProperty(gIOInterruptSpecifiersKey, m_interruptSpecifiers); 92 | } 93 | 94 | /* Release the arrays we allocated. Our properties dictionary has them retained */ 95 | m_interruptControllers->release(); 96 | m_interruptControllers = NULL; 97 | m_interruptSpecifiers->release(); 98 | m_interruptSpecifiers = NULL; 99 | 100 | /* Make ourselves the ps2controller nub and register so ApplePS2Controller can find us. */ 101 | setName("ps2controller"); 102 | registerService(); 103 | 104 | DEBUG_LOG("AppleACPIPS2Nub::start: startup complete\n"); 105 | 106 | return true; 107 | } 108 | 109 | void AppleACPIPS2Nub::stop(IOService *provider) 110 | { 111 | PMstop(); 112 | return super::stop(provider); 113 | } 114 | 115 | IOService *AppleACPIPS2Nub::findMouseDevice() 116 | { 117 | OSObject *prop = getProperty("MouseNameMatch"); 118 | /* Slight delay to allow PS2 mouse entry in IOACPIPlane to populate */ 119 | UInt32 findMouseDelay = 100; // default 100ms delay before checking iroeg for mouse matches 120 | if (OSNumber* number = OSDynamicCast(OSNumber, getProperty("FindMouseDelay"))) 121 | findMouseDelay = number->unsigned32BitValue(); 122 | UInt32 vps2FindMouseDelay; 123 | if (PE_parse_boot_argn("vps2_findmousedelay", &vps2FindMouseDelay, sizeof vps2FindMouseDelay)) 124 | findMouseDelay = vps2FindMouseDelay; 125 | if (findMouseDelay) 126 | IOSleep(findMouseDelay); 127 | /* Search from the root of the ACPI plane for the mouse PNP nub */ 128 | IORegistryIterator *i = IORegistryIterator::iterateOver(gIOACPIPlane, kIORegistryIterateRecursively); 129 | IORegistryEntry *entry; 130 | if(i != NULL) 131 | { 132 | while((entry = i->getNextObject())) 133 | { 134 | if(entry->compareNames(prop)) 135 | break; 136 | } 137 | i->release(); 138 | } 139 | else 140 | entry = NULL; 141 | return OSDynamicCast(IOService, entry); 142 | } 143 | 144 | void AppleACPIPS2Nub::mergeInterruptProperties(IOService *pnpProvider, long) 145 | { 146 | /* Get the interrupt controllers/specifiers arrays from the provider, and make sure they 147 | * exist and contain at least one entry. We assume they contain exactly one entry. 148 | */ 149 | OSArray *controllers = OSDynamicCast(OSArray,pnpProvider->getProperty(gIOInterruptControllersKey)); 150 | OSArray *specifiers = OSDynamicCast(OSArray,pnpProvider->getProperty(gIOInterruptSpecifiersKey)); 151 | if(controllers == NULL || specifiers == NULL) 152 | return; 153 | if(controllers->getCount() == 0 || specifiers->getCount() == 0) 154 | return; 155 | 156 | /* Append the first object of each array into our own respective array */ 157 | m_interruptControllers->setObject(controllers->getObject(0)); 158 | m_interruptSpecifiers->setObject(specifiers->getObject(0)); 159 | } 160 | 161 | IOReturn AppleACPIPS2Nub::registerInterrupt(int source, OSObject *target, IOInterruptAction handler, void *refCon) 162 | { 163 | if(source == LEGACY_KEYBOARD_IRQ) 164 | return super::registerInterrupt(0, target, handler, refCon); 165 | else if(source == LEGACY_MOUSE_IRQ) 166 | return super::registerInterrupt(1, target, handler, refCon); 167 | else 168 | return kIOReturnBadArgument; 169 | } 170 | 171 | IOReturn AppleACPIPS2Nub::unregisterInterrupt(int source) 172 | { 173 | if(source == LEGACY_KEYBOARD_IRQ) 174 | return super::unregisterInterrupt(0); 175 | else if(source == LEGACY_MOUSE_IRQ) 176 | return super::unregisterInterrupt(1); 177 | else 178 | return kIOReturnBadArgument; 179 | } 180 | 181 | IOReturn AppleACPIPS2Nub::getInterruptType(int source, int *interruptType) 182 | { 183 | if(source == LEGACY_KEYBOARD_IRQ) 184 | return super::getInterruptType(0, interruptType); 185 | else if(source == LEGACY_MOUSE_IRQ) 186 | return super::getInterruptType(1, interruptType); 187 | else 188 | return kIOReturnBadArgument; 189 | } 190 | 191 | IOReturn AppleACPIPS2Nub::enableInterrupt(int source) 192 | { 193 | if(source == LEGACY_KEYBOARD_IRQ) 194 | return super::enableInterrupt(0); 195 | else if(source == LEGACY_MOUSE_IRQ) 196 | return super::enableInterrupt(1); 197 | else 198 | return kIOReturnBadArgument; 199 | } 200 | 201 | IOReturn AppleACPIPS2Nub::disableInterrupt(int source) 202 | { 203 | if(source == LEGACY_KEYBOARD_IRQ) 204 | return super::disableInterrupt(0); 205 | else if(source == LEGACY_MOUSE_IRQ) 206 | return super::disableInterrupt(1); 207 | else 208 | return kIOReturnBadArgument; 209 | } 210 | 211 | bool AppleACPIPS2Nub::compareName( OSString * name, OSString ** matched ) const 212 | { 213 | // return gAppleACPIPlatformExpert->compareNubName( this, name, matched ); 214 | return( this->IORegistryEntry::compareName( name, matched )); 215 | } 216 | 217 | IOReturn AppleACPIPS2Nub::getResources( void ) 218 | { 219 | // return gAppleACPIPlatformExpert->getNubResources(this); 220 | return( kIOReturnSuccess ); 221 | } 222 | 223 | IOReturn AppleACPIPS2Nub::message( UInt32 type, IOService *provider, void *argument ) 224 | { 225 | ////DEBUG_LOG("AppleACPIPS2Nub::message: type=%x, provider=%p, argument=%p\n", type, provider, argument); 226 | 227 | // forward to all interested sub-entries 228 | IORegistryIterator *i = IORegistryIterator::iterateOver(this, gIOServicePlane, kIORegistryIterateRecursively); 229 | IORegistryEntry *entry; 230 | if(i != NULL) 231 | { 232 | while((entry = i->getNextObject())) 233 | { 234 | IOService* service = OSDynamicCast(IOService, entry); 235 | if(service != NULL && service->getProperty(kDeliverNotifications)) 236 | { 237 | service->message(type, provider, argument); 238 | } 239 | } 240 | i->release(); 241 | } 242 | 243 | return( kIOReturnSuccess ); 244 | } 245 | -------------------------------------------------------------------------------- /VoodooPS2Controller/AppleACPIPS2Nub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /*! @file AppleACPIPS2Nub.h 24 | @abstract AppleACPIPS2Nub class definition 25 | @discussion 26 | Implements the ACPI PS/2 nub for ApplePS2Controller.kext. 27 | Reverse-engineered from the Darwin 8 binary ACPI kext. 28 | Copyright 2007 David Elliott 29 | */ 30 | 31 | #ifndef __AppleACPIPS2Nub__ 32 | #define __AppleACPIPS2Nub__ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "ApplePS2Device.h" 39 | 40 | #define EXPORT __attribute__((visibility("default"))) 41 | 42 | class IOPlatformExpert; 43 | 44 | /*! @class AppleACPIPS2Nub 45 | @abstract Provides a nub that ApplePS2Controller can attach to 46 | @discussion 47 | The ApplePS2Controller driver is written to the nub provided by the 48 | AppleI386PlatformExpert class which exposes the controller as it is found 49 | on a legacy x86 machine. 50 | 51 | To make that kext work on an ACPI machine, a nub providing the same 52 | service must exist. Previous releases of the official ACPI PE included 53 | this class. Newer release do not. This implementation is intended 54 | to be fully ABI compatible with the one Apple used to provide. 55 | */ 56 | class EXPORT AppleACPIPS2Nub: public IOPlatformDevice 57 | { 58 | typedef IOPlatformDevice super; 59 | OSDeclareDefaultStructors(AppleACPIPS2Nub); 60 | 61 | private: 62 | /*! @field m_mouseProvider 63 | @abstract Our second provider which provides the mouse nub 64 | @discussion 65 | We attach to the keyboard nub but we need to be attached to both the 66 | keyboard and mouse nub in order to make ourselves a proper nub for 67 | the ApplePS2Controller.kext driver. 68 | */ 69 | IOService *m_mouseProvider; 70 | 71 | /*! @field m_interruptControllers 72 | @abstract Our array of interrupt controllers 73 | */ 74 | OSArray *m_interruptControllers; 75 | 76 | /*! @field m_interruptSpecifiers 77 | @abstract Our array of interrupt specifiers 78 | */ 79 | OSArray *m_interruptSpecifiers; 80 | 81 | enum LegacyInterrupts 82 | { 83 | LEGACY_KEYBOARD_IRQ = 1, 84 | LEGACY_MOUSE_IRQ = 12, 85 | }; 86 | 87 | public: 88 | bool start(IOService *provider) override; 89 | void stop(IOService *provider) override; 90 | 91 | /*! @method findMouseDevice 92 | @abstract Locates the mouse nub in the IORegistry 93 | */ 94 | virtual IOService *findMouseDevice(); 95 | 96 | /*! @method mergeInterruptProperties 97 | @abstract Merges the interrupt specifiers and controllers from our two providers 98 | @param pnpProvider The provider nub 99 | @discussion 100 | This is called once for each of our providers. The interrupt controller and interrupt 101 | specifier objects from the provider's arrays are appended to our arrays. 102 | */ 103 | virtual void mergeInterruptProperties(IOService *pnpProvider, long source); 104 | 105 | /*! @method registerInterrupt 106 | @abstract Overriden to translate the legacy interrupt numbers to ours 107 | @discussion 108 | The legacy interrupts are 1 for the keyboard and 12 (0xc) for the mouse. 109 | However, the base class code works off of the controller and specifier 110 | objects in our IOInterruptControllers and IOInterruptSpecifiers keys. 111 | Therefore, we must translate the keyboard interrupt (1) to the index 112 | into our array (0) and the mouse interrupt (12) to the index into 113 | our array (1). 114 | 115 | This has to be done for every *Interrupt* method 116 | */ 117 | IOReturn registerInterrupt(int source, OSObject *target, 118 | IOInterruptAction handler, 119 | void *refCon = 0) override; 120 | IOReturn unregisterInterrupt(int source) override; 121 | IOReturn getInterruptType(int source, int *interruptType) override; 122 | IOReturn enableInterrupt(int source) override; 123 | IOReturn disableInterrupt(int source) override; 124 | 125 | /*! @method compareName 126 | @abstract Overridden to call the IOPlatformExpert compareNubName method 127 | @discussion 128 | I have no idea why this is done, but the Apple code did it, so this 129 | code does too. 130 | */ 131 | bool compareName( OSString * name, OSString ** matched = 0 ) const override; 132 | 133 | /*! @method getResources 134 | @abstract Overridden to call the IOPlatformExpert getNubResources method 135 | @discussion 136 | I have no idea why this is done, but the Apple code did it, so this 137 | code does too. 138 | */ 139 | IOReturn getResources( void ) override; 140 | 141 | /*! @method message 142 | @abstract Overridden to receive ACPI notifications 143 | @discussion 144 | Allows the notifications to be forwarded to the keyboard device such that 145 | ACPI Notify can be used to push keystrokes. This is used to convert ACPI 146 | keys such that they appear to be PS2 keys. 147 | */ 148 | IOReturn message( UInt32 type, IOService* provider, void* argument ) override; 149 | }; 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /VoodooPS2Controller/ApplePS2Device.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #include "ApplePS2Device.h" 24 | #include "VoodooPS2Controller.h" 25 | 26 | OSDefineMetaClassAndStructors(ApplePS2Device, IOService); 27 | 28 | // ============================================================================= 29 | // ApplePS2Device Class Implementation 30 | // 31 | 32 | bool ApplePS2Device::init(size_t port) 33 | { 34 | _port = port; 35 | return super::init(); 36 | } 37 | 38 | bool ApplePS2Device::attach(IOService * provider) 39 | { 40 | if (!super::attach(provider)) 41 | return false; 42 | 43 | _workloop = IOWorkLoop::workLoop(); 44 | _interruptSource = IOInterruptEventSource::interruptEventSource(this, 45 | OSMemberFunctionCast(IOInterruptEventAction, this, &ApplePS2Device::packetAction)); 46 | 47 | if (!_interruptSource || !_workloop) 48 | { 49 | OSSafeReleaseNULL(_workloop); 50 | OSSafeReleaseNULL(_interruptSource); 51 | return false; 52 | } 53 | 54 | if (_workloop->addEventSource(_interruptSource) != kIOReturnSuccess) 55 | { 56 | OSSafeReleaseNULL(_workloop); 57 | OSSafeReleaseNULL(_interruptSource); 58 | return false; 59 | } 60 | 61 | setProperty(kPortKey, _port, 8); 62 | 63 | assert(_controller == 0); 64 | _controller = (ApplePS2Controller*)provider; 65 | _controller->retain(); 66 | 67 | return true; 68 | } 69 | 70 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 71 | 72 | void ApplePS2Device::detach( IOService * provider ) 73 | { 74 | assert(_controller == provider); 75 | _controller->release(); 76 | _controller = 0; 77 | 78 | if (_interruptSource && _workloop) 79 | { 80 | _workloop->removeEventSource(_interruptSource); 81 | } 82 | 83 | OSSafeReleaseNULL(_interruptSource); 84 | OSSafeReleaseNULL(_workloop); 85 | 86 | super::detach(provider); 87 | } 88 | 89 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 90 | 91 | PS2Request * ApplePS2Device::allocateRequest(int max) 92 | { 93 | return _controller->allocateRequest(max); 94 | } 95 | 96 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 97 | 98 | void ApplePS2Device::freeRequest(PS2Request * request) 99 | { 100 | _controller->freeRequest(request); 101 | } 102 | 103 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 104 | 105 | bool ApplePS2Device::submitRequest(PS2Request * request) 106 | { 107 | request->port = _port; 108 | return _controller->submitRequest(request); 109 | } 110 | 111 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 112 | 113 | void ApplePS2Device::submitRequestAndBlock(PS2Request * request) 114 | { 115 | request->port = _port; 116 | _controller->submitRequestAndBlock(request); 117 | } 118 | 119 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 120 | 121 | UInt8 ApplePS2Device::setCommandByte(UInt8 setBits, UInt8 clearBits) 122 | { 123 | return _controller->setCommandByte(setBits, clearBits); 124 | } 125 | 126 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 127 | 128 | void ApplePS2Device::lock() 129 | { 130 | _controller->lock(); 131 | } 132 | 133 | void ApplePS2Device::unlock() 134 | { 135 | _controller->unlock(); 136 | } 137 | 138 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 139 | 140 | void ApplePS2Device::installInterruptAction(OSObject * target, 141 | PS2InterruptAction interruptAction, 142 | PS2PacketAction packetAction) 143 | { 144 | _client = target; 145 | _controller->installInterruptAction(_port); 146 | _interrupt_action = interruptAction; 147 | _packet_action = packetAction; 148 | } 149 | 150 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 151 | 152 | void ApplePS2Device::uninstallInterruptAction() 153 | { 154 | _controller->uninstallInterruptAction(_port); 155 | _interrupt_action = nullptr; 156 | _packet_action = nullptr; 157 | _client = nullptr; 158 | } 159 | 160 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 161 | 162 | void ApplePS2Device::installPowerControlAction(OSObject * target, 163 | PS2PowerControlAction action) 164 | { 165 | _power_action = action; 166 | } 167 | 168 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 169 | 170 | void ApplePS2Device::uninstallPowerControlAction() 171 | { 172 | _power_action = nullptr; 173 | } 174 | 175 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 176 | 177 | void ApplePS2Device::dispatchMessage(int message, void *data) 178 | { 179 | _controller->dispatchMessage(message, data); 180 | } 181 | 182 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 183 | 184 | IOReturn ApplePS2Device::startSMBusCompanion(OSDictionary *companionData, UInt8 smbusAddr) 185 | { 186 | return _controller->startSMBusCompanion(companionData, smbusAddr); 187 | } 188 | 189 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 190 | 191 | ApplePS2Controller* ApplePS2Device::getController() 192 | { 193 | return _controller; 194 | } 195 | 196 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 197 | 198 | PS2InterruptResult ApplePS2Device::interruptAction(UInt8 data) 199 | { 200 | if (_client == nullptr || _interrupt_action == nullptr) 201 | { 202 | return kPS2IR_packetBuffering; 203 | } 204 | 205 | return (*_interrupt_action)(_client, data); 206 | } 207 | 208 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 209 | 210 | void ApplePS2Device::packetActionInterrupt() 211 | { 212 | _interruptSource->interruptOccurred(0, 0, 0); 213 | } 214 | 215 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 216 | 217 | void ApplePS2Device::powerAction(UInt32 whatToDo) 218 | { 219 | if (_client == nullptr || _power_action == nullptr) 220 | { 221 | return; 222 | } 223 | 224 | (*_power_action)(_client, whatToDo); 225 | } 226 | 227 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 228 | 229 | void ApplePS2Device::packetAction(IOInterruptEventSource *, int) 230 | { 231 | if (_client == nullptr || _packet_action == nullptr) 232 | { 233 | return; 234 | } 235 | 236 | (*_packet_action)(_client); 237 | } 238 | -------------------------------------------------------------------------------- /VoodooPS2Controller/ApplePS2KeyboardDevice.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #include "ApplePS2KeyboardDevice.h" 24 | #include "VoodooPS2Controller.h" 25 | 26 | // ============================================================================= 27 | // ApplePS2KeyboardDevice Class Implementation 28 | // 29 | 30 | OSDefineMetaClassAndStructors(ApplePS2KeyboardDevice, ApplePS2Device); 31 | -------------------------------------------------------------------------------- /VoodooPS2Controller/ApplePS2KeyboardDevice.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2KEYBOARDDEVICE_H 24 | #define _APPLEPS2KEYBOARDDEVICE_H 25 | 26 | #include "ApplePS2Device.h" 27 | 28 | class ApplePS2Controller; 29 | 30 | class EXPORT ApplePS2KeyboardDevice : public ApplePS2Device 31 | { 32 | typedef ApplePS2Device super; 33 | OSDeclareDefaultStructors(ApplePS2KeyboardDevice); 34 | }; 35 | 36 | #endif /* !_APPLEPS2KEYBOARDDEVICE_H */ 37 | -------------------------------------------------------------------------------- /VoodooPS2Controller/ApplePS2MouseDevice.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #include "ApplePS2MouseDevice.h" 24 | #include "VoodooPS2Controller.h" 25 | 26 | // ============================================================================= 27 | // ApplePS2MouseDevice Class Implementation 28 | // 29 | 30 | OSDefineMetaClassAndStructors(ApplePS2MouseDevice, ApplePS2Device); 31 | -------------------------------------------------------------------------------- /VoodooPS2Controller/ApplePS2MouseDevice.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2MOUSEDEVICE_H 24 | #define _APPLEPS2MOUSEDEVICE_H 25 | 26 | #include "ApplePS2Device.h" 27 | 28 | class ApplePS2Controller; 29 | 30 | class EXPORT ApplePS2MouseDevice : public ApplePS2Device 31 | { 32 | typedef ApplePS2Device super; 33 | OSDeclareDefaultStructors(ApplePS2MouseDevice); 34 | }; 35 | 36 | #endif /* !_APPLEPS2MOUSEDEVICE_H */ 37 | -------------------------------------------------------------------------------- /VoodooPS2Controller/VoodooPS2Controller-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | VoodooPS2Controller 7 | CFBundleGetInfoString 8 | ${MODULE_VERSION}, Copyright Apple Computer, Inc. 2000-2003, David Elliot 2007, RehabMan 2012-2013 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Voodoo PS/2 Controller 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | ${MODULE_VERSION} 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${MODULE_VERSION} 23 | IOKitPersonalities 24 | 25 | ACPI PS/2 Nub 26 | 27 | CFBundleIdentifier 28 | as.acidanthera.voodoo.driver.PS2Controller 29 | FindMouseDelay 30 | 100 31 | IOClass 32 | AppleACPIPS2Nub 33 | IONameMatch 34 | 35 | PNP0303 36 | PNP030B 37 | PNP0320 38 | 39 | IOProviderClass 40 | IOACPIPlatformDevice 41 | MouseNameMatch 42 | 43 | PNP0F03 44 | PNP0F0B 45 | PNP0F0E 46 | PNP0F13 47 | 48 | 49 | ApplePS2Controller 50 | 51 | CFBundleIdentifier 52 | as.acidanthera.voodoo.driver.PS2Controller 53 | IOClass 54 | ApplePS2Controller 55 | IONameMatch 56 | ps2controller 57 | IOProviderClass 58 | IOPlatformDevice 59 | Platform Profile 60 | 61 | Default 62 | 63 | MouseWakeFirst 64 | 65 | WakeDelay 66 | 10 67 | 68 | HPQOEM 69 | 70 | 1411 71 | ProBook 72 | 1619 73 | ProBook 74 | 161C 75 | ProBook 76 | 164F 77 | ProBook 78 | 167C 79 | ProBook 80 | 167E 81 | ProBook 82 | 1680 83 | ProBook 84 | 179B 85 | ProBook 86 | 179C 87 | ProBook 88 | 17A9 89 | ProBook 90 | 17F0 91 | ProBook 92 | 17F3 93 | ProBook 94 | 17F6 95 | ProBook 96 | 1942 97 | ProBook 98 | 1949 99 | ProBook 100 | 198F 101 | ProBook 102 | ProBook 103 | 104 | WakeDelay 105 | 0 106 | 107 | ProBook-102 108 | ProBook 109 | ProBook-87 110 | ProBook 111 | 112 | 113 | RM,deliverNotifications 114 | 115 | 116 | 117 | OSBundleCompatibleVersion 118 | ${MODULE_VERSION} 119 | OSBundleLibraries 120 | 121 | com.apple.iokit.IOACPIFamily 122 | 1.0.0d1 123 | com.apple.kpi.bsd 124 | 8.0.0 125 | com.apple.kpi.iokit 126 | 8.0.0 127 | com.apple.kpi.libkern 128 | 8.0.0 129 | com.apple.kpi.mach 130 | 8.0.0 131 | com.apple.kpi.unsupported 132 | 8.0.0 133 | 134 | OSBundleRequired 135 | Console 136 | 137 | 138 | -------------------------------------------------------------------------------- /VoodooPS2Controller/VoodooPS2Controller.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2CONTROLLER_H 24 | #define _APPLEPS2CONTROLLER_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "ApplePS2Device.h" 31 | 32 | class ApplePS2KeyboardDevice; 33 | class ApplePS2MouseDevice; 34 | 35 | // 36 | // This section describes the problem with the PS/2 controller design and what 37 | // we are doing about it (OUT_OF_ORDER_DATA_CORRECTION_FEATURE). 38 | // 39 | // While the controller processes requests sent by the client drivers, at some 40 | // point in most requests, a read needs to be made from the data port to check 41 | // an acknowledge or receive some sort of data. We illustrate this issue with 42 | // an example -- a write LEDs request to the keyboard: 43 | // 44 | // 1. Write Write LED command. 45 | // 2. Read 0xFA Verify the acknowledge (0xFA). 46 | // 3. Write Write LED state. 47 | // 4. Read 0xFA Verify the acknowledge (0xFA). 48 | // 49 | // The problem is that the keyboard (when it is enabled) can send key events 50 | // to the controller at any time, including when the controller is expecting 51 | // to read an acknowledge next. What ends up happening is this sequence: 52 | // 53 | // a. Write Write LED command. 54 | // b. Read 0x21 Keyboard reports [F] key was depressed, not realizing that 55 | // we're still expecting a response to the command we JUST 56 | // sent the keyboard. We receive 0x21 as a response to our 57 | // command, and figure the command failed. 58 | // c. Get 0xFA Keyboard NOW decides to respond to the command with an 59 | // acknowledge. We're not waiting to read anything, so 60 | // this byte gets dispatched to the driver's interrupt 61 | // handler, which spews out an error message saying it 62 | // wasn't expecting an acknowledge. 63 | // 64 | // What can we do about this? In the above case, we can take note of the fact 65 | // that we are specifically looking for the 0xFA acknowledgement byte (through 66 | // the information passed in the kPS2C_ReadAndCompare primitive). If we don't 67 | // receive this byte next on the input data stream, we put the byte we did get 68 | // aside for a moment, and give the keyboard (or mouse) a second chance to 69 | // respond correctly. 70 | // 71 | // If we receive the 0xFA acknowledgement byte on the second read, that we 72 | // assume that situation described above just happened. We transparently 73 | // dispatch the first byte to the driver's interrupt handler, where it was 74 | // meant to go, and return the second correct byte to the read-and-compare 75 | // logic, where it was meant to go. Everyone wins. 76 | // 77 | // The only situation this feature cannot help is where a kPS2C_ReadDataPort 78 | // primitive is issued in place of a kPS2C_ReadDataPortAndCompare primitive. 79 | // This is necessary in some requests because the driver does not know what 80 | // it is going to receive. This can be illustrated in the mouse get info 81 | // command. 82 | // 83 | // 1. Write Prepare to write to mouse. 84 | // 2. Write Write information command. 85 | // 3. Read 0xFA Verify the acknowledge (0xFA). __-> mouse can report mouse 86 | // 4. Read Get first information byte. __-> packet bytes in between 87 | // 5. Read Get second information byte. __-> these reads 88 | // 6. Rrad Get third information byte. 89 | // 90 | // Controller cannot build any defenses against this. It is suggested that the 91 | // driver writer disable the mouse first, then send any dangerous commands, and 92 | // re-enable the mouse when the command completes. 93 | // 94 | // Note that the OUT_OF_ORDER_DATA_CORRECTION_FEATURE can be turned off at 95 | // compile time. Please see the readDataPort:expecting: method for more 96 | // information about the assumptions necessary for this feature. 97 | // 98 | 99 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 100 | // Definitions 101 | // 102 | 103 | // Enable debugger support (eg. mini-monitor). 104 | 105 | #define DEBUGGER_SUPPORT 0 106 | 107 | // Enable dynamic "second chance" re-ordering of input stream data if a 108 | // command response fails to match the expected byte. 109 | 110 | #define OUT_OF_ORDER_DATA_CORRECTION_FEATURE 1 111 | 112 | // Enable handling of interrupt data in workloop instead of at interrupt 113 | // time. This way is easier to debug. For production use, this should 114 | // be zero, such that PS2 data is buffered at real interrupt time, and handled 115 | // as packets later in the workloop. 116 | 117 | #define HANDLE_INTERRUPT_DATA_LATER 0 118 | #define WATCHDOG_TIMER 0 119 | 120 | // Interrupt definitions. 121 | 122 | #define kIRQ_Keyboard 1 123 | #define kIRQ_Mouse 12 124 | #define kIPL_Keyboard 6 125 | #define kIPL_Mouse 3 126 | 127 | // Port timings. 128 | 129 | #define kDataDelay 7 // usec to delay before data is valid 130 | 131 | // Ports used to control the PS/2 keyboard/mouse and read data from it. 132 | 133 | #define kDataPort 0x60 // keyboard data & cmds (read/write) 134 | #define kCommandPort 0x64 // keybd status (read), command (write) 135 | 136 | // Bit definitions for kCommandPort read values (status). 137 | 138 | #define kOutputReady 0x01 // output (from keybd) buffer full 139 | #define kInputBusy 0x02 // input (to keybd) buffer full 140 | #define kSystemFlag 0x04 // "System Flag" 141 | #define kCommandLastSent 0x08 // 1 = cmd, 0 = data last sent 142 | #define kKeyboardInhibited 0x10 // 0 if keyboard inhibited 143 | #define kMouseData 0x20 // mouse data available 144 | 145 | // Watchdog timer definitions 146 | 147 | #define kWatchdogTimerInterval 100 148 | 149 | // Enable Mux commands 150 | // Constants are from Linux 151 | // https://github.com/torvalds/linux/blob/c2d7ed9d680fd14aa5486518bd0d0fa5963c6403/drivers/input/serio/i8042.c#L685-L693 152 | 153 | #define kDP_MuxCmd 0xF0 154 | #define kDP_EnableMuxCmd1 0x56 155 | #define kDP_GetMuxVersion 0xA4 156 | #define kDP_DisableMuxCmd1 0xF6 157 | #define kDP_DisableMuxCmd2 0xA5 158 | 159 | #if DEBUGGER_SUPPORT 160 | // Definitions for our internal keyboard queue (holds keys processed by the 161 | // interrupt-time mini-monitor-key-sequence detection code). 162 | 163 | #define kKeyboardQueueSize 32 // number of KeyboardQueueElements 164 | 165 | typedef struct KeyboardQueueElement KeyboardQueueElement; 166 | struct KeyboardQueueElement 167 | { 168 | queue_chain_t chain; 169 | UInt8 data; 170 | }; 171 | #endif //DEBUGGER_SUPPORT 172 | 173 | // Info.plist definitions 174 | 175 | #define kDisableDevice "DisableDevice" 176 | #define kPlatformProfile "Platform Profile" 177 | 178 | #ifdef DEBUG 179 | #define kMergedConfiguration "Merged Configuration" 180 | #endif 181 | 182 | // ps2rst flags 183 | #define RESET_CONTROLLER_ON_BOOT 1 184 | #define RESET_CONTROLLER_ON_WAKEUP 2 185 | 186 | class IOACPIPlatformDevice; 187 | 188 | enum { 189 | kPS2PowerStateSleep = 0, 190 | kPS2PowerStateDoze = 1, 191 | kPS2PowerStateNormal = 2, 192 | kPS2PowerStateCount 193 | }; 194 | 195 | // i8042 Mux indexes 196 | #define PS2_MUX_PORTS 4 197 | 198 | #define PS2_STA_MUX_MASK 0x03 199 | #define PS2_STA_MUX_SHIFT 0x06 200 | 201 | // Normally, the i8042 controller has 2 ports. With the mux active, 202 | // there are 5 ports. 1 Keyboard port and 4 mux ports. All the muxed ports 203 | // share the same IRQ. When the controller is in a multiplexed mode, 3 204 | // additional ports are added. 205 | 206 | enum { 207 | kPS2KbdIdx = 0, 208 | kPS2AuxIdx = 1, 209 | kPS2AuxMaxIdx = 2, 210 | kPS2MuxMaxIdx = PS2_MUX_PORTS + 1 211 | }; 212 | 213 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 214 | // ApplePS2Controller Class Declaration 215 | // 216 | 217 | class EXPORT ApplePS2Controller : public IOService 218 | { 219 | typedef IOService super; 220 | OSDeclareDefaultStructors(ApplePS2Controller); 221 | 222 | public: 223 | // interrupt-time variables and functions 224 | #if HANDLE_INTERRUPT_DATA_LATER 225 | IOInterruptEventSource * _interruptSourceMouse {nullptr}; 226 | IOInterruptEventSource * _interruptSourceKeyboard {nullptr}; 227 | #endif 228 | IOInterruptEventSource * _interruptSourceQueue {nullptr}; 229 | 230 | #if DEBUGGER_SUPPORT 231 | bool _debuggingEnabled {false}; 232 | 233 | void lockController(int * state); 234 | void unlockController(int state); 235 | 236 | bool doEscape(UInt8 key); 237 | bool dequeueKeyboardData(UInt8 * key); 238 | void enqueueKeyboardData(UInt8 key); 239 | #endif //DEBUGGER_SUPPORT 240 | 241 | private: 242 | IOWorkLoop * _workLoop {nullptr}; 243 | queue_head_t _requestQueue {nullptr}; 244 | IOLock* _requestQueueLock {nullptr}; 245 | IOLock* _cmdbyteLock {nullptr}; 246 | 247 | bool _interruptInstalledKeyboard {false}; 248 | int _interruptInstalledMouse {0}; 249 | 250 | int _ignoreInterrupts {0}; 251 | int _ignoreOutOfOrder {0}; 252 | 253 | ApplePS2Device * _devices [kPS2MuxMaxIdx] {nullptr}; 254 | 255 | IONotifier* _publishNotify {nullptr}; 256 | IONotifier* _terminateNotify {nullptr}; 257 | 258 | OSSet* _notificationServices {nullptr}; 259 | 260 | #if DEBUGGER_SUPPORT 261 | IOSimpleLock * _controllerLock {nullptr}; // mach simple spin lock 262 | 263 | KeyboardQueueElement * _keyboardQueueAlloc {nullptr}; // queues' allocation space 264 | queue_head_t _keyboardQueue {nullptr}; // queue of available keys 265 | queue_head_t _keyboardQueueUnused {nullptr}; // queue of unused entries 266 | 267 | bool _extendedState {false}; 268 | UInt16 _modifierState {0}; 269 | #endif //DEBUGGER_SUPPORT 270 | 271 | thread_call_t _powerChangeThreadCall {0}; 272 | UInt32 _currentPowerState {kPS2PowerStateNormal}; 273 | bool _hardwareOffline {false}; 274 | bool _suppressTimeout {false}; 275 | int _wakedelay {10}; 276 | bool _mouseWakeFirst {false}; 277 | bool _muxPresent {false}; 278 | size_t _nubsCount {0}; 279 | IOCommandGate* _cmdGate {nullptr}; 280 | #if WATCHDOG_TIMER 281 | IOTimerEventSource* _watchdogTimer {nullptr}; 282 | #endif 283 | OSDictionary* _rmcfCache {nullptr}; 284 | const OSSymbol* _deliverNotification {nullptr}; 285 | const OSSymbol* _smbusCompanion {nullptr}; 286 | 287 | int _resetControllerFlag {RESET_CONTROLLER_ON_BOOT | RESET_CONTROLLER_ON_WAKEUP}; 288 | bool _kbdOnly {0}; 289 | 290 | virtual PS2InterruptResult _dispatchDriverInterrupt(size_t port, UInt8 data); 291 | virtual void dispatchDriverInterrupt(size_t port, UInt8 data); 292 | #if HANDLE_INTERRUPT_DATA_LATER 293 | virtual void interruptOccurred(IOInterruptEventSource *, int); 294 | #endif 295 | void handleInterrupt(bool watchdog = false); 296 | #if WATCHDOG_TIMER 297 | void onWatchdogTimer(); 298 | #endif 299 | virtual void processRequest(PS2Request * request); 300 | virtual void processRequestQueue(IOInterruptEventSource *, int); 301 | 302 | #if OUT_OF_ORDER_DATA_CORRECTION_FEATURE 303 | virtual UInt8 readDataPort(size_t port, UInt8 expectedByte); 304 | #endif 305 | 306 | virtual UInt8 readDataPort(size_t port); 307 | virtual void writeCommandPort(UInt8 byte); 308 | virtual void writeDataPort(UInt8 byte); 309 | void resetController(void); 310 | bool setMuxMode(bool); 311 | void flushDataPort(void); 312 | void resetDevices(void); 313 | 314 | static void interruptHandlerMouse(OSObject*, void* refCon, IOService*, int); 315 | static void interruptHandlerKeyboard(OSObject*, void* refCon, IOService*, int); 316 | 317 | void notificationHandlerPublishGated(IOService * newService, IONotifier * notifier); 318 | bool notificationHandlerPublish(void * refCon, IOService * newService, IONotifier * notifier); 319 | 320 | void notificationHandlerTerminateGated(IOService * newService, IONotifier * notifier); 321 | bool notificationHandlerTerminate(void * refCon, IOService * newService, IONotifier * notifier); 322 | 323 | void dispatchMessageGated(int* message, void* data); 324 | 325 | static void setPowerStateCallout(thread_call_param_t param0, 326 | thread_call_param_t param1); 327 | 328 | static IOReturn setPowerStateAction(OSObject * target, 329 | void * arg0, void * arg1, 330 | void * arg2, void * arg3); 331 | 332 | virtual void setPowerStateGated(UInt32 newPowerState); 333 | 334 | virtual void dispatchDriverPowerControl(UInt32 whatToDo, size_t port); 335 | void free(void) override; 336 | IOReturn setPropertiesGated(OSObject* props); 337 | void submitRequestAndBlockGated(PS2Request* request); 338 | 339 | size_t getPortFromStatus(UInt8 status); 340 | 341 | public: 342 | bool init(OSDictionary * properties) override; 343 | ApplePS2Controller* probe(IOService* provider, SInt32* score) override; 344 | bool start(IOService * provider) override; 345 | void stop(IOService * provider) override; 346 | 347 | IOWorkLoop * getWorkLoop() const override; 348 | 349 | void enableMuxPorts(); 350 | virtual void installInterruptAction(size_t port); 351 | virtual void uninstallInterruptAction(size_t port); 352 | 353 | virtual PS2Request* allocateRequest(int max = kMaxCommands); 354 | virtual void freeRequest(PS2Request * request); 355 | virtual bool submitRequest(PS2Request * request); 356 | virtual void submitRequestAndBlock(PS2Request * request); 357 | virtual UInt8 setCommandByte(UInt8 setBits, UInt8 clearBits); 358 | void setCommandByteGated(PS2Request* request); 359 | 360 | IOReturn setPowerState(unsigned long powerStateOrdinal, 361 | IOService * policyMaker) override; 362 | 363 | virtual void dispatchMessage(int message, void* data); 364 | 365 | IOReturn setProperties(OSObject* props) override; 366 | virtual void lock(); 367 | virtual void unlock(); 368 | 369 | static OSDictionary* getConfigurationNode(IORegistryEntry* entry, OSDictionary* list); 370 | virtual OSDictionary* makeConfigurationNode(OSDictionary* list, const char* section); 371 | 372 | OSDictionary* getConfigurationOverride(IOACPIPlatformDevice* acpi, const char* method); 373 | OSObject* translateArray(OSArray* array); 374 | OSObject* translateEntry(OSObject* obj); 375 | 376 | IOReturn startSMBusCompanion(OSDictionary *companionData, UInt8 smbusAddr); 377 | }; 378 | 379 | #endif /* _APPLEPS2CONTROLLER_H */ 380 | -------------------------------------------------------------------------------- /VoodooPS2Controller/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | -------------------------------------------------------------------------------- /VoodooPS2Keyboard/VoodooPS2Keyboard-Breakless-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleGetInfoString 6 | ${MODULE_VERSION}, Copyright Apple Computer, Inc. 2000-2003, RehabMan 2012-2013 7 | CFBundleExecutable 8 | VoodooPS2Keyboard 9 | CFBundleIdentifier 10 | as.acidanthera.voodoo.driver.PS2Keyboard 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Voodoo PS/2 Keyboard 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | ${MODULE_VERSION} 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${MODULE_VERSION} 23 | IOKitPersonalities 24 | 25 | ApplePS2Keyboard 26 | 27 | CFBundleIdentifier 28 | as.acidanthera.voodoo.driver.PS2Keyboard 29 | IOClass 30 | ApplePS2Keyboard 31 | IOProviderClass 32 | ApplePS2KeyboardDevice 33 | Platform Profile 34 | 35 | Default 36 | 37 | Make Application key into Apple Fn key 38 | 39 | Make Application key into right windows 40 | 41 | Make right modifier keys into Hangul and Hanja 42 | 43 | Swap capslock and left control 44 | 45 | Swap command and option 46 | 47 | Use ISO layout keyboard 48 | 49 | alt_handler_id 50 | 3 51 | SleepPressTime 52 | 3000 53 | Breakless PS2 54 | 55 | ;Items must be strings in the form of breaklessscan (in hex) 56 | e05f 57 | e012 58 | e017 59 | e06e 60 | e00a 61 | e009 62 | e020 63 | e02e 64 | e030 65 | e010 66 | e022 67 | e019 68 | 69 | Function Keys Standard 70 | 71 | ;Items must be strings in the form of scanfrom=scanto (in hex) 72 | ;The following 12 items map Fn+fkeys to Fn+fkeys 73 | e05f=e05f 74 | e012=e012 75 | e017=e017 76 | e06e=e06e 77 | e00a=e00a 78 | e009=e009 79 | e020=e020 80 | e02e=e02e 81 | e030=e030 82 | e010=e010 83 | e022=e022 84 | e019=e019 85 | ;The following 12 items map fkeys to fkeys 86 | 3b=3b 87 | 3c=3c 88 | 3d=3d 89 | 3e=3e 90 | 3f=3f 91 | 40=40 92 | 41=41 93 | 42=42 94 | 43=43 95 | 44=44 96 | 57=57 97 | 58=58 98 | 99 | Function Keys Special 100 | 101 | ;Items must be strings in the form of scanfrom=scanto (in hex) 102 | ;The following 12 items map Fn+fkeys to fkeys 103 | e05f=3b 104 | e012=3c 105 | e017=3d 106 | e06e=3e 107 | e00a=3f 108 | e009=40 109 | e020=41 110 | e02e=42 111 | e030=43 112 | e010=44 113 | e022=57 114 | e019=58 115 | ;The following 12 items map fkeys to Fn+fkeys 116 | 3b=e05f 117 | 3c=e012 118 | 3d=e017 119 | 3e=e06e 120 | 3f=e00a 121 | 40=e009 122 | 41=e020 123 | 42=e02e 124 | 43=e030 125 | 44=e010 126 | 57=e022 127 | 58=e019 128 | 129 | Custom PS2 Map 130 | 131 | ;Items must be strings in the form of scanfrom=scanto (in hex) 132 | 133 | Custom ADB Map 134 | 135 | ;Items must be strings in the form of scanfrom=adbto (in hex) 136 | 137 | LogScanCodes 138 | 0 139 | 140 | 141 | 142 | 143 | OSBundleLibraries 144 | 145 | com.apple.iokit.IOHIDFamily 146 | 1.0.0b1 147 | com.apple.kpi.bsd 148 | 8.0.0 149 | com.apple.kpi.iokit 150 | 8.0.0 151 | com.apple.kpi.libkern 152 | 8.0.0 153 | com.apple.kpi.mach 154 | 8.0.0 155 | com.apple.kpi.unsupported 156 | 8.0.0 157 | as.acidanthera.voodoo.driver.PS2Controller 158 | ${MODULE_VERSION} 159 | 160 | OSBundleRequired 161 | Console 162 | 163 | 164 | -------------------------------------------------------------------------------- /VoodooPS2Keyboard/VoodooPS2Keyboard-RemapFN-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleGetInfoString 6 | ${MODULE_VERSION}, Copyright Apple Computer, Inc. 2000-2003, RehabMan 2012-2013 7 | CFBundleExecutable 8 | VoodooPS2Keyboard 9 | CFBundleIdentifier 10 | as.acidanthera.voodoo.driver.PS2Keyboard 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Voodoo PS/2 Keyboard 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | ${MODULE_VERSION} 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${MODULE_VERSION} 23 | IOKitPersonalities 24 | 25 | ApplePS2Keyboard 26 | 27 | CFBundleIdentifier 28 | as.acidanthera.voodoo.driver.PS2Keyboard 29 | IOClass 30 | ApplePS2Keyboard 31 | IOProviderClass 32 | ApplePS2KeyboardDevice 33 | Platform Profile 34 | 35 | Default 36 | 37 | Make Application key into Apple Fn key 38 | 39 | Make Application key into right windows 40 | 41 | Make right modifier keys into Hangul and Hanja 42 | 43 | Swap capslock and left control 44 | 45 | Swap command and option 46 | 47 | Use ISO layout keyboard 48 | 49 | alt_handler_id 50 | 3 51 | SleepPressTime 52 | 3000 53 | Breakless PS2 54 | 55 | ;Items must be strings in the form of breaklessscan (in hex) 56 | 57 | Function Keys Standard 58 | 59 | ;Items must be strings in the form of scanfrom=scanto (in hex) 60 | ;The following 12 items map Fn+fkeys to Fn+fkeys 61 | e05f=e05f 62 | e012=e012 63 | e017=e017 64 | e06e=e06e 65 | e00a=e00a 66 | e009=e009 67 | e020=e020 68 | e02e=e02e 69 | e030=e030 70 | e010=e010 71 | e022=e022 72 | e019=e019 73 | ;The following 12 items map fkeys to fkeys 74 | 3b=3b 75 | 3c=3c 76 | 3d=3d 77 | 3e=3e 78 | 3f=3f 79 | 40=40 80 | 41=41 81 | 42=42 82 | 43=43 83 | 44=44 84 | 57=57 85 | 58=58 86 | 87 | Function Keys Special 88 | 89 | ;Items must be strings in the form of scanfrom=scanto (in hex) 90 | ;The following 12 items map Fn+fkeys to fkeys 91 | e05f=3b 92 | e012=3c 93 | e017=3d 94 | e06e=3e 95 | e00a=3f 96 | e009=40 97 | e020=41 98 | e02e=42 99 | e030=43 100 | e010=44 101 | e022=57 102 | e019=58 103 | ;The following 12 items map fkeys to Fn+fkeys 104 | 3b=e05f 105 | 3c=e012 106 | 3d=e017 107 | 3e=e06e 108 | 3f=e00a 109 | 40=e009 110 | 41=e020 111 | 42=e02e 112 | 43=e030 113 | 44=e010 114 | 57=e022 115 | 58=e019 116 | 117 | Custom PS2 Map 118 | 119 | ;Items must be strings in the form of scanfrom=scanto (in hex) 120 | 121 | Custom ADB Map 122 | 123 | ;Items must be strings in the form of scanfrom=adbto (in hex) 124 | 125 | LogScanCodes 126 | 0 127 | 128 | 129 | 130 | 131 | OSBundleLibraries 132 | 133 | com.apple.iokit.IOHIDFamily 134 | 1.0.0b1 135 | com.apple.kpi.bsd 136 | 8.0.0 137 | com.apple.kpi.iokit 138 | 8.0.0 139 | com.apple.kpi.libkern 140 | 8.0.0 141 | com.apple.kpi.mach 142 | 8.0.0 143 | com.apple.kpi.unsupported 144 | 8.0.0 145 | as.acidanthera.voodoo.driver.PS2Controller 146 | ${MODULE_VERSION} 147 | 148 | OSBundleRequired 149 | Console 150 | 151 | 152 | -------------------------------------------------------------------------------- /VoodooPS2Keyboard/VoodooPS2Keyboard.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidanthera/VoodooPS2/b6713c37b9919bd95c3b7f4d484bd049371bcfc1/VoodooPS2Keyboard/VoodooPS2Keyboard.cpp -------------------------------------------------------------------------------- /VoodooPS2Keyboard/VoodooPS2Keyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2KEYBOARD_H 24 | #define _APPLEPS2KEYBOARD_H 25 | 26 | #include 27 | #include "../VoodooPS2Controller/ApplePS2KeyboardDevice.h" 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | 34 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 35 | // Definitions used to keep track of key state. Key up/down state is tracked 36 | // in a bit list. Bits are set for key-down, and cleared for key-up. The bit 37 | // vector and macros for it's manipulation are defined here. 38 | // 39 | 40 | #define KBV_NUM_KEYCODES 512 // related with ADB_CONVERTER_LEN 41 | #define KBV_BITS_PER_UNIT 32 // for UInt32 42 | #define KBV_BITS_MASK 31 43 | #define KBV_BITS_SHIFT 5 // 1<<5 == 32, for cheap divide 44 | #define KBV_NUNITS ((KBV_NUM_KEYCODES + \ 45 | (KBV_BITS_PER_UNIT-1))/KBV_BITS_PER_UNIT) 46 | 47 | #define KBV_KEYDOWN(n) \ 48 | (_keyBitVector)[((n)>>KBV_BITS_SHIFT)] |= (1U << ((n) & KBV_BITS_MASK)) 49 | 50 | #define KBV_KEYUP(n) \ 51 | (_keyBitVector)[((n)>>KBV_BITS_SHIFT)] &= ~(1U << ((n) & KBV_BITS_MASK)) 52 | 53 | #define KBV_IS_KEYDOWN(n) \ 54 | (((_keyBitVector)[((n)>>KBV_BITS_SHIFT)] & (1U << ((n) & KBV_BITS_MASK))) != 0) 55 | 56 | #define KBV_NUM_SCANCODES 256 57 | 58 | // Special bits for _PS2ToPS2Map 59 | 60 | #define kBreaklessKey 0x01 // keys with this flag don't generate break codes 61 | 62 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 63 | // ApplePS2Keyboard Class Declaration 64 | // 65 | 66 | #define kPacketLength (2+6+8) // 2 bytes for key data, 6-bytes not used, 8 bytes for timestamp 67 | #define kPacketKeyOffset 0 68 | #define kPacketTimeOffset 8 69 | #define kPacketKeyDataLength 2 70 | 71 | class EXPORT ApplePS2Keyboard : public IOHIKeyboard 72 | { 73 | typedef IOHIKeyboard super; 74 | OSDeclareDefaultStructors(ApplePS2Keyboard); 75 | 76 | private: 77 | ApplePS2KeyboardDevice * _device; 78 | UInt32 _keyBitVector[KBV_NUNITS]; 79 | UInt8 _extendCount; 80 | RingBuffer _ringBuffer; 81 | UInt8 _lastdata; 82 | bool _interruptHandlerInstalled; 83 | bool _powerControlHandlerInstalled; 84 | UInt8 _ledState; 85 | IOCommandGate* _cmdGate; 86 | 87 | // for keyboard remapping 88 | UInt16 _PS2modifierState; 89 | UInt16 _PS2ToPS2Map[KBV_NUM_SCANCODES*2]; 90 | UInt16 _PS2flags[KBV_NUM_SCANCODES*2]; 91 | UInt8 _PS2ToADBMap[ADB_CONVERTER_LEN]; 92 | UInt8 _PS2ToADBMapMapped[ADB_CONVERTER_LEN]; 93 | UInt32 _fkeymode; 94 | bool _fkeymodesupported; 95 | OSArray* _keysStandard; 96 | OSArray* _keysSpecial; 97 | bool _swapcommandoption; 98 | int _logscancodes; 99 | UInt32 _f12ejectdelay; 100 | enum { kTimerSleep, kTimerEject } _timerFunc; 101 | bool _remapPrntScr; 102 | bool _numLockSupport; 103 | bool _numLockOnAtBoot; 104 | 105 | // dealing with sleep key delay 106 | IOTimerEventSource* _sleepEjectTimer; 107 | UInt32 _maxsleeppresstime; 108 | 109 | // ACPI support for keyboard backlight 110 | IOACPIPlatformDevice * _provider; 111 | int * _backlightLevels; 112 | int _backlightCount; 113 | 114 | // special hack for Envy brightness access, while retaining F2/F3 functionality 115 | bool _brightnessHack; 116 | 117 | // Toggle keyboard input along with touchpad when Windows+printscreen is pressed 118 | bool _disableInput; 119 | 120 | // macro processing 121 | OSData** _macroTranslation; 122 | OSData** _macroInversion; 123 | UInt8* _macroBuffer; 124 | int _macroMax; 125 | int _macroCurrent; 126 | uint64_t _macroMaxTime; 127 | IOTimerEventSource* _macroTimer; 128 | 129 | // fix caps lock led 130 | bool _ignoreCapsLedChange; 131 | 132 | virtual bool dispatchKeyboardEventWithPacket(const UInt8* packet); 133 | virtual void setLEDs(UInt8 ledState); 134 | virtual void setKeyboardEnable(bool enable); 135 | virtual void initKeyboard(); 136 | virtual void setDevicePowerState(UInt32 whatToDo); 137 | void modifyKeyboardBacklight(int adbKeyCode, bool goingDown); 138 | void modifyScreenBrightness(int adbKeyCode, bool goingDown); 139 | inline bool checkModifierState(UInt16 mask) 140 | { return mask == (_PS2modifierState & mask); } 141 | inline bool checkModifierStateAny(UInt16 mask) 142 | { return (_PS2modifierState & mask); } 143 | 144 | void loadCustomPS2Map(OSArray* pArray); 145 | void loadBreaklessPS2(OSDictionary* dict, const char* name); 146 | void loadCustomADBMap(OSDictionary* dict, const char* name); 147 | void setParamPropertiesGated(OSDictionary* dict); 148 | void onSleepEjectTimer(void); 149 | 150 | static OSData** loadMacroData(OSDictionary* dict, const char* name); 151 | static void freeMacroData(OSData** data); 152 | void onMacroTimer(void); 153 | bool invertMacros(const UInt8* packet); 154 | void dispatchInvertBuffer(); 155 | static bool compareMacro(const UInt8* packet, const UInt8* data, int count); 156 | 157 | protected: 158 | const unsigned char * defaultKeymapOfLength(UInt32 * length) override; 159 | void setAlphaLockFeedback(bool locked) override; 160 | void setNumLockFeedback(bool locked) override; 161 | UInt32 maxKeyCodes() override; 162 | inline void dispatchKeyboardEventX(unsigned int keyCode, bool goingDown, uint64_t time) 163 | { dispatchKeyboardEvent(keyCode, goingDown, *(AbsoluteTime*)&time); } 164 | inline void setTimerTimeout(IOTimerEventSource* timer, uint64_t time) 165 | { timer->setTimeout(*(AbsoluteTime*)&time); } 166 | inline void cancelTimer(IOTimerEventSource* timer) 167 | { timer->cancelTimeout(); } 168 | 169 | public: 170 | bool init(OSDictionary * dict) override; 171 | ApplePS2Keyboard * probe(IOService * provider, SInt32 * score) override; 172 | 173 | bool start(IOService * provider) override; 174 | void stop(IOService * provider) override; 175 | 176 | virtual PS2InterruptResult interruptOccurred(UInt8 scanCode); 177 | virtual void packetReady(); 178 | 179 | UInt32 deviceType() override; 180 | UInt32 interfaceID() override; 181 | 182 | IOReturn setParamProperties(OSDictionary* dict) override; 183 | IOReturn setProperties (OSObject *props) override; 184 | 185 | IOReturn message(UInt32 type, IOService* provider, void* argument) override; 186 | }; 187 | 188 | #endif /* _APPLEPS2KEYBOARD_H */ 189 | -------------------------------------------------------------------------------- /VoodooPS2Keyboard/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | -------------------------------------------------------------------------------- /VoodooPS2Mouse/VoodooPS2Mouse-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | VoodooPS2Mouse 7 | CFBundleGetInfoString 8 | ${MODULE_VERSION}, Copyright Apple Computer, Inc. 2000-2004, Slice 2010, RehabMan 2012-2013 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Voodoo PS/2 Mouse 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | ${MODULE_VERSION} 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${MODULE_VERSION} 23 | IOKitPersonalities 24 | 25 | ApplePS2Mouse 26 | 27 | CFBundleIdentifier 28 | as.acidanthera.voodoo.driver.PS2Mouse 29 | IOClass 30 | ApplePS2Mouse 31 | IOProviderClass 32 | ApplePS2MouseDevice 33 | Platform Profile 34 | 35 | Default 36 | 37 | ButtonCount 38 | 3 39 | DefaultResolution 40 | 240 41 | DisableDevice 42 | 43 | FakeMiddleButton 44 | 45 | ForceDefaultResolution 46 | 47 | ForceSetResolution 48 | 49 | MiddleClickTime 50 | 100000000 51 | MouseCount 52 | 0 53 | MouseYInverter 54 | 1 55 | ResolutionMode 56 | 3 57 | ScrollResolution 58 | 5 59 | ScrollYInverter 60 | 1 61 | WakeDelay 62 | 1000 63 | 64 | 65 | 66 | 67 | OSBundleLibraries 68 | 69 | com.apple.iokit.IOHIDFamily 70 | 1.0.0b1 71 | com.apple.kpi.iokit 72 | 9.0.0 73 | com.apple.kpi.libkern 74 | 9.0.0 75 | com.apple.kpi.mach 76 | 9.0.0 77 | as.acidanthera.voodoo.driver.PS2Controller 78 | ${MODULE_VERSION} 79 | 80 | OSBundleRequired 81 | Console 82 | 83 | 84 | -------------------------------------------------------------------------------- /VoodooPS2Mouse/VoodooPS2Mouse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.1 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2MOUSE_H 24 | #define _APPLEPS2MOUSE_H 25 | 26 | #include "../VoodooPS2Controller/ApplePS2MouseDevice.h" 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 33 | // Local Declarations 34 | // 35 | 36 | #define kPacketLengthMax 4 37 | #define kPacketLengthStandard 3 38 | #define kPacketLengthIntellimouse 4 39 | 40 | typedef enum 41 | { 42 | kMouseTypeStandard = 0x00, 43 | kMouseTypeIntellimouse = 0x03, 44 | kMouseTypeIntellimouseExplorer = 0x04 45 | } PS2MouseId; 46 | 47 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 48 | // ApplePS2Mouse Class Declaration 49 | // 50 | 51 | class EXPORT ApplePS2Mouse : public IOHIPointing 52 | { 53 | typedef IOHIPointing super; 54 | OSDeclareDefaultStructors(ApplePS2Mouse); 55 | 56 | private: 57 | ApplePS2MouseDevice * _device; 58 | bool _interruptHandlerInstalled; 59 | bool _powerControlHandlerInstalled; 60 | RingBuffer _ringBuffer; 61 | UInt32 _packetByteCount; 62 | UInt8 _lastdata; 63 | UInt32 _packetLength; 64 | IOFixed _resolution; // (dots per inch) 65 | PS2MouseId _type; 66 | int _buttonCount; 67 | UInt32 _mouseInfoBytes; 68 | UInt32 _mouseResetCount; 69 | IOCommandGate* _cmdGate; 70 | int defres; 71 | int forceres; 72 | int mouseyinverter; 73 | int scrollyinverter; 74 | int forcesetres; 75 | int32_t resmode; 76 | int32_t scrollres; 77 | int wakedelay; 78 | 79 | // for middle button simulation 80 | enum mbuttonstate 81 | { 82 | STATE_NOBUTTONS, 83 | STATE_MIDDLE, 84 | STATE_WAIT4TWO, 85 | STATE_WAIT4NONE, 86 | STATE_NOOP, 87 | } _mbuttonstate; 88 | 89 | UInt32 lastbuttons; 90 | UInt32 _pendingbuttons; 91 | uint64_t _buttontime; 92 | IOTimerEventSource* _buttonTimer; 93 | uint64_t _maxmiddleclicktime; 94 | int _fakemiddlebutton; 95 | 96 | void onButtonTimer(void); 97 | enum MBComingFrom { fromTimer, fromMouse }; 98 | UInt32 middleButton(UInt32 butttons, uint64_t now, MBComingFrom from); 99 | 100 | virtual void dispatchRelativePointerEventWithPacket(UInt8 * packet, 101 | UInt32 packetSize); 102 | virtual UInt8 getMouseID(); 103 | virtual UInt32 getMouseInformation(); 104 | virtual PS2MouseId setIntellimouseMode(); 105 | virtual void setMouseEnable(bool enable); 106 | virtual void setMouseSampleRate(UInt8 sampleRate); 107 | virtual void setMouseResolution(UInt8 resolution); 108 | virtual void initMouse(); 109 | virtual void resetMouse(); 110 | virtual void setDevicePowerState(UInt32 whatToDo); 111 | 112 | void setParamPropertiesGated(OSDictionary * dict); 113 | 114 | protected: 115 | IOItemCount buttonCount() override; 116 | IOFixed resolution() override; 117 | inline void dispatchRelativePointerEventX(int dx, int dy, UInt32 buttonState, uint64_t now) 118 | { dispatchRelativePointerEvent(dx, dy, buttonState, *(AbsoluteTime*)&now); } 119 | inline void dispatchScrollWheelEventX(short deltaAxis1, short deltaAxis2, short deltaAxis3, uint64_t now) 120 | { dispatchScrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, *(AbsoluteTime*)&now); } 121 | inline void setTimerTimeout(IOTimerEventSource* timer, uint64_t time) 122 | { timer->setTimeout(*(AbsoluteTime*)&time); } 123 | inline void cancelTimer(IOTimerEventSource* timer) 124 | { timer->cancelTimeout(); } 125 | public: 126 | bool init(OSDictionary * properties) override; 127 | ApplePS2Mouse * probe(IOService * provider, SInt32 * score) override; 128 | 129 | bool start(IOService * provider) override; 130 | void stop(IOService * provider) override; 131 | 132 | virtual PS2InterruptResult interruptOccurred(UInt8 data); 133 | virtual void packetReady(); 134 | 135 | UInt32 deviceType() override; 136 | UInt32 interfaceID() override; 137 | 138 | IOReturn setParamProperties(OSDictionary * dict) override; 139 | IOReturn setProperties (OSObject *props) override; 140 | }; 141 | 142 | #endif /* _APPLEPS2MOUSE_H */ 143 | -------------------------------------------------------------------------------- /VoodooPS2Mouse/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2ALPSGlidePoint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.2 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2ALPSTOUCHPAD_H 24 | #define _APPLEPS2ALPSTOUCHPAD_H 25 | 26 | #include "ApplePS2MouseDevice.h" 27 | #include 28 | #include 29 | #include "VoodooInputMultitouch/VoodooInputEvent.h" 30 | #include "VoodooPS2TrackpadCommon.h" 31 | 32 | #define ALPS_PROTO_V1 0x100 33 | #define ALPS_PROTO_V2 0x200 34 | #define ALPS_PROTO_V3 0x300 35 | #define ALPS_PROTO_V3_RUSHMORE 0x310 36 | #define ALPS_PROTO_V4 0x400 37 | #define ALPS_PROTO_V5 0x500 38 | #define ALPS_PROTO_V6 0x600 39 | #define ALPS_PROTO_V7 0x700 /* t3btl t4s */ 40 | #define ALPS_PROTO_V8 0x800 /* SS4btl SS4s */ 41 | #define ALPS_PROTO_V9 0x900 /* ss3btl */ 42 | 43 | #define MAX_TOUCHES 5 44 | 45 | #define DOLPHIN_COUNT_PER_ELECTRODE 64 46 | #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ 47 | #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ 48 | 49 | struct alps_virtual_finger_state { 50 | UInt32 x; 51 | UInt32 y; 52 | uint8_t pressure; 53 | bool touch; 54 | bool button; 55 | MT2FingerType fingerType; 56 | }; 57 | 58 | /* 59 | * enum SS4_PACKET_ID - defines the packet type for V8 60 | * SS4_PACKET_ID_IDLE: There's no finger and no button activity. 61 | * SS4_PACKET_ID_ONE: There's one finger on touchpad 62 | * or there's button activities. 63 | * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad 64 | * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad 65 | * SS4_PACKET_ID_STICK: A stick pointer packet 66 | */ 67 | enum SS4_PACKET_ID { 68 | SS4_PACKET_ID_IDLE = 0, 69 | SS4_PACKET_ID_ONE, 70 | SS4_PACKET_ID_TWO, 71 | SS4_PACKET_ID_MULTI, 72 | SS4_PACKET_ID_STICK, 73 | }; 74 | 75 | #define SS4_COUNT_PER_ELECTRODE 256 76 | #define SS4_NUMSENSOR_XOFFSET 7 77 | #define SS4_NUMSENSOR_YOFFSET 7 78 | #define SS4_MIN_PITCH_MM 50 79 | 80 | #define SS4_MASK_NORMAL_BUTTONS 0x07 81 | 82 | #define SS4PLUS_COUNT_PER_ELECTRODE 128 83 | #define SS4PLUS_NUMSENSOR_XOFFSET 16 84 | #define SS4PLUS_NUMSENSOR_YOFFSET 5 85 | #define SS4PLUS_MIN_PITCH_MM 37 86 | 87 | #define IS_SS4PLUS_DEV(_b) (((_b[0]) == 0x73) && \ 88 | ((_b[1]) == 0x03) && \ 89 | ((_b[2]) == 0x28) \ 90 | ) 91 | 92 | #define SS4_IS_IDLE_V2(_b) (((_b[0]) == 0x18) && \ 93 | ((_b[1]) == 0x10) && \ 94 | ((_b[2]) == 0x00) && \ 95 | ((_b[3] & 0x88) == 0x08) && \ 96 | ((_b[4]) == 0x10) && \ 97 | ((_b[5]) == 0x00) \ 98 | ) 99 | 100 | #define SS4_1F_X_V2(_b) (((_b[0]) & 0x0007) | \ 101 | ((_b[1] << 3) & 0x0078) | \ 102 | ((_b[1] << 2) & 0x0380) | \ 103 | ((_b[2] << 5) & 0x1C00) \ 104 | ) 105 | 106 | #define SS4_1F_Y_V2(_b) (((_b[2]) & 0x000F) | \ 107 | ((_b[3] >> 2) & 0x0030) | \ 108 | ((_b[4] << 6) & 0x03C0) | \ 109 | ((_b[4] << 5) & 0x0C00) \ 110 | ) 111 | 112 | #define SS4_1F_Z_V2(_b) (((_b[5]) & 0x0F) | \ 113 | ((_b[5] >> 1) & 0x70) | \ 114 | ((_b[4]) & 0x80) \ 115 | ) 116 | 117 | #define SS4_1F_LFB_V2(_b) (((_b[2] >> 4) & 0x01) == 0x01) 118 | 119 | #define SS4_MF_LF_V2(_b, _i) ((_b[1 + (_i) * 3] & 0x0004) == 0x0004) 120 | 121 | #define SS4_BTN_V2(_b) ((_b[0] >> 5) & SS4_MASK_NORMAL_BUTTONS) 122 | 123 | #define SS4_STD_MF_X_V2(_b, _i) (((_b[0 + (_i) * 3] << 5) & 0x00E0) | \ 124 | ((_b[1 + _i * 3] << 5) & 0x1F00) \ 125 | ) 126 | 127 | #define SS4_PLUS_STD_MF_X_V2(_b, _i) (((_b[0 + (_i) * 3] << 4) & 0x0070) | \ 128 | ((_b[1 + (_i) * 3] << 4) & 0x0F80) \ 129 | ) 130 | 131 | #define SS4_STD_MF_Y_V2(_b, _i) (((_b[1 + (_i) * 3] << 3) & 0x0010) | \ 132 | ((_b[2 + (_i) * 3] << 5) & 0x01E0) | \ 133 | ((_b[2 + (_i) * 3] << 4) & 0x0E00) \ 134 | ) 135 | 136 | #define SS4_BTL_MF_X_V2(_b, _i) (SS4_STD_MF_X_V2(_b, _i) | \ 137 | ((_b[0 + (_i) * 3] >> 3) & 0x0010) \ 138 | ) 139 | 140 | #define SS4_PLUS_BTL_MF_X_V2(_b, _i) (SS4_PLUS_STD_MF_X_V2(_b, _i) | \ 141 | ((_b[0 + (_i) * 3] >> 4) & 0x0008) \ 142 | ) 143 | 144 | #define SS4_BTL_MF_Y_V2(_b, _i) (SS4_STD_MF_Y_V2(_b, _i) | \ 145 | ((_b[0 + (_i) * 3] >> 3) & 0x0008) \ 146 | ) 147 | 148 | #define SS4_MF_Z_V2(_b, _i) (((_b[1 + (_i) * 3]) & 0x0001) | \ 149 | ((_b[1 + (_i) * 3] >> 1) & 0x0002) \ 150 | ) 151 | 152 | #define SS4_IS_MF_CONTINUE(_b) ((_b[2] & 0x10) == 0x10) 153 | #define SS4_IS_5F_DETECTED(_b) ((_b[2] & 0x10) == 0x10) 154 | 155 | #define SS4_MFPACKET_NO_AX 8160 /* X-Coordinate value */ 156 | #define SS4_MFPACKET_NO_AY 4080 /* Y-Coordinate value */ 157 | #define SS4_MFPACKET_NO_AX_BL 8176 /* Buttonless X-Coord value */ 158 | #define SS4_MFPACKET_NO_AY_BL 4088 /* Buttonless Y-Coord value */ 159 | #define SS4_PLUS_MFPACKET_NO_AX 4080 /* SS4 PLUS, X */ 160 | #define SS4_PLUS_MFPACKET_NO_AX_BL 4088 /* Buttonless SS4 PLUS, X */ 161 | 162 | /* 163 | * enum V7_PACKET_ID - defines the packet type for V7 164 | * V7_PACKET_ID_IDLE: There's no finger and no button activity. 165 | * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad 166 | * or there's button activities. 167 | * V7_PACKET_ID_MULTI: There are at least three non-resting fingers. 168 | * V7_PACKET_ID_NEW: The finger position in slot is not continues from 169 | * previous packet. 170 | */ 171 | enum V7_PACKET_ID { 172 | V7_PACKET_ID_IDLE, 173 | V7_PACKET_ID_TWO, 174 | V7_PACKET_ID_MULTI, 175 | V7_PACKET_ID_NEW, 176 | V7_PACKET_ID_UNKNOWN, 177 | }; 178 | 179 | /** 180 | * struct alps_protocol_info - information about protocol used by a device 181 | * @version: Indicates V1/V2/V3/... 182 | * @byte0: Helps figure out whether a position report packet matches the 183 | * known format for this model. The first byte of the report, ANDed with 184 | * mask0, should match byte0. 185 | * @mask0: The mask used to check the first byte of the report. 186 | * @flags: Additional device capabilities (passthrough port, trackstick, etc.). 187 | */ 188 | struct alps_protocol_info { 189 | UInt16 version; 190 | UInt8 byte0, mask0; 191 | unsigned int flags; 192 | }; 193 | 194 | /** 195 | * struct alps_model_info - touchpad ID table 196 | * @signature: E7 response string to match. 197 | * @protocol_info: information about protocol used by the device. 198 | * 199 | * Many (but not all) ALPS touchpads can be identified by looking at the 200 | * values returned in the "E7 report" and/or the "EC report." This table 201 | * lists a number of such touchpads. 202 | */ 203 | struct alps_model_info { 204 | UInt8 signature[3]; 205 | struct alps_protocol_info protocol_info; 206 | }; 207 | 208 | /** 209 | * struct alps_nibble_commands - encodings for register accesses 210 | * @command: PS/2 command used for the nibble 211 | * @data: Data supplied as an argument to the PS/2 command, if applicable 212 | * 213 | * The ALPS protocol uses magic sequences to transmit binary data to the 214 | * touchpad, as it is generally not OK to send arbitrary bytes out the 215 | * PS/2 port. Each of the sequences in this table sends one nibble of the 216 | * register address or (write) data. Different versions of the ALPS protocol 217 | * use slightly different encodings. 218 | */ 219 | struct alps_nibble_commands { 220 | SInt32 command; 221 | UInt8 data; 222 | }; 223 | 224 | struct alps_bitmap_point { 225 | int start_bit; 226 | int num_bits; 227 | }; 228 | 229 | struct input_mt_pos { 230 | UInt32 x; 231 | UInt32 y; 232 | }; 233 | 234 | /** 235 | * struct alps_fields - decoded version of the report packet 236 | * @x_map: Bitmap of active X positions for MT. 237 | * @y_map: Bitmap of active Y positions for MT. 238 | * @fingers: Number of fingers for MT. 239 | * @pressure: Pressure. 240 | * @st: position for ST. 241 | * @mt: position for MT. 242 | * @first_mp: Packet is the first of a multi-packet report. 243 | * @is_mp: Packet is part of a multi-packet report. 244 | * @left: Left touchpad button is active. 245 | * @right: Right touchpad button is active. 246 | * @middle: Middle touchpad button is active. 247 | * @ts_left: Left trackstick button is active. 248 | * @ts_right: Right trackstick button is active. 249 | * @ts_middle: Middle trackstick button is active. 250 | */ 251 | struct alps_fields { 252 | unsigned int x_map; 253 | unsigned int y_map; 254 | unsigned int fingers; 255 | 256 | int pressure; 257 | struct input_mt_pos st; 258 | struct input_mt_pos mt[MAX_TOUCHES]; 259 | 260 | unsigned int first_mp:1; 261 | unsigned int is_mp:1; 262 | 263 | unsigned int left:1; 264 | unsigned int right:1; 265 | unsigned int middle:1; 266 | 267 | unsigned int ts_left:1; 268 | unsigned int ts_right:1; 269 | unsigned int ts_middle:1; 270 | }; 271 | 272 | class ApplePS2ALPSGlidePoint; 273 | 274 | /** 275 | * struct alps_data - private data structure for the ALPS driver 276 | * @nibble_commands: Command mapping used for touchpad register accesses. 277 | * @addr_command: Command used to tell the touchpad that a register address 278 | * follows. 279 | * @proto_version: Indicates V1/V2/V3/... 280 | * @byte0: Helps figure out whether a position report packet matches the 281 | * known format for this model. The first byte of the report, ANDed with 282 | * mask0, should match byte0. 283 | * @mask0: The mask used to check the first byte of the report. 284 | * @fw_ver: cached copy of firmware version (EC report) 285 | * @flags: Additional device capabilities (passthrough port, trackstick, etc.). 286 | * @x_max: Largest possible X position value. 287 | * @y_max: Largest possible Y position value. 288 | * @x_bits: Number of X bits in the MT bitmap. 289 | * @y_bits: Number of Y bits in the MT bitmap. 290 | * @prev_fin: Finger bit from previous packet. 291 | * @multi_packet: Multi-packet data in progress. 292 | * @multi_data: Saved multi-packet data. 293 | * @f: Decoded packet data fields. 294 | * @quirks: Bitmap of ALPS_QUIRK_*. 295 | */ 296 | struct alps_data { 297 | /* these are autodetected when the device is identified */ 298 | const struct alps_nibble_commands *nibble_commands; 299 | SInt32 addr_command; 300 | UInt16 proto_version; 301 | UInt8 byte0, mask0; 302 | UInt8 dev_id[3]; 303 | UInt8 fw_ver[3]; 304 | int flags; 305 | SInt32 x_max; 306 | SInt32 y_max; 307 | SInt32 x_bits; 308 | SInt32 y_bits; 309 | unsigned int x_res; 310 | unsigned int y_res; 311 | 312 | SInt32 prev_fin; 313 | SInt32 multi_packet; 314 | int second_touch; 315 | UInt8 multi_data[6]; 316 | struct alps_fields f; 317 | UInt8 quirks; 318 | bool PSMOUSE_BAD_DATA; 319 | 320 | int pktsize = 6; 321 | }; 322 | 323 | // Pulled out of alps_data, now saved as vars on class 324 | // makes invoking a little easier 325 | typedef bool (ApplePS2ALPSGlidePoint::*hw_init)(); 326 | typedef bool (ApplePS2ALPSGlidePoint::*decode_fields)(struct alps_fields *f, UInt8 *p); 327 | typedef void (ApplePS2ALPSGlidePoint::*process_packet)(UInt8 *packet); 328 | //typedef void (ALPS::*set_abs_params)(); 329 | 330 | #define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */ 331 | 332 | // 333 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 334 | // ApplePS2ALPSGlidePoint Class Declaration 335 | // 336 | 337 | typedef struct ALPSStatus { 338 | UInt8 bytes[3]; 339 | } ALPSStatus_t; 340 | 341 | #define XMIN 0 342 | #define XMAX 6143 343 | #define YMIN 0 344 | #define YMAX 6143 345 | #define XMIN_NOMINAL 1472 346 | #define XMAX_NOMINAL 5472 347 | #define YMIN_NOMINAL 1408 348 | #define YMAX_NOMINAL 4448 349 | 350 | #define ABS_POS_BITS 13 351 | #define X_MAX_POSITIVE 8176 352 | #define Y_MAX_POSITIVE 8176 353 | 354 | #define kPacketLength 6 355 | #define kDP_CommandNibble10 0xf2 356 | 357 | // predeclure stuff 358 | struct alps_data; 359 | 360 | class EXPORT ApplePS2ALPSGlidePoint : public IOService { 361 | OSDeclareDefaultStructors( ApplePS2ALPSGlidePoint ); 362 | 363 | private: 364 | IOService *voodooInputInstance {nullptr}; 365 | ApplePS2MouseDevice * _device {nullptr}; 366 | bool _interruptHandlerInstalled {false}; 367 | bool _powerControlHandlerInstalled {false}; 368 | RingBuffer _ringBuffer {}; 369 | UInt32 _packetByteCount {0}; 370 | 371 | IOCommandGate* _cmdGate {nullptr}; 372 | 373 | VoodooInputEvent inputEvent {}; 374 | 375 | // buttons and scroll wheel 376 | unsigned int clicked:1; 377 | unsigned int left:1; 378 | unsigned int right:1; 379 | unsigned int middle:1; 380 | 381 | unsigned int left_ts:1; 382 | 383 | // VoodooInput 384 | int margin_size_x {0}; 385 | 386 | uint32_t logical_max_x {0}; 387 | uint32_t logical_max_y {0}; 388 | 389 | uint32_t physical_max_x {0}; 390 | uint32_t physical_max_y {0}; 391 | 392 | alps_virtual_finger_state virtualFingerStates[MAX_TOUCHES] {}; 393 | 394 | int clampedFingerCount {0}; 395 | int lastFingerCount; 396 | bool reportVoodooInput; 397 | 398 | int minXOverride {-1}, minYOverride {-1}, maxXOverride {-1}, maxYOverride {-1}; 399 | 400 | ForceTouchMode _forceTouchMode {FORCE_TOUCH_DISABLED}; 401 | int _forceTouchPressureThreshold {100}; 402 | 403 | int _forceTouchCustomDownThreshold {90}; 404 | int _forceTouchCustomUpThreshold {20}; 405 | int _forceTouchCustomPower {8}; 406 | 407 | // normal state 408 | UInt32 lastbuttons {0}; 409 | UInt32 lastTrackStickButtons, lastTouchpadButtons; 410 | uint64_t keytime {0}; 411 | bool ignoreall {false}; 412 | int z_finger {45}; 413 | uint64_t maxaftertyping {100000000}; 414 | int wakedelay {1000}; 415 | // HID Notification 416 | bool usb_mouse_stops_trackpad {true}; 417 | 418 | int _processusbmouse {true}; 419 | int _processbluetoothmouse {true}; 420 | 421 | OSSet* attachedHIDPointerDevices {nullptr}; 422 | 423 | IONotifier* usb_hid_publish_notify {nullptr}; // Notification when an USB mouse HID device is connected 424 | IONotifier* usb_hid_terminate_notify {nullptr}; // Notification when an USB mouse HID device is disconnected 425 | 426 | IONotifier* bluetooth_hid_publish_notify {nullptr}; // Notification when a bluetooth HID device is connected 427 | IONotifier* bluetooth_hid_terminate_notify {nullptr}; // Notification when a bluetooth HID device is disconnected 428 | 429 | int _modifierdown {0}; // state of left+right control keys 430 | 431 | // for scaling x/y values 432 | int xupmm {50}, yupmm {50}; // 50 is just arbitrary, but same 433 | 434 | alps_data priv; 435 | hw_init hw_init; 436 | decode_fields decode_fields; 437 | process_packet process_packet; 438 | // set_abs_params set_abs_params; 439 | 440 | void injectVersionDependentProperties(OSDictionary* dict); 441 | bool resetMouse(); 442 | bool handleOpen(IOService *forClient, IOOptionBits options, void *arg) override; 443 | void handleClose(IOService *forClient, IOOptionBits options) override; 444 | bool handleIsOpen(const IOService *forClient) const override; 445 | PS2InterruptResult interruptOccurred(UInt8 data); 446 | void packetReady(); 447 | virtual bool deviceSpecificInit(); 448 | 449 | void alps_process_packet_v1_v2(UInt8 *packet); 450 | int alps_process_bitmap(struct alps_data *priv, struct alps_fields *f); 451 | void alps_process_trackstick_packet_v3(UInt8 * packet); 452 | bool alps_decode_buttons_v3(struct alps_fields *f, UInt8 *p); 453 | bool alps_decode_pinnacle(struct alps_fields *f, UInt8 *p); 454 | bool alps_decode_rushmore(struct alps_fields *f, UInt8 *p); 455 | bool alps_decode_dolphin(struct alps_fields *f, UInt8 *p); 456 | void alps_process_touchpad_packet_v3_v5(UInt8 * packet); 457 | void alps_process_packet_v3(UInt8 *packet); 458 | void alps_process_packet_v6(UInt8 *packet); 459 | void alps_process_packet_v4(UInt8 *packet); 460 | unsigned char alps_get_packet_id_v7(UInt8 *byte); 461 | void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, UInt8 *pkt, UInt8 pkt_id); 462 | int alps_get_mt_count(struct input_mt_pos *mt); 463 | bool alps_decode_packet_v7(struct alps_fields *f, UInt8 *p); 464 | void alps_process_trackstick_packet_v7(UInt8 *packet); 465 | void alps_process_touchpad_packet_v7(UInt8 *packet); 466 | void alps_process_packet_v7(UInt8 *packet); 467 | unsigned char alps_get_pkt_id_ss4_v2(UInt8 *byte); 468 | bool alps_decode_ss4_v2(struct alps_fields *f, UInt8 *p); 469 | void alps_process_packet_ss4_v2(UInt8 *packet); 470 | bool alps_command_mode_send_nibble(int value); 471 | bool alps_command_mode_set_addr(int addr); 472 | int alps_command_mode_read_reg(int addr); 473 | bool alps_command_mode_write_reg(int addr, UInt8 value); 474 | bool alps_command_mode_write_reg(UInt8 value); 475 | bool alps_rpt_cmd(SInt32 init_command, SInt32 init_arg, SInt32 repeated_command, ALPSStatus_t *report); 476 | bool alps_enter_command_mode(); 477 | bool alps_exit_command_mode(); 478 | bool alps_passthrough_mode_v2(bool enable); 479 | bool alps_absolute_mode_v1_v2(); 480 | int alps_monitor_mode_send_word(int word); 481 | int alps_monitor_mode_write_reg(int addr, int value); 482 | int alps_monitor_mode(bool enable); 483 | void alps_absolute_mode_v6(); 484 | bool alps_get_status(ALPSStatus_t *status); 485 | bool alps_tap_mode(bool enable); 486 | bool alps_hw_init_v1_v2(); 487 | bool alps_hw_init_v6(); 488 | bool alps_passthrough_mode_v3(int regBase, bool enable); 489 | bool alps_absolute_mode_v3(); 490 | IOReturn alps_probe_trackstick_v3_v7(int regBase); 491 | IOReturn alps_setup_trackstick_v3(int regBase); 492 | bool alps_hw_init_v3(); 493 | bool alps_get_v3_v7_resolution(int reg_pitch); 494 | bool alps_hw_init_rushmore_v3(); 495 | bool alps_absolute_mode_v4(); 496 | bool alps_hw_init_v4(); 497 | void alps_get_otp_values_ss4_v2(unsigned char index, unsigned char otp[]); 498 | void alps_update_device_area_ss4_v2(unsigned char otp[][4], struct alps_data *priv); 499 | void alps_update_btn_info_ss4_v2(unsigned char otp[][4], struct alps_data *priv); 500 | void alps_update_dual_info_ss4_v2(unsigned char otp[][4], struct alps_data *priv); 501 | void alps_set_defaults_ss4_v2(struct alps_data *priv); 502 | int alps_dolphin_get_device_area(struct alps_data *priv); 503 | bool alps_hw_init_dolphin_v1(); 504 | bool alps_hw_init_v7(); 505 | bool alps_hw_init_ss4_v2(); 506 | void set_protocol(); 507 | bool matchTable(ALPSStatus_t *e7, ALPSStatus_t *ec); 508 | IOReturn identify(); 509 | void setTouchPadEnable(bool enable); 510 | void ps2_command(unsigned char value, UInt8 command); 511 | void ps2_command_short(UInt8 command); 512 | int abs(int x); 513 | void set_resolution(); 514 | void voodooTrackpoint(UInt32 type, SInt8 x, SInt8 y, int buttons); 515 | void alps_buttons(struct alps_fields &f); 516 | 517 | void prepareVoodooInput(struct alps_fields &f, int fingers); 518 | void sendTouchData(); 519 | 520 | virtual void initTouchPad(); 521 | virtual void setParamPropertiesGated(OSDictionary* dict); 522 | virtual void setDevicePowerState(UInt32 whatToDo); 523 | 524 | void registerHIDPointerNotifications(); 525 | void unregisterHIDPointerNotifications(); 526 | 527 | void notificationHIDAttachedHandlerGated(IOService * newService, IONotifier * notifier); 528 | bool notificationHIDAttachedHandler(void * refCon, IOService * newService, IONotifier * notifier); 529 | 530 | public: 531 | bool init(OSDictionary * dict) override; 532 | ApplePS2ALPSGlidePoint * probe(IOService *provider, SInt32 *score) override; 533 | 534 | bool start(IOService *provider) override; 535 | void stop(IOService *provider) override; 536 | 537 | IOReturn setProperties(OSObject *props) override; 538 | 539 | IOReturn message(UInt32 type, IOService* provider, void* argument) override; 540 | }; 541 | 542 | #endif /* _APPLEPS2ALPSTOUCHPAD_H */ 543 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2Elan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Elan PS2 touchpad integration 3 | * 4 | * Mostly contains code ported from Linux 5 | * https://github.com/torvalds/linux/blob/master/drivers/input/mouse/elantech.c 6 | * 7 | * Created by Bartosz Korczyński (@bandysc), Hiep Bao Le (@hieplpvip) 8 | * Special thanks to Kishor Prins (@kprinssu), EMlyDinEsHMG and whole VoodooInput team 9 | */ 10 | 11 | #ifndef _APPLEPS2ELAN_H 12 | #define _APPLEPS2ELAN_H 13 | 14 | #include "../VoodooPS2Controller/ApplePS2MouseDevice.h" 15 | #include 16 | #include 17 | #include 18 | 19 | #include "VoodooInputMultitouch/VoodooInputEvent.h" 20 | #include "VoodooPS2TrackpadCommon.h" 21 | 22 | struct elan_virtual_finger_state { 23 | TouchCoordinates prev; 24 | TouchCoordinates now; 25 | uint8_t pressure; 26 | uint8_t width; 27 | bool touch; 28 | bool button; 29 | MT2FingerType fingerType; 30 | }; 31 | 32 | #define kPacketLengthMax 6 33 | 34 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 35 | // 36 | // FROM LINUX ELANTECH.C 37 | 38 | /* 39 | * Command values for Synaptics style queries 40 | */ 41 | #define ETP_FW_ID_QUERY 0x00 42 | #define ETP_FW_VERSION_QUERY 0x01 43 | #define ETP_CAPABILITIES_QUERY 0x02 44 | #define ETP_SAMPLE_QUERY 0x03 45 | #define ETP_RESOLUTION_QUERY 0x04 46 | 47 | /* 48 | * Command values for register reading or writing 49 | */ 50 | #define ETP_REGISTER_READ 0x10 51 | #define ETP_REGISTER_WRITE 0x11 52 | #define ETP_REGISTER_READWRITE 0x00 53 | 54 | /* 55 | * Hardware version 2 custom PS/2 command value 56 | */ 57 | #define ETP_PS2_CUSTOM_COMMAND 0xf8 58 | 59 | /* 60 | * Times to retry a ps2_command and millisecond delay between tries 61 | */ 62 | #define ETP_PS2_COMMAND_TRIES 3 63 | #define ETP_PS2_COMMAND_DELAY 500 64 | 65 | /* 66 | * Times to try to read back a register and millisecond delay between tries 67 | */ 68 | #define ETP_READ_BACK_TRIES 5 69 | #define ETP_READ_BACK_DELAY 2000 70 | 71 | /* 72 | * Register bitmasks for hardware version 1 73 | */ 74 | #define ETP_R10_ABSOLUTE_MODE 0x04 75 | #define ETP_R11_4_BYTE_MODE 0x02 76 | 77 | /* 78 | * Capability bitmasks 79 | */ 80 | #define ETP_CAP_HAS_ROCKER 0x04 81 | 82 | /* 83 | * One hard to find application note states that X axis range is 0 to 576 84 | * and Y axis range is 0 to 384 for harware version 1. 85 | * Edge fuzz might be necessary because of bezel around the touchpad 86 | */ 87 | #define ETP_EDGE_FUZZ_V1 32 88 | 89 | #define ETP_XMIN_V1 ( 0 + ETP_EDGE_FUZZ_V1) 90 | #define ETP_XMAX_V1 (576 - ETP_EDGE_FUZZ_V1) 91 | #define ETP_YMIN_V1 ( 0 + ETP_EDGE_FUZZ_V1) 92 | #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) 93 | 94 | /* 95 | * The resolution for older v2 hardware doubled. 96 | * (newer v2's firmware provides command so we can query) 97 | */ 98 | #define ETP_XMIN_V2 0 99 | #define ETP_XMAX_V2 1152 100 | #define ETP_YMIN_V2 0 101 | #define ETP_YMAX_V2 768 102 | 103 | // Preasure min-max 104 | #define ETP_PMIN_V2 0 105 | #define ETP_PMAX_V2 255 106 | 107 | // Width min-max 108 | #define ETP_WMIN_V2 0 109 | #define ETP_WMAX_V2 15 110 | 111 | /* 112 | * v3 hardware has 2 kinds of packet types, 113 | * v4 hardware has 3. 114 | */ 115 | #define PACKET_UNKNOWN 0x01 116 | #define PACKET_DEBOUNCE 0x02 117 | #define PACKET_V3_HEAD 0x03 118 | #define PACKET_V3_TAIL 0x04 119 | #define PACKET_V4_HEAD 0x05 120 | #define PACKET_V4_MOTION 0x06 121 | #define PACKET_V4_STATUS 0x07 122 | #define PACKET_TRACKPOINT 0x08 123 | 124 | /* 125 | * track up to 5 fingers for v4 hardware 126 | */ 127 | #define ETP_MAX_FINGERS 5 128 | 129 | /* 130 | * weight value for v4 hardware 131 | */ 132 | #define ETP_WEIGHT_VALUE 5 133 | 134 | /* 135 | * Bus information on 3rd byte of query ETP_RESOLUTION_QUERY(0x04) 136 | */ 137 | #define ETP_BUS_PS2_ONLY 0 138 | #define ETP_BUS_SMB_ALERT_ONLY 1 139 | #define ETP_BUS_SMB_HST_NTFY_ONLY 2 140 | #define ETP_BUS_PS2_SMB_ALERT 3 141 | #define ETP_BUS_PS2_SMB_HST_NTFY 4 142 | 143 | /* 144 | * New ICs are either using SMBus Host Notify or just plain PS2. 145 | * 146 | * ETP_FW_VERSION_QUERY is: 147 | * Byte 1: 148 | * - bit 0..3: IC BODY 149 | * Byte 2: 150 | * - bit 4: HiddenButton 151 | * - bit 5: PS2_SMBUS_NOTIFY 152 | * - bit 6: PS2CRCCheck 153 | */ 154 | #define ETP_NEW_IC_SMBUS_HOST_NOTIFY(fw_version) \ 155 | ((((fw_version) & 0x0f2000) == 0x0f2000) && \ 156 | ((fw_version) & 0x0000ff) > 0) 157 | 158 | /* 159 | * The base position for one finger, v4 hardware 160 | */ 161 | struct finger_pos { 162 | unsigned int x; 163 | unsigned int y; 164 | }; 165 | 166 | struct elantech_device_info { 167 | unsigned char capabilities[3]; 168 | unsigned char samples[3]; 169 | unsigned char debug; 170 | unsigned char hw_version; 171 | unsigned int fw_version; 172 | unsigned int x_min; 173 | unsigned int y_min; 174 | unsigned int x_max; 175 | unsigned int y_max; 176 | unsigned int x_res; 177 | unsigned int y_res; 178 | unsigned int x_traces; 179 | unsigned int y_traces; 180 | unsigned int width; 181 | unsigned int bus; 182 | bool paritycheck; 183 | bool jumpy_cursor; 184 | bool reports_pressure; 185 | bool crc_enabled; 186 | bool set_hw_resolution; 187 | bool is_buttonpad; 188 | bool has_trackpoint; 189 | bool has_middle_button; 190 | }; 191 | 192 | struct elantech_data { 193 | unsigned char reg_07; 194 | unsigned char reg_10; 195 | unsigned char reg_11; 196 | unsigned char reg_20; 197 | unsigned char reg_21; 198 | unsigned char reg_22; 199 | unsigned char reg_23; 200 | unsigned char reg_24; 201 | unsigned char reg_25; 202 | unsigned char reg_26; 203 | unsigned int single_finger_reports; 204 | struct finger_pos mt[ETP_MAX_FINGERS]; 205 | unsigned char parity[256]; 206 | }; 207 | 208 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 209 | // ApplePS2Elan Class Declaration 210 | // 211 | 212 | class EXPORT ApplePS2Elan : public IOService { 213 | typedef IOService super; 214 | OSDeclareDefaultStructors(ApplePS2Elan); 215 | 216 | private: 217 | IOService* voodooInputInstance {nullptr}; 218 | ApplePS2MouseDevice* _device {nullptr}; 219 | bool _interruptHandlerInstalled {false}; 220 | bool _powerControlHandlerInstalled {false}; 221 | UInt32 _packetByteCount {0}; 222 | UInt32 _packetLength {0}; 223 | RingBuffer _ringBuffer {}; 224 | 225 | IOCommandGate* _cmdGate {nullptr}; 226 | 227 | VoodooInputEvent inputEvent {}; 228 | TrackpointReport trackpointReport {}; 229 | 230 | // when trackpad has physical button 231 | UInt32 leftButton = 0; 232 | UInt32 rightButton = 0; 233 | UInt32 lastLeftButton = 0; 234 | UInt32 lastRightButton = 0; 235 | 236 | const float sin30deg = 0.5f; 237 | const float cos30deg = 0.86602540378f; 238 | UInt32 lastFingers = 0; 239 | 240 | int heldFingers = 0; 241 | int headPacketsCount = 0; 242 | elan_virtual_finger_state virtualFinger[ETP_MAX_FINGERS] {}; 243 | 244 | static_assert(ETP_MAX_FINGERS <= kMT2FingerTypeLittleFinger, "Too many fingers for one hand"); 245 | 246 | ForceTouchMode _forceTouchMode {FORCE_TOUCH_BUTTON}; 247 | 248 | int wakedelay {1000}; 249 | int _trackpointDeadzone {1}; 250 | int _trackpointMultiplierX {120}; 251 | int _trackpointMultiplierY {120}; 252 | int _trackpointDividerX {120}; 253 | int _trackpointDividerY {120}; 254 | int _trackpointScrollMultiplierX {120}; 255 | int _trackpointScrollMultiplierY {120}; 256 | int _trackpointScrollDividerX {120}; 257 | int _trackpointScrollDividerY {120}; 258 | 259 | int _mouseResolution {0x3}; 260 | int _mouseSampleRate {200}; 261 | 262 | bool _set_hw_resolution {false}; 263 | 264 | bool ignoreall {false}; 265 | bool usb_mouse_stops_trackpad {true}; 266 | 267 | bool _processusbmouse {true}; 268 | bool _processbluetoothmouse {true}; 269 | 270 | uint64_t keytime {0}; 271 | uint64_t maxaftertyping {500000000}; 272 | 273 | OSSet *attachedHIDPointerDevices {nullptr}; 274 | 275 | IONotifier *usb_hid_publish_notify {nullptr}; // Notification when an USB mouse HID device is connected 276 | IONotifier *usb_hid_terminate_notify {nullptr}; // Notification when an USB mouse HID device is disconnected 277 | 278 | IONotifier *bluetooth_hid_publish_notify {nullptr}; // Notification when a bluetooth HID device is connected 279 | IONotifier *bluetooth_hid_terminate_notify {nullptr}; // Notification when a bluetooth HID device is disconnected 280 | 281 | virtual PS2InterruptResult interruptOccurred(UInt8 data); 282 | virtual void packetReady(); 283 | virtual void setDevicePowerState(UInt32 whatToDo); 284 | 285 | bool handleOpen(IOService *forClient, IOOptionBits options, void *arg) override; 286 | void handleClose(IOService *forClient, IOOptionBits options) override; 287 | bool handleIsOpen(const IOService *forClient) const override; 288 | 289 | void setParamPropertiesGated(OSDictionary *dict); 290 | void injectVersionDependentProperties(OSDictionary *dict); 291 | void setTrackpointProperties(); 292 | 293 | void registerHIDPointerNotifications(); 294 | void unregisterHIDPointerNotifications(); 295 | 296 | void notificationHIDAttachedHandlerGated(IOService *newService, IONotifier *notifier); 297 | bool notificationHIDAttachedHandler(void *refCon, IOService *newService, IONotifier *notifier); 298 | 299 | elantech_data etd {}; 300 | elantech_device_info info {}; 301 | int elantechDetect(); 302 | int elantechQueryInfo(); 303 | int elantechSetProperties(); 304 | int elantechSetAbsoluteMode(); 305 | int elantechSetInputParams(); 306 | int elantechSetupPS2(); 307 | int elantechReadReg(unsigned char reg, unsigned char *val); 308 | int elantechWriteReg(unsigned char reg, unsigned char val); 309 | int elantechDebounceCheckV2(); 310 | int elantechPacketCheckV1(); 311 | int elantechPacketCheckV2(); 312 | int elantechPacketCheckV3(); 313 | int elantechPacketCheckV4(); 314 | void elantechRescale(unsigned int x, unsigned int y); 315 | void elantechReportAbsoluteV1(); 316 | void elantechReportAbsoluteV2(); 317 | void elantechReportAbsoluteV3(int packetType); 318 | void elantechReportAbsoluteV4(int packetType); 319 | void elantechReportTrackpoint(); 320 | void processPacketStatusV4(); 321 | void processPacketHeadV4(); 322 | void processPacketMotionV4(); 323 | void sendTouchData(); 324 | void resetMouse(); 325 | void setTouchPadEnable(bool enable); 326 | 327 | static MT2FingerType GetBestFingerType(int i); 328 | 329 | template 330 | int ps2_command(UInt8* params, unsigned int command); 331 | template 332 | int elantech_ps2_command(unsigned char *param, int command); 333 | int ps2_sliced_command(UInt8 command); 334 | template 335 | int synaptics_send_cmd(unsigned char c, unsigned char *param); 336 | template 337 | int elantech_send_cmd(unsigned char c, unsigned char *param); 338 | template 339 | int send_cmd(unsigned char c, unsigned char *param); 340 | 341 | bool elantech_is_signature_valid(const unsigned char *param); 342 | static unsigned int elantech_convert_res(unsigned int val); 343 | int elantech_get_resolution_v4(unsigned int *x_res, unsigned int *y_res, unsigned int *bus); 344 | 345 | public: 346 | bool init(OSDictionary *properties) override; 347 | ApplePS2Elan *probe(IOService *provider, SInt32 *score) override; 348 | bool start(IOService *provider) override; 349 | void stop(IOService *provider) override; 350 | 351 | IOReturn setProperties(OSObject *props) override; 352 | 353 | IOReturn message(UInt32 type, IOService* provider, void* argument) override; 354 | }; 355 | 356 | #endif /* _ApplePS2Elan_H */ 357 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2SMBusDevice.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // VoodooPS2SMBusDevice.cpp 3 | // VoodooPS2Trackpad 4 | // 5 | // Created by Avery Black on 9/13/24. 6 | // Copyright © 2024 Acidanthera. All rights reserved. 7 | // 8 | 9 | #include "VoodooPS2SMBusDevice.h" 10 | 11 | // ============================================================================= 12 | // ApplePS2SmbusDevice Class Implementation 13 | // 14 | 15 | OSDefineMetaClassAndStructors(ApplePS2SmbusDevice, IOService); 16 | 17 | ApplePS2SmbusDevice *ApplePS2SmbusDevice::withReset(bool resetNeeded, OSDictionary *data, uint8_t addr) { 18 | ApplePS2SmbusDevice *dev = OSTypeAlloc(ApplePS2SmbusDevice); 19 | 20 | if (dev == nullptr) { 21 | return nullptr; 22 | } 23 | 24 | if (!dev->init()) { 25 | OSSafeReleaseNULL(dev); 26 | return nullptr; 27 | } 28 | 29 | dev->_resetNeeded = resetNeeded; 30 | dev->_data = data; 31 | dev->_data->retain(); 32 | dev->_addr = addr; 33 | return dev; 34 | } 35 | 36 | bool ApplePS2SmbusDevice::start(IOService *provider) { 37 | if (!super::start(provider)) 38 | return false; 39 | 40 | _nub = OSDynamicCast(ApplePS2MouseDevice, provider); 41 | if (_nub == nullptr) 42 | return false; 43 | 44 | if (_resetNeeded) 45 | resetDevice(); 46 | 47 | if (_nub->startSMBusCompanion(_data, _addr) != kIOReturnSuccess) { 48 | return false; 49 | } 50 | 51 | _nub->installPowerControlAction(this, 52 | OSMemberFunctionCast(PS2PowerControlAction, this, &ApplePS2SmbusDevice::powerAction)); 53 | return true; 54 | } 55 | 56 | void ApplePS2SmbusDevice::stop(IOService *provider) { 57 | _nub->uninstallPowerControlAction(); 58 | resetDevice(); 59 | super::stop(provider); 60 | } 61 | 62 | void ApplePS2SmbusDevice::free() { 63 | OSSafeReleaseNULL(_data); 64 | super::free(); 65 | } 66 | 67 | void ApplePS2SmbusDevice::powerAction(uint32_t ordinal) { 68 | if (ordinal == kPS2C_EnableDevice && _resetNeeded) { 69 | (void) resetDevice(); 70 | } 71 | } 72 | 73 | IOReturn ApplePS2SmbusDevice::resetDevice() { 74 | TPS2Request<> request; 75 | request.commands[0].command = kPS2C_SendCommandAndCompareAck; 76 | request.commands[0].inOrOut = kDP_SetDefaultsAndDisable; // F5 77 | request.commandsCount = 1; 78 | _nub->submitRequestAndBlock(&request); 79 | 80 | if (request.commandsCount == 1) { 81 | DEBUG_LOG("VoodooPS2Trackpad: sending $FF failed: %d\n", request.commandsCount); 82 | return kIOReturnError; 83 | } 84 | 85 | return kIOReturnSuccess; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2SMBusDevice.h: -------------------------------------------------------------------------------- 1 | // 2 | // VoodooPS2SMBusDevice.hpp 3 | // VoodooPS2Trackpad 4 | // 5 | // Created by Avery Black on 9/13/24. 6 | // Copyright © 2024 Acidanthera. All rights reserved. 7 | // 8 | 9 | #ifndef VoodooPS2SMBusDevice_hpp 10 | #define VoodooPS2SMBusDevice_hpp 11 | 12 | 13 | #include "../VoodooPS2Controller/ApplePS2MouseDevice.h" 14 | #include 15 | 16 | #include "VoodooPS2TrackpadCommon.h" 17 | 18 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 19 | // ApplePS2SmbusDevice Class Declaration 20 | // Synaptics and Elans devices still need resets over PS2. This acts as a 21 | // PS/2 stub driver that attaches in lieu of the full touchpad driver to reset 22 | // on wakeups and sleep. This also prevents other devices attaching and using 23 | // the otherwise unused PS/2 interface 24 | // 25 | 26 | class EXPORT ApplePS2SmbusDevice : public IOService { 27 | typedef IOService super; 28 | OSDeclareDefaultStructors(ApplePS2SmbusDevice); 29 | public: 30 | static ApplePS2SmbusDevice *withReset(bool resetNeeded, OSDictionary *data, uint8_t addr); 31 | 32 | bool start(IOService *provider) override; 33 | void stop(IOService *provider) override; 34 | void free() override; 35 | 36 | private: 37 | ApplePS2MouseDevice *_nub {nullptr}; 38 | bool _resetNeeded {false}; 39 | OSDictionary *_data {nullptr}; 40 | uint8_t _addr{0}; 41 | 42 | IOReturn resetDevice(); 43 | void powerAction(uint32_t ordinal); 44 | }; 45 | 46 | #endif /* VoodooPS2SMBusDevice_hpp */ 47 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2SentelicFSP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.2 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2SENTILICSFSP_H 24 | #define _APPLEPS2SENTILICSFSP_H 25 | 26 | #include "../VoodooPS2Controller/ApplePS2MouseDevice.h" 27 | 28 | #include 29 | 30 | #define kPacketLengthMax 4 31 | #define kPacketLengthStandard 3 32 | #define kPacketLengthLarge 4 33 | 34 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 35 | // ApplePS2SentelicFSP Class Declaration 36 | // 37 | 38 | class EXPORT ApplePS2SentelicFSP : public IOHIPointing 39 | { 40 | typedef IOHIPointing super; 41 | OSDeclareDefaultStructors( ApplePS2SentelicFSP ); 42 | 43 | private: 44 | ApplePS2MouseDevice * _device; 45 | bool _interruptHandlerInstalled; 46 | bool _powerControlHandlerInstalled; 47 | RingBuffer _ringBuffer; 48 | UInt32 _packetByteCount; 49 | UInt8 _packetSize; 50 | IOFixed _resolution; 51 | UInt16 _touchPadVersion; 52 | UInt8 _touchPadModeByte; 53 | 54 | virtual void dispatchRelativePointerEventWithPacket( UInt8 * packet, UInt32 packetSize ); 55 | 56 | virtual void setTouchPadEnable( bool enable ); 57 | virtual UInt32 getTouchPadData( UInt8 dataSelector ); 58 | virtual bool setTouchPadModeByte( UInt8 modeByteValue, 59 | bool enableStreamMode = false ); 60 | 61 | virtual PS2InterruptResult interruptOccurred(UInt8 data); 62 | virtual void packetReady(); 63 | virtual void setDevicePowerState(UInt32 whatToDo); 64 | 65 | protected: 66 | IOItemCount buttonCount() override; 67 | IOFixed resolution() override; 68 | 69 | inline void dispatchRelativePointerEventX(int dx, int dy, UInt32 buttonState, uint64_t now) 70 | { dispatchRelativePointerEvent(dx, dy, buttonState, *(AbsoluteTime*)&now); } 71 | inline void dispatchScrollWheelEventX(short deltaAxis1, short deltaAxis2, short deltaAxis3, uint64_t now) 72 | { dispatchScrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, *(AbsoluteTime*)&now); } 73 | 74 | 75 | public: 76 | bool init( OSDictionary * properties ) override; 77 | ApplePS2SentelicFSP * probe( IOService * provider, 78 | SInt32 * score ) override; 79 | 80 | bool start( IOService * provider ) override; 81 | void stop( IOService * provider ) override; 82 | 83 | UInt32 deviceType() override; 84 | UInt32 interfaceID() override; 85 | 86 | IOReturn setParamProperties( OSDictionary * dict ) override; 87 | }; 88 | 89 | #endif /* _APPLEPS2SENTILICSFSP_H */ 90 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2SynapticsTouchPad.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * The contents of this file constitute Original Code as defined in and 7 | * are subject to the Apple Public Source License Version 1.2 (the 8 | * "License"). You may not use this file except in compliance with the 9 | * License. Please obtain a copy of the License at 10 | * http://www.apple.com/publicsource and read it before using this file. 11 | * 12 | * This Original Code and all software distributed under the License are 13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 | * License for the specific language governing rights and limitations 18 | * under the License. 19 | * 20 | * @APPLE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | #ifndef _APPLEPS2SYNAPTICSTOUCHPAD_H 24 | #define _APPLEPS2SYNAPTICSTOUCHPAD_H 25 | 26 | #include "../VoodooPS2Controller/ApplePS2MouseDevice.h" 27 | #include 28 | #include 29 | #include "VoodooInputMultitouch/VoodooInputEvent.h" 30 | #include "VoodooPS2TrackpadCommon.h" 31 | 32 | struct synaptics_hw_state { 33 | int x; 34 | int y; 35 | int z; 36 | int w; 37 | int virtualFingerIndex; 38 | }; 39 | 40 | /* 41 | Если touch = false, то палец игнорируется. 42 | Соответствие физических и виртуальных пальцев - динамическое. 43 | transducers заполняются каждый раз с номером виртуального пальца столько, сколько надо. 44 | Будут ли при этом отжиматься отпущенные пальцы? 45 | */ 46 | struct synaptics_virtual_finger_state { 47 | SimpleAverage x_avg; 48 | SimpleAverage y_avg; 49 | uint8_t pressure; 50 | uint8_t width; 51 | bool touch; 52 | bool button; 53 | MT2FingerType fingerType; 54 | }; 55 | 56 | #pragma pack(push) 57 | #pragma pack(1) 58 | 59 | #define SYNAPTICS_IDENTIFY_QUERY 0x00 60 | struct synaptics_identify_trackpad { 61 | uint8_t minor_ver; 62 | uint8_t synaptics_const; 63 | uint8_t major_ver : 4; 64 | uint8_t model_code : 4; // Unused field 65 | }; 66 | static_assert(sizeof(synaptics_identify_trackpad) == 3, "Invalid Identity packet size"); 67 | 68 | #define SYNA_MODEL_QUERY 0x01 69 | struct synaptics_model { 70 | uint8_t guest_present: 1; 71 | uint8_t more_extended_caps: 1; 72 | uint16_t model_number: 14; 73 | uint8_t mode_byte; 74 | }; 75 | static_assert(sizeof(synaptics_model) == 3, "Invalid Model packet size"); 76 | 77 | #define SYNA_CAPABILITIES_QUERY 0x02 78 | struct synaptics_capabilities { 79 | // Byte 0 80 | uint8_t _reserved0: 2; 81 | uint8_t middle_btn: 1; 82 | uint8_t _reserved1: 1; 83 | uint8_t extended_queries: 3; 84 | uint8_t has_extended_queries: 1; 85 | // Byte 1 86 | uint8_t model_sub_num; 87 | // Byte 2 88 | uint8_t palm_detect: 1; 89 | uint8_t multi_finger: 1; 90 | uint8_t ballistics: 1; 91 | uint8_t sleep: 1; 92 | uint8_t four_buttons: 1; // Currently unsupported 93 | uint8_t extended_w_supported: 1; 94 | uint8_t low_power: 1; 95 | uint8_t passthrough: 1; 96 | }; 97 | static_assert(sizeof(synaptics_capabilities) == 3, "Invalid Capabilities packet size"); 98 | 99 | #define SYNA_SCALE_QUERY 0x08 100 | struct synaptics_scale { 101 | uint8_t xupmm; 102 | uint8_t reserved; 103 | uint8_t yupmm; 104 | }; 105 | static_assert(sizeof(synaptics_scale) == 3, "Invalid Scale packet size"); 106 | 107 | #define SYNA_EXTENDED_ID_QUERY 0x09 108 | struct synaptics_extended_id { 109 | // Byte 0 110 | uint8_t vert_scroll_zone: 1; 111 | uint8_t horiz_scroll_zone: 1; 112 | uint8_t extended_w_supported: 1; 113 | uint8_t vertical_wheel: 1; 114 | uint8_t transparent_passthru: 1; 115 | uint8_t peak_detection: 1; 116 | uint8_t has_leds: 1; 117 | uint8_t reserved0: 1; 118 | // Byte 1 119 | uint8_t reserved1: 2; 120 | uint8_t info_sensor: 2; 121 | uint8_t extended_btns: 4; 122 | // Byte 2 123 | uint8_t product_id; 124 | }; 125 | static_assert(sizeof(synaptics_extended_id) == 3, "Invalid Extended ID packet size"); 126 | 127 | #define SYNA_CONT_CAPS_QUERY 0x0C 128 | struct synaptics_cont_capabilities { 129 | // Byte 0 130 | uint8_t adj_button_threshold: 1; 131 | uint8_t reports_max: 1; 132 | uint8_t is_clearpad: 1; 133 | uint8_t advanced_gestures: 1; 134 | uint8_t one_btn_clickpad: 1; 135 | uint8_t multifinger_mode: 2; 136 | uint8_t covered_pad_gesture: 1; 137 | // Byte 1 138 | uint8_t two_btn_clickpad: 1; 139 | uint8_t deluxe_leds: 1; 140 | uint8_t no_abs_pos_filter: 1; 141 | uint8_t reports_v: 1; 142 | uint8_t uniform_clickpad: 1; 143 | uint8_t reports_min: 1; 144 | uint8_t intertouch: 1; 145 | uint8_t reserved: 1; 146 | // Byte 2 147 | uint8_t intertouch_addr; 148 | }; 149 | static_assert(sizeof(synaptics_cont_capabilities) == 3, "Invalid continued capabilities packet size"); 150 | 151 | #define SYNA_LOGIC_MAX_QUERY 0x0D 152 | #define SYNA_LOGIC_MIN_QUERY 0x0F 153 | #define SYNA_LOGIC_X(x) ((x.x_high << 5) | (x.x_low << 1)) 154 | #define SYNA_LOGIC_Y(x) (x.y << 1) 155 | struct synaptics_logic_min_max { 156 | uint8_t x_high; 157 | uint8_t x_low: 4; 158 | uint16_t y: 12; 159 | }; 160 | static_assert(sizeof(synaptics_logic_min_max) == 3, "Invalid logic packet size"); 161 | 162 | #define SYNA_SECUREPAD_QUERY 0x10 163 | struct synaptics_securepad_id { 164 | uint8_t trackstick_btns: 1; 165 | uint8_t is_securepad: 1; 166 | uint8_t unused: 6; 167 | uint8_t securepad_width; 168 | uint8_t securepad_height; 169 | }; 170 | static_assert(sizeof(synaptics_securepad_id) == 3, "Invalid securepad packet size"); 171 | 172 | #define SYNA_MODE_ABSOLUTE 0x80 173 | #define SYNA_MODE_HIGH_RATE 0x40 174 | #define SYNA_MODE_SLEEP 0x08 175 | #define SYNA_MODE_EXT_W 0x04 176 | #define SYNA_MODE_W_MODE 0x01 177 | 178 | // W Values for packet types 179 | #define SYNA_W_EXTENDED 0x02 180 | #define SYNA_W_PASSTHRU 0x03 181 | 182 | #pragma pack(pop) 183 | 184 | #define SYNAPTICS_MAX_EXT_BTNS 8 185 | #define SYNAPTICS_MAX_FINGERS 5 186 | 187 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 188 | // ApplePS2SynapticsTouchPad Class Declaration 189 | // 190 | 191 | #define XMIN 0 192 | #define XMAX 6143 193 | #define YMIN 0 194 | #define YMAX 6143 195 | #define XMIN_NOMINAL 1472 196 | #define XMAX_NOMINAL 5472 197 | #define YMIN_NOMINAL 1408 198 | #define YMAX_NOMINAL 4448 199 | 200 | #define ABS_POS_BITS 13 201 | #define X_MAX_POSITIVE 8176 202 | #define Y_MAX_POSITIVE 8176 203 | 204 | 205 | #define kPacketLength 6 206 | 207 | class EXPORT ApplePS2SynapticsTouchPad : public IOService 208 | { 209 | typedef IOService super; 210 | OSDeclareDefaultStructors(ApplePS2SynapticsTouchPad); 211 | 212 | private: 213 | IOService *voodooInputInstance {nullptr}; 214 | ApplePS2MouseDevice * _device {nullptr}; 215 | bool _interruptHandlerInstalled {false}; 216 | bool _powerControlHandlerInstalled {false}; 217 | RingBuffer _ringBuffer {}; 218 | UInt32 _packetByteCount {0}; 219 | UInt8 _lastdata {0}; 220 | 221 | synaptics_identify_trackpad _identity {0}; 222 | synaptics_capabilities _capabilities {0}; 223 | synaptics_extended_id _extended_id {0}; 224 | synaptics_securepad_id _securepad {0}; 225 | synaptics_scale _scale {0}; 226 | synaptics_cont_capabilities _cont_caps {0}; 227 | 228 | IOCommandGate* _cmdGate {nullptr}; 229 | IOACPIPlatformDevice*_provider {nullptr}; 230 | 231 | VoodooInputEvent inputEvent {}; 232 | TrackpointReport trackpointReport {}; 233 | 234 | // buttons and scroll wheel 235 | bool _clickpad_pressed { false }; 236 | 237 | int margin_size_x {0}, margin_size_y {0}; 238 | uint32_t logical_max_x {0}; 239 | uint32_t logical_max_y {0}; 240 | uint32_t logical_min_x {0}; 241 | uint32_t logical_min_y {0}; 242 | 243 | uint32_t physical_max_x {0}; 244 | uint32_t physical_max_y {0}; 245 | 246 | synaptics_hw_state fingerStates[SYNAPTICS_MAX_FINGERS] {}; 247 | synaptics_virtual_finger_state virtualFingerStates[SYNAPTICS_MAX_FINGERS] {}; 248 | bool freeFingerTypes[kMT2FingerTypeCount]; 249 | 250 | bool disableDeepSleep {false}; 251 | 252 | static_assert(SYNAPTICS_MAX_FINGERS <= kMT2FingerTypeLittleFinger, "Too many fingers for one hand"); 253 | 254 | void assignVirtualFinger(int physicalFinger); 255 | void assignFingerType(synaptics_virtual_finger_state &vf); 256 | int lastFingerCount; 257 | int lastSentFingerCount; 258 | bool hadLiftFinger; 259 | int upperFingerIndex() const; 260 | const synaptics_hw_state& upperFinger() const; 261 | void swapFingers(int dst, int src); 262 | 263 | void synaptics_parse_normal_packet(const UInt8 buf[], const int w); 264 | void synaptics_parse_agm_packet(const UInt8 buf[]); 265 | void synaptics_parse_passthru(const UInt8 buf[], const UInt32 buttons); 266 | int synaptics_parse_ext_btns(const UInt8 buf[], const int w); 267 | void synaptics_parse_hw_state(const UInt8 buf[]); 268 | 269 | /// Translates physical fingers into virtual fingers so that host software doesn't see 'jumps' and has coordinates for all fingers. 270 | /// @return True if is ready to send finger state to host interface 271 | bool renumberFingers(); 272 | void sendTouchData(); 273 | void freeAndMarkVirtualFingers(); 274 | int dist(int physicalFinger, int virtualFinger); 275 | 276 | ForceTouchMode _forceTouchMode {FORCE_TOUCH_BUTTON}; 277 | int _forceTouchPressureThreshold {100}; 278 | 279 | int _forceTouchCustomDownThreshold {90}; 280 | int _forceTouchCustomUpThreshold {20}; 281 | int _forceTouchCustomPower {8}; 282 | 283 | int clampedFingerCount {0}; 284 | int agmFingerCount {0}; 285 | bool wasSkipped {false}; 286 | int z_finger {45}; 287 | int zlimit {0}; 288 | int noled {0}; 289 | uint64_t maxaftertyping {500000000}; 290 | uint64_t maxafterspecialtyping {0}; 291 | int specialKey {0x80}; 292 | int wakedelay {1000}; 293 | int hwresetonstart {0}; 294 | int diszl {0}, diszr {0}, diszt {0}, diszb {0}; 295 | int minXOverride {-1}, minYOverride {-1}, maxXOverride {-1}, maxYOverride {-1}; 296 | 297 | int _lastExtendedButtons {0}; 298 | int _lastPassthruButtons {0}; 299 | 300 | // Trackpoint information 301 | int _scrollMultiplierX {1}; 302 | int _scrollMultiplierY {1}; 303 | int _scrollDivisorX {1}; 304 | int _scrollDivisorY {1}; 305 | int _mouseMultiplierX {1}; 306 | int _mouseMultiplierY {1}; 307 | int _mouseDivisorX {1}; 308 | int _mouseDivisorY {1}; 309 | int _deadzone {1}; 310 | 311 | // state related to secondary packets/extendedwmode 312 | bool tracksecondary {false}; 313 | 314 | // normal state 315 | uint64_t keytime {0}; 316 | UInt16 keycode {0}; 317 | bool ignoreall {false}; 318 | #ifdef SIMULATE_PASSTHRU 319 | UInt32 trackbuttons {0}; 320 | #endif 321 | bool usb_mouse_stops_trackpad {true}; 322 | 323 | int _processusbmouse {true}; 324 | int _processbluetoothmouse {true}; 325 | 326 | const OSSymbol* _smbusCompanion {nullptr}; 327 | 328 | OSSet* attachedHIDPointerDevices {nullptr}; 329 | 330 | IONotifier* usb_hid_publish_notify {nullptr}; // Notification when an USB mouse HID device is connected 331 | IONotifier* usb_hid_terminate_notify {nullptr}; // Notification when an USB mouse HID device is disconnected 332 | 333 | IONotifier* bluetooth_hid_publish_notify {nullptr}; // Notification when a bluetooth HID device is connected 334 | IONotifier* bluetooth_hid_terminate_notify {nullptr}; // Notification when a bluetooth HID device is disconnected 335 | 336 | int _modifierdown {0}; // state of left+right control keys 337 | 338 | inline bool isInDisableZone(int x, int y) 339 | { return x > diszl && x < diszr && y > diszb && y < diszt; } 340 | 341 | // Sony: coordinates captured from single touch event 342 | // Don't know what is the exact value of x and y on edge of touchpad 343 | // the best would be { return x > xmax/2 && y < ymax/4; } 344 | 345 | virtual void setTouchPadEnable( bool enable ); 346 | virtual bool getTouchPadData( UInt8 dataSelector, UInt8 buf3[] ); 347 | virtual bool getTouchPadStatus( UInt8 buf3[] ); 348 | virtual PS2InterruptResult interruptOccurred(UInt8 data); 349 | virtual void packetReady(); 350 | virtual void setDevicePowerState(UInt32 whatToDo); 351 | 352 | void updateTouchpadLED(); 353 | bool setTouchpadLED(UInt8 touchLED); 354 | void initTouchPad(); 355 | bool enterAdvancedGestureMode(); 356 | bool setModeByte(bool sleep); 357 | 358 | inline bool isFingerTouch(int z) { return z>z_finger && z 2 | 3 | 4 | 5 | CFBundleExecutable 6 | VoodooPS2Trackpad 7 | CFBundleGetInfoString 8 | ${MODULE_VERSION}, Copyright Apple Computer, Inc. 2002-2003, mackerintel 2008, RehabMan 2012-2013 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Voodoo PS/2 Trackpad 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | ${MODULE_VERSION} 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${MODULE_VERSION} 23 | IOKitPersonalities 24 | 25 | ALPS GlidePoint 26 | 27 | CFBundleIdentifier 28 | as.acidanthera.voodoo.driver.PS2Trackpad 29 | IOClass 30 | ApplePS2ALPSGlidePoint 31 | IOProbeScore 32 | 1500 33 | IOProviderClass 34 | ApplePS2MouseDevice 35 | Platform Profile 36 | 37 | Default 38 | 39 | Darwin 16+ 40 | 41 | ApplePreferenceCapability 42 | 43 | ApplePreferenceIdentifier 44 | com.apple.AppleMultitouchTrackpad 45 | MT Built-in 46 | 47 | MTHIDDevice 48 | 49 | SupportsGestureScrolling 50 | 51 | TrackpadEmbedded 52 | 53 | TrackpadFourFingerGestures 54 | 55 | TrackpadSecondaryClickCorners 56 | 57 | TrackpadThreeFingerDrag 58 | 59 | 60 | DisableDevice 61 | 62 | DragLockTempMask 63 | 1048592 64 | FingerZ 65 | 1 66 | ForceTouchCustomDownThreshold 67 | 90 68 | ForceTouchCustomPower 69 | 8 70 | ForceTouchCustomUpThreshold 71 | 20 72 | ForceTouchMode 73 | 0 74 | ForceTouchPressureThreshold 75 | 100 76 | ProcessBluetoothMouseStopsTrackpad 77 | 78 | ProcessUSBMouseStopsTrackpad 79 | 80 | QuietTimeAfterTyping 81 | 100000000 82 | USBMouseStopsTrackpad 83 | 0 84 | UnitsPerMMX 85 | 50 86 | UnitsPerMMY 87 | 50 88 | WakeDelay 89 | 1000 90 | 91 | HPQOEM 92 | 93 | 1411 94 | ProBook 95 | 1619 96 | ProBook 97 | 161C 98 | ProBook 99 | 164F 100 | ProBook 101 | 167C 102 | ProBook 103 | 167E 104 | ProBook 105 | 1680 106 | ProBook 107 | 179B 108 | ProBook 109 | 179C 110 | ProBook 111 | 17A9 112 | ProBook 113 | 17F0 114 | ProBook 115 | 17F3 116 | ProBook 117 | 17F6 118 | ProBook 119 | 1942 120 | ProBook 121 | 1949 122 | ProBook 123 | 198F 124 | ProBook 125 | ProBook 126 | 127 | DisableDevice 128 | 129 | 130 | ProBook-102 131 | ProBook 132 | ProBook-87 133 | ProBook 134 | 135 | 136 | ProductID 137 | 547 138 | RM,deliverNotifications 139 | 140 | VendorID 141 | 1452 142 | 143 | Elantech TouchPad 144 | 145 | IOProbeScore 146 | 7000 147 | IOProviderClass 148 | ApplePS2MouseDevice 149 | IOClass 150 | ApplePS2Elan 151 | CFBundleIdentifier 152 | as.acidanthera.voodoo.driver.PS2Trackpad 153 | Platform Profile 154 | 155 | Default 156 | 157 | ButtonCount 158 | 3 159 | Darwin 16+ 160 | 161 | ApplePreferenceCapability 162 | 163 | ApplePreferenceIdentifier 164 | com.apple.AppleMultitouchTrackpad 165 | MT Built-in 166 | 167 | MTHIDDevice 168 | 169 | SupportsGestureScrolling 170 | 171 | TrackpadEmbedded 172 | 173 | TrackpadFourFingerGestures 174 | 175 | TrackpadSecondaryClickCorners 176 | 177 | TrackpadThreeFingerDrag 178 | 179 | 180 | DisableDevice 181 | 182 | ForceTouchMode 183 | 1 184 | MouseResolution 185 | 3 186 | MouseSampleRate 187 | 200 188 | ProcessBluetoothMouseStopsTrackpad 189 | 190 | ProcessUSBMouseStopsTrackpad 191 | 192 | QuietTimeAfterTyping 193 | 500000000 194 | ScrollResolution 195 | 400 196 | SetHwResolution 197 | 198 | TrackpointDividerX 199 | 120 200 | TrackpointDividerY 201 | 120 202 | TrackpointMultiplierX 203 | 120 204 | TrackpointMultiplierY 205 | 120 206 | USBMouseStopsTrackpad 207 | 0 208 | UseHighRate 209 | 210 | WakeDelay 211 | 1000 212 | 213 | 214 | RM,deliverNotifications 215 | 216 | 217 | Native Multitouch Engine 218 | 219 | CFBundleIdentifier 220 | as.acidanthera.voodoo.driver.PS2Trackpad 221 | IOClass 222 | VoodooPS2NativeEngine 223 | IOMatchCategory 224 | VoodooPS2NativeEngine 225 | IOProviderClass 226 | VoodooPS2MultitouchInterface 227 | 228 | Sentelic FSP 229 | 230 | CFBundleIdentifier 231 | as.acidanthera.voodoo.driver.PS2Trackpad 232 | IOClass 233 | ApplePS2SentelicFSP 234 | IOProbeScore 235 | 5500 236 | IOProviderClass 237 | ApplePS2MouseDevice 238 | Platform Profile 239 | 240 | Default 241 | 242 | DisableDevice 243 | 244 | 245 | HPQOEM 246 | 247 | 1411 248 | ProBook 249 | 1619 250 | ProBook 251 | 161C 252 | ProBook 253 | 164F 254 | ProBook 255 | 167C 256 | ProBook 257 | 167E 258 | ProBook 259 | 1680 260 | ProBook 261 | 179B 262 | ProBook 263 | 179C 264 | ProBook 265 | 17A9 266 | ProBook 267 | 17F0 268 | ProBook 269 | 17F3 270 | ProBook 271 | 17F6 272 | ProBook 273 | 1942 274 | ProBook 275 | 1949 276 | ProBook 277 | 198F 278 | ProBook 279 | ProBook 280 | 281 | DisableDevice 282 | 283 | 284 | ProBook-102 285 | ProBook 286 | ProBook-87 287 | ProBook 288 | 289 | 290 | 291 | Synaptics TouchPad 292 | 293 | CFBundleIdentifier 294 | as.acidanthera.voodoo.driver.PS2Trackpad 295 | IOClass 296 | ApplePS2SynapticsTouchPad 297 | IOProbeScore 298 | 6000 299 | IOProviderClass 300 | ApplePS2MouseDevice 301 | Platform Profile 302 | 303 | Default 304 | 305 | DisableDevice 306 | 307 | DisableLEDUpdating 308 | 309 | TrackpointDeadzone 310 | 1 311 | ForceTouchPressureThreshold 312 | 100 313 | ForceTouchCustomDownThreshold 314 | 90 315 | ForceTouchCustomUpThreshold 316 | 20 317 | ForceTouchCustomPower 318 | 8 319 | ProcessBluetoothMouseStopsTrackpad 320 | 321 | ProcessUSBMouseStopsTrackpad 322 | 323 | QuietTimeAfterTyping 324 | 500000000 325 | SkipPassThrough 326 | 327 | USBMouseStopsTrackpad 328 | 0 329 | WakeDelay 330 | 1000 331 | 332 | HPQOEM 333 | 334 | 1411 335 | ProBook 336 | 1619 337 | ProBook 338 | 161C 339 | ProBook 340 | 164F 341 | ProBook 342 | 167C 343 | ProBook 344 | 167E 345 | ProBook 346 | 1680 347 | ProBook 348 | 179B 349 | ProBook 350 | 179C 351 | ProBook 352 | 17A9 353 | ProBook 354 | 17F0 355 | ProBook 356 | 17F3 357 | ProBook 358 | 17F6 359 | ProBook 360 | 1942 361 | ProBook 362 | 1949 363 | ProBook 364 | 198F 365 | ProBook 366 | ProBook 367 | 368 | FingerZ 369 | 40 370 | 371 | ProBook-102 372 | ProBook 373 | ProBook-87 374 | ProBook 375 | 376 | LENOVO 377 | 378 | T420 379 | Thinkpad_TrackPad 380 | T460 381 | Thinkpad_ClickPad 382 | T560 383 | Thinkpad_ClickPad 384 | Thinkpad_ClickPad 385 | 386 | FingerZ 387 | 30 388 | HWResetOnStart 389 | 390 | TrackpointMultiplierX 391 | 2 392 | TrackpointMultiplierY 393 | 2 394 | TrackpointScrollMultiplierX 395 | 2 396 | TrackpointScrollMultiplierY 397 | 2 398 | 399 | Thinkpad_TrackPad 400 | 401 | FingerZ 402 | 47 403 | HWResetOnStart 404 | 405 | 406 | X1CG3 407 | Thinkpad_ClickPad 408 | 409 | 410 | ProductID 411 | 547 412 | RM,deliverNotifications 413 | 414 | VendorID 415 | 1452 416 | 417 | 418 | OSBundleLibraries 419 | 420 | com.apple.iokit.IOHIDFamily 421 | 1.0.0b1 422 | com.apple.kpi.iokit 423 | 9.0.0 424 | com.apple.kpi.libkern 425 | 9.0.0 426 | com.apple.kpi.mach 427 | 9.0.0 428 | as.acidanthera.voodoo.driver.PS2Controller 429 | ${MODULE_VERSION} 430 | 431 | OSBundleRequired 432 | Console 433 | 434 | 435 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/VoodooPS2TrackpadCommon.h: -------------------------------------------------------------------------------- 1 | // 2 | // VoodooPS2TrackpadCommon.h 3 | // VoodooPS2Trackpad 4 | // 5 | // Created by Le Bao Hiep on 27/09/2020. 6 | // Copyright © 2020 Acidanthera. All rights reserved. 7 | // 8 | 9 | #ifndef VoodooPS2TrackpadCommon_h 10 | #define VoodooPS2TrackpadCommon_h 11 | 12 | #define TEST_BIT(x, y) ((x >> y) & 0x1) 13 | 14 | void inline PS2DictSetNumber(OSDictionary *dict, const char *key, unsigned int num) { 15 | OSNumber *val = OSNumber::withNumber(num, 32); 16 | if (val != nullptr) { 17 | dict->setObject(key, val); 18 | val->release(); 19 | } 20 | } 21 | 22 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 23 | // SimpleAverage Class Declaration 24 | // 25 | 26 | template 27 | class SimpleAverage 28 | { 29 | private: 30 | T m_buffer[N]; 31 | int m_count; 32 | int m_sum; 33 | int m_index; 34 | 35 | public: 36 | inline SimpleAverage() { reset(); } 37 | T filter(T data) 38 | { 39 | // add new entry to sum 40 | m_sum += data; 41 | // if full buffer, then we are overwriting, so subtract old from sum 42 | if (m_count == N) 43 | m_sum -= m_buffer[m_index]; 44 | // new entry into buffer 45 | m_buffer[m_index] = data; 46 | // move index to next position with wrap around 47 | if (++m_index >= N) 48 | m_index = 0; 49 | // keep count moving until buffer is full 50 | if (m_count < N) 51 | ++m_count; 52 | // return average of current items 53 | return m_sum / m_count; 54 | } 55 | inline void reset() 56 | { 57 | m_count = 0; 58 | m_sum = 0; 59 | m_index = 0; 60 | } 61 | inline int count() const { return m_count; } 62 | inline int sum() const { return m_sum; } 63 | T oldest() const 64 | { 65 | // undefined if nothing in here, return zero 66 | if (m_count == 0) 67 | return 0; 68 | // if it is not full, oldest is at index 0 69 | // if full, it is right where the next one goes 70 | if (m_count < N) 71 | return m_buffer[0]; 72 | else 73 | return m_buffer[m_index]; 74 | } 75 | T newest() const 76 | { 77 | // undefined if nothing in here, return zero 78 | if (m_count == 0) 79 | return 0; 80 | // newest is index - 1, with wrap 81 | int index = m_index; 82 | if (--index < 0) 83 | index = m_count-1; 84 | return m_buffer[index]; 85 | } 86 | T average() const 87 | { 88 | if (m_count == 0) 89 | return 0; 90 | return m_sum / m_count; 91 | } 92 | }; 93 | 94 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 95 | // DecayingAverage Class Declaration 96 | // 97 | 98 | template 99 | class DecayingAverage 100 | { 101 | private: 102 | T m_last; 103 | bool m_lastvalid; 104 | 105 | public: 106 | inline DecayingAverage() { reset(); } 107 | T filter(T data, int fingers) 108 | { 109 | TT result = data; 110 | TT last = m_last; 111 | if (m_lastvalid) 112 | result = (result * N1) / D + (last * N2) / D; 113 | m_lastvalid = true; 114 | m_last = (T)result; 115 | return m_last; 116 | } 117 | inline void reset() 118 | { 119 | m_lastvalid = false; 120 | } 121 | }; 122 | 123 | template 124 | class UndecayAverage 125 | { 126 | private: 127 | T m_last; 128 | bool m_lastvalid; 129 | 130 | public: 131 | inline UndecayAverage() { reset(); } 132 | T filter(T data) 133 | { 134 | TT result = data; 135 | TT last = m_last; 136 | if (m_lastvalid) 137 | result = (result * D) / N1 - (last * N2) / N1; 138 | m_lastvalid = true; 139 | m_last = (T)data; 140 | return (T)result; 141 | } 142 | inline void reset() 143 | { 144 | m_lastvalid = false; 145 | } 146 | }; 147 | 148 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 149 | // Force Touch Modes 150 | // 151 | 152 | typedef enum { 153 | FORCE_TOUCH_DISABLED = 0, 154 | FORCE_TOUCH_BUTTON = 1, 155 | FORCE_TOUCH_THRESHOLD = 2, 156 | FORCE_TOUCH_VALUE = 3, 157 | FORCE_TOUCH_CUSTOM = 4 158 | } ForceTouchMode; 159 | 160 | #endif /* VoodooPS2TrackpadCommon_h */ 161 | -------------------------------------------------------------------------------- /VoodooPS2Trackpad/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | --------------------------------------------------------------------------------