From 57ca67f108051d8867b8161c85b26e537cdac4f4 Mon Sep 17 00:00:00 2001 From: Joshua Rogers Date: Mon, 17 Aug 2026 20:18:40 +0200 Subject: [PATCH] fix: reply to the legacy PIN request instead of letting the pair hang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `devicePairingPINCodeRequest` logged the request and returned without calling `replyPINCode`, which the delegate contract requires. Any peripheral that falls back to legacy PIN pairing sat in `.connecting` until the 60s pair watchdog fired, every attempt. Reply with the all-zero PIN legacy HID peripherals use, and only for a pair this app installed in `pendingPairs` — a request belonging to any other pair is left alone rather than answered on its behalf. --- .../Model/Store/BluetoothPeripheralStore.swift | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Magic Switch/Model/Store/BluetoothPeripheralStore.swift b/Magic Switch/Model/Store/BluetoothPeripheralStore.swift index 3e0b80f..e764102 100644 --- a/Magic Switch/Model/Store/BluetoothPeripheralStore.swift +++ b/Magic Switch/Model/Store/BluetoothPeripheralStore.swift @@ -1568,7 +1568,21 @@ final class BluetoothPeripheralStore: NSObject, ObservableObject, BluetoothPerip else { return } - print("Bluetooth pairing requested a PIN code for \(address)") + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + guard self.pendingPairs[address] === pair else { + print("Ignoring Bluetooth PIN code request for \(address): not our pairing") + return + } + print("Replying to Bluetooth PIN code request for \(address)") + // Legacy HID peripherals with no keypad take the all-zero PIN. + var code = BluetoothPINCode() + let digits = Array("0000".utf8) + withUnsafeMutableBytes(of: &code.data) { raw in + for (index, byte) in digits.enumerated() { raw[index] = byte } + } + pair.replyPINCode(digits.count, pinCode: &code) + } } /// Selector target for `IOBluetoothDevice.register(forDisconnectNotification:...)`.