mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-01 14:50:03 +00:00
feat(nimble): read multiple variable length characteristics
This commit is contained in:
committed by
Abhinav Kudnar
parent
02ef2e088f
commit
2795cb8849
@@ -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.
|
||||
|
||||
@@ -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 },
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user