feat(nimble): read multiple variable length characteristics

This commit is contained in:
Sumeet Singh
2024-03-11 10:48:23 +05:30
committed by Abhinav Kudnar
parent 02ef2e088f
commit 2795cb8849
15 changed files with 190 additions and 24 deletions
+15
View File
@@ -468,6 +468,17 @@ typedef int ble_gatt_attr_fn(uint16_t conn_handle,
struct ble_gatt_attr *attr,
void *arg);
/**
* The host will free the attribute mbuf automatically after the callback is
* executed. The application can take ownership of the mbuf and prevent it
* from being freed by assigning NULL to attr->om.
*/
typedef int ble_gatt_attr_mult_fn(uint16_t conn_handle,
const struct ble_gatt_error *error,
struct ble_gatt_attr *attrs,
uint8_t num_attrs,
void *arg);
/**
* The host will free the attribute mbufs automatically after the callback is
* executed. The application can take ownership of the mbufs and prevent them
@@ -690,6 +701,10 @@ int ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, ble_gatt_attr_fn *cb,
void *cb_arg);
int ble_gattc_read_mult_var(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, ble_gatt_attr_mult_fn *cb,
void *cb_arg);
/**
* Initiates GATT procedure: Write Without Response. This function consumes
* the supplied mbuf regardless of the outcome.
+1
View File
@@ -70,6 +70,7 @@ static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = {
{ BLE_ATT_OP_INDICATE_REQ, ble_att_svr_rx_indicate },
{ BLE_ATT_OP_INDICATE_RSP, ble_att_clt_rx_indicate },
{ BLE_ATT_OP_READ_MULT_VAR_REQ, ble_att_svr_rx_read_mult_var },
{ BLE_ATT_OP_READ_MULT_VAR_RSP, ble_att_clt_rx_read_mult_var },
{ BLE_ATT_OP_WRITE_CMD, ble_att_svr_rx_write_no_rsp },
{ BLE_ATT_OP_SIGNED_WRITE_CMD, ble_att_svr_rx_signed_write },
};
+18 -3
View File
@@ -537,7 +537,7 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
*****************************************************************************/
int
ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles,
int num_handles)
int num_handles, bool variable)
{
#if !NIMBLE_BLE_ATT_CLT_READ_MULT
return BLE_HS_ENOTSUP;
@@ -546,12 +546,15 @@ ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles,
struct ble_att_read_mult_req *req;
struct os_mbuf *txom;
int i;
uint8_t op;
if (num_handles < 1) {
return BLE_HS_EINVAL;
}
req = ble_att_cmd_get(BLE_ATT_OP_READ_MULT_REQ,
op = variable ? BLE_ATT_OP_READ_MULT_VAR_REQ : BLE_ATT_OP_READ_MULT_REQ;
req = ble_att_cmd_get(op,
sizeof(req->handles[0]) * num_handles,
&txom);
if (req == NULL) {
@@ -573,7 +576,19 @@ ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom)
#endif
/* Pass the Attribute Value field to GATT. */
ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom);
ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, false);
return 0;
}
int
ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom)
{
#if !NIMBLE_BLE_ATT_CLT_READ_MULT_VAR
return BLE_HS_ENOTSUP;
#endif
/* Pass the Attribute Value field to GATT. */
ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, true);
return 0;
}
+2 -1
View File
@@ -273,8 +273,9 @@ int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle,
uint16_t offset);
int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_mult(uint16_t conn_handle,
const uint16_t *handles, int num_handles);
const uint16_t *handles, int num_handles, bool variable);
int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, const ble_uuid_t *uuid);
int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom);
+1 -1
View File
@@ -1858,7 +1858,7 @@ done:
int
ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom)
{
#if (!MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) || (MYNEWT_VAL(BLE_VERSION) < 52))
#if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT)
return BLE_HS_ENOTSUP;
#endif
+1 -1
View File
@@ -137,7 +137,7 @@ void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status,
void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status,
struct os_mbuf **rxom);
void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status,
struct os_mbuf **rxom);
struct os_mbuf **rxom, bool variable);
void ble_gattc_rx_read_group_type_adata(
uint16_t conn_handle, struct ble_att_read_group_type_adata *adata);
void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc);
+121 -16
View File
@@ -94,11 +94,12 @@
#define BLE_GATT_OP_READ_UUID 8
#define BLE_GATT_OP_READ_LONG 9
#define BLE_GATT_OP_READ_MULT 10
#define BLE_GATT_OP_WRITE 11
#define BLE_GATT_OP_WRITE_LONG 12
#define BLE_GATT_OP_WRITE_RELIABLE 13
#define BLE_GATT_OP_INDICATE 14
#define BLE_GATT_OP_CNT 15
#define BLE_GATT_OP_READ_MULT_VAR 11
#define BLE_GATT_OP_WRITE 12
#define BLE_GATT_OP_WRITE_LONG 13
#define BLE_GATT_OP_WRITE_RELIABLE 14
#define BLE_GATT_OP_INDICATE 15
#define BLE_GATT_OP_CNT 16
/** Procedure stalled due to resource exhaustion. */
#define BLE_GATTC_PROC_F_STALLED 0x01
@@ -189,7 +190,9 @@ struct ble_gattc_proc {
struct {
uint16_t handles[MYNEWT_VAL(BLE_GATT_READ_MAX_ATTRS)];
uint8_t num_handles;
bool variable;
ble_gatt_attr_fn *cb;
ble_gatt_attr_mult_fn *cb_mult;
void *cb_arg;
} read_mult;
@@ -586,7 +589,7 @@ ble_gattc_log_read_long(struct ble_gattc_proc *proc)
}
static void
ble_gattc_log_read_mult(const uint16_t *handles, uint8_t num_handles)
ble_gattc_log_read_mult(const uint16_t *handles, uint8_t num_handles, bool variable)
{
int i;
@@ -3322,6 +3325,73 @@ done:
* $read multiple *
*****************************************************************************/
static int
ble_gattc_read_mult_cb_var(struct ble_gattc_proc *proc, int status,
uint16_t att_handle, struct os_mbuf **om)
{
struct ble_gatt_attr attr[proc->read_mult.num_handles];
int rc;
int i;
uint16_t attr_len;
if (proc->read_mult.cb_mult == NULL) {
return 0;
}
memset(attr, 0, sizeof(*attr));
for (i = 0; i < proc->read_mult.num_handles; i++) {
attr[i].handle = proc->read_mult.handles[i];
attr[i].offset = 0;
if (om == NULL || OS_MBUF_PKTLEN(*om) == 0) {
continue;
}
*om = os_mbuf_pullup(*om, 2);
assert(*om);
attr_len = get_le16((*om)->om_data);
os_mbuf_adj(*om, 2);
if (attr_len > BLE_ATT_ATTR_MAX_LEN) {
/*TODO Figure out what to do here */
break;
}
attr[i].om = os_msys_get_pkthdr(attr_len, 0);
if (!attr[i].om) {
/*TODO Figure out what to do here */
break;
}
rc = os_mbuf_appendfrom(attr[i].om, *om, 0, attr_len);
if (rc) {
/*TODO Figure out what to do here */
break;
}
os_mbuf_adj(*om, attr_len);
}
/*FIXME Testing assert */
assert(i == proc->read_mult.num_handles);
proc->read_mult.cb_mult(proc->conn_handle,
ble_gattc_error(status, att_handle), &attr[0],
i,
proc->read_mult.cb_arg);
for (i = 0; i < proc->read_mult.num_handles; i++) {
if (attr[i].om != NULL) {
os_mbuf_free_chain(attr[i].om);
}
}
return 0;
}
/**
* Calls a read-multiple-characteristics proc's callback with the specified
* parameters. If the proc has no callback, this function is a no-op.
@@ -3344,6 +3414,10 @@ ble_gattc_read_mult_cb(struct ble_gattc_proc *proc, int status,
STATS_INC(ble_gattc_stats, read_mult_fail);
}
if (proc->read_mult.variable) {
return ble_gattc_read_mult_cb_var(proc, status, att_handle, om);
}
attr.handle = 0;
attr.offset = 0;
if (om == NULL) {
@@ -3400,7 +3474,7 @@ ble_gattc_read_mult_tx(struct ble_gattc_proc *proc)
int rc;
rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->read_mult.handles,
proc->read_mult.num_handles);
proc->read_mult.num_handles, proc->read_mult.variable);
if (rc != 0) {
return rc;
}
@@ -3409,10 +3483,11 @@ ble_gattc_read_mult_tx(struct ble_gattc_proc *proc)
}
int
ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, ble_gatt_attr_fn *cb,
void *cb_arg)
static int
ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, bool variable, ble_gatt_attr_fn *cb,
ble_gatt_attr_mult_fn *cb_mult,
void *cb_arg)
{
#if !MYNEWT_VAL(BLE_GATT_READ_MULT)
return BLE_HS_ENOTSUP;
@@ -3436,14 +3511,20 @@ ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles,
goto done;
}
proc->op = BLE_GATT_OP_READ_MULT;
if (variable) {
proc->op = BLE_GATT_OP_READ_MULT_VAR;
} else {
proc->op = BLE_GATT_OP_READ_MULT;
}
proc->conn_handle = conn_handle;
memcpy(proc->read_mult.handles, handles, num_handles * sizeof *handles);
proc->read_mult.num_handles = num_handles;
proc->read_mult.variable = variable;
proc->read_mult.cb = cb;
proc->read_mult.cb_mult = cb_mult;
proc->read_mult.cb_arg = cb_arg;
ble_gattc_log_read_mult(handles, num_handles);
ble_gattc_log_read_mult(handles, num_handles, variable);
rc = ble_gattc_read_mult_tx(proc);
if (rc != 0) {
goto done;
@@ -3458,6 +3539,28 @@ done:
return rc;
}
int
ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, ble_gatt_attr_fn *cb,
void *cb_arg)
{
return ble_gattc_read_mult_internal(conn_handle, handles,
num_handles, false, cb, NULL, cb_arg);
}
int
ble_gattc_read_mult_var(uint16_t conn_handle, const uint16_t *handles,
uint8_t num_handles, ble_gatt_attr_mult_fn *cb,
void *cb_arg)
{
#if MYNEWT_VAL(BLE_GATT_READ_MULT_VAR)
return ble_gattc_read_mult_internal(conn_handle, handles, num_handles,
true, NULL, cb, cb_arg);
#else
return BLE_HS_ENOTSUP;
#endif
}
/*****************************************************************************
* $write no response *
*****************************************************************************/
@@ -4875,16 +4978,18 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status,
*/
void
ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status,
struct os_mbuf **om)
struct os_mbuf **om, bool variable)
{
#if !NIMBLE_BLE_ATT_CLT_READ_MULT
return;
#endif
struct ble_gattc_proc *proc;
uint8_t op;
proc = ble_gattc_extract_first_by_conn_op(conn_handle,
BLE_GATT_OP_READ_MULT);
op = variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT;
proc = ble_gattc_extract_first_by_conn_op(conn_handle, op);
if (proc != NULL) {
ble_gattc_read_mult_cb(proc, status, 0, om);
ble_gattc_process_status(proc, BLE_HS_EDONE);
+5
View File
@@ -244,6 +244,11 @@ syscfg.defs:
Enables the Read Multiple Characteristic Values GATT procedure.
(0/1)
value: MYNEWT_VAL_BLE_ROLE_CENTRAL
BLE_GATT_READ_MULT_VAR:
description: >
Enables the Read Multiple Variable Characteristic Values GATT procedure.
(0/1)
value: MYNEWT_VAL_BLE_ROLE_CENTRAL
BLE_GATT_WRITE_NO_RSP:
description: >
Enables the Write Without Response GATT procedure. (0/1)
+2 -2
View File
@@ -380,7 +380,7 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read_mult)
conn_handle = ble_att_clt_test_misc_init();
/*** Success. */
rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2);
rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2, false);
TEST_ASSERT(rc == 0);
om = ble_hs_test_util_prev_tx_dequeue_pullup();
@@ -392,7 +392,7 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read_mult)
TEST_ASSERT(get_le16(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ + 2) == 2);
/*** Error: no handles. */
rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0);
rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0, false);
TEST_ASSERT(rc == BLE_HS_EINVAL);
ble_hs_test_util_assert_mbufs_freed(NULL);
+4
View File
@@ -77,6 +77,10 @@ extern "C" {
#define NIMBLE_BLE_ATT_CLT_READ_MULT \
(MYNEWT_VAL(BLE_GATT_READ_MULT))
#undef NIMBLE_BLE_ATT_CLT_READ_MULT_VAR
#define NIMBLE_BLE_ATT_CLT_READ_MULT_VAR \
(MYNEWT_VAL(BLE_GATT_READ_MULT_VAR))
#undef NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE
#define NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE \
(MYNEWT_VAL(BLE_GATT_DISC_ALL_SVCS))
@@ -631,6 +631,10 @@
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR
#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
@@ -632,6 +632,10 @@
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR
#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
@@ -631,6 +631,10 @@
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR
#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
+4
View File
@@ -634,6 +634,10 @@
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR
#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
+4
View File
@@ -1502,6 +1502,10 @@
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR
#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif