Files
SharpKey/main/include/BT.h
2022-09-04 14:51:38 +01:00

223 lines
9.7 KiB
C++

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: BT.h
// Created: Jan 2022
// Version: v1.0
// Author(s): Philip Smart
// Description: Header file for the Bluetooth Class.
//
// Credits:
// Copyright: (c) 2022 Philip Smart <philip.smart@net2net.org>
//
// History: Mar 2022 - Initial write.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef BT_H_
#define BT_H_
#include <string>
#include <vector>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_bt.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_hidh.h"
#include "esp_hid_common.h"
#include "esp_gap_bt_api.h"
#include "esp_gap_ble_api.h"
// Bluetooth interface class. Provides Mouse and Keyboard functionality via the Bluetooth wireless interface.
class BT {
#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(*a))
public:
typedef void t_pairingHandler(uint32_t code, uint8_t trigger);
// Structure to contain details of a single device forming a scanned device list.
//
typedef struct {
esp_bd_addr_t bda;
std::string name;
int8_t rssi;
esp_hid_usage_t usage;
esp_hid_transport_t transport; //BT, BLE or USB
union {
struct {
esp_bt_cod_t cod;
esp_bt_uuid_t uuid;
} bt;
struct {
esp_ble_addr_type_t addr_type;
uint16_t appearance;
} ble;
};
// Display format values.
std::string deviceAddr; // MAC address of the Bluetooth device.
std::string deviceType; // BT, BLE or USB
} t_scanListItem;
// Prototypes.
BT(void);
virtual ~BT(void);
void getDeviceList(std::vector<t_scanListItem> &scanList, int waitTime);
bool setup(t_pairingHandler *handler = nullptr);
inline uint8_t getBatteryLevel() { return btCtrl.batteryLevel; }
inline void setBatteryLevel(uint8_t level) { btCtrl.batteryLevel = level; }
private:
static constexpr char const *TAG = "BT";
#ifdef CONFIG_CLASSIC_BT_ENABLED
const char *gap_bt_prop_type_names[5] = { "", "BDNAME", "COD", "RSSI", "EIR" };
const char *bt_gap_evt_names[10] = { "DISC_RES", "DISC_STATE_CHANGED", "RMT_SRVCS", "RMT_SRVC_REC", "AUTH_CMPL", "PIN_REQ", "CFM_REQ", "KEY_NOTIF", "KEY_REQ", "READ_RSSI_DELTA" };
#endif
const char *ble_gap_evt_names[28] = { "ADV_DATA_SET_COMPLETE", "SCAN_RSP_DATA_SET_COMPLETE", "SCAN_PARAM_SET_COMPLETE", "SCAN_RESULT", "ADV_DATA_RAW_SET_COMPLETE",
"SCAN_RSP_DATA_RAW_SET_COMPLETE", "ADV_START_COMPLETE", "SCAN_START_COMPLETE", "AUTH_CMPL", "KEY",
"SEC_REQ", "PASSKEY_NOTIF", "PASSKEY_REQ", "OOB_REQ", "LOCAL_IR",
"LOCAL_ER", "NC_REQ", "ADV_STOP_COMPLETE", "SCAN_STOP_COMPLETE", "SET_STATIC_RAND_ADDR",
"UPDATE_CONN_PARAMS", "SET_PKT_LENGTH_COMPLETE", "SET_LOCAL_PRIVACY_COMPLETE", "REMOVE_BOND_DEV_COMPLETE", "CLEAR_BOND_DEV_COMPLETE",
"GET_BOND_DEV_COMPLETE", "READ_RSSI_COMPLETE", "UPDATE_WHITELIST_COMPLETE" };
const char *ble_addr_type_names[4] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" };
// Define possible HIDH host modes.
static const esp_bt_mode_t HIDH_IDLE_MODE = (esp_bt_mode_t) 0x00;
static const esp_bt_mode_t HIDH_BLE_MODE = (esp_bt_mode_t) 0x01;
static const esp_bt_mode_t HIDH_BT_MODE = (esp_bt_mode_t) 0x02;
static const esp_bt_mode_t HIDH_BTDM_MODE = (esp_bt_mode_t) 0x03;
// Structure to maintain control variables.
typedef struct {
#ifdef CONFIG_CLASSIC_BT_ENABLED
std::vector<t_scanListItem> btScanList;
#endif
std::vector<t_scanListItem> bleScanList;
t_pairingHandler *pairingHandler;
esp_hidh_dev_t *hidhDevHdl;
int8_t batteryLevel;
#ifdef CONFIG_CLASSIC_BT_ENABLED
xSemaphoreHandle bt_hidh_cb_semaphore;
#endif
xSemaphoreHandle ble_hidh_cb_semaphore;
BT *pThis;
} t_btCtrl;
// All control variables are stored in a struct for ease of reference.
t_btCtrl btCtrl;
// Prototypes.
static void processBTGapEvent(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t * param);
static void processBLEGapEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
t_scanListItem* findValidScannedDevice(esp_bd_addr_t bda, std::vector<t_scanListItem> &scanList);
void processBLEDeviceScanResult(esp_ble_gap_cb_param_t * scan_rst);
void addBLEScanDevice(esp_bd_addr_t bda, esp_ble_addr_type_t addr_type, uint16_t appearance, uint8_t *name, uint8_t name_len, int rssi);
#ifdef CONFIG_CLASSIC_BT_ENABLED
void processBTDeviceScanResult(esp_bt_gap_cb_param_t * param);
void addBTScanDevice(esp_bd_addr_t bda, esp_bt_cod_t *cod, esp_bt_uuid_t *uuid, uint8_t *name, uint8_t name_len, int rssi);
#endif
esp_err_t scanForBLEDevices(uint32_t timeout);
esp_err_t scanForBTDevices(uint32_t timeout);
esp_err_t scanForAllDevices(uint32_t timeout, size_t *noDevices, std::vector<t_scanListItem> &scanList);
void printUUID(esp_bt_uuid_t * uuid);
const char *ble_addr_type_str(esp_ble_addr_type_t ble_addr_type)
{
if (ble_addr_type > BLE_ADDR_TYPE_RPA_RANDOM)
{
return "UNKNOWN";
}
return ble_addr_type_names[ble_addr_type];
}
const char *ble_gap_evt_str(uint8_t event)
{
if (event >= SIZEOF_ARRAY(ble_gap_evt_names))
{
return "UNKNOWN";
}
return ble_gap_evt_names[event];
}
#ifdef CONFIG_CLASSIC_BT_ENABLED
const char *bt_gap_evt_str(uint8_t event)
{
if (event >= SIZEOF_ARRAY(bt_gap_evt_names))
{
return "UNKNOWN";
}
return bt_gap_evt_names[event];
}
#endif
const char *ble_key_type_str(esp_ble_key_type_t key_type)
{
const char *key_str = nullptr;
switch (key_type)
{
case ESP_LE_KEY_NONE:
key_str = "ESP_LE_KEY_NONE";
break;
case ESP_LE_KEY_PENC:
key_str = "ESP_LE_KEY_PENC";
break;
case ESP_LE_KEY_PID:
key_str = "ESP_LE_KEY_PID";
break;
case ESP_LE_KEY_PCSRK:
key_str = "ESP_LE_KEY_PCSRK";
break;
case ESP_LE_KEY_PLK:
key_str = "ESP_LE_KEY_PLK";
break;
case ESP_LE_KEY_LLK:
key_str = "ESP_LE_KEY_LLK";
break;
case ESP_LE_KEY_LENC:
key_str = "ESP_LE_KEY_LENC";
break;
case ESP_LE_KEY_LID:
key_str = "ESP_LE_KEY_LID";
break;
case ESP_LE_KEY_LCSRK:
key_str = "ESP_LE_KEY_LCSRK";
break;
default:
key_str = "INVALID BLE KEY TYPE";
break;
}
return key_str;
}
};
#endif // BT_H_