Skip to content
Open
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
12 changes: 10 additions & 2 deletions nimble/host/include/host/ble_gatt.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ struct ble_hs_cfg;
*/

/** GATT service 16-bit UUID. */
#define BLE_GATT_SVC_UUID16 0x1801
#define BLE_GATT_SVC_UUID16 0x1801

/** GATT Client Characteristic Configuration descriptor 16-bit UUID. */
#define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902
#define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902

/** GATT Characteristic Extended Porperties descriptor 16-bit UUID. */
#define BLE_GATT_DSC_EXT_PROP_UUID16 0x2900

/** @} */

Expand Down Expand Up @@ -246,6 +249,11 @@ struct ble_gatt_dsc {
ble_uuid_any_t uuid;
};

/** Represents a Characteristic Extended Properties descriptor */
struct ble_gatt_cep_dsc {
/** Characteristic Extended properties **/
uint16_t properties;
};

/** Represents a handle-value tuple for multiple handle notifications. */
struct ble_gatt_notif {
Expand Down
21 changes: 15 additions & 6 deletions nimble/host/src/ble_gatt_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,16 @@ int ble_gattc_any_jobs(void);
int ble_gattc_init(void);

/*** @server. */
#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001
#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002
#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */
#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc
#define BLE_GATTS_CLT_CFG_F_NOTIFY 0x0001
#define BLE_GATTS_CLT_CFG_F_INDICATE 0x0002
#define BLE_GATTS_CLT_CFG_F_MODIFIED 0x0080 /* Internal only. */
#define BLE_GATTS_CLT_CFG_F_RESERVED 0xfffc

#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4
#define BLE_GATTS_INC_SVC_LEN_UUID 6
#define BLE_GATTS_INC_SVC_LEN_NO_UUID 4
#define BLE_GATTS_INC_SVC_LEN_UUID 6

#define BLE_GATTS_CEP_F_RELIABLE_WRITE 0x0001
#define BLE_GATTS_CEP_F_AUX_WRITE 0x0002

/**
* Contains counts of resources required by the GATT server. The contents of
Expand All @@ -183,6 +186,12 @@ struct ble_gatt_resources {
*/
uint16_t cccds;

/**
* Number of characteristic extended properties descriptors. Each of
* these also contributes to the total descriptor count.
*/
uint16_t ceps;

/** Total number of ATT attributes. */
uint16_t attrs;
};
Expand Down
105 changes: 95 additions & 10 deletions nimble/host/src/ble_gatts.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,12 @@
#define BLE_GATTS_INCLUDE_SZ 6
#define BLE_GATTS_CHR_MAX_SZ 19

static const ble_uuid_t *uuid_pri =
BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE);
static const ble_uuid_t *uuid_sec =
BLE_UUID16_DECLARE(BLE_ATT_UUID_SECONDARY_SERVICE);
static const ble_uuid_t *uuid_inc =
BLE_UUID16_DECLARE(BLE_ATT_UUID_INCLUDE);
static const ble_uuid_t *uuid_chr =
BLE_UUID16_DECLARE(BLE_ATT_UUID_CHARACTERISTIC);
static const ble_uuid_t *uuid_ccc =
BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16);
static const ble_uuid_t *uuid_pri = BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE);
static const ble_uuid_t *uuid_sec = BLE_UUID16_DECLARE(BLE_ATT_UUID_SECONDARY_SERVICE);
static const ble_uuid_t *uuid_inc = BLE_UUID16_DECLARE(BLE_ATT_UUID_INCLUDE);
static const ble_uuid_t *uuid_chr = BLE_UUID16_DECLARE(BLE_ATT_UUID_CHARACTERISTIC);
static const ble_uuid_t *uuid_ccc = BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16);
static const ble_uuid_t *uuid_cep = BLE_UUID16_DECLARE(BLE_GATT_DSC_EXT_PROP_UUID16);

static const struct ble_gatt_svc_def **ble_gatts_svc_defs;
static int ble_gatts_num_svc_defs;
Expand Down Expand Up @@ -154,6 +150,22 @@ ble_gatts_chr_clt_cfg_allowed(const struct ble_gatt_chr_def *chr)
return flags;
}

static uint16_t
ble_gatts_chr_ext_prop_allowed(const struct ble_gatt_chr_def *chr)
{
uint16_t flags;

flags = 0;
if (chr->flags & BLE_GATT_CHR_F_RELIABLE_WRITE) {
flags |= BLE_GATTS_CEP_F_RELIABLE_WRITE;
}
if (chr->flags & BLE_GATT_CHR_F_AUX_WRITE) {
flags |= BLE_GATTS_CEP_F_AUX_WRITE;
}

return flags;
}

static uint8_t
ble_gatts_att_flags_from_chr_flags(ble_gatt_chr_flags chr_flags)
{
Expand Down Expand Up @@ -804,6 +816,55 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle)
return 0;
}

static int
ble_gatts_cep_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t att_op,
uint16_t offset, struct os_mbuf **om, void *arg)
{
uint16_t prop = POINTER_TO_UINT(arg);
uint8_t *buf;

ble_gatts_dsc_inc_stat(ble_gatts_dsc_op(att_op));

if (att_op != BLE_ATT_ACCESS_OP_READ) {
return BLE_ATT_ERR_WRITE_NOT_PERMITTED;
}

buf = os_mbuf_extend(*om, sizeof(prop));
if (buf == NULL) {
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
put_le16(buf, prop);

return 0;
}

static int
ble_gatts_register_cep_dsc(uint16_t *att_handle, ble_gatt_chr_flags flags)
{
struct ble_gatt_cep_dsc cep;
int rc;

cep.properties = 0x0000;
if (flags & BLE_GATT_CHR_F_RELIABLE_WRITE) {
cep.properties |= BLE_GATTS_CEP_F_RELIABLE_WRITE;
}
if (flags & BLE_GATT_CHR_F_AUX_WRITE) {
/* TODO: Implement Characteristic User Description
* (Core specification 6.0, vol 3, part G, section 3.3.3.2)*/
cep.properties |= BLE_GATTS_CEP_F_AUX_WRITE;
}

rc = ble_att_svr_register(uuid_cep, BLE_ATT_F_READ, 0, att_handle,
ble_gatts_cep_access, UINT_TO_POINTER(cep.properties));
if (rc != 0) {
return rc;
}

STATS_INC(ble_gatts_stats, dscs);

return 0;
}

static int
ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
const struct ble_gatt_chr_def *chr,
Expand All @@ -814,6 +875,7 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
uint16_t def_handle;
uint16_t val_handle;
uint16_t dsc_handle;
uint16_t cep_handle;
uint8_t att_flags;
int rc;

Expand Down Expand Up @@ -870,6 +932,14 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc,
BLE_HS_DBG_ASSERT(dsc_handle == def_handle + 2);
}

if (ble_gatts_chr_ext_prop_allowed(chr) != 0) {
rc = ble_gatts_register_cep_dsc(&cep_handle, chr->flags);
if (rc != 0) {
return rc;
}
BLE_HS_DBG_ASSERT(cep_handle == def_handle + 3);
}

/* Register each descriptor. */
if (chr->descriptors != NULL) {
for (dsc = chr->descriptors; dsc->uuid != NULL; dsc++) {
Expand Down Expand Up @@ -2172,6 +2242,21 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs,
res->attrs++;
}

/* If the characteristic permits reliable writes or auxiliary
* writes, it has an Extended Properties descriptor.
*/
if (chr->flags & BLE_GATT_CHR_F_AUX_WRITE ||
chr->flags & BLE_GATT_CHR_F_RELIABLE_WRITE) {

/* Each CEP requires:
* o 1 descriptor
* o 1 attribute
*/
res->dscs++;
res->ceps++;
res->attrs++;
}

if (chr->descriptors != NULL) {
for (d = 0; chr->descriptors[d].uuid != NULL; d++) {
if (!ble_gatts_dsc_is_sane(chr->descriptors + d)) {
Expand Down