Skip to content

About

Linux HID-over-SPI driver for the Microsoft Surface Laptop 3/4 (AMD) touchscreen

Topics

Resources

Stars

3 stars

Watchers

2 watching

Forks

Latest commit

 

History

513 Commits

Folders and files

Repository files navigation

SL4A TouchScreen

Linux kernel driver for the Microsoft Surface Laptop 3/4 (AMD) touchscreen, implementing the MSHW0231 / MSHW0162 V0 HID-over-SPI transport and a beta raw-heatmap multitouch pipeline on the AMD Cezanne FCH SPI controller.

Status Release CI License

Warning

Beta software. This is an experimental, reverse-engineered kernel driver. Use at your own risk. No warranty; provided "as is".

What to Expect

  • Standard HID mode (default) provides single-touch only — basic tap, drag, and single-finger interaction. This is the qualified profile.
  • A stylus/pen input node is published by the HID descriptor but is untested — pen behavior has not been observed or validated.
  • No multi-touch in standard mode. Multi-touch requires the beta raw pipeline (raw_mode=1).
  • Raw mode is beta — functional on hardware, still under field review. Finger tracking is observed to degrade at 4 contacts; pipeline tuning is ongoing.

See docs/QUICKSTART.md for a 5-step install and activation guide.

Device

Component Detail
Model Surface Laptop 4 (AMD Cezanne) / Surface Laptop 3 (AMD)
Touch ACPI ID MSHW0231 (SL4, HID VID/PID: 0x045E/0x0C19) / MSHW0162 (SL3)
SPI Controller AMDI0060 (AMD FCH SPI V2 at MMIO 0xFEC10000)
Protocol HID-over-SPI Version 0
Touch grid 72×48 cells (SL4) / 78×52 cells (SL3) — selected by ACPI ID
Report rate ~100 Hz (raw mode, field observation)

Feature Status

Feature Implementation status Release qualification
HID descriptor discovery Implemented, with a hardcoded fallback Hardware matrix required
Standard HID report forwarding Implemented Contact behavior requires hardware evidence
Raw CCL and multitouch pipeline Implemented Beta (functional on hardware, under field review)
Cold-boot retry and recovery Implemented Hardware matrix required
Candidate classification and per-cycle gain Not implemented Not planned for v1.x

Architecture

┌──────────────────────────────────────────────────────────────┐
│ Userspace: libinput / evdev ← hid-multitouch                 │
├──────────────────────────────────────────────────────────────┤
│ sl4a-spi-hid.ko (spi-hid-core.c, explicit opt-in only)        │
│   ├─ HID LL driver (DESCREQ → DEVICE_DESC → RPT_DESC)        │
│   ├─ IRQ-driven input (IRQ → SPI read → input_report)        │
│   └─ Raw heatmap pipeline:                                   │
│        baseline → peak gate → CCL → velocity → edge →        │
│        split → centroid → pre-merge → Hungarian →            │
│        EMA + deadband + stationary lock → MT emission         │
├──────────────────────────────────────────────────────────────┤
│ sl4a-spi-amd.ko (spi-amd.c, explicit opt-in only)            │
│   AMD FCH SPI controller V2 PIO driver                       │
│   TX/RX FIFO, chunked reads, opcode model                    │
├──────────────────────────────────────────────────────────────┤
│ Hardware: AMD FCH SPI @ 0xFEC10000 → MSHW0231 / MSHW0162       │
└──────────────────────────────────────────────────────────────┘

Raw Touch Pipeline

The raw multitouch pipeline is an experimental implementation that processes the current 72×48 fallback grid into HID contacts. Its comparison targets and unresolved frame-layout assumptions are recorded in docs/EVIDENCE.md.

Stage Function
c590 LUT Byte-indexed CapImg sample → fixed-point: max(0, 10000 - ((i·22204 + 500)/1000 + 6000))
Baseline 30-frame asymmetric EMA per cell
Noise floor c590 < 400 → suppressed (0.04 in the reference stack's fixed-point units)
Peak gate Full radius-2 neighbourhood scan of touched cells, rise ≥200, max 20 peaks (equal-signal plateaus contribute one peak, anchored at the region's centre)
CCL flood-fill 4-connected BFS, filters: n≥2, max_rise≥200, weight≥1000
Velocity rejection Blob must be within 6 cells of a detected peak
Edge penalty Bottom edge ×0.23, other edges ×0.97
Blob splitting Multi-peak blobs (≥4 cells apart) split into sub-blobs
Centroid Signal-weighted ×100 fixed-point on full blob extent
Eigenvalues Second moments → touch major/minor/orientation
Pre-merge Merge blobs within ghost_dist=6 (distance² < 36)
Hungarian Assignment with multi-finger radii (1×2.2, 2×1.0, 3×2.8, 4×3.4, 5+×4.0)
EMA + deadband Alpha=2 smoothing, ±0.2 cell deadband, 2-frame stationary lock
Lift lookback Emit lift at position from 2 frames ago

Install

Read docs/SUPPORT.md before installing. This repository is only for the Surface Laptop 3/4 AMD AMDI0060 + MSHW0231/MSHW0162 hardware contracts. The installer stages the modules through DKMS and then activates them right away (Step 7): it binds the experimental modules as soon as it finishes, and enables a systemd unit that keeps them bound on every future boot. Have recovery access ready (a local console or a remote shell) before running it. On Secure Boot systems the MOK key must be enrolled first; until it is, activation is skipped and the boot unit does it after the enrollment reboot. Modules use distinct sl4a-spi-amd and sl4a-spi-hid names and never replace in-tree drivers. See docs/COMPATIBILITY.md before treating a setup as supported.

git clone https://github.com/Syax89/SL4A_TouchScreen.git
cd SL4A_TouchScreen
./tools/sl4a-touch.sh install --check
sudo ./tools/sl4a-touch.sh install

install prompts interactively for a profile (standard HID, the supported default, or the experimental raw multitouch profile) unless --standard or --raw is given explicitly. --check performs a read-only ACPI and build-prerequisite preflight and needs no root; --force only to investigate unsupported hardware.

install activates the driver before it returns (Step 7), so have local/remote recovery access available before running it. Two cases skip that activation, and the installer says so when they apply: with Secure Boot the MOK key must be enrolled first (the boot unit activates after the enrollment reboot), and when the selected profile changes the load-time raw_mode parameter the modules keep the previous profile until the next boot, where the boot unit activates the new one. The experimental controller can also be activated by hand with:

sudo ./tools/sl4a-touch.sh activate

The command refuses to displace existing AMDI0060 or touchscreen (MSHW0231/MSHW0162) drivers, then verifies both bindings. To recover after a failed experiment, run sudo modprobe -r sl4a-spi-hid sl4a-spi-amd and reboot. Use sudo ./tools/sl4a-touch.sh install --raw only for the experimental raw heatmap profile. ./tools/sl4a-touch.sh status shows the installed version, active profile, and whether the driver is currently loaded and bound; sudo ./tools/sl4a-touch.sh logs collects a diagnostic bundle for bug reports.

The DKMS installer contains dependency guidance for Arch/CachyOS, Ubuntu/Debian, Fedora, and openSUSE. Neither module exports aliases, so the kernel never binds them on its own — the systemd unit install enables is what repeats the binding after every boot. Secure Boot remains unqualified until recorded in the compatibility matrix. See docs/ROLLBACK.md for the complete rollback and upgrade procedure.

Module Parameters

/etc/modprobe.d/sl4a-spi-hid.conf:
  options sl4a_spi_hid raw_mode=N wire_double_opcode=1

The explicit raw profile written by sl4a-touch.sh install --raw uses raw_mode=Y raw_input_beta=Y skip_getfeat=Y wire_double_opcode=1. Every raw control is experimental and load-time-only. The complete release, diagnostic, and experimental contract is in docs/PARAMETERS.md.

What Will Not Work

  • Multi-touch in standard mode (raw_mode=0) — the multi-touch input device is registered only by the raw pipeline (mshw0231-raw.c); standard mode forwards HID reports with no host-side tracking.
  • Pen input — the raw input device publishes touch contacts only and the driver contains no pen-specific handling, so pen behavior is unvalidated.
  • Palm rejection — no palm/rejection stage exists in the pipeline.
  • Other Surface models — the ACPI match tables accept only MSHW0231 / MSHW0162 (touch) and AMDI0060 (SPI controller).

Troubleshooting

Issue Fix
No touch after cold boot Power off → unplug AC → wait 30s → reboot
No touch after cold boot, but the driver looks ready (dmesg shows the descriptor, HID registered, ready) Set std_liveness_ms=8000 (echo 'options sl4a_spi_hid std_liveness_ms=8000' | sudo tee /etc/modprobe.d/sl4a-liveness.conf), cold boot, then read the standard-mode liveness line in dmesg: it reports the controller activity (IRQs) seen in that window, so a healthy idle device prints the alarm too (issue #4)
No touch after cold boot and no RESET_RSP in dmesg at all Enable the backstop: echo 'options sl4a_spi_hid wait_reset_kick_ms=4000' | sudo tee /etc/modprobe.d/sl4a-kick.conf, then cold boot. dmesg then shows no RESET_RSP and no IRQ at all after 4000 ms, forcing DESCREQ, and the descriptor poller keeps reading until the device answers. A DESCREQ write to a silent controller failed 3 times line instead means the SPI write itself is failing (bus level), not that the device stayed quiet. If the touchscreen never comes back, power off, unplug AC, wait 30 s, reboot and report the log in issue #4
No multi-touch (only single-touch) Check raw_mode=Y in modprobe config
Fingers lost during fast movement Increase blob_lift_frames
Jitter during pinch-to-zoom Verify ema_alpha=2, stationary lock active
Module rejected (Secure Boot) Enroll DKMS signing key via distribution MOK

Build from Source

For development without DKMS (modules built this way are unsigned — turn Secure Boot off, or sign them yourself):

make -C /lib/modules/$(uname -r)/build M=$PWD/driver modules
sudo cp driver/sl4a-spi-amd.ko driver/sl4a-spi-hid.ko /lib/modules/$(uname -r)/updates/dkms/
sudo depmod -a
sudo ./tools/sl4a-touch.sh activate

The modules export no aliases, so the kernel never loads them on its own: after a reboot run activate again, or use install, which also sets up the boot unit that repeats the binding automatically.

Documentation

Document Content
Wiki Project wiki: protocol, pipeline, config, hardware
docs/QUICKSTART.md 5-step install and activation guide
docs/HIDSPI_PROTOCOL.md HID-over-SPI V0 wire protocol
docs/PIPELINE.md Touch pipeline specification
docs/SPI_REGISTERS.md AMD FCH SPI controller registers
docs/AMDI0060_CONTRACT.md AMDI0060 controller boundary and safety contract
docs/CONFIG_TABLE.md Config table values
docs/ACTIVATION.md Raw mode activation (SET_FEATURE ID5)
docs/CONTACT_ABI.md Contact struct ABI
docs/ETW_CSV_FORMAT.md Windows trace format
docs/decomp/ Driver reference captures
docs/SUPPORT.md Supported hardware and release profiles
docs/COMPATIBILITY.md Hardware validation matrix
docs/TESTING.md Reproducible validation procedure
docs/EVIDENCE.md Evidence ledger and open discrepancies
docs/HARDWARE_VALIDATION.md Blinded hardware-validation protocol and bounded input captures

License

GPL-2.0. See LICENSE.

About

Linux HID-over-SPI driver for the Microsoft Surface Laptop 3/4 (AMD) touchscreen

Topics

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages