Skip to content

BluetoothSerial SSP Authentication with callbacks #4634

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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);
}
}
37 changes: 35 additions & 2 deletions libraries/BluetoothSerial/src/BluetoothSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ static EventGroupHandle_t _spp_event_group = NULL;
static boolean secondConnectionAttempt;
static esp_spp_cb_t * custom_spp_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_NUM_RSPS 20
Expand Down Expand Up @@ -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:
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
log_v("authentication success: %s", param->auth_cmpl.device_name);
if (auth_complete_callback) {
auth_complete_callback(true);
}
} else {
log_e("authentication failed, status:%d", param->auth_cmpl.stat);
if (auth_complete_callback) {
auth_complete_callback(false);
}
}
break;

Expand All @@ -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:
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;

case ESP_BT_GAP_KEY_NOTIF_EVT:
Expand Down Expand Up @@ -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");
return false;
}
Expand Down Expand Up @@ -672,6 +689,22 @@ void BluetoothSerial::end()
_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)
{
custom_spp_callback = callback;
Expand Down
6 changes: 6 additions & 0 deletions libraries/BluetoothSerial/src/BluetoothSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <functional>

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
{
Expand All @@ -44,6 +46,10 @@ class BluetoothSerial: public Stream
void end(void);
void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t * callback);

void onConfirmRequest(ConfirmRequestCb cb);
void onAuthComplete(AuthCompleteCb cb);
void confirmReply(boolean confirm);

void enableSSP();
bool setPin(const char *pin);
Expand Down