#!/bin/bash # import-bluez-bond.sh — share a BlueZ (Linux) Bluetooth pairing with MontaukOS. # # Dual-boot problem: the AX211's BD_ADDR override (0xFC31) is cosmetic — the # baseband keeps answering pages on the FACTORY address, so a peer (headset) # sees Linux and MontaukOS as ONE device with ONE link-key slot. Each OS # pairing clobbers the key the other OS depends on, and every reconnect from # the other OS then dies with Authentication Failure (reason 0x05). # # Fix: both OSes share the SAME identity and the SAME link key. This script # copies a BlueZ link key into MontaukOS's key store (os/btkeys.bin on the # installed root) and pins MontaukOS's configured MAC to the adapter's factory # address so the app reports the identity actually used on air. # # Usage: # sudo ./scripts/import-bluez-bond.sh [adapter-mac] [--reverse-key] # # Example: # sudo ./scripts/import-bluez-bond.sh /run/media/$USER/ E4:58:BC:5F:E0:30 # # --reverse-key: byte-swap the key (fallback if authentication still fails). # # NOTE: replaces the MontaukOS key store with this single bond. Re-pair other # devices from MontaukOS afterwards if you had more. set -euo pipefail if [ "$(id -u)" -ne 0 ]; then echo "error: must run as root (reads /var/lib/bluetooth)" >&2 exit 1 fi TARGET="${1:?usage: import-bluez-bond.sh [adapter-mac] [--reverse-key]}" DEVICE="${2:?missing device MAC}" ADAPTER="${3:-}" REVERSE=0 for arg in "$@"; do [ "$arg" = "--reverse-key" ] && REVERSE=1; done [ "$ADAPTER" = "--reverse-key" ] && ADAPTER="" DEVICE="${DEVICE^^}" # Auto-detect the adapter: the directory under /var/lib/bluetooth that holds # this device, preferring a factory (not locally-administered "x2:") address. if [ -z "$ADAPTER" ]; then for dir in /var/lib/bluetooth/*/; do a="$(basename "$dir")" [ -f "/var/lib/bluetooth/$a/$DEVICE/info" ] || continue if [ -z "$ADAPTER" ] || [[ "${ADAPTER:1:1}" == "2" && "${a:1:1}" != "2" ]]; then ADAPTER="$a" fi done fi [ -n "$ADAPTER" ] || { echo "error: no adapter dir holds a bond for $DEVICE" >&2; exit 1; } INFO="/var/lib/bluetooth/$ADAPTER/$DEVICE/info" [ -f "$INFO" ] || { echo "error: $INFO not found" >&2; exit 1; } KEY="$(sed -n '/^\[LinkKey\]/,/^\[/{s/^Key=//p}' "$INFO" | head -1)" [ -n "$KEY" ] || { echo "error: no [LinkKey] Key= in $INFO" >&2; exit 1; } [ -d "$TARGET/os" ] || { echo "error: $TARGET/os missing — is the MontaukOS root mounted there?" >&2; exit 1; } echo "adapter (factory identity): $ADAPTER" echo "device: $DEVICE" echo "key: ${KEY:0:4}... (${#KEY} hex chars)" python3 - "$TARGET/os/btkeys.bin" "$DEVICE" "$KEY" "$REVERSE" <<'EOF' import sys path, device, keyhex, reverse = sys.argv[1], sys.argv[2], sys.argv[3], int(sys.argv[4]) # MontaukOS on-disk layout (kernel Hci.cpp): 'BTK1' + 8 x { addr[6], key[16], valid[1] }. # addr is stored LSB-first (HCI wire order); BlueZ's hex key is already in HCI order. addr = bytes(int(b, 16) for b in reversed(device.split(":"))) key = bytes.fromhex(keyhex) assert len(key) == 16, "link key must be 16 bytes" if reverse: key = key[::-1] blob = bytearray(b"BTK1") blob += addr + key + b"\x01" # slot 0: the imported bond blob += b"\x00" * 23 * 7 # slots 1..7 empty with open(path, "wb") as f: f.write(blob) print(f"wrote {path} ({len(blob)} bytes, 1 bond)") EOF # Pin the configured MAC to the factory address (truthful display; the 0xFC31 # override is cosmetic on this hardware anyway). CONF="$TARGET/config/bluetooth.toml" mkdir -p "$TARGET/config" if [ -f "$CONF" ] && grep -q '^ *mac *=' "$CONF"; then sed -i "s/^ *mac *=.*/mac = \"$ADAPTER\"/" "$CONF" else printf 'mac = "%s"\n' "$ADAPTER" >> "$CONF" fi echo "set $CONF mac = $ADAPTER" echo "done — boot MontaukOS; the device should reconnect without re-pairing."