Skip to content

Bluetooth pairing on a second Linux based machines invalidate the pairing key on the first one #6626

Open
@hyx0329

Description

@hyx0329

CircuitPython version

- Adafruit CircuitPython 7.3.2 on 2022-07-20; MakerDiary nRF52840 MDK USB Dongle with nRF52840
- Customized CircuitPython 7.3.1; MakerDiary M60 Keyboard with nRF52840

Code/REPL

"""
Minimum working example adapted from https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/main/examples/ble_hid_periph.py
"""

# import board
import sys
import time
import microcontroller

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS

import adafruit_ble
import _bleio
from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_ble.services.standard.device_info import DeviceInfoService

# Use default HID descriptor
hid = HIDService()
device_info = DeviceInfoService(
    software_revision=adafruit_ble.__version__, manufacturer="Adafruit Industries"
)
advertisement = ProvideServicesAdvertisement(hid)
advertisement.appearance = 961
# scan_response = Advertisement()  # not used

# ble handle
ble = adafruit_ble.BLERadio()

# prepare mac address pool
cpu_id = list(microcontroller.cpu.uid)
cpu_id_reverse = list(microcontroller.cpu.uid)
cpu_id_reverse.reverse()
mac_pool = bytearray(cpu_id + cpu_id_reverse)

# set bt id
# that's to say:
#   1. stop advertising and drop all existing connections
#   2. change full_name, MAC address
#   3. start advertising
def set_bt_id(bt_id):
    ble.stop_advertising()
    if ble.connected:
        for c in ble.connections:
            c.disconnect()
    # change name
    name = 'PYKB %d' % bt_id
    advertisement.full_name = name
    ble.name = name
    # change mac
    uid = mac_pool[bt_id : bt_id + 6]
    uid[-1] = uid[-1] | 0xC0
    address = _bleio.Address(uid, _bleio.Address.RANDOM_STATIC)
    ble._adapter.address = address
    # log
    print(ble._adapter.address)
    print(ble.name)
    # start advertising
    print("advertising")
    ble.start_advertising(advertisement, timeout=60)  # 60 secs

# set bt id and start the main loop
set_bt_id(0)
k = Keyboard(hid.devices)
kl = KeyboardLayoutUS(k)
while True:
    while not ble.connected:
        pass
    print("Start typing:")
    while ble.connected:
        c = sys.stdin.read(1)
        # change to PYKB #n by entering corresponding number
        if '0' <= c <= '9':
            set_bt_id(int(c))
            continue
        sys.stdout.write(c)
        kl.write(c)
        # print("sleeping")
        time.sleep(0.1)
    if not ble.advertising:
        print('restart advertising')
        ble.start_advertising(advertisement)

Behavior

I'm using a custom bluetooth keyboard based on CircuitPython which can switch to different hosts by changing its bluetooth MAC and full name. The code above is provided as a minimum working example. You can switch to different MAC and full name by entering 0-9 in the REPL. There should be no error.

Recently I encounter the issue that if I use the keyboard on two different Linux setups, after pairing to the second host, the pairing key for the first linux host is replaced/invalidated(my presumption), and the first host won't be able to connect to my keyboard without another manual pairing(connected and then immediately disconnected, see btmon.log). I have to adapt some tricks for dual boot pairing to share keys between two different Linux hosts to work it around.

There may be some bugs in either CircuitPython or Linux's bluetooth implementation(I think it's the latter).

Description

  • Only occurs between my Linux based hosts
  • on iPad, Windows, Android device work as expected
  • tested with 2 Arch Linux hosts, my laptop and my mini PC

Additional information

btmon.log

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions