This is an automated email from the ASF dual-hosted git repository. kopyscinski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 0711811c9f002391c7cd3c86dc96be3e411dd816 Author: Ćukasz Rymanowski <[email protected]> AuthorDate: Thu Mar 12 13:50:52 2020 +0100 nimble/gatt: Add support for newt ATT opcodes This is initial implementation of handling new GATT opcodes. Gatt Client supports now: ATT multi Variable read req receiving ATT multi notifications Gatt server supports now: ATT multi Variable read rsp --- nimble/host/include/host/ble_att.h | 8 + nimble/host/include/host/ble_gatt.h | 14 ++ nimble/host/services/gatt/src/ble_svc_gatt.c | 4 + nimble/host/src/ble_att.c | 3 + nimble/host/src/ble_att_clt.c | 21 ++- nimble/host/src/ble_att_cmd_priv.h | 14 ++ nimble/host/src/ble_att_priv.h | 7 +- nimble/host/src/ble_att_svr.c | 164 +++++++++++++++++++++ nimble/host/src/ble_gatt_priv.h | 2 +- nimble/host/src/ble_gattc.c | 144 +++++++++++++++--- nimble/host/syscfg.yml | 11 ++ nimble/host/test/src/ble_att_clt_test.c | 4 +- nimble/include/nimble/nimble_opt_auto.h | 4 + porting/examples/linux/include/syscfg/syscfg.h | 8 + .../examples/linux_blemesh/include/syscfg/syscfg.h | 8 + porting/nimble/include/syscfg/syscfg.h | 8 + porting/npl/riot/include/syscfg/syscfg.h | 8 + 17 files changed, 405 insertions(+), 27 deletions(-) diff --git a/nimble/host/include/host/ble_att.h b/nimble/host/include/host/ble_att.h index cb98eab4..5a3a2a1f 100644 --- a/nimble/host/include/host/ble_att.h +++ b/nimble/host/include/host/ble_att.h @@ -195,6 +195,14 @@ struct os_mbuf; /** Indicate Response. */ #define BLE_ATT_OP_INDICATE_RSP 0x1e +/** Read Multiple Variable Lenght Request */ +#define BLE_ATT_OP_READ_MULT_VAR_REQ 0x20 + +/** Read Multiple Variable Lenght Response */ +#define BLE_ATT_OP_READ_MULT_VAR_RSP 0x21 + +/** Notify Multiple Request */ +#define BLE_ATT_OP_NOTIFY_MULTI_REQ 0x23 /** Write Command. */ #define BLE_ATT_OP_WRITE_CMD 0x52 diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index b3bea2bd..b38dd32b 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -267,6 +267,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 @@ -489,6 +500,9 @@ 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. diff --git a/nimble/host/services/gatt/src/ble_svc_gatt.c b/nimble/host/services/gatt/src/ble_svc_gatt.c index 961c23fc..501164d5 100644 --- a/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -179,4 +179,8 @@ ble_svc_gatt_init(void) if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0) { ble_svc_gatt_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT); } + + if (MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) > 0) { + ble_svc_gatt_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT); + } } diff --git a/nimble/host/src/ble_att.c b/nimble/host/src/ble_att.c index ae5041f6..3295bc86 100644 --- a/nimble/host/src/ble_att.c +++ b/nimble/host/src/ble_att.c @@ -69,6 +69,9 @@ static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = { { BLE_ATT_OP_NOTIFY_REQ, ble_att_svr_rx_notify }, { 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_NOTIFY_MULTI_REQ, ble_att_svr_rx_notify_multi}, { BLE_ATT_OP_WRITE_CMD, ble_att_svr_rx_write_no_rsp }, }; diff --git a/nimble/host/src/ble_att_clt.c b/nimble/host/src/ble_att_clt.c index 7fcccbb9..1bbb32f1 100644 --- a/nimble/host/src/ble_att_clt.c +++ b/nimble/host/src/ble_att_clt.c @@ -540,7 +540,7 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx *****************************************************************************/ int ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, const uint16_t *handles, - int num_handles) + int num_handles, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; @@ -549,12 +549,15 @@ ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, const uint16_t *han 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) { @@ -576,7 +579,19 @@ ble_att_clt_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom); + ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom, false); + return 0; +} + +int +ble_att_clt_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, 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, cid, 0, rxom, true); return 0; } diff --git a/nimble/host/src/ble_att_cmd_priv.h b/nimble/host/src/ble_att_cmd_priv.h index 7202e0b7..78c60d5e 100644 --- a/nimble/host/src/ble_att_cmd_priv.h +++ b/nimble/host/src/ble_att_cmd_priv.h @@ -309,6 +309,20 @@ struct ble_att_exec_write_req { */ #define BLE_ATT_EXEC_WRITE_RSP_SZ 1 +/** + * | Parameter | Size (octets) | + * +-----------------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle Length Value Tuple List | 8 to (ATT_MTU-1) | + */ +#define BLE_ATT_NOTIFY_MULTI_REQ_BASE_SZ 9 + +struct ble_att_tuple_list { + uint16_t handle; + uint16_t value_len; + uint8_t data[0]; +} __attribute__((packed)); + /** * | Parameter | Size (octets) | * +------------------------------------+-------------------+ diff --git a/nimble/host/src/ble_att_priv.h b/nimble/host/src/ble_att_priv.h index f596cf91..ac65250f 100644 --- a/nimble/host/src/ble_att_priv.h +++ b/nimble/host/src/ble_att_priv.h @@ -198,6 +198,8 @@ int ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); int ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); @@ -207,6 +209,8 @@ int ble_att_svr_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_notify_multi(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); int ble_att_svr_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); @@ -261,8 +265,9 @@ int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t cid, uint16_t handle uint16_t offset); int ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, - 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, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid); int ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 7cdcd1db..eb91e3e1 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -1629,6 +1629,113 @@ ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx att_err, err_handle); } +static int +ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom, + struct os_mbuf **out_txom, + uint8_t *att_err, + uint16_t *err_handle) +{ + struct os_mbuf *txom; + uint16_t handle; + uint16_t mtu; + uint16_t tuple_len; + struct os_mbuf *tmp = NULL; + int rc; + + mtu = ble_att_mtu_by_cid(conn_handle, cid); + + rc = ble_att_svr_pkt(rxom, &txom, att_err); + if (rc != 0) { + *err_handle = 0; + goto done; + } + + if (ble_att_cmd_prepare(BLE_ATT_OP_READ_MULT_VAR_RSP, 0, txom) == NULL) { + *att_err = BLE_ATT_ERR_INSUFFICIENT_RES; + *err_handle = 0; + rc = BLE_HS_ENOMEM; + goto done; + } + + tmp = os_msys_get_pkthdr(2, 0); + + /* Iterate through requested handles, reading the corresponding attribute + * for each. Stop when there are no more handles to process, or the + * response is full. + */ + while (OS_MBUF_PKTLEN(*rxom) >= 2 && OS_MBUF_PKTLEN(txom) < mtu) { + /* Ensure the full 16-bit handle is contiguous at the start of the + * mbuf. + */ + rc = ble_att_svr_pullup_req_base(rxom, 2, att_err); + if (rc != 0) { + *err_handle = 0; + goto done; + } + + /* Extract the 16-bit handle and strip it from the front of the + * mbuf. + */ + handle = get_le16((*rxom)->om_data); + os_mbuf_adj(*rxom, 2); + + rc = ble_att_svr_read_handle(conn_handle, handle, 0, tmp, att_err); + if (rc != 0) { + *err_handle = handle; + goto done; + } + tuple_len = OS_MBUF_PKTLEN(tmp); + rc = os_mbuf_append(txom, &tuple_len, sizeof(tuple_len)); + if (rc != 0) { + *err_handle = handle; + goto done; + } + if (tuple_len != 0) { + rc = os_mbuf_appendfrom(txom, tmp, 0, tuple_len); + if (rc != 0) { + *err_handle = handle; + goto done; + } + os_mbuf_adj(tmp, tuple_len); + } + } + rc = 0; + +done: + + if (tmp) { + os_mbuf_free_chain(tmp); + } + *out_txom = txom; + return rc; +} + +int +ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) +{ +#if (!MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) || (MYNEWT_VAL(BLE_VERSION) < 52)) + return BLE_HS_ENOTSUP; +#endif + + struct os_mbuf *txom; + uint16_t err_handle; + uint8_t att_err; + int rc; + + /* Initialize some values in case of early error. */ + txom = NULL; + err_handle = 0; + att_err = 0; + + rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, cid, rxom, &txom, &att_err, + &err_handle); + + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, + BLE_ATT_OP_READ_MULT_VAR_REQ, + att_err, err_handle); +} + static int ble_att_svr_is_valid_read_group_type(const ble_uuid_t *uuid) { @@ -2504,6 +2611,63 @@ ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) return 0; } +int +ble_att_svr_rx_notify_multi(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) +{ +#if !MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) + return BLE_HS_ENOTSUP; +#endif + + struct ble_att_tuple_list *req; + uint16_t handle; + int rc; + uint16_t pkt_len; + struct os_mbuf *tmp; + uint16_t attr_len; + + pkt_len = OS_MBUF_PKTLEN(*rxom); + while (pkt_len > 0) { + rc = ble_att_svr_pullup_req_base(rxom, sizeof(struct ble_att_tuple_list), NULL); + if (rc != 0) { + return BLE_HS_ENOMEM; + } + + req = (struct ble_att_tuple_list *)(*rxom)->om_data; + + handle = le16toh(req->handle); + attr_len = le16toh(req->value_len); + + os_mbuf_adj(*rxom, 4); + + if (attr_len > BLE_ATT_ATTR_MAX_LEN) { + /*TODO Figure out what to do here */ + break; + } + + tmp = os_msys_get_pkthdr(attr_len, 0); + if (!tmp) { + /*TODO Figure out what to do here */ + break; + } + + rc = os_mbuf_appendfrom(tmp, *rxom, 0, attr_len); + if (rc) { + /*TODO Figure out what to do here */ + break; + } + + ble_gap_notify_rx_event(conn_handle, handle, tmp, 0); + + os_mbuf_adj(*rxom, attr_len); + pkt_len = OS_MBUF_PKTLEN(*rxom); + } + + os_mbuf_free_chain(*rxom); + *rxom = NULL; + + return 0; +} + /** * @return 0 on success; nonzero on failure. */ diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index 595a813d..f77c78ad 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -113,7 +113,7 @@ void ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, - struct os_mbuf **rxom); + struct os_mbuf **rxom, bool variable); void ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_group_type_adata *adata); void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int rc); diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 7467ff60..17f302cd 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -93,11 +93,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; @@ -584,7 +587,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; @@ -3324,8 +3327,74 @@ done: } /***************************************************************************** - * $read multiple * - *****************************************************************************/ +* $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 @@ -3349,6 +3418,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 +3473,7 @@ ble_gattc_read_mult_tx(struct ble_gattc_proc *proc) int rc; rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->cid, 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 +3482,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 +3510,20 @@ ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, goto done; } - ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_MULT); + if (variable) { + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_MULT_VAR); + } else { + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_MULT); + } 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,9 +3538,31 @@ 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 * - *****************************************************************************/ +* $write no response * +*****************************************************************************/ int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, @@ -4762,16 +4864,18 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, */ void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, 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_cid_op(conn_handle, cid, - 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_cid_op(conn_handle, cid, op); if (proc != NULL) { ble_gattc_read_mult_cb(proc, status, 0, om); ble_gattc_process_status(proc, BLE_HS_EDONE); diff --git a/nimble/host/syscfg.yml b/nimble/host/syscfg.yml index bfe38192..f94111c6 100644 --- a/nimble/host/syscfg.yml +++ b/nimble/host/syscfg.yml @@ -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 && (MYNEWT_VAL_BLE_VERSION >= 52) BLE_GATT_WRITE_NO_RSP: description: > Enables the Write Without Response GATT procedure. (0/1) @@ -362,6 +367,12 @@ syscfg.defs: Enables processing of incoming Handle Value Notification ATT commands. (0/1) value: 1 + BLE_ATT_SVR_NOTIFY_MULTI: + description: > + Enables processing of incoming Multi Handle Value Notification ATT + commands. (0/1) + value: MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52) + BLE_ATT_SVR_INDICATE: description: > Enables processing of incoming Handle Value Indication ATT diff --git a/nimble/host/test/src/ble_att_clt_test.c b/nimble/host/test/src/ble_att_clt_test.c index 7d41371e..a944f6ee 100644 --- a/nimble/host/test/src/ble_att_clt_test.c +++ b/nimble/host/test/src/ble_att_clt_test.c @@ -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, BLE_L2CAP_CID_ATT, ((uint16_t[]){ 1, 2 }), 2); + rc = ble_att_clt_tx_read_mult(conn_handle, BLE_L2CAP_CID_ATT, ((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, BLE_L2CAP_CID_ATT, NULL, 0); + rc = ble_att_clt_tx_read_mult(conn_handle, BLE_L2CAP_CID_ATT, NULL, 0, false); TEST_ASSERT(rc == BLE_HS_EINVAL); ble_hs_test_util_assert_mbufs_freed(NULL); diff --git a/nimble/include/nimble/nimble_opt_auto.h b/nimble/include/nimble/nimble_opt_auto.h index 33a1e2aa..55f62199 100644 --- a/nimble/include/nimble/nimble_opt_auto.h +++ b/nimble/include/nimble/nimble_opt_auto.h @@ -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)) diff --git a/porting/examples/linux/include/syscfg/syscfg.h b/porting/examples/linux/include/syscfg/syscfg.h index c262ff8a..04438c21 100644 --- a/porting/examples/linux/include/syscfg/syscfg.h +++ b/porting/examples/linux/include/syscfg/syscfg.h @@ -531,6 +531,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -643,6 +647,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 && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ_UUID #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 2aba7d61..c9fd5411 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -532,6 +532,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -644,6 +648,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 && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ_UUID #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/nimble/include/syscfg/syscfg.h b/porting/nimble/include/syscfg/syscfg.h index f0732c21..dcea02fd 100644 --- a/porting/nimble/include/syscfg/syscfg.h +++ b/porting/nimble/include/syscfg/syscfg.h @@ -530,6 +530,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -642,6 +646,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 && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ_UUID #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index b70d7b90..b381d328 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -1394,6 +1394,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -1506,6 +1510,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 && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ_UUID #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif
