Microsoft Surface Dial plugin now available (play control, volume etc.)

Microsoft Surface Dial support for Volumio 4

I’ve put together a new experimental Volumio plugin that adds support for the Microsoft Surface Dial as a physical controller for Volumio.

The plugin communicates directly with the Dial over Bluetooth/HID, so there is no companion application, separate daemon or software to install on another computer. Once installed and paired, the Dial talks directly to the Volumio device.

GitHub – volumio-surface-dial

What it does

The Surface Dial becomes a compact wireless hardware controller for Volumio.

Current functionality includes:

  • Rotate - volume control
  • 50 haptic detents per complete revolution
  • 2% volume change per detent, so one complete revolution represents the full 0–100% volume range
  • Press - configurable, default is Play/Pause
  • Double press - configurable, default is Next track
  • Long press - configurable, default is Previous track
  • Optional reverse rotation
  • Haptics On/Off, enabled by default
  • Bluetooth scanning and pairing from the plugin’s Volumio settings page
  • Automatic reconnection after the Dial disconnects or sleeps

The press actions can individually be assigned to Play/Pause, Next, Previous or Do Nothing.

This has been developed and tested against Volumio 4. It should still be regarded as an early release, so feedback from anyone trying it on other Volumio hardware would be useful.

Installation

The plugin isn’t currently in the official Volumio Plugin Store, so installation is from GitHub via SSH.

SSH into your Volumio device and run:

cd ~
git clone https://github.com/jhscann/volumio-surface-dial.git
cd volumio-surface-dial
volumio plugin install

Volumio will warn that this is an unverified plugin. Accept the warning to continue.

Once installation completes, go to:

Plugins → Installed Plugins → Surface Dial

Enable the plugin and open Settings.

Put the Surface Dial into Bluetooth pairing mode, then use Scan for Surface Dial followed by Pair. The plugin handles the necessary Bluetooth/HID configuration, including configuring the Dial’s haptic detents.

No separate Bluetooth utilities or Surface Dial applications need to be manually configured by the user.

Updating

For subsequent versions:

cd ~/volumio-surface-dial
git pull

For now, I recommend uninstalling the existing Surface Dial plugin through the Volumio Installed Plugins page and then running:

cd ~/volumio-surface-dial
volumio plugin install

again, particularly while the plugin is undergoing active development.

Feedback

This started as an experiment to see whether the Surface Dial could be made into a genuinely useful physical Volumio controller without requiring additional software outside Volumio. The basic controls, Bluetooth pairing and hardware haptic feedback are now working.

If anyone has a Surface Dial gathering dust and wants to try it, reports on different Raspberry Pi/Volumio configurations, Bluetooth reconnect behaviour and general usability would be very welcome.

Source, installation files and documentation are available here:

jhscann/volumio-surface-dial on GitHub

@balbuze

Hi Balbuze, a candidate for an official plugin?

Why not!
But before, @jhscann please see GitHub - volumio/volumio-plugins-sources-bookworm · GitHub
And Welcome to Volumio Developers Docs | Volumio Developers Documentation
Thanks :blush:

done :slight_smile:

Thank you!
Available as beta :wink:

1 Like

Update: version 0.2.1 and Bluetooth audio compatibility

Thanks to @balbuze for making the Surface Dial plugin available in the Beta Plugin Store.

I have now prepared version 0.2.1 and submitted it through the existing beta pull request. The Store will continue to show the current version until the updated beta package is refreshed by a Volumio maintainer.

What changed in 0.2.1

Testing on a real Surface Dial revealed that its input reports are nine bytes long, with occasional unrelated shorter reports also appearing on the HID interface.

Version 0.2.1 now:

  • Validates the complete nine-byte Surface Dial reports.
  • Ignores unrelated, incomplete or malformed HID data.
  • Prevents duplicate or unmatched button reports from producing playback commands.
  • Clears any unfinished button gesture when the Dial disconnects or sleeps.
  • Fixes an observed problem where one physical press could issue two Play/Pause actions.
  • Preserves all existing settings and controls.

Rotation, volume control, haptic feedback and configurable single-, double- and long-press actions remain unchanged.

The update has passed the automated tests and has also been tested with a physical Surface Dial on Volumio 4.

Important Wireless Output Manager limitation

During testing, I found a compatibility issue when the Surface Dial and a Bluetooth speaker managed by Wireless Output Manager use the same Bluetooth adapter.

When the Dial sleeps or reconnects, the resulting Bluetooth activity can interrupt audio sent to the speaker. The speaker itself remains paired, but its audio transport may be disturbed, causing playback to stutter or restart.

Changes in 0.2.1 prevent invalid Dial input from issuing unintended playback commands, but they do not completely solve this shared-adapter Bluetooth conflict.

Using two adapters worked much better in my testing:

  • Microsoft Surface Dial on a TP-Link UB400 USB Bluetooth adapter.
  • Bluetooth speaker on the Raspberry Pi’s built-in Bluetooth adapter.

With the devices separated, the Dial could sleep, reconnect and resume working without causing audio stutter. However, there is currently another limitation: after a reboot, Wireless Output Manager may select the wrong default Bluetooth adapter and fail to reconnect the speaker automatically. Explicit adapter selection in Wireless Output Manager would likely be needed for this arrangement to be reliable.

For now, if you use Wireless Output Manager and experience Bluetooth audio stuttering after enabling Surface Dial:

  • Disable the Surface Dial plugin, or
  • Use separate Bluetooth adapters and be aware that speaker reconnection after reboot may require manual intervention.

For systems that are not using Bluetooth audio output, this particular conflict should not apply.

Version 0.2.1 should remain a beta release while it receives wider testing. Feedback is particularly welcome from anyone using a different Raspberry Pi, Bluetooth adapter or audio-output arrangement.

Source and current release: