From 9ef504392b96173b3772b537f68e860ae601a73a Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Sun, 13 Apr 2025 16:56:45 +0200 Subject: [PATCH] Improved ESP32 BLE pairing. Added unpair command. --- BLESerial.cpp | 11 +++ BLESerial.h | 1 + Bluetooth.h | 169 ++++++++++++++++++++++++--------------------- Framing.h | 9 +-- Makefile | 8 +-- RNode_Firmware.ino | 4 ++ 6 files changed, 116 insertions(+), 86 deletions(-) diff --git a/BLESerial.cpp b/BLESerial.cpp index 80bcaf2..ee3b531 100644 --- a/BLESerial.cpp +++ b/BLESerial.cpp @@ -96,6 +96,17 @@ void BLESerial::flush() { } } +void BLESerial::disconnect() { + if (ble_server->getConnectedCount() > 0) { + uint16_t conn_id = ble_server->getConnId(); + Serial.printf("Have connected: %d\n", conn_id); + ble_server->disconnect(conn_id); + Serial.println("Disconnected"); + } else { + Serial.println("No connected"); + } +} + void BLESerial::begin(const char *name) { ConnectedDeviceCount = 0; BLEDevice::init(name); diff --git a/BLESerial.h b/BLESerial.h index 1dcae99..f845b56 100644 --- a/BLESerial.h +++ b/BLESerial.h @@ -78,6 +78,7 @@ public: void begin(const char *name); void end(); + void disconnect(); void startAdvertising(); void stopAdvertising(); void onWrite(BLECharacteristic *characteristic); diff --git a/Bluetooth.h b/Bluetooth.h index 6347a45..e5165e1 100644 --- a/Bluetooth.h +++ b/Bluetooth.h @@ -170,31 +170,42 @@ char bt_devname[11]; } #elif HAS_BLE == true + bool bt_setup_hw(); void bt_security_setup(); BLESecurity *ble_security = new BLESecurity(); bool ble_authenticated = false; uint32_t pairing_pin = 0; void bt_flush() { if (bt_state == BT_STATE_CONNECTED) { SerialBT.flush(); } } - void bt_disable_pairing() { + void bt_start() { + // Serial.println("BT start"); display_unblank(); - bt_allow_pairing = false; - bt_ssp_pin = 0; - bt_state = BT_STATE_ON; + if (bt_state == BT_STATE_OFF) { + bt_state = BT_STATE_ON; + SerialBT.begin(bt_devname); + SerialBT.setTimeout(10); + } } - void bt_passkey_notify_callback(uint32_t passkey) { - // Serial.printf("Got passkey notification: %d\n", passkey); - bt_ssp_pin = passkey; - bt_state = BT_STATE_PAIRING; - bt_allow_pairing = true; - bt_pairing_started = millis(); - kiss_indicate_btpin(); + void bt_stop() { + // Serial.println("BT stop"); + display_unblank(); + if (bt_state != BT_STATE_OFF) { + bt_allow_pairing = false; + bt_state = BT_STATE_OFF; + SerialBT.end(); + } } - bool bt_confirm_pin_callback(uint32_t pin) { - // Serial.printf("Confirm PIN callback: %d\n", pin); - return true; + bool bt_init() { + // Serial.println("BT init"); + bt_state = BT_STATE_OFF; + if (bt_setup_hw()) { + if (bt_enabled && !console_active) bt_start(); + return true; + } else { + return false; + } } void bt_debond_all() { @@ -206,6 +217,44 @@ char bt_devname[11]; free(dev_list); } + void bt_enable_pairing() { + // Serial.println("BT enable pairing"); + display_unblank(); + if (bt_state == BT_STATE_OFF) bt_start(); + + bt_security_setup(); + + bt_allow_pairing = true; + bt_pairing_started = millis(); + bt_state = BT_STATE_PAIRING; + bt_ssp_pin = pairing_pin; + } + + void bt_disable_pairing() { + // Serial.println("BT disable pairing"); + display_unblank(); + bt_allow_pairing = false; + bt_ssp_pin = 0; + bt_state = BT_STATE_ON; + } + + void bt_passkey_notify_callback(uint32_t passkey) { + // Serial.printf("Got passkey notification: %d\n", passkey); + if (bt_allow_pairing) { + bt_ssp_pin = passkey; + bt_pairing_started = millis(); + kiss_indicate_btpin(); + } else { + // Serial.println("Pairing not allowed, re-init"); + SerialBT.disconnect(); + } + } + + bool bt_confirm_pin_callback(uint32_t pin) { + // Serial.printf("Confirm PIN callback: %d\n", pin); + return true; + } + void bt_update_passkey() { // Serial.println("Updating passkey"); pairing_pin = random(899999)+100000; @@ -222,31 +271,6 @@ char bt_devname[11]; return ble_authenticated; } - void bt_security_setup() { - uint32_t passkey = bt_passkey_callback(); - - // Serial.printf("Executing BT security setup, passkey is %d\n", passkey); - - uint8_t key_size = 16; - uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; - uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; - - esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND; - uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE; - uint8_t oob_support = ESP_BLE_OOB_DISABLE; - - esp_ble_io_cap_t iocap = ESP_IO_CAP_OUT; - - esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t)); - esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t)); - } - bool bt_security_request_callback() { if (bt_allow_pairing) { // Serial.println("Accepting security request"); @@ -261,7 +285,10 @@ char bt_devname[11]; if (auth_result.success == true) { // Serial.println("Authentication success"); ble_authenticated = true; - bt_state = BT_STATE_CONNECTED; + if (bt_state == BT_STATE_PAIRING) { + // Serial.println("Pairing complete, disconnecting"); + delay(2000); SerialBT.disconnect(); + } else { bt_state = BT_STATE_CONNECTED; } } else { // Serial.println("Authentication fail"); ble_authenticated = false; @@ -274,16 +301,16 @@ char bt_devname[11]; } void bt_connect_callback(BLEServer *server) { - // uint16_t conn_id = server->getConnId(); + uint16_t conn_id = server->getConnId(); // Serial.printf("Connected: %d\n", conn_id); display_unblank(); ble_authenticated = false; - bt_state = BT_STATE_CONNECTED; + if (bt_state != BT_STATE_PAIRING) { bt_state = BT_STATE_CONNECTED; } cable_state = CABLE_STATE_DISCONNECTED; } void bt_disconnect_callback(BLEServer *server) { - // uint16_t conn_id = server->getConnId(); + uint16_t conn_id = server->getConnId(); // Serial.printf("Disconnected: %d\n", conn_id); display_unblank(); ble_authenticated = false; @@ -291,6 +318,7 @@ char bt_devname[11]; } bool bt_setup_hw() { + // Serial.println("BT setup hw"); if (!bt_ready) { if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) { bt_enabled = true; @@ -322,45 +350,30 @@ char bt_devname[11]; } else { return false; } } - void bt_start() { - display_unblank(); - if (bt_state == BT_STATE_OFF) { - bt_state = BT_STATE_ON; - SerialBT.begin(bt_devname); - SerialBT.setTimeout(10); - } - } + void bt_security_setup() { + // Serial.println("Executing BT security setup"); + if (pairing_pin == 0) { bt_update_passkey(); } + uint32_t passkey = pairing_pin; + // Serial.printf("Passkey is %d\n", passkey); - void bt_stop() { - display_unblank(); - if (bt_state != BT_STATE_OFF) { - bt_allow_pairing = false; - bt_state = BT_STATE_OFF; - SerialBT.end(); - } - } + uint8_t key_size = 16; + uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; + uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; - bool bt_init() { - bt_state = BT_STATE_OFF; - if (bt_setup_hw()) { - if (bt_enabled && !console_active) bt_start(); - return true; - } else { - return false; - } - } + esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND; + uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE; + uint8_t oob_support = ESP_BLE_OOB_DISABLE; - void bt_enable_pairing() { - display_unblank(); - if (bt_state == BT_STATE_OFF) bt_start(); + esp_ble_io_cap_t iocap = ESP_IO_CAP_OUT; - bt_security_setup(); - //bt_debond_all(); - //bt_update_passkey(); - - bt_allow_pairing = true; - bt_pairing_started = millis(); - bt_state = BT_STATE_PAIRING; + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t)); + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t)); } void update_bt() { diff --git a/Framing.h b/Framing.h index 6dffb98..9346f70 100644 --- a/Framing.h +++ b/Framing.h @@ -61,6 +61,7 @@ #define CMD_DISP_RCND 0x68 #define CMD_NP_INT 0x65 #define CMD_BT_CTRL 0x46 + #define CMD_BT_UNPAIR 0x70 #define CMD_BT_PIN 0x62 #define CMD_DIS_IA 0x69 @@ -82,10 +83,10 @@ #define CMD_RESET 0x55 #define CMD_RESET_BYTE 0xF8 - #define CMD_LOG 0x70 - #define CMD_TIME 0x70 - #define CMD_MUX_CHAIN 0x80 - #define CMD_MUX_DSCVR 0x81 + #define CMD_LOG 0x80 + #define CMD_TIME 0x81 + #define CMD_MUX_CHAIN 0x82 + #define CMD_MUX_DSCVR 0x83 #define DETECT_REQ 0x73 #define DETECT_RESP 0x46 diff --git a/Makefile b/Makefile index 59a73dd..c17bf38 100644 --- a/Makefile +++ b/Makefile @@ -198,8 +198,8 @@ upload-heltec32_v3: arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:heltec_wifi_lora_32_V3 @sleep 1 rnodeconf /dev/ttyUSB0 --firmware-hash $$(./partition_hashes ./build/esp32.esp32.heltec_wifi_lora_32_V3/RNode_Firmware.ino.bin) - @sleep 3 - python ./Release/esptool/esptool.py --chip esp32-s3 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin +# @sleep 3 +# python ./Release/esptool/esptool.py --chip esp32-s3 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin upload-tdeck: arduino-cli upload -p /dev/ttyACM0 --fqbn esp32:esp32:esp32s3 @@ -233,8 +233,8 @@ upload-t3s3: arduino-cli upload -p /dev/ttyACM0 --fqbn esp32:esp32:esp32s3 @sleep 1 rnodeconf /dev/ttyACM0 --firmware-hash $$(./partition_hashes ./build/esp32.esp32.esp32s3/RNode_Firmware.ino.bin) - @sleep 3 - python ./Release/esptool/esptool.py --chip esp32s3 --port /dev/ttyACM0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin +# @sleep 3 +# python ./Release/esptool/esptool.py --chip esp32s3 --port /dev/ttyACM0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin upload-featheresp32: arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:featheresp32 diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 9c5d5ce..24e10a2 100644 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -1144,6 +1144,10 @@ void serial_callback(uint8_t sbyte) { } } #endif + } else if (command == CMD_BT_UNPAIR) { + #if HAS_BLE + if (sbyte == 0x01) { bt_debond_all(); } + #endif } else if (command == CMD_DISP_INT) { #if HAS_DISPLAY if (sbyte == FESC) {