# Architecture `surface-dial-renewed` is a userspace Linux driver. It reads the Microsoft Surface Dial through evdev, emits virtual input devices through uinput, uses HID for haptic feedback, and uses KDE's OSD service for sensitivity feedback. ## Runtime Threads The process has one main event loop and one input worker thread. The input worker is created by `DialReader::spawn` in `src/dial.rs`. It finds the `Surface Dial System Multi Axis` event node through udev, blocks on evdev events, and sends simplified raw events through a channel. The main thread owns all output state: - `DriverState` in `src/main.rs` - `VirtualInput` in `src/virtual_input.rs` - `Haptics` in `src/haptics.rs` - `SensitivityNotifier` in `src/notify.rs` Keeping output ownership on one thread avoids locking around uinput devices and keeps gesture lifecycle decisions local to the main loop. ## Module Responsibilities `src/main.rs` The state machine. It decides whether a Dial rotation means scroll or sensitivity adjustment. It starts and ends multitouch gestures, updates sensitivity, and calls haptics/OSD hooks. `src/dial.rs` Device discovery and event decoding. It converts evdev events into `DialEventKind` values: connect, disconnect, button press/release, long press, rotation, and ignored noise. `src/virtual_input.rs` Creates two uinput devices: - `Surface Dial Renewed Touchpad` for multitouch scrolling. - `Surface Dial Renewed Wheel` for regular wheel mode. The touchpad device is intentionally not advertised as a buttonpad and does not expose `BTN_LEFT`, reducing the chance that very short gestures become tap or right-click behavior. `src/sensitivity.rs` Defines the 1-32 sensitivity scale and maps each level to scroll scaling. `src/haptics.rs` Opens the Dial's HID device and sends manual haptic buzz reports. Haptics are best-effort; failure disables haptics but does not stop scrolling. `src/notify.rs` Shows the sensitivity value. KDE uses `qdbus6` with `org.kde.osdService.showText`. If that fails, the code falls back to FreeDesktop notifications. `src/error.rs` Small shared error enum for the concept driver. ## Data Flow 1. `DialReader` finds `Surface Dial System Multi Axis`. 2. Raw evdev events are sent to the main loop. 3. `main.rs` decodes intent: - button held + rotate: sensitivity adjustment - rotate alone: scrolling - connect/disconnect: haptics and gesture cleanup 4. `VirtualInput` emits either multitouch or wheel events. 5. `Haptics` buzzes on selector entry and sensitivity level changes. 6. `SensitivityNotifier` displays `Surface Dial sensitivity N/32`. ## Reconnect Model The input worker scans for an existing Dial at startup. If the device is removed or an input read fails, it sends a disconnect event, sleeps briefly, and retries discovery/monitoring. The main loop ends any active multitouch gesture and drops the HID haptics handle on disconnect. On reconnect it reopens haptics.