BluetoothSerial SSP Authentication with callbacks (#4634)

Added authentication callbacks and example, resolves #4622.
This commit is contained in:
richardclli 2021-01-11 17:58:15 +08:00 committed by GitHub
parent 434d02c49f
commit 81b9130d8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 116 additions and 2 deletions

View File

@ -0,0 +1,75 @@
//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Richard Li - 2020
//
//This example creates a bridge between Serial and Classical Bluetooth (SPP with authentication)
//and also demonstrate that SerialBT have the same functionalities of a normal Serial
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
boolean confirmRequestPending = true;
void BTConfirmRequestCallback(uint32_t numVal)
{
confirmRequestPending = true;
Serial.println(numVal);
}
void BTAuthCompleteCallback(boolean success)
{
confirmRequestPending = false;
if (success)
{
Serial.println("Pairing success!!");
}
else
{
Serial.println("Pairing failed, rejected by user!!");
}
}
void setup()
{
Serial.begin(115200);
SerialBT.enableSSP();
SerialBT.onConfirmRequest(BTConfirmRequestCallback);
SerialBT.onAuthComplete(BTAuthCompleteCallback);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop()
{
if (confirmRequestPending)
{
if (Serial.available())
{
int dat = Serial.read();
if (dat == 'Y' || dat == 'y')
{
SerialBT.confirmReply(true);
}
else
{
SerialBT.confirmReply(false);
}
}
}
else
{
if (Serial.available())
{
SerialBT.write(Serial.read());
}
if (SerialBT.available())
{
Serial.write(SerialBT.read());
}
delay(20);
}
}

View File

@ -51,6 +51,9 @@ static EventGroupHandle_t _spp_event_group = NULL;
static boolean secondConnectionAttempt; static boolean secondConnectionAttempt;
static esp_spp_cb_t * custom_spp_callback = NULL; static esp_spp_cb_t * custom_spp_callback = NULL;
static BluetoothSerialDataCb custom_data_callback = NULL; static BluetoothSerialDataCb custom_data_callback = NULL;
static esp_bd_addr_t current_bd_addr;
static ConfirmRequestCb confirm_request_callback = NULL;
static AuthCompleteCb auth_complete_callback = NULL;
#define INQ_LEN 0x10 #define INQ_LEN 0x10
#define INQ_NUM_RSPS 20 #define INQ_NUM_RSPS 20
@ -398,8 +401,14 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
case ESP_BT_GAP_AUTH_CMPL_EVT: case ESP_BT_GAP_AUTH_CMPL_EVT:
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
log_v("authentication success: %s", param->auth_cmpl.device_name); log_v("authentication success: %s", param->auth_cmpl.device_name);
if (auth_complete_callback) {
auth_complete_callback(true);
}
} else { } else {
log_e("authentication failed, status:%d", param->auth_cmpl.stat); log_e("authentication failed, status:%d", param->auth_cmpl.stat);
if (auth_complete_callback) {
auth_complete_callback(false);
}
} }
break; break;
@ -421,7 +430,13 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
case ESP_BT_GAP_CFM_REQ_EVT: case ESP_BT_GAP_CFM_REQ_EVT:
log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); log_i("ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); if (confirm_request_callback) {
memcpy(current_bd_addr, param->cfm_req.bda, sizeof(esp_bd_addr_t));
confirm_request_callback(param->cfm_req.num_val);
}
else {
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
}
break; break;
case ESP_BT_GAP_KEY_NOTIF_EVT: case ESP_BT_GAP_KEY_NOTIF_EVT:
@ -500,7 +515,9 @@ static bool _init_bt(const char *deviceName)
} }
} }
if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) { // Why only master need this? Slave need this during pairing as well
// if (_isMaster && esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
if (esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) {
log_e("gap register failed"); log_e("gap register failed");
return false; return false;
} }
@ -672,6 +689,22 @@ void BluetoothSerial::end()
_stop_bt(); _stop_bt();
} }
void BluetoothSerial::onConfirmRequest(ConfirmRequestCb cb)
{
confirm_request_callback = cb;
}
void BluetoothSerial::onAuthComplete(AuthCompleteCb cb)
{
auth_complete_callback = cb;
}
void BluetoothSerial::confirmReply(boolean confirm)
{
esp_bt_gap_ssp_confirm_reply(current_bd_addr, confirm);
}
esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback) esp_err_t BluetoothSerial::register_callback(esp_spp_cb_t * callback)
{ {
custom_spp_callback = callback; custom_spp_callback = callback;

View File

@ -25,6 +25,8 @@
#include <functional> #include <functional>
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb; typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
typedef std::function<void(uint32_t num_val)> ConfirmRequestCb;
typedef std::function<void(boolean success)> AuthCompleteCb;
class BluetoothSerial: public Stream class BluetoothSerial: public Stream
{ {
@ -44,6 +46,10 @@ class BluetoothSerial: public Stream
void end(void); void end(void);
void onData(BluetoothSerialDataCb cb); void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t * callback); esp_err_t register_callback(esp_spp_cb_t * callback);
void onConfirmRequest(ConfirmRequestCb cb);
void onAuthComplete(AuthCompleteCb cb);
void confirmReply(boolean confirm);
void enableSSP(); void enableSSP();
bool setPin(const char *pin); bool setPin(const char *pin);