mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-30 05:40:03 +00:00
feat(nimble): Added two GATT features:
1. Automatically initiate security if a GATT service request fails 2. Encryption, Authentication, and Authorization requirement on CCCD
This commit is contained in:
@@ -127,50 +127,58 @@ struct ble_hs_cfg;
|
||||
*/
|
||||
|
||||
/** GATT Characteristic Flag: Broadcast. */
|
||||
#define BLE_GATT_CHR_F_BROADCAST 0x0001
|
||||
#define BLE_GATT_CHR_F_BROADCAST 0x00000001
|
||||
|
||||
/** GATT Characteristic Flag: Read. */
|
||||
#define BLE_GATT_CHR_F_READ 0x0002
|
||||
#define BLE_GATT_CHR_F_READ 0x00000002
|
||||
|
||||
/** GATT Characteristic Flag: Write without Response. */
|
||||
#define BLE_GATT_CHR_F_WRITE_NO_RSP 0x0004
|
||||
#define BLE_GATT_CHR_F_WRITE_NO_RSP 0x00000004
|
||||
|
||||
/** GATT Characteristic Flag: Write. */
|
||||
#define BLE_GATT_CHR_F_WRITE 0x0008
|
||||
#define BLE_GATT_CHR_F_WRITE 0x00000008
|
||||
|
||||
/** GATT Characteristic Flag: Notify. */
|
||||
#define BLE_GATT_CHR_F_NOTIFY 0x0010
|
||||
#define BLE_GATT_CHR_F_NOTIFY 0x00000010
|
||||
|
||||
/** GATT Characteristic Flag: Indicate. */
|
||||
#define BLE_GATT_CHR_F_INDICATE 0x0020
|
||||
#define BLE_GATT_CHR_F_INDICATE 0x00000020
|
||||
|
||||
/** GATT Characteristic Flag: Authenticated Signed Writes. */
|
||||
#define BLE_GATT_CHR_F_AUTH_SIGN_WRITE 0x0040
|
||||
#define BLE_GATT_CHR_F_AUTH_SIGN_WRITE 0x00000040
|
||||
|
||||
/** GATT Characteristic Flag: Reliable Writes. */
|
||||
#define BLE_GATT_CHR_F_RELIABLE_WRITE 0x0080
|
||||
#define BLE_GATT_CHR_F_RELIABLE_WRITE 0x00000080
|
||||
|
||||
/** GATT Characteristic Flag: Auxiliary Writes. */
|
||||
#define BLE_GATT_CHR_F_AUX_WRITE 0x0100
|
||||
#define BLE_GATT_CHR_F_AUX_WRITE 0x00000100
|
||||
|
||||
/** GATT Characteristic Flag: Read Encrypted. */
|
||||
#define BLE_GATT_CHR_F_READ_ENC 0x0200
|
||||
#define BLE_GATT_CHR_F_READ_ENC 0x00000200
|
||||
|
||||
/** GATT Characteristic Flag: Read Authenticated. */
|
||||
#define BLE_GATT_CHR_F_READ_AUTHEN 0x0400
|
||||
#define BLE_GATT_CHR_F_READ_AUTHEN 0x00000400
|
||||
|
||||
/** GATT Characteristic Flag: Read Authorized. */
|
||||
#define BLE_GATT_CHR_F_READ_AUTHOR 0x0800
|
||||
#define BLE_GATT_CHR_F_READ_AUTHOR 0x00000800
|
||||
|
||||
/** GATT Characteristic Flag: Write Encrypted. */
|
||||
#define BLE_GATT_CHR_F_WRITE_ENC 0x1000
|
||||
#define BLE_GATT_CHR_F_WRITE_ENC 0x00001000
|
||||
|
||||
/** GATT Characteristic Flag: Write Authenticated. */
|
||||
#define BLE_GATT_CHR_F_WRITE_AUTHEN 0x2000
|
||||
#define BLE_GATT_CHR_F_WRITE_AUTHEN 0x00002000
|
||||
|
||||
/** GATT Characteristic Flag: Write Authorized. */
|
||||
#define BLE_GATT_CHR_F_WRITE_AUTHOR 0x4000
|
||||
#define BLE_GATT_CHR_F_WRITE_AUTHOR 0x00004000
|
||||
|
||||
/** GATT Characteristic Flag: CCCD Write Encrypted */
|
||||
#define BLE_GATT_CHR_F_NOTIFY_INDICATE_ENC 0x00008000
|
||||
|
||||
/** GATT Characteristic Flag: CCCD Write Authenticated */
|
||||
#define BLE_GATT_CHR_F_NOTIFY_INDICATE_AUTHEN 0x00010000
|
||||
|
||||
/** GATT Characteristic Flag: CCCD Write Authorized */
|
||||
#define BLE_GATT_CHR_F_NOTIFY_INDICATE_AUTHOR 0x00020000
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -996,7 +1004,7 @@ typedef int ble_gatt_access_fn(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
/** Type definition for GATT characteristic flags. */
|
||||
typedef uint16_t ble_gatt_chr_flags;
|
||||
typedef uint32_t ble_gatt_chr_flags;
|
||||
|
||||
/** Represents the definition of a GATT characteristic. */
|
||||
struct ble_gatt_chr_def {
|
||||
@@ -1031,6 +1039,8 @@ struct ble_gatt_chr_def {
|
||||
/**
|
||||
* At registration time, this is filled in with the characteristic's value
|
||||
* attribute handle.
|
||||
*
|
||||
* The attribute handle for CCCD is `val_handle + 1`
|
||||
*/
|
||||
uint16_t *val_handle;
|
||||
|
||||
|
||||
@@ -8513,6 +8513,10 @@ ble_gap_enc_event(uint16_t conn_handle, int status,
|
||||
ble_gap_event_listener_call(&event);
|
||||
ble_gap_call_conn_event_cb(&event, conn_handle);
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATTC) && MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
ble_gattc_recover_gatt_proc(conn_handle, status);
|
||||
#endif
|
||||
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,9 @@ int32_t ble_gattc_timer(void);
|
||||
|
||||
int ble_gattc_any_jobs(void);
|
||||
int ble_gattc_init(void);
|
||||
#if MYNEWT_VAL(BLE_GATTC) && MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
void ble_gattc_recover_gatt_proc(uint16_t conn_handle, int enc_status);
|
||||
#endif
|
||||
|
||||
/*** @server. */
|
||||
#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001
|
||||
@@ -224,7 +227,6 @@ int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs,
|
||||
int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
uint8_t op, uint16_t offset, struct os_mbuf **om,
|
||||
void *arg);
|
||||
void ble_gatts_set_clt_cfg_perm_flags(uint8_t flags);
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATT_CACHING)
|
||||
struct ble_gatts_aware_state {
|
||||
|
||||
@@ -113,6 +113,9 @@
|
||||
struct ble_gattc_proc {
|
||||
STAILQ_ENTRY(ble_gattc_proc) next;
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
struct ble_gatt_error error;
|
||||
#endif
|
||||
uint32_t exp_os_ticks;
|
||||
uint16_t conn_handle;
|
||||
uint16_t cid;
|
||||
@@ -210,6 +213,9 @@ struct ble_gattc_proc {
|
||||
uint16_t att_handle;
|
||||
ble_gatt_attr_fn *cb;
|
||||
void *cb_arg;
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
struct os_mbuf * om;
|
||||
#endif
|
||||
} write;
|
||||
|
||||
struct {
|
||||
@@ -461,6 +467,11 @@ static struct os_mempool ble_gattc_proc_pool;
|
||||
/* The list of active GATT client procedures. */
|
||||
static struct ble_gattc_proc_list ble_gattc_procs;
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
/** Retry procedure after encryption response. */
|
||||
static struct ble_gattc_proc_list ble_gattc_cached_procs;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATTC)
|
||||
/* The time when we should attempt to resume stalled procedures, in OS ticks.
|
||||
* A value of 0 indicates no stalled procedures.
|
||||
@@ -780,6 +791,13 @@ ble_gattc_proc_free(struct ble_gattc_proc *proc)
|
||||
ble_gattc_dbg_assert_proc_not_inserted(proc);
|
||||
|
||||
switch (proc->op) {
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
case BLE_GATT_OP_WRITE:
|
||||
if (MYNEWT_VAL(BLE_GATT_WRITE)) {
|
||||
os_mbuf_free_chain(proc->write.om);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case BLE_GATT_OP_WRITE_LONG:
|
||||
if (MYNEWT_VAL(BLE_GATT_WRITE_LONG)) {
|
||||
os_mbuf_free_chain(proc->write_long.attr.om);
|
||||
@@ -1389,6 +1407,94 @@ ble_gattc_error(int status, uint16_t att_handle)
|
||||
return &error;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
void
|
||||
ble_gattc_recover_gatt_proc(uint16_t conn_handle, int enc_status)
|
||||
{
|
||||
struct ble_gattc_proc * prev;
|
||||
struct ble_gattc_proc * proc;
|
||||
struct ble_gattc_proc * next;
|
||||
struct os_mbuf * om;
|
||||
struct ble_gatt_attr attrs[MYNEWT_VAL(BLE_GATT_WRITE_MAX_ATTRS)];
|
||||
ble_gattc_err_fn *err_cb;
|
||||
|
||||
prev = NULL;
|
||||
proc = STAILQ_FIRST(&ble_gattc_cached_procs);
|
||||
while (proc != NULL) {
|
||||
next = STAILQ_NEXT(proc, next);
|
||||
|
||||
if (proc->conn_handle == conn_handle) {
|
||||
if (enc_status == 0) {
|
||||
switch (proc->op) {
|
||||
case BLE_GATT_OP_READ:
|
||||
ble_gattc_read(conn_handle, proc->read.handle,
|
||||
proc->read.cb, proc->read.cb_arg);
|
||||
break;
|
||||
case BLE_GATT_OP_READ_UUID:
|
||||
ble_gattc_read_by_uuid(conn_handle, proc->read_uuid.start_handle,
|
||||
proc->read_uuid.end_handle, &proc->read_uuid.chr_uuid.u,
|
||||
proc->read_uuid.cb, proc->read_uuid.cb_arg);
|
||||
break;
|
||||
case BLE_GATT_OP_READ_LONG:
|
||||
ble_gattc_read_long(conn_handle, proc->read_long.handle,
|
||||
proc->read_long.offset, proc->read_long.cb,
|
||||
proc->read_long.cb_arg);
|
||||
break;
|
||||
case BLE_GATT_OP_READ_MULT:
|
||||
ble_gattc_read_mult(conn_handle, proc->read_mult.handles,
|
||||
proc->read_mult.num_handles, proc->read_mult.cb,
|
||||
proc->read_mult.cb_arg);
|
||||
break;
|
||||
case BLE_GATT_OP_READ_MULT_VAR:
|
||||
ble_gattc_read_mult_var(conn_handle, proc->read_mult.handles,
|
||||
proc->read_mult.num_handles, proc->read_mult.cb_mult,
|
||||
proc->read_mult.cb_arg);
|
||||
break;
|
||||
case BLE_GATT_OP_WRITE:
|
||||
/* Mbuf will be consumed by the API. */
|
||||
om = os_mbuf_dup(proc->write.om);
|
||||
ble_gattc_write(conn_handle, proc->write.att_handle,
|
||||
om, proc->write.cb, proc->write.cb_arg);
|
||||
break;
|
||||
case BLE_GATT_OP_WRITE_LONG:
|
||||
/* Mbuf will be consumed by the API. */
|
||||
om = os_mbuf_dup(proc->write_long.attr.om);
|
||||
ble_gattc_write_long(conn_handle, proc->write_long.attr.handle,
|
||||
proc->write_long.attr.offset, om,
|
||||
proc->write_long.cb, proc->write_long.cb_arg);
|
||||
case BLE_GATT_OP_WRITE_RELIABLE:
|
||||
for (int i = 0; i < proc->write_reliable.num_attrs; i++) {
|
||||
attrs[i].handle = proc->write_reliable.attrs[i].handle;
|
||||
attrs[i].offset = 0;
|
||||
attrs[i].om = os_mbuf_dup(proc->write_reliable.attrs[i].om);
|
||||
}
|
||||
ble_gattc_write_reliable(conn_handle, attrs,
|
||||
proc->write_reliable.num_attrs,
|
||||
proc->write_reliable.cb, proc->write_reliable.cb_arg);
|
||||
}
|
||||
} else {
|
||||
err_cb = ble_gattc_err_dispatch_get(proc->op);
|
||||
if (err_cb != NULL) {
|
||||
err_cb(proc, BLE_HS_ERR_ATT_BASE + proc->error.status, proc->error.att_handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (!prev) {
|
||||
STAILQ_REMOVE_HEAD(&ble_gattc_cached_procs, next);
|
||||
} else {
|
||||
STAILQ_REMOVE_AFTER(&ble_gattc_cached_procs, prev, next);
|
||||
}
|
||||
|
||||
ble_gattc_proc_free(proc);
|
||||
proc = prev;
|
||||
}
|
||||
|
||||
prev = proc;
|
||||
proc = next;
|
||||
}
|
||||
}
|
||||
#endif /* MYNEWT_VAL(BLE_GATTC_AUTO_PAIR) */
|
||||
|
||||
/*****************************************************************************
|
||||
* $mtu *
|
||||
*****************************************************************************/
|
||||
@@ -4391,6 +4497,9 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle,
|
||||
proc->write.att_handle = attr_handle;
|
||||
proc->write.cb = cb;
|
||||
proc->write.cb_arg = cb_arg;
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
proc->write.om = os_mbuf_dup(txom);
|
||||
#endif
|
||||
|
||||
ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 1);
|
||||
|
||||
@@ -5486,9 +5595,30 @@ ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t s
|
||||
{
|
||||
struct ble_gattc_proc *proc;
|
||||
ble_gattc_err_fn *err_cb;
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
struct ble_gap_conn_desc desc;
|
||||
int rc;
|
||||
#endif
|
||||
|
||||
proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_NONE);
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
ble_gap_conn_find(conn_handle, &desc);
|
||||
proc->error.att_handle = handle;
|
||||
proc->error.status = status;
|
||||
#endif
|
||||
|
||||
if (proc != NULL) {
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
if (desc.sec_state.encrypted == 0 &&
|
||||
(status == BLE_ATT_ERR_INSUFFICIENT_ENC ||
|
||||
status == BLE_ATT_ERR_INSUFFICIENT_AUTHEN)) {
|
||||
rc = ble_gap_security_initiate(conn_handle);
|
||||
if (rc == 0) {
|
||||
STAILQ_INSERT_TAIL(&ble_gattc_cached_procs, proc, next);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
err_cb = ble_gattc_err_dispatch_get(proc->op);
|
||||
if (err_cb != NULL) {
|
||||
err_cb(proc, BLE_HS_ERR_ATT_BASE + status, handle);
|
||||
@@ -5913,6 +6043,9 @@ ble_gattc_init(void)
|
||||
STAILQ_INIT(&temp_proc_list);
|
||||
#endif
|
||||
STAILQ_INIT(&ble_gattc_procs);
|
||||
#if MYNEWT_VAL(BLE_GATTC_AUTO_PAIR)
|
||||
STAILQ_INIT(&ble_gattc_cached_procs);
|
||||
#endif
|
||||
|
||||
if (MYNEWT_VAL(BLE_GATT_MAX_PROCS) > 0) {
|
||||
rc = os_mempool_init(&ble_gattc_proc_pool,
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "esp_nimble_mem.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_GATTS)
|
||||
static uint8_t perm_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE ;
|
||||
|
||||
#if MYNEWT_VAL(BLE_DYNAMIC_SERVICE)
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
@@ -179,11 +178,6 @@ ble_gatts_clt_cfg_free(struct ble_gatts_clt_cfg *cfg)
|
||||
}
|
||||
#endif
|
||||
|
||||
void ble_gatts_set_clt_cfg_perm_flags(uint8_t flags)
|
||||
{
|
||||
perm_flags = flags ;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
uint8_t op, uint16_t offset, struct os_mbuf **om,
|
||||
@@ -259,6 +253,26 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr)
|
||||
return flags;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_gatts_chr_clt_cfg_flags_from_chr_flags(ble_gatt_chr_flags chr_flags)
|
||||
{
|
||||
uint8_t cccd_flags;
|
||||
|
||||
cccd_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE;
|
||||
|
||||
if (chr_flags & BLE_GATT_CHR_F_NOTIFY_INDICATE_ENC) {
|
||||
cccd_flags |= BLE_ATT_F_WRITE_ENC;
|
||||
}
|
||||
if (chr_flags & BLE_GATT_CHR_F_NOTIFY_INDICATE_AUTHEN) {
|
||||
cccd_flags |= BLE_ATT_F_WRITE_AUTHEN;
|
||||
}
|
||||
if (chr_flags & BLE_GATT_CHR_F_NOTIFY_INDICATE_AUTHOR) {
|
||||
cccd_flags |= BLE_ATT_F_WRITE_AUTHOR;
|
||||
}
|
||||
|
||||
return cccd_flags;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ble_gatts_att_flags_from_chr_flags(ble_gatt_chr_flags chr_flags)
|
||||
{
|
||||
@@ -1011,10 +1025,10 @@ ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
}
|
||||
|
||||
static int
|
||||
ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
|
||||
ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle, uint8_t cccd_flags)
|
||||
{
|
||||
int rc;
|
||||
rc = ble_att_svr_register(uuid_ccc, perm_flags, 0,
|
||||
rc = ble_att_svr_register(uuid_ccc, cccd_flags, 0,
|
||||
att_handle, ble_gatts_clt_cfg_access, NULL);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
@@ -1190,7 +1204,8 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
|
||||
}
|
||||
|
||||
if (ble_gatts_chr_clt_cfg_allowed(chr) != 0) {
|
||||
rc = ble_gatts_register_clt_cfg_dsc(&dsc_handle);
|
||||
att_flags = ble_gatts_chr_clt_cfg_flags_from_chr_flags(chr->flags);
|
||||
rc = ble_gatts_register_clt_cfg_dsc(&dsc_handle, att_flags);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user