Repository navigation
bledev: pairing and bonding for the REPL and file services - #88
Conversation
… parser bledev.hidreport parses HID report descriptors and decodes input reports into events.Key and events.Joy* records, matching usbif's boot-keyboard decoder event for event. bledev.hid is the HOGP host (reads the Report Map, pairs when the device demands it, subscribes to every input report) and a peripheral that serves a keyboard, consumer control and gamepad. The contract gains descriptors (server and client), encrypted characteristics, Connection.pair()/encrypted and a long_read capability; fake, mpble and bleak implement them.
…ss probed; two mpble MTU fixes Windows hides the HID service from apps, so Peripheral and Host take a service_uuid and hid.INSPECT_SERVICE serves the same characteristics where bleak can read them. The bless probe (the board as central, Windows as peripheral) found mpble missing an MTU exchanged before aioble records a central-role connection, and exchange_mtu() raising EALREADY when the peer already exchanged.
…ng; notification burst scripts (#87)
# Conflicts: # docs/bledev-internals.md # docs/bledev.md # pydevices-desktop.toml
bledev.security keeps the bonds in NVS on an ESP32 (a filesystem erase keeps them, a chip erase loses them), handles the passkey step aioble leaves out, and tracks each link's security. bledev.repl and bledev.filetransfer serve with pairing=justworks|passkey|numeric|auto; the password stays the default. Clients pair with pair=True and passkey=; filetransfer pairs on its own when the board asks, as a CircuitPython board does. bledev.bleak pairs through WinRT's custom pairing, so a passkey needs no system dialog. The fake models passkey pairing, authenticated characteristics and a lost bond, and tests/bledev_pairing.py checks the clients against it.
The stack's key store failed mid-pairing when the scheduler queue was full: aioble saves secrets through micropython.schedule and raises when it can't, and drawing the passkey inside a scheduled callback while the REPL's 5 ms timer queues filled it. bledev.security now answers the secret IRQs itself and saves inline when the queue is full, answers the passkey from the IRQ, and only defers the drawing. The REPL opens on the client's first line when pairing is the lock, so the client sees one prompt. A board no longer hangs up the instant encryption fails (the host couldn't tell why); it hangs up a link that isn't paired within 30 s instead. A host whose every attempt drops after encrypting with keys it already had is told its bond is stale. bledev.bleak reports the ceremony it ran: WinRT says protection level NONE even after a passkey. The hardware gate is tests/bledev_board/pair_server.py, pair_client.py and uart_say.py.
…essage; tighter gate pair/unpair from a terminal, typing the passkey the board shows, for tools (mpftp) that use the OS's bond. A dropped link after encrypting with stored keys can be a stale bond or a dead link Windows hands out after a board reset; the host can't tell, so the message says both, and retries back off. The wrong-passkey check now demands that pairing itself fails.
…le-buffered panel The LCD-7's dot-clock framebuffer swaps its two buffers on every refresh, so a passkey drawn once lived in one of them and the next refresh lost it (and hide() cleared only one). Read back from the panel: the passkey is now in both buffers while shown and gone from both after. tests/bledev_board/files_pair_client.py is the board-to-board gate.
A paired Windows listed the LCD-7 as 'MPY ESP32', MicroPython's default GAP name, not the name it advertises, so two paired boards looked alike. Read back over the air: the Device Name is now the name passed to start().
|
This isn't proven on hardware yet. A board entering a passkey that another board displays fails on stock MicroPython, on every board. What happened. The LCD-7 ran The cause. In Two fixes, neither on a board yet:
Both stopped at the same point: the session lost permission to flash the P4 and then to drive the boards, before the rerun. What's owed is One other thing, seen once: after a 30 s failed pairing, printing a long list of logged IRQ tuples at the P4's REPL gave a Guru Meditation (load access fault, core 1). It didn't happen again in the rerun, which logged fewer events, and I didn't chase it. Both boards are left with no bonds (NVS namespace |
|
A board typing in a passkey another board shows now works on hardware. It passes with #89's bledev workaround alone, on the stock #12 P4 image, with no firmware patch; the patched P4 image was never flashed. The LCD-7 served files with
The LCD-7 printed the passkey 3.3-3.9 s after the start, and the P4 asked for it 1.2 s later. That's the workaround's 1.5 s wait running out, which confirms the stack never asks on its own. No run was disturbed. Both boards are left idle at the REPL with no bonds, and the LCD-7's |
Pairing and bonding for
bledev.replandbledev.filetransfer(docs/ble.md §3 "pairing later", §4, §7 "Bonding"). The password alone stays the default.Stacking. Based on
bledev-filetransfer(#86), withbledev-hid(#83) merged in, because this builds on #83'sConnection.pair(), encrypted characteristics and bond store. Until #83 merges, its commits show in this diff too. Merge order: #78, #81, #84, #85, #86, #83, then this.What you get
bledev.repl.start(..., pairing="passkey")(orbledev.filetransfer.start): the board draws a six-digit passkey onboard_config.display_drv(and prints it), the host types it in, and the two are bonded.password=Falsemakes the passkey the only lock. Also"justworks"(password still required: anyone can pair),"numeric"(withconfirm=), and"auto"(passkey with a display, just works without).repl.connect(..., pair=True, passkey=...);filetransfer.connect()pairs by itself when the board asks, which a CircuitPython board always does (noAUTHcharacteristic, transfer encrypted).bledev.bleakpairs through WinRT's custom pairing (no system dialog, passkey supplied behind a deferral), andpython -m bledev.bleak pair|unpair NAMEpairs a computer once for tools like mpftp.bledev.security): a filesystem reformat keeps it, a chip erase loses it. A host with a stale bond is told to unpair and pair again.Fixed on the way, all from the LCD-7: aioble saves keys through
micropython.scheduleand raises when the queue is full, which failed the stack's key store mid-pairing (the host thought it had paired). The passkey step, which aioble leaves unhandled, is answered from the IRQ. The passkey is drawn into both buffers of the double-buffered panel.Gates (laptop and LCD-7; each planted fault turned its gate red):
Passkey pairing, then REPL and 20 KB through files on the paired link: PASS, three fresh pairings. After a hard reset of the board and a new laptop process, reconnect from the bond with no passkey: 10 of 10, median 2.1 s to a prompt. Plant (board forgets its keys): FAIL, and unpair plus pair again recovers.
Wrong passkey refused, nothing bonded: PASS, six runs. Plant (board pairs just works): FAIL.
Unpaired host: RX, transfer and AUTH reads and writes all refused (ATT 0x05): PASS. Plant (unprotected): FAIL.
Fake-backed checks, CPython and MicroPython:
tests/bledev_pairing.py, four plants.Board to board, T-Embed to the LCD-7 (just works plus password): the file client paired by itself, 20 KB both ways byte for byte (the LCD-7's copy had the same SHA-256), and a second connection encrypted from the bond: PASS. Plants
nopair(refused) andflip(byte check): FAIL.Not run on hardware: a board as central typing in a passkey another board shows. The fake covers it.
mpftp's side: PyDevices/mpftp#48, stacked on mpftp#47. Numbers and method:
docs/bledev-internals.md, "How pairing gets there" and "Pairing".