Packages
mob
0.6.20
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.26
0.6.25
0.6.24
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.2
0.6.1
0.6.0
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.11
0.5.10
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.0
BEAM-on-device mobile framework for Elixir
Current section
Files
Jump to
Current section
Files
lib/mob/bt/hid.ex
defmodule Mob.Bt.Hid do
@moduledoc """
Bluetooth Classic Human Interface Device (HID) — input listener.
Use this for Bluetooth keyboards, mice, gamepads, finger PTTs, scanners,
presenter remotes, and any device that emits HID input reports
(button/key/axis events) over Bluetooth.
See `Mob.Bt` for pairing, discovery, and disconnect.
## Scope
This module is **read-only** by design. HID hosts (phones) almost never
send output reports to peripherals — that's a force-feedback /
rumble-pack edge case. If your hardware genuinely needs output reports,
open an issue.
## Typical flow
# 1. Pair (Mob.Bt.pair/2)
# 2. Connect HID profile.
socket = Mob.Bt.Hid.connect(socket, device)
# {:bt, :hid_connected, session_id, device}
# 3. Input reports stream:
# {:bt, :hid_input, session_id,
# %{usage_page: 0x07, usage: 0x29, value: 1}}
# (HID Keyboard/Keypad, key 0x29 = Escape, pressed)
# 4. Disconnect (Mob.Bt.disconnect/2)
## Input report shape
Reports are decoded by the Android HID stack into usage-page +
usage + value triples per the HID Usage Tables spec. Common pages:
* `0x01` — Generic Desktop (mouse/joystick X/Y, wheel, etc.)
* `0x07` — Keyboard/Keypad
* `0x09` — Button (gamepad face buttons)
* `0x0C` — Consumer (volume, play, mute, custom)
* `0xFF00`–`0xFFFF` — Vendor-defined
Multi-axis events arrive as separate messages, one per axis. Synthesize
combined input on the receive side if needed.
## Receiving raw reports
If the device's HID descriptor is non-standard or the high-level
`:hid_input` shape isn't sufficient, subscribe to raw reports with
`subscribe_raw/2` and parse the bytes yourself.
Stream: `{:bt, :hid_raw_report, session_id, %{report_id: integer, bytes: binary}}`.
"""
alias Mob.Bt
@doc """
Open an HID profile connection to `device`. The device must already be
paired.
Result: `{:bt, :hid_connected, session_id, device}` on success,
`{:bt, :hid_connect_failed, nil, %{device: device, reason: atom()}}`
on failure.
"""
@spec connect(socket :: term(), Bt.device()) :: term()
def connect(socket, device) do
json = Bt.encode_device(device)
:mob_nif.bt_hid_connect(json)
socket
end
@doc """
Subscribe to raw HID input reports (bypasses Android's parser).
Use only when the device's HID descriptor is non-standard or the
high-level `:hid_input` events miss data you need.
Stream: `{:bt, :hid_raw_report, session_id, %{report_id, bytes}}`.
"""
@spec subscribe_raw(socket :: term(), Bt.session_id()) :: term()
def subscribe_raw(socket, session_id) when is_integer(session_id) do
:mob_nif.bt_hid_subscribe_raw(session_id)
socket
end
end