1
0

README updates

This commit is contained in:
Daniel Prilik
2020-11-07 11:15:15 -05:00
parent c66fac539f
commit b237f4a0f3

View File

@@ -8,11 +8,11 @@ Things will change.
Things will break.
Things are probably buggy.
Bug reports are appreciated!
Bug reports and PRs are appreciated!
## Overview
`surface-dial-daemon` is a background daemon which receives raw events from the surface dial, and translates them to various actions.
`surface-dial-daemon` receives raw events from the surface dial and translates them to more conventional input events.
The daemon uses FreeDesktop notifications to provide visual feedback when switching between actions.
@@ -20,43 +20,28 @@ The daemon uses FreeDesktop notifications to provide visual feedback when switch
It would be cool to create some sort of GUI overlay (similar to the Windows one), though that's out of scope at the moment.
## Implementation
#### Operating Modes
Core functionality is provided by the following libraries.
Holding down the button for \~750ms will open up a meta-menu (using FreeDesktop notifications) which allows you to switch between operating modes on-the-fly. The daemon persists the last selected mode on-disk, so if you only care about one mode (e.g: scrolling), you can just set it and forget it.
- `libudev` to monitor when the dial connects/disconnects.
- `libevdev` to read events from the surface dial through `/dev/input/eventXX`, and to fake input through `/dev/uinput`.
- `hidapi` to configure dial sensitivity + haptics.
- `notify-rust` to send desktop notifications over D-Bus.
At the moment, these modes (along with their meta-menu ordering) are hard-coded into the daemon itself.
While the device-handling code itself is somewhat messy at the moment, it should be really easy to add new operating modes. Just add a new mode implementation under `src/controller/controls` (making sure to update `src/controller/controls/mod.rs`), and add it to the list of available modes in `main.rs`!
Modes in **bold** should be considered **EXPERIMENTAL**. They seem to work alright (some of the time), but they would really benefit from some more polish / bug fixes.
## Functionality
| Mode | Click | Rotate | Notes |
| ---------------------------- | ----------------- | -------------------- | ------------------------------------------------------------------------------------- |
| Scroll | - | Scroll | Fakes chunky mouse-wheel scrolling <sup>1</sup> |
| **Scroll (Fake Multitouch)** | Reset Touch Event | Scroll | Fakes smooth two-finger scrolling |
| Zoom | - | Zoom | |
| Volume | Play/Pause | Volume | Double-click to mute |
| Media | Play/Pause | Next/Prev Track | |
| **Paddle Controller** | Space | Left/Right Arrow Key | Like those old [paddle controllers](https://www.google.com/search?q=arkanoid+paddle). |
- [x] Interpret raw Surface Dial event
- Operating Modes
- [x] Volume Controls
- [x] Media Controls
- [x] Scrolling - using a virtual mouse-wheel
- [x] Scrolling - using a virtual touchpad (for [smoother scrolling](https://who-t.blogspot.com/2020/04/high-resolution-wheel-scrolling-in.html)) - **EXPERIMENTAL**
- [x] Zooming
- [x] [Paddle](https://www.google.com/search?q=arkanoid+paddle) (emulated left, right, and space key)
- [ ] \(meta\) custom modes specified via config file(s)
- [x] Dynamically switch between operating modes
- [x] Using a long-press activated "meta" mode
- [ ] Context-sensitive (based on currently open application)
- [x] Mode Persistence (keep mode when dial disconnects)
- [x] Haptic Feedback
- https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/radial-controller-protocol-implementation
- https://www.usb.org/sites/default/files/hutrr63b_-_haptics_page_redline_0.pdf
- https://www.usb.org/sites/default/files/hut1_21.pdf
- _This was tricky to figure out, but in the end, it was surprisingly straightforward! Big thanks to [Geo](https://www.linkedin.com/in/geo-palakunnel-57718245/) for pointing me in the right direction!_
- [x] Visual Feedback
- [x] FreeDesktop Notifications
<sup>1</sup> At the time of writing, almost all Linux userspace programs don't take advantage of the newer high-resolution scroll wheel events, and only support the older, chunkier scroll wheel events. Check out [this blog post](https://who-t.blogspot.com/2020/04/high-resolution-wheel-scrolling-in.html) for more details.
Feel free to contribute new features!
If you don't mind hacking together a bit of Rust code, adding new modes should be fairly straightforward - just add a new mode implementation under `src/controller/controls` (making sure to update `src/controller/controls/mod.rs`), and instantiate the mode in `main.rs`.
## Dependencies
## Building
Building `surface-dial-daemon` requires the following:
@@ -75,9 +60,7 @@ Unless you're a cool hackerman, the easiest way to get `libudev`, `libevdev`, an
sudo apt install libevdev-dev libhidapi-dev libudev-dev
```
## Building
`surface-dial-daemon` uses the standard `cargo build` flow.
Once those are installed, `surface-dial-daemon` can be built using the standard `cargo build` flow.
```bash
cargo build -p surface-dial-daemon --release
@@ -148,4 +131,45 @@ You may need to reboot to have the various groups / udev rules propagate.
If things aren't working, feel free to file a bug report!
_Call for Contributors:_ It would be awesome to have a proper rpm/deb package as well.
_Call for Contributors:_ It would be awesome to have a proper packaging pipeline set up as well (e.g for deb/rpm).
## Implementation Notes
Core functionality is provided by the following libraries.
- `libudev` to monitor when the dial connects/disconnects.
- `libevdev` to read events from the surface dial through `/dev/input/eventXX`, and to fake input through `/dev/uinput`.
- `hidapi` to configure dial sensitivity + haptics.
- `notify-rust` to send desktop notifications over D-Bus.
The code makes heavy use of threads + channels to do non-blocking event handling. While async/await would have been a great fit for an application like this, I optimized for getting something up-and-running rather than maximum performance. Plus, the Rust wrappers around `libudev`, `libevdev`, and `hidapi` don't have native async/await support, so it would have been a lot more work for not too much gain.
The codebase is reasonably well organized, aside from the `dial_device` implementation, which is admittedly a bit gnarly. There's a bit of of thread/channel spaghetti going on to ensure that the lifetime of the haptics object lines up with the lifetime of the `libevdev` objects (as reported by `libudev`). All things considered, it's not _too_ messy, but it could certainly use some cleanup. Fortunately, if you're only interested in implementing new operating modes, you won't have to worry about any of that, as all the nitty-gritty device interaction is neatly encapsulated behind the `ControlMode` trait.
## Feature Roadmap
This is a rough outline of features I'd like to see implemented in this daemon. There's a non-zero chance that at some point the daemon will be "good enough" for me, and some features will be left unimplemented.
Contributions are more than welcome!
- [x] Interpreting raw Surface Dial events
- [x] Haptic Feedback
- https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/radial-controller-protocol-implementation
- https://www.usb.org/sites/default/files/hutrr63b_-_haptics_page_redline_0.pdf
- https://www.usb.org/sites/default/files/hut1_21.pdf
- _This was tricky to figure out, but in the end, it was surprisingly straightforward! Big thanks to [Geo](https://www.linkedin.com/in/geo-palakunnel-57718245/) for pointing me in the right direction!_
- [x] Set up a framework to easily implement various operating modes
- [x] In-code abstraction over Surface Dial Events / Haptics API
- [ ] Config file(s) to create simple custom modes
- [x] Dynamically switching between operating modes
- [x] Using a long-press activated "meta-mode"
- [ ] Context-sensitive (based on the currently open application)
- [ ] Config-file support
- [ ] Adjusting timings (e.g: long press timeout, double-click window, etc...)
- [ ] Custom operating mode ordering in the meta-menu
- [x] Visual Feedback
- [x] FreeDesktop Notifications
- [ ] \(longshot\) Windows-like Wheel menu
- [x] Last selected mode persistence (between daemon invocations)
- [x] Gracefully handling disconnect/reconnect
- [ ] Packaging pipeline (e.g: deb/rpm)