Skip to content

Releases

v0.6.0 - Shake-to-switch and host lock-state reporting

Choose a tag to compare

@github-actions github-actions released this 12 Oct 19:10

Switch targets with a pointer shake, see the remote host's lock-key state, and use the keypad independently of local Num Lock.

New Features

  • Shake to switch: move the pointer rapidly back and forth to cycle between this PC and connected hosts. It is off by default; enable it in Settings or with gesture on in the CLI. Sensitivity can be tuned in switch-gesture.json, and changes apply without restarting capture.
  • Per-host lock-key feedback: Caps Lock and Num Lock state appears in the CLI, on the Capture page, and in the tray. State is measured when a host writes HID LED reports, otherwise inferred from forwarded keys. Num Lock-off warnings appear only after the numpad has been used on that host.
  • Physical keypad mapping: keypad keys are identified by scan code, so local Num Lock no longer determines what the remote receives. Keypad Enter is distinct from the main Enter, and dedicated navigation keys retain their normal behavior.

The existing Ctrl+Alt+CapsLock and Ctrl+D+C cycle shortcuts remain available. Ctrl+Alt+Q still stops capture, or returns input locally in background mode.

Fixes

  • Send held mouse-button releases to the outgoing host before switching targets, including when switching with the shake gesture.
  • Preserve local mouse-button releases when switching away from this PC during a drag.
  • Keep pending pointer input on the correct side of queued target changes, including during pointer-pacing delays.
  • Evaluate broadcast lock warnings per host, so Num Lock being on at one host cannot hide it being off at another.
  • Keep the Settings gesture toggle synchronized with external configuration changes and refresh it when returning to the page.

Upgrading

This version adds a HID LED output report, which changes the GATT database. Previously paired hosts may retain the old layout. If input or lock-state reporting does not work after upgrading, forget the PC on the affected host and pair it again.

Known Limitations

  • I am still investigating input latency while capture is active, including with This PC selected. This release does not claim to fix that issue.
  • Host LED reporting is confirmed on Android 16; it remains unverified on other host platforms. Inference remains the fallback.
  • Existing provider-restart and reconnect limitations remain; keeping the app running in the notification area avoids unnecessary provider restarts.

Downloads

  • Desktop app: BleHid-App-v0.6.0-<rid>.zip. Extract the entire archive and keep the bundled DLLs beside the executable.
  • Command line: BleHid-Cli-v0.6.0-<rid>.zip. Includes a self-contained portable executable.

Choose win-x64 for Intel/AMD Windows PCs or win-arm64 for Windows on Arm.

Validation: 250 automated tests pass, and the Windows x64 and ARM64 release builds succeeded. The full manual hardware checklist has not been rerun for this build.

Full Changelog: v0.5.2...v0.6.0

v0.5.2

Choose a tag to compare

@github-actions github-actions released this 19 Sep 04:34

This release adds an alternative device-cycle shortcut and fixes local modifier keys remaining pressed after switching targets.

Changes

  • Added Ctrl+Alt+CapsLock to cycle through targets, including This PC, without triggering the Ctrl+D or Ctrl+C shortcuts used by some applications.
  • The new shortcut cycles once per Caps Lock press, ignores key repeat, and does not toggle Caps Lock.
  • Fixed local Ctrl/Alt remaining pressed after switching away with Ctrl+Alt+CapsLock and returning with Ctrl+D+C.
  • Existing shortcuts remain available: Ctrl+D+C cycles targets; Ctrl+Alt+Q stops capture, or returns input to this PC in background mode.
  • Made the cycling shortcut labels consistent in size and updated the UI, CLI help, and documentation.
  • Refined the application icon and project documentation layout.

Known Issue

I am still investigating input latency while capture is active, including with This PC selected. This release does not include a fix for that issue.

Downloads

  • Desktop app: BleHid-App-v0.5.2-<rid>.zip. Extract the whole archive and keep the bundled DLLs beside the executable.
  • Command line: BleHid-Cli-v0.5.2-<rid>.zip. Contains a self-contained portable executable.

Choose win-x64 for Intel/AMD Windows PCs or win-arm64 for Windows on Arm.

Full Changelog: v0.5.1...v0.5.2

v0.5.1

Choose a tag to compare

@github-actions github-actions released this 12 Sep 02:42

Adds an application icon. The exe, taskbar, Alt+Tab entry, title bar and tray now use a drawn Bluetooth-keyboard-and-mouse mark rather than the stock .NET icon.

The tray icon no longer follows the system theme — it previously redrew itself in black or white because a monochrome glyph disappears against one of the two taskbar themes, which the new tile does not.

No functional change: capture, host switching and diagnostics are untouched.

Assets are split as before: BleHid-Cli-v0.5.1-.zip is one portable executable; BleHid-App-v0.5.1-.zip contains the desktop app and its WPF native DLLs, which must stay together.

Full Changelog: v0.5.0...v0.5.1

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 12 Sep 02:45

Android companion (experimental)

Adds a source-only Android 12+ companion in android/BleHid.Companion, for diagnosing and
working around the reconnect failure after a Windows provider restart. It associates through
Android's Companion Device Manager, keeps an app-owned GATT connection alive in a foreground
service, and records HOGP presence, report counts, Service Changed events and Database Hash
changes into an exportable timeline.

In two consecutive Android 16 trials its presence-triggered connection bootstrapped a full
automatic HOGP reconnect after the provider restarted — Android reread the HID metadata and
restored both report subscriptions with no manual Connect. That is an experimental result
based on connection ordering, not a proven platform fix; manual Connect and re-pairing remain
the fallback.

The companion deliberately does not subscribe to the HID report characteristics: an app-owned
subscription is separate from Android's system input path. Android 12-16 do not expose the
profile reconnect API to companion apps, so on those versions the recovery action opens
Bluetooth settings instead.

Fixes

Input is no longer swallowed when the target disappears. If the selected host
disconnected, capture kept running and kept eating keystrokes locally. Capture now returns
input to this PC. Reconnecting the host does not retarget it automatically — use
Ctrl + D + C when you are ready to switch back.

Disconnected hosts leave the list. WinRT keeps a bonded host's CCCD entry in
SubscribedClients after the ACL drops, so a device that had gone away stayed listed and
capture stayed enabled with nothing connected. Host enumeration and subscriber counts now
ignore clients whose device has been seen disconnecting.

The capture toggle follows the session again. Assigning IsChecked in the click handler
replaced its one-way binding, so the switch stopped tracking the session after the first click
and never reflected Ctrl + Alt + Q. It now uses SetCurrentValue, which snaps the switch
without detaching the binding.

The pointer pacing slider works during a session. The interval was read once at session
start, so the slider was inert for the life of a session and had to be disabled. The pump
re-reads it per report, allowing live retuning.

Changes

Hosts and Capture are now one page. Splitting them meant changing tabs to do a single thing.
Host names are part of the refresh signature, so the list resolves them on its own and the
Refresh button is gone.

Ctrl + Alt + Q now ends the capture session in the desktop app, as it already did in the
CLI, leaving Ctrl + D + C as the way to cycle targets. The two hotkeys no longer overlap.

Known issues

Plain mode (--plain) is still untested. Windows 11 hosts still have the reconnect bug. The
Android reconnect workaround above is measured on one device across two trials only.

Assets

BleHid-Cli-v0.5.0-<rid>.zip is a single portable executable.
BleHid-App-v0.5.0-<rid>.zip contains the desktop app and its WPF native DLLs, which must stay
together.

Full Changelog: v0.4.0...v0.5.0

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 30 Aug 11:06

v0.4.0

This release improves pointer responsiveness across hosts and documents the root cause of the Android reconnect failure.

What changed

  • Added adaptive pointer pacing based on each host’s negotiated BLE connection interval.
  • Added persistent host-name pacing overrides through %LOCALAPPDATA%\BleHid\pointer-pacing.json.
  • Improved multi-host target switching and pacing diagnostics.
  • Added Bumble HOGP controls, GATT discovery tools, and an Android HCI snoop analyzer.
  • Reworked the README around installation, usage, and known limitations.
  • Added detailed engineering findings in DEVELOPMENT.md.

Android reconnect limitation

Android reconnects normally after range loss or a Bluetooth toggle while the same GattServiceProvider remains alive.

After the provider process restarts, Windows recreates an identical HOGP database with the same handles and Database Hash, but still delivers a pending Service Changed indication. Android then clears its HOGP cache while generic GATT retains the unchanged database, preventing automatic profile recovery.

Provider recreation also loses bonded HID report CCCD values, although the Bluetooth specification requires them to persist for bonded devices. A Windows-side change is likely required to reconcile unnecessary pending Service Changed indications and preserve bonded CCCD state.

Until then, manually reconnect after restarting the provider. If input subscriptions are not restored, forget and re-pair the device.

Compatibility

  • Windows 10 version 2004 or later
  • Adaptive negotiated-interval pacing on Windows 11
  • Self-contained win-x64 and win-arm64 builds

Validated with all 81 Core tests and Release publishes for both architectures.

Full Changelog: v0.3.2...v0.4.0

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 27 Aug 05:35

Fixed

A blocking Bluetooth policy no longer looks like broken hardware.

AllowAdvertising = 0 stops Windows from advertising before the radio is ever
asked, so every probe added in v0.3.1 failed — and the report concluded the driver
was at fault and suggested trying a different adapter. The value was printed
correctly a few lines above; the verdict simply ignored it.

Policy findings now outrank the probe results. When advertising is blocked, the
report names the value, gives both registry paths it can live under, and states
that the adapter and driver are fine. It also warns that on a managed machine the
setting may return after a policy refresh.

Found by a user whose machine had this set without them ever touching it.

Notes

Nothing changes if advertising already works for you.

Full Changelog: v0.3.1...v0.3.2

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 26 Aug 00:34

Fixed

--diagnose gave wrong advice. It printed all four possible causes regardless of
what it had just measured, so a machine reporting Peripheral role : True was still
told its radio could not be a keyboard. The verdict is now built from the actual
readings.

appearance never worked. It failed with "Attempted to perform an unauthorized
operation" on every machine, not just some. Windows only lets a desktop app publish
manufacturer data in an advertisement, so the GAP Appearance workaround could never
have worked. Documented rather than silently retried.

Added

When advertising fails, --diagnose now narrows down where:

  • Bluetooth policy — reads the Group Policy and MDM keys that can disable LE
    advertising outright. On a managed machine this is indistinguishable from broken
    hardware from inside the app.
  • Advertisement budget — a discoverable advertisement carries the device name in a
    31-byte payload. Reports the name's length, not the name.
  • A staged probe — bare advertisement, then a custom connectable GATT service, then
    the exact HID configuration. The first step that fails tells you whether the problem
    is the driver, connectable advertising in general, or HID specifically.

Notes

Nothing changes if advertising already works for you; this release is entirely about
diagnosing the machines where it doesn't.

Two PCs with the same dongle, the same driver version and the same Swift Pair setting
have been observed to disagree, so the cause is machine state rather than hardware.
That is what these probes are for.

Full Changelog: v0.3.0...v0.3.1

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 25 Aug 18:22

Highlights

A desktop app. BLE HID is no longer CLI-only. The new Windows app gives you a
host list you can click, capture start/stop, a live view of subscribers and
advertisement state, and a settings page. It can live in the notification area and
start with Windows, so the machine acts as a keyboard without a console window open.

The CLI and the app cooperate. Only one process may own the Bluetooth radio.
Either front end can now stop the other: blehid --stop shuts down the desktop app
as well as background mode, and launching the app while the CLI holds the radio
offers to take over.

Diagnostics for bug reports. blehid --diagnose writes a shareable report to
%LOCALAPPDATA%\BleHid\logs\diagnostics.txt covering your radios, adapter
capabilities, and the full startup sequence. Please attach it when filing an issue.

Which download do I want?

Asset What it is
BleHid-Cli-v0.3.0-win-x64.zip Command line. A single portable .exe.
BleHid-App-v0.3.0-win-x64.zip Desktop app. Keep the extracted folder intact — the app needs the DLLs next to it.

Use the win-arm64 variants on ARM machines. No .NET install is required; both are
self-contained.

Added

  • WPF desktop app: target selection, capture control, live status, log view
  • Tray residency with close-to-tray, autostart, and hotkeys that work with no window
  • --diagnose report, and a warning when a radio cannot act as a peripheral
  • Regression suite: 68 unit tests, 9 process-level tests, and a manual checklist

Changed

  • All logs now live in %LOCALAPPDATA%\BleHid\logs\, including the app crash log
    that previously hid in %TEMP%
  • Release assets are split; the CLI archive was previously BleHid-<tag>-<rid>.zip
    and is now BleHid-Cli-<tag>-<rid>.zip
  • The adapter address in diagnostics is masked to the vendor prefix, since the report
    is meant to be shared publicly

Fixed

  • "advertising aborted" was a false alarm. A healthy radio reports Aborted once
    on the way up, immediately before Started, so the log line looked fatal on every
    successful run. It is now annotated, and only an abort after advertising started
    is reported as a failure.
  • A stop request could carry over and terminate the next process to start, leaving
    nothing owning the radio
  • Selecting a target in the UI now actually changes where input goes
  • Mouse input is redirected in tray mode, not just the keyboard

Known issues

  • Plain mode (--plain, and the "Require encryption" toggle) is untested. It has
    never been exercised against a real host. Additionally it is not persisted, so a
    tray or autostart launch is always encrypted.
  • Windows 11 hosts pair but have a reconnect bug
  • Some Android 11 devices fail to work, binding BR/EDR instead of LE
  • On iPhone, pointer control requires AssistiveTouch
  • The win-arm64 builds compile but have not been run on ARM hardware
    Full Changelog: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 21 Aug 19:49

Turn a Windows PC into a Bluetooth LE keyboard and mouse for your other devices.
capture redirects your real keyboard and mouse over the air; Ctrl+D+C switches
which machine you are driving, including back to this PC.

New

Background mode. The peripheral can run detached, with no console window, so the
hotkeys are always live and switching machines costs one keystroke:

BleHid.Cli.exe --background          # run detached
BleHid.Cli.exe --stop
BleHid.Cli.exe --install-autostart   # opt-in, per-user, no admin

Auto-start is opt-in — nothing is written to the Run key unless you ask for it.
Logs go to %LOCALAPPDATA%\BleHid\blehid.log.

Fixed

  • Apps that grab the keyboard no longer swallow the hotkey. Low-level hook chains run
    newest-first, so Windows App / mstsc and similar clients could win simply by hooking
    after us. Hooks are now re-installed on every foreground change. Verified against
    Windows App with the remote session focused.

Verified this release

  • arm64 build exercised on a Snapdragon-based Surface, including capture driving a
    remote host.
  • iPhone works as a host. iOS draws no mouse cursor until
    Settings → Accessibility → Touch → AssistiveTouch is enabled; the keyboard needs no
    such setting.

Known issues

  • A Windows host lists this PC twice. Pair the entry shown as a PC, not the audio
    one — the audio entry binds Classic BR/EDR, which this app cannot service, and nothing
    works.
  • A Windows host will not reconnect after the app restarts. Measured: 180 s hands-off
    and a further 120 s after clicking Connect both produced no connection at all. macOS and
    Android reconnect on their own. Only removing the device and re-pairing recovers it —
    or use background mode and avoid restarting.
  • The DPI awareness fix is untested. It was written on a 1920×1080 machine, where the
    bug cannot reproduce. On a scaled display, run capture and check the screen= value
    in the [hook] line matches your panel's physical resolution.

See the README for the
full list.

Downloads

Self-contained single files — no .NET runtime required. Unzip and run BleHid.Cli.exe.
The binaries are unsigned, so SmartScreen will warn on first launch
(More info → Run anyway).

Full Changelog: v0.1.0...v0.2.0

BleHid v0.1.0

Choose a tag to compare

@abhishek-raj abhishek-raj released this 03 Aug 15:49

BleHid v0.1.0 - first release.

Turns a Windows PC into a Bluetooth LE keyboard and mouse. Self-contained; no .NET runtime required. Download the zip for your architecture, unzip, run BleHid.Cli.exe.

Binaries are unsigned - SmartScreen will warn on first launch (More info → Run anyway). Verify against SHA256SUMS.txt if you prefer.

Verified on macOS and Android 16. A Windows host will not reconnect after the app restarts and must be re-paired — see Known issues in the README before relying on this.

Full Changelog: https://github.com/abhishek-raj/windows-ble-hid/commits/v0.1.0