From a690a0596597294fd85bee397e9df9ca81b0b48d Mon Sep 17 00:00:00 2001 From: Sumeet Singh Date: Mon, 8 Apr 2024 16:43:46 +0530 Subject: [PATCH] feat(nimble): Added support for Enhanced ATT or ATT over Enhanced L2CAP Credit Based Flow Control Mode --- nimble/host/include/host/ble_att.h | 9 +- nimble/host/include/host/ble_gap.h | 26 + nimble/host/include/host/ble_gatt.h | 37 ++ nimble/host/pkg.yml | 3 + .../gatt/include/services/gatt/ble_svc_gatt.h | 2 +- nimble/host/services/gatt/src/ble_svc_gatt.c | 16 + nimble/host/src/ble_att.c | 198 +++++- nimble/host/src/ble_att_clt.c | 181 ++++-- nimble/host/src/ble_att_cmd.c | 55 +- nimble/host/src/ble_att_cmd_priv.h | 23 +- nimble/host/src/ble_att_priv.h | 112 ++-- nimble/host/src/ble_att_svr.c | 207 +++--- nimble/host/src/ble_eatt.c | 601 ++++++++++++++++++ nimble/host/src/ble_eatt_priv.h | 58 ++ nimble/host/src/ble_gap.c | 21 + nimble/host/src/ble_gap_priv.h | 1 + nimble/host/src/ble_gatt_priv.h | 40 +- nimble/host/src/ble_gattc.c | 417 +++++++++--- nimble/host/src/ble_hs.c | 8 +- nimble/host/src/ble_hs_conn.c | 1 + nimble/host/src/ble_hs_conn_priv.h | 6 + nimble/host/src/ble_hs_priv.h | 1 + nimble/host/src/ble_l2cap_coc.c | 2 +- nimble/host/syscfg.yml | 37 ++ nimble/host/test/src/ble_att_clt_test.c | 53 +- nimble/host/test/src/ble_att_svr_test.c | 27 +- nimble/host/test/src/ble_gatt_conn_test.c | 36 ++ nimble/host/test/src/ble_gatt_disc_c_test.c | 32 +- nimble/host/test/src/ble_gatt_disc_d_test.c | 24 +- nimble/host/test/src/ble_gatt_disc_s_test.c | 52 +- nimble/host/test/src/ble_gatt_find_s_test.c | 37 +- nimble/host/test/src/ble_gatt_read_test.c | 44 +- nimble/host/test/src/ble_gatt_write_test.c | 73 +-- nimble/host/test/src/ble_hs_test_util.c | 9 +- nimble/host/test/src/ble_hs_test_util.h | 6 +- nimble/host/test/syscfg.yml | 1 + nimble/include/nimble/nimble_opt_auto.h | 4 + .../examples/linux/include/logcfg/logcfg.h | 7 + .../examples/linux/include/syscfg/syscfg.h | 24 + .../linux_blemesh/include/logcfg/logcfg.h | 7 + .../linux_blemesh/include/syscfg/syscfg.h | 24 + .../examples/nuttx/include/syscfg/syscfg.h | 4 + porting/nimble/include/logcfg/logcfg.h | 7 + porting/nimble/include/syscfg/syscfg.h | 24 + porting/npl/riot/include/logcfg/logcfg.h | 7 + porting/npl/riot/include/syscfg/syscfg.h | 24 + 46 files changed, 2070 insertions(+), 518 deletions(-) create mode 100644 nimble/host/src/ble_eatt.c create mode 100644 nimble/host/src/ble_eatt_priv.h diff --git a/nimble/host/include/host/ble_att.h b/nimble/host/include/host/ble_att.h index a4665aa3d..29c21393f 100644 --- a/nimble/host/include/host/ble_att.h +++ b/nimble/host/include/host/ble_att.h @@ -189,7 +189,6 @@ struct os_mbuf; /** Execute Write Response. */ #define BLE_ATT_OP_EXEC_WRITE_RSP 0x19 - /** Read Multiple Variable Lenght Request */ #define BLE_ATT_OP_READ_MULT_VAR_REQ 0x20 @@ -205,8 +204,13 @@ struct os_mbuf; /** Indicate Response. */ #define BLE_ATT_OP_INDICATE_RSP 0x1e +/** Multiple Handle Value Length Notification Request */ +#define BLE_ATT_OP_NOTIFY_MULTI_REQ 0x23 + /** Write Command. */ #define BLE_ATT_OP_WRITE_CMD 0x52 + +/** Signed Write Command */ #define BLE_ATT_OP_SIGNED_WRITE_CMD 0xD2 /** @} */ @@ -343,6 +347,9 @@ uint16_t ble_att_preferred_mtu(void); */ int ble_att_set_preferred_mtu(uint16_t mtu); +int ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid); +uint16_t ble_att_get_default_bearer_cid(uint16_t conn_handle); + #ifdef __cplusplus } #endif diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index 6b8fd7baf..3f38621e4 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -165,6 +165,7 @@ struct hci_conn_update; #define BLE_GAP_EVENT_CONN_IQ_REPORT 36 #define BLE_GAP_EVENT_CTE_REQ_FAILED 37 #define BLE_GAP_EVENT_LINK_ESTAB 38 +#define BLE_GAP_EVENT_EATT 39 /* DTM events */ #define BLE_GAP_DTM_TX_START_EVT 0 @@ -1229,6 +1230,31 @@ struct ble_gap_event { int out_response; } authorize; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + /** + * EATT Event + * + * Valid for the following event types: + * o BLE_GAP_EVENT_EATT + * + */ + struct { + /* Connection Handle */ + uint16_t conn_handle; + + /** Connected Status + * + * EATT Connected: 0 + * EATT Disconnected: 1 + */ + uint8_t status; + + /* CID of the bearer */ + uint16_t cid; + + } eatt; +#endif + #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) /** * Represents a event mentioning connection reattempt diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index c2facf299..068639395 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -386,6 +386,16 @@ struct ble_hs_cfg; #define BLE_GATT_CHR_BT_SIG_DESC_INTERNAL 0x010F #define BLE_GATT_CHR_BT_SIG_DESC_EXTERNAL 0x0110 +/*** @server. */ +/** Represents one notification tuple in a multi notification PDU */ +struct ble_gatt_notif { + /** The attribute handle on which to notify. */ + uint16_t handle; + + /** The notification value. */ + struct os_mbuf * value; +}; + /*** @client. */ /** Represents a GATT error. */ struct ble_gatt_error { @@ -851,6 +861,33 @@ int ble_gattc_write_reliable(uint16_t conn_handle, int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t att_handle, struct os_mbuf *om); +/** + * Sends a "free-form" multiple handle variable length characteristic + * notification. This function consumes supplied mbufs regardless of the + * outcome. Notifications are sent in order of supplied entries. + * Function tries to send minimum amount of PDUs. If PDU can't contain all + * of the characteristic values, multiple notifications are sent. If only one + * handle-value pair fits into PDU, or only one characteristic remains in the + * list, regular characteristic notification is sent. + * + * If GATT client doesn't support receiving multiple handle notifications, + * this will use GATT notification for each characteristic, separately. + * + * If value of characteristic is not specified it will be read from local + * GATT database. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param chr_count Number of characteristics to notify about. + * @param tuples Handle-value pairs in form of `ble_gatt_notif` + * structures. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gatts_notify_multiple_custom(uint16_t conn_handle, + size_t chr_count, + struct ble_gatt_notif *tuples); + /** * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. */ diff --git a/nimble/host/pkg.yml b/nimble/host/pkg.yml index c069283cf..cab496cae 100644 --- a/nimble/host/pkg.yml +++ b/nimble/host/pkg.yml @@ -41,6 +41,9 @@ pkg.deps.BLE_SM_SC: pkg.deps.BLE_MESH: - nimble/host/mesh +pkg.deps.BLE_EATT_CHAN_NUM: + - nimble/host/services/gatt + pkg.req_apis: - ble_transport - console diff --git a/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h b/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h index a035f9a12..bb0a415bb 100644 --- a/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h +++ b/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h @@ -29,7 +29,7 @@ extern "C" { struct ble_hs_cfg; -#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 +#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 #define BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16 0x2b3a #define BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16 0x2b29 diff --git a/nimble/host/services/gatt/src/ble_svc_gatt.c b/nimble/host/services/gatt/src/ble_svc_gatt.c index f32b72944..9061ad327 100644 --- a/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -232,4 +232,20 @@ ble_svc_gatt_init(void) rc = ble_gatts_add_svcs(ble_svc_gatt_defs); SYSINIT_PANIC_ASSERT(rc == 0); + + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0) { + ble_svc_gatt_local_srv_sup_feat |= (1 << BLE_SVC_GATT_SRV_SUP_FEAT_EATT_BIT); + } + + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT); + } + + if (MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT); + } + + if (MYNEWT_VAL(BLE_GATT_CACHING) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_ROBUST_CATCHING_BIT); + } } diff --git a/nimble/host/src/ble_att.c b/nimble/host/src/ble_att.c index 91e770808..9614efffb 100644 --- a/nimble/host/src/ble_att.c +++ b/nimble/host/src/ble_att.c @@ -35,7 +35,7 @@ static uint16_t ble_att_preferred_mtu_val; /** Dispatch table for incoming ATT requests. Sorted by op code. */ -typedef int ble_att_rx_fn(uint16_t conn_handle, struct os_mbuf **om); +typedef int ble_att_rx_fn(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om); struct ble_att_rx_dispatch_entry { uint8_t bde_op; ble_att_rx_fn *bde_fn; @@ -71,6 +71,7 @@ static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = { { 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 }, { BLE_ATT_OP_SIGNED_WRITE_CMD, ble_att_svr_rx_signed_write }, }; @@ -132,6 +133,8 @@ STATS_NAME_START(ble_att_stats) STATS_NAME(ble_att_stats, indicate_req_tx) STATS_NAME(ble_att_stats, indicate_rsp_rx) STATS_NAME(ble_att_stats, indicate_rsp_tx) + STATS_NAME(ble_att_stats, multi_notify_req_rx) + STATS_NAME(ble_att_stats, multi_notify_req_tx) STATS_NAME(ble_att_stats, write_cmd_rx) STATS_NAME(ble_att_stats, write_cmd_tx) STATS_NAME_END(ble_att_stats) @@ -157,13 +160,21 @@ ble_att_rx_dispatch_entry_find(uint8_t op) } int -ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, +ble_att_conn_chan_find(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan) { - return ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, + return ble_hs_misc_conn_chan_find(conn_handle, cid, out_conn, out_chan); } +int +ble_att_conn_chan_find_by_psm(uint16_t conn_handle, uint16_t psm, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan) +{ + return ble_hs_misc_conn_chan_find(conn_handle, psm, out_conn, out_chan); +} + void ble_att_inc_tx_stat(uint8_t att_op) { @@ -272,6 +283,10 @@ ble_att_inc_tx_stat(uint8_t att_op) STATS_INC(ble_att_stats, indicate_rsp_tx); break; + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + STATS_INC(ble_att_stats, multi_notify_req_tx); + break; + case BLE_ATT_OP_WRITE_CMD: STATS_INC(ble_att_stats, write_cmd_tx); break; @@ -389,6 +404,10 @@ ble_att_inc_rx_stat(uint8_t att_op) STATS_INC(ble_att_stats, indicate_rsp_rx); break; + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + STATS_INC(ble_att_stats, multi_notify_req_rx); + break; + case BLE_ATT_OP_WRITE_CMD: STATS_INC(ble_att_stats, write_cmd_rx); break; @@ -413,7 +432,7 @@ ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, } uint16_t -ble_att_mtu(uint16_t conn_handle) +ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; @@ -422,7 +441,7 @@ ble_att_mtu(uint16_t conn_handle) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, &conn, &chan); if (rc == 0) { mtu = ble_att_chan_mtu(chan); } else { @@ -434,6 +453,12 @@ ble_att_mtu(uint16_t conn_handle) return mtu; } +uint16_t +ble_att_mtu(uint16_t conn_handle) +{ + return ble_att_mtu_by_cid(conn_handle, BLE_L2CAP_CID_ATT); +} + void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu) { @@ -449,6 +474,16 @@ ble_att_chan_mtu(const struct ble_l2cap_chan *chan) { uint16_t mtu; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (chan->psm == BLE_EATT_PSM) { + /* The ATT_MTU for the Enhanced ATT bearer shall be set to the minimum of the + * MTU field values of the two devices. Reference: + * Core v5.4 Vol 3 Part G 5.3.1 ATT_MTU + */ + return min(chan->coc_tx.mtu, chan->coc_rx.mtu); + } +#endif + /* If either side has not exchanged MTU size, use the default. Otherwise, * use the lesser of the two exchanged values. */ @@ -467,7 +502,7 @@ ble_att_chan_mtu(const struct ble_l2cap_chan *chan) static void ble_att_rx_handle_unknown_request(uint8_t op, uint16_t conn_handle, - struct os_mbuf **om) + uint16_t cid, struct os_mbuf **om) { /* If this is command (bit6 is set to 1), do nothing */ if (op & 0x40) { @@ -475,27 +510,37 @@ ble_att_rx_handle_unknown_request(uint8_t op, uint16_t conn_handle, } os_mbuf_adj(*om, OS_MBUF_PKTLEN(*om)); - ble_att_svr_tx_error_rsp(conn_handle, *om, op, 0, + ble_att_svr_tx_error_rsp(conn_handle, cid, *om, op, 0, BLE_ATT_ERR_REQ_NOT_SUPPORTED); *om = NULL; } +static void +ble_att_send_outstanding_after_response(uint16_t conn_handle) +{ + struct ble_hs_conn *conn; + struct ble_l2cap_chan *chan; + int rc; + + ble_hs_lock(); + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, + &chan); + if (rc) { + return; + } + conn->client_att_busy = false; + ble_att_tx_with_conn(conn, chan, NULL); + ble_hs_unlock(); +} + static int -ble_att_rx(struct ble_l2cap_chan *chan) +ble_att_rx_extended(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om) { const struct ble_att_rx_dispatch_entry *entry; uint8_t op; - uint16_t conn_handle; - struct os_mbuf **om; int rc; - conn_handle = ble_l2cap_get_conn_handle(chan); - if (conn_handle == BLE_HS_CONN_HANDLE_NONE) { - return BLE_HS_ENOTCONN; - } - - om = &chan->rx_buf; BLE_HS_DBG_ASSERT(*om != NULL); rc = os_mbuf_copydata(*om, 0, 1, &op); @@ -503,9 +548,13 @@ ble_att_rx(struct ble_l2cap_chan *chan) return BLE_HS_EMSGSIZE; } + if (cid == BLE_L2CAP_CID_ATT && ble_att_is_response_op(op)) { + ble_att_send_outstanding_after_response(conn_handle); + } + entry = ble_att_rx_dispatch_entry_find(op); if (entry == NULL) { - ble_att_rx_handle_unknown_request(op, conn_handle, om); + ble_att_rx_handle_unknown_request(op, conn_handle, cid, om); return BLE_HS_ENOTSUP; } @@ -514,10 +563,10 @@ ble_att_rx(struct ble_l2cap_chan *chan) /* Strip L2CAP ATT header from the front of the mbuf. */ os_mbuf_adj(*om, 1); - rc = entry->bde_fn(conn_handle, om); + rc = entry->bde_fn(conn_handle, cid, om); if (rc != 0) { if (rc == BLE_HS_ENOTSUP) { - ble_att_rx_handle_unknown_request(op, conn_handle, om); + ble_att_rx_handle_unknown_request(op, conn_handle, cid, om); } return rc; } @@ -525,6 +574,19 @@ ble_att_rx(struct ble_l2cap_chan *chan) return 0; } +static int +ble_att_rx(struct ble_l2cap_chan *chan) +{ + uint16_t conn_handle; + + conn_handle = ble_l2cap_get_conn_handle(chan); + if (conn_handle == BLE_HS_CONN_HANDLE_NONE) { + return BLE_HS_ENOTCONN; + } + + return ble_att_rx_extended(conn_handle, chan->scid, &chan->rx_buf); +} + uint16_t ble_att_preferred_mtu(void) { @@ -585,6 +647,102 @@ ble_att_create_chan(uint16_t conn_handle) return chan; } +bool +ble_att_is_request_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_MTU_REQ: + case BLE_ATT_OP_FIND_INFO_REQ: + case BLE_ATT_OP_FIND_TYPE_VALUE_REQ: + case BLE_ATT_OP_READ_TYPE_REQ: + case BLE_ATT_OP_READ_REQ: + case BLE_ATT_OP_READ_BLOB_REQ: + case BLE_ATT_OP_READ_MULT_REQ: + case BLE_ATT_OP_READ_GROUP_TYPE_REQ: + case BLE_ATT_OP_WRITE_REQ: + case BLE_ATT_OP_PREP_WRITE_REQ: + case BLE_ATT_OP_EXEC_WRITE_REQ: + case BLE_ATT_OP_INDICATE_REQ: + case BLE_ATT_OP_READ_MULT_VAR_REQ: + return true; + } + return false; +} + +bool +ble_att_is_response_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_MTU_RSP: + case BLE_ATT_OP_ERROR_RSP: + case BLE_ATT_OP_FIND_INFO_RSP: + case BLE_ATT_OP_FIND_TYPE_VALUE_RSP: + case BLE_ATT_OP_READ_TYPE_RSP: + case BLE_ATT_OP_INDICATE_RSP: + case BLE_ATT_OP_READ_RSP: + case BLE_ATT_OP_READ_BLOB_RSP: + case BLE_ATT_OP_READ_MULT_RSP: + case BLE_ATT_OP_READ_GROUP_TYPE_RSP: + case BLE_ATT_OP_WRITE_RSP: + case BLE_ATT_OP_PREP_WRITE_RSP: + case BLE_ATT_OP_EXEC_WRITE_RSP: + case BLE_ATT_OP_READ_MULT_VAR_RSP: + return true; + } + + return false; +} + +bool +ble_att_is_att_pdu_op(uint8_t opcode) +{ + if (ble_att_is_request_op(opcode)) { + return true; + } + + if (ble_att_is_response_op(opcode)) { + return true; + } + + switch (opcode) { + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + case BLE_ATT_OP_WRITE_CMD: + case BLE_ATT_OP_SIGNED_WRITE_CMD: + case BLE_ATT_OP_NOTIFY_REQ: + return true; + } + return false; +} + +int +ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid) { +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_hs_conn * conn; + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return BLE_HS_ENOTCONN; + } + conn->default_cid = cid; + return 0; +#endif + return BLE_HS_ENOTSUP; +} + +uint16_t +ble_att_get_default_bearer_cid(uint16_t conn_handle) { +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_hs_conn * conn; + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return 0; + } + return conn->default_cid; +#endif + return 0; +} + int ble_att_init(void) { @@ -599,6 +757,8 @@ ble_att_init(void) return BLE_HS_EOS; } + ble_eatt_init(ble_att_rx_extended); + return 0; } diff --git a/nimble/host/src/ble_att_clt.c b/nimble/host/src/ble_att_clt.c index 2b62e27b8..dd11a9a5c 100644 --- a/nimble/host/src/ble_att_clt.c +++ b/nimble/host/src/ble_att_clt.c @@ -37,7 +37,7 @@ *****************************************************************************/ int -ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_error(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_error_rsp *rsp; int rc; @@ -49,7 +49,7 @@ ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom) rsp = (struct ble_att_error_rsp *)(*rxom)->om_data; - ble_gattc_rx_err(conn_handle, le16toh(rsp->baep_handle), + ble_gattc_rx_err(conn_handle, cid, le16toh(rsp->baep_handle), le16toh(rsp->baep_error_code)); return 0; @@ -74,7 +74,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc != 0) { rc = BLE_HS_ENOTCONN; } else if (chan->flags & BLE_L2CAP_CHAN_F_TXED_MTU) { @@ -95,14 +95,14 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) req->bamc_mtu = htole16(mtu); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, BLE_L2CAP_CID_ATT, txom); if (rc != 0) { return rc; } ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc == 0) { chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU; } @@ -113,7 +113,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) } int -ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_mtu_cmd *cmd; struct ble_l2cap_chan *chan; @@ -122,13 +122,19 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) mtu = 0; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (cid != BLE_L2CAP_CID_ATT) { + return BLE_HS_ENOTSUP; + } +#endif + rc = ble_hs_mbuf_pullup_base(rxom, sizeof(*cmd)); if (rc == 0) { cmd = (struct ble_att_mtu_cmd *)(*rxom)->om_data; ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, NULL, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, NULL, &chan); if (rc == 0) { ble_att_set_peer_mtu(chan, le16toh(cmd->bamc_mtu)); mtu = ble_att_chan_mtu(chan); @@ -141,7 +147,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) } } - ble_gattc_rx_mtu(conn_handle, rc, mtu); + ble_gattc_rx_mtu(conn_handle, BLE_L2CAP_CID_ATT, rc, mtu); return rc; } @@ -150,7 +156,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, +ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO @@ -172,7 +178,7 @@ ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, req->bafq_start_handle = htole16(start_handle); req->bafq_end_handle = htole16(end_handle); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -227,7 +233,7 @@ ble_att_clt_parse_find_info_entry(struct os_mbuf **rxom, uint8_t rsp_format, } int -ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) +ble_att_clt_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO return BLE_HS_ENOTSUP; @@ -254,14 +260,14 @@ ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) } /* Hand find-info entry to GATT. */ - ble_gattc_rx_find_info_idata(conn_handle, &idata); + ble_gattc_rx_find_info_idata(conn_handle, cid, &idata); } rc = 0; done: /* Notify GATT that response processing is done. */ - ble_gattc_rx_find_info_complete(conn_handle, rc); + ble_gattc_rx_find_info_complete(conn_handle, cid, rc); return rc; } @@ -274,8 +280,9 @@ done: * anyway */ int -ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, uint16_t attribute_type, +ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t cid, + uint16_t start_handle, uint16_t end_handle, + uint16_t attribute_type, const void *attribute_value, int value_len) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE @@ -300,7 +307,7 @@ ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, req->bavq_attr_type = htole16(attribute_type); memcpy(req->bavq_value, attribute_value, value_len); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -326,7 +333,7 @@ ble_att_clt_parse_find_type_value_hinfo( } int -ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE return BLE_HS_ENOTSUP; @@ -343,11 +350,11 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) break; } - ble_gattc_rx_find_type_value_hinfo(conn_handle, &hinfo); + ble_gattc_rx_find_type_value_hinfo(conn_handle, cid, &hinfo); } /* Notify GATT client that the full response has been parsed. */ - ble_gattc_rx_find_type_value_complete(conn_handle, rc); + ble_gattc_rx_find_type_value_complete(conn_handle, cid, rc); return 0; } @@ -357,7 +364,7 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, +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) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE @@ -382,11 +389,11 @@ ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, ble_uuid_flat(uuid, req->uuid); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } int -ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE return BLE_HS_ENOTSUP; @@ -428,13 +435,13 @@ ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) adata.value_len = data_len - sizeof(*data); adata.value = data->value; - ble_gattc_rx_read_type_adata(conn_handle, &adata); + ble_gattc_rx_read_type_adata(conn_handle, cid, &adata); os_mbuf_adj(*rxom, data_len); } done: /* Notify GATT that the response is done being parsed. */ - ble_gattc_rx_read_type_complete(conn_handle, rc); + ble_gattc_rx_read_type_complete(conn_handle, cid, rc); return rc; } @@ -444,7 +451,7 @@ done: *****************************************************************************/ int -ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) +ble_att_clt_tx_read(uint16_t conn_handle, uint16_t cid, uint16_t handle) { #if !NIMBLE_BLE_ATT_CLT_READ return BLE_HS_ENOTSUP; @@ -465,7 +472,7 @@ ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) req->barq_handle = htole16(handle); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -474,14 +481,14 @@ ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) } int -ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_rsp(conn_handle, cid, 0, rxom); return 0; } @@ -490,7 +497,7 @@ ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) +ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB return BLE_HS_ENOTSUP; @@ -512,7 +519,7 @@ ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) req->babq_handle = htole16(handle); req->babq_offset = htole16(offset); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -521,14 +528,14 @@ 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) +ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_blob_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_blob_rsp(conn_handle, cid, 0, rxom); return 0; } @@ -536,8 +543,8 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) * $read multiple * *****************************************************************************/ int -ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, - int num_handles, bool variable) +ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, + const uint16_t *handles, int num_handles, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; @@ -565,30 +572,30 @@ ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, req->handles[i] = htole16(handles[i]); } - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } int -ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, false); + 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, struct os_mbuf **rxom) +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, 0, rxom, true); + ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom, true); return 0; } @@ -597,7 +604,7 @@ ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_group_type(uint16_t conn_handle, +ble_att_clt_tx_read_group_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid) { @@ -622,7 +629,7 @@ ble_att_clt_tx_read_group_type(uint16_t conn_handle, req->bagq_end_handle = htole16(end_handle); ble_uuid_flat(uuid, req->uuid); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -650,7 +657,7 @@ ble_att_clt_parse_read_group_type_adata( } int -ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE return BLE_HS_ENOTSUP; @@ -680,13 +687,13 @@ ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - ble_gattc_rx_read_group_type_adata(conn_handle, &adata); + ble_gattc_rx_read_group_type_adata(conn_handle, cid, &adata); os_mbuf_adj(*rxom, len); } done: /* Notify GATT that the response is done being parsed. */ - ble_gattc_rx_read_group_type_complete(conn_handle, rc); + ble_gattc_rx_read_group_type_complete(conn_handle, cid, rc); return rc; } @@ -695,7 +702,7 @@ done: *****************************************************************************/ int -ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, +ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t cid, uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_WRITE @@ -714,12 +721,12 @@ ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, req->bawq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); } int -ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom) +ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP return BLE_HS_ENOTSUP; @@ -753,24 +760,24 @@ ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, cmd->handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); } int -ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_WRITE return BLE_HS_ENOTSUP; #endif /* No payload. */ - ble_gattc_rx_write_rsp(conn_handle); + ble_gattc_rx_write_rsp(conn_handle, cid); return 0; } int -ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t *csrk, - uint32_t counter, struct os_mbuf *txom) +ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t cid, uint16_t handle, + uint8_t *csrk, uint32_t counter, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_SIGNED_WRITE return BLE_HS_ENOTSUP; @@ -856,7 +863,7 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * if(message != NULL) nimble_platform_mem_free(message); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: if(message != NULL) nimble_platform_mem_free(message); os_mbuf_free_chain(txom2); @@ -868,7 +875,7 @@ err: *****************************************************************************/ int -ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, +ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_PREP_WRITE @@ -897,7 +904,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, #endif if (OS_MBUF_PKTLEN(txom) > - ble_att_mtu(conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) { + ble_att_mtu_by_cid(conn_handle, cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) { rc = BLE_HS_EINVAL; goto err; } @@ -912,7 +919,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, req->bapc_offset = htole16(offset); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: os_mbuf_free_chain(txom); @@ -920,7 +927,7 @@ err: } int -ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_PREP_WRITE return BLE_HS_ENOTSUP; @@ -949,7 +956,7 @@ ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) done: /* Notify GATT client that the full response has been parsed. */ - ble_gattc_rx_prep_write_rsp(conn_handle, rc, handle, offset, rxom); + ble_gattc_rx_prep_write_rsp(conn_handle, cid, rc, handle, offset, rxom); return rc; } @@ -958,7 +965,7 @@ done: *****************************************************************************/ int -ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) +ble_att_clt_tx_exec_write(uint16_t conn_handle, uint16_t cid, uint8_t flags) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return BLE_HS_ENOTSUP; @@ -975,7 +982,7 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) req->baeq_flags = flags; - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -984,13 +991,13 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) } int -ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return BLE_HS_ENOTSUP; #endif - ble_gattc_rx_exec_write_rsp(conn_handle, 0); + ble_gattc_rx_exec_write_rsp(conn_handle, cid, 0); return 0; } @@ -1008,6 +1015,7 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, struct ble_att_notify_req *req; struct os_mbuf *txom2; + uint16_t cid; int rc; if (handle == 0) { @@ -1024,7 +1032,10 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, req->banq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_tx(conn_handle, cid, txom2); + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); + return rc; err: os_mbuf_free_chain(txom); @@ -1036,8 +1047,8 @@ err: *****************************************************************************/ int -ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom) +ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return BLE_HS_ENOTSUP; @@ -1061,7 +1072,7 @@ ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, req->baiq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: os_mbuf_free_chain(txom); @@ -1069,15 +1080,47 @@ err: } int -ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return BLE_HS_ENOTSUP; #endif /* No payload. */ - ble_gatts_rx_indicate_rsp(conn_handle); + ble_gatts_rx_indicate_rsp(conn_handle, cid); return 0; } +/***************************************************************************** +* $multiple handle value notification * +*****************************************************************************/ + +int +ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct os_mbuf *txom) +{ +#if !NIMBLE_BLE_ATT_CLT_NOTIFY_MULT + return BLE_HS_ENOTSUP; +#endif + + struct os_mbuf *txom2; + uint16_t cid; + int rc; + + if (ble_att_cmd_get(BLE_ATT_OP_NOTIFY_MULTI_REQ, 0, &txom2) == NULL) { + return BLE_HS_ENOMEM; + goto err; + } + + os_mbuf_concat(txom2, txom); + + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_tx(conn_handle, cid, txom2); + if (cid != BLE_L2CAP_CID_ATT) { + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); + } + +err: + return rc; +} + #endif diff --git a/nimble/host/src/ble_att_cmd.c b/nimble/host/src/ble_att_cmd.c index 6669392f1..159df9801 100644 --- a/nimble/host/src/ble_att_cmd.c +++ b/nimble/host/src/ble_att_cmd.c @@ -55,28 +55,67 @@ ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom) } int -ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom) +ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, struct os_mbuf *txom) +{ + int rc; + struct os_mbuf_pkthdr *omp; + + if (!txom) { + if (conn->client_att_busy) { + return 0; + } + omp = STAILQ_FIRST(&conn->att_tx_q); + if (omp == NULL) { + return 0; + } + STAILQ_REMOVE_HEAD(&conn->att_tx_q, omp_next); + txom = OS_MBUF_PKTHDR_TO_MBUF(omp); + BLE_EATT_LOG_DEBUG("%s: wakeup will send %p\n", __func__, txom); + } + + BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1); + + if (ble_att_is_request_op(txom->om_data[0])) { + if (conn->client_att_busy) { + BLE_EATT_LOG_DEBUG("ATT Queue %p, client busy %d\n", txom, conn->client_att_busy); + STAILQ_INSERT_TAIL(&conn->att_tx_q, OS_MBUF_PKTHDR(txom), omp_next); + return 0; + } + conn->client_att_busy = true; + } + + ble_att_inc_tx_stat(txom->om_data[0]); + + ble_att_truncate_to_mtu(chan, txom); + rc = ble_l2cap_tx(conn, chan, txom); + assert(rc == 0); + return rc; +} + +int +ble_att_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; int rc; - BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1); - ble_att_inc_tx_stat(txom->om_data[0]); +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (cid != BLE_L2CAP_CID_ATT) { + return ble_eatt_tx(conn_handle, cid, txom); + } +#endif ble_hs_lock(); - rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc != 0) { + ble_hs_unlock(); os_mbuf_free_chain(txom); - } else { - ble_att_truncate_to_mtu(chan, txom); - rc = ble_l2cap_tx(conn, chan, txom); + return rc; } + rc = ble_att_tx_with_conn(conn, chan, txom); ble_hs_unlock(); - return rc; } diff --git a/nimble/host/src/ble_att_cmd_priv.h b/nimble/host/src/ble_att_cmd_priv.h index 54052a985..f3090d11d 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) | * +------------------------------------+-------------------+ @@ -454,8 +468,15 @@ void ble_att_indicate_rsp_write(void *payload, int len); void *ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom); void *ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); -int ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom); +int ble_att_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom); +struct ble_l2cap_chan; +struct ble_hs_conn; +int ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, + struct os_mbuf *txom); +bool ble_att_is_response_op(uint8_t opcode); +bool ble_att_is_request_op(uint8_t opcode); +bool ble_att_is_att_pdu_op(uint8_t opcode); #ifdef __cplusplus } #endif diff --git a/nimble/host/src/ble_att_priv.h b/nimble/host/src/ble_att_priv.h index 0e723de92..ae8f4b920 100644 --- a/nimble/host/src/ble_att_priv.h +++ b/nimble/host/src/ble_att_priv.h @@ -102,6 +102,8 @@ STATS_SECT_START(ble_att_stats) STATS_SECT_ENTRY(indicate_req_tx) STATS_SECT_ENTRY(indicate_rsp_rx) STATS_SECT_ENTRY(indicate_rsp_tx) + STATS_SECT_ENTRY(multi_notify_req_rx) + STATS_SECT_ENTRY(multi_notify_req_tx) STATS_SECT_ENTRY(write_cmd_rx) STATS_SECT_ENTRY(write_cmd_tx) STATS_SECT_END @@ -171,13 +173,15 @@ SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); /*** @gen */ struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); -int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, +int ble_att_conn_chan_find(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan); void ble_att_inc_tx_stat(uint8_t att_op); void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, struct os_mbuf *txom); void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); +uint16_t ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid); int ble_att_init(void); /*** @svr */ @@ -190,36 +194,38 @@ ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, const ble_uuid_t *uuid, uint16_t end_handle); uint16_t ble_att_svr_prev_handle(void); -int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, ble_npl_time_t now); -int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_find_type_value(uint16_t conn_handle, +int ble_att_svr_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_type(uint16_t conn_handle, +int ble_att_svr_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_group_type(uint16_t conn_handle, +int ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read(uint16_t conn_handle, +int ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_blob(uint16_t conn_handle, +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_var(uint16_t conn_handle, +int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult(uint16_t conn_handle, +int ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_write(uint16_t conn_handle, +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, struct os_mbuf **rxom); -int ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_prep_write(uint16_t conn_handle, +int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_signed_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_exec_write(uint16_t conn_handle, +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, +int ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_indicate(uint16_t conn_handle, +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); int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, @@ -231,7 +237,7 @@ int ble_att_svr_init(void); void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); -int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, +int ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom, uint8_t req_op, uint16_t handle, uint8_t error_code); /*** $clt */ @@ -264,52 +270,56 @@ struct ble_att_read_group_type_adata { uint8_t *value; }; -int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_rx_error(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); -int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); -int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, +int ble_att_clt_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t cid, uint16_t handle); +int ble_att_clt_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +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, struct os_mbuf **rxom); -int ble_att_clt_tx_read_mult(uint16_t conn_handle, +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, 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, +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, struct os_mbuf **rxom); -int ble_att_clt_tx_read_group_type(uint16_t conn_handle, +int ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_group_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid128); -int ble_att_clt_rx_read_group_type(uint16_t conn_handle, +int ble_att_clt_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle); -int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, uint16_t attribute_type, const void *attribute_value, int value_len); -int ble_att_clt_rx_find_type_value(uint16_t conn_handle, +int ble_att_clt_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, - uint16_t offset, struct os_mbuf *txom); -int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); -int ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, - uint8_t * csrk, uint32_t counter, - struct os_mbuf * txom); -int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t cid, + uint16_t handle, uint16_t offset, + struct os_mbuf *txom); +int ble_att_clt_rx_prep_write(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); +int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint16_t cid, + uint8_t flags); +int ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, uint8_t * csrk, + uint32_t counter, struct os_mbuf * txom); +int ble_att_clt_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, struct os_mbuf *txom); -int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct os_mbuf *txom); #ifdef __cplusplus } diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 1dca00f59..977efe565 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -623,7 +623,7 @@ ble_att_svr_write_handle(uint16_t conn_handle, uint16_t attr_handle, } int -ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, +ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom, uint8_t req_op, uint16_t handle, uint8_t error_code) { struct ble_att_error_rsp *rsp; @@ -640,7 +640,7 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, rsp->baep_handle = htole16(handle); rsp->baep_error_code = error_code; - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } /** @@ -667,13 +667,10 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, * field. */ static int -ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, +ble_att_svr_tx_rsp(uint16_t conn_handle, uint16_t cid, int hs_status, struct os_mbuf *om, uint8_t att_op, uint8_t err_status, uint16_t err_handle) { - struct ble_l2cap_chan *chan; - struct ble_hs_conn *conn; int do_tx; - int rc; if (hs_status != 0 && err_status == 0) { /* Processing failed, but err_status of 0 means don't send error. */ @@ -683,28 +680,14 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, } if (do_tx) { - ble_hs_lock(); - - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); - if (rc != 0) { - /* No longer connected. */ - hs_status = rc; - } else { - if (hs_status == 0) { - BLE_HS_DBG_ASSERT(om != NULL); - - ble_att_inc_tx_stat(om->om_data[0]); - ble_att_truncate_to_mtu(chan, om); - hs_status = ble_l2cap_tx(conn, chan, om); - om = NULL; - if (hs_status != 0) { - err_status = BLE_ATT_ERR_UNLIKELY; - } - } + if (hs_status == 0) { + hs_status = ble_att_tx(conn_handle, cid, om); + om = NULL; + if (hs_status) { + err_status = BLE_ATT_ERR_UNLIKELY; + } } - ble_hs_unlock(); - if (hs_status != 0) { STATS_INC(ble_att_stats, error_rsp_tx); @@ -715,7 +698,7 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, os_mbuf_adj(om, OS_MBUF_PKTLEN(om)); } if (om != NULL) { - ble_att_svr_tx_error_rsp(conn_handle, om, att_op, + ble_att_svr_tx_error_rsp(conn_handle, cid, om, att_op, err_handle, err_status); om = NULL; } @@ -742,7 +725,7 @@ ble_att_svr_build_mtu_rsp(uint16_t conn_handle, struct os_mbuf **rxom, txom = NULL; ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, NULL, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, NULL, &chan); if (rc == 0) { mtu = chan->my_mtu; } @@ -774,7 +757,7 @@ done: } int -ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_mtu_cmd *cmd; struct ble_l2cap_chan *chan; @@ -787,6 +770,10 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) txom = NULL; mtu = 0; + if (cid != BLE_L2CAP_CID_ATT) { + return BLE_HS_ENOTSUP; + } + rc = ble_att_svr_pullup_req_base(rxom, sizeof(*cmd), &att_err); if (rc != 0) { goto done; @@ -804,12 +791,12 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_MTU_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, BLE_L2CAP_CID_ATT, rc, txom, BLE_ATT_OP_MTU_REQ, att_err, 0); if (rc == 0) { ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc == 0) { ble_att_set_peer_mtu(chan, mtu); chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU; @@ -908,7 +895,7 @@ done: } static int -ble_att_svr_build_find_info_rsp(uint16_t conn_handle, +ble_att_svr_build_find_info_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, struct os_mbuf **rxom, struct os_mbuf **out_txom, @@ -937,7 +924,7 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle, /* Write the variable length Information Data field, populating the format * field as appropriate. */ - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_fill_info(start_handle, end_handle, txom, mtu, &rsp->bafp_format); if (rc != 0) { @@ -954,7 +941,7 @@ done: } int -ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_FIND_INFO) return BLE_HS_ENOTSUP; @@ -991,7 +978,7 @@ ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - rc = ble_att_svr_build_find_info_rsp(conn_handle, + rc = ble_att_svr_build_find_info_rsp(conn_handle, cid, start_handle, end_handle, rxom, &txom, &att_err); if (rc != 0) { @@ -1002,7 +989,7 @@ ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_FIND_INFO_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_FIND_INFO_REQ, att_err, err_handle); return rc; } @@ -1217,7 +1204,7 @@ done: } static int -ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, +ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, ble_uuid16_t attr_type, @@ -1244,7 +1231,7 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, } /* Write the variable length Information Data field. */ - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_fill_type_value(conn_handle, start_handle, end_handle, attr_type, *rxom, txom, mtu, @@ -1261,7 +1248,7 @@ done: } int -ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_FIND_TYPE) return BLE_HS_ENOTSUP; @@ -1299,7 +1286,7 @@ ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) rc = BLE_HS_EBADDATA; goto done; } - rc = ble_att_svr_build_find_type_value_rsp(conn_handle, start_handle, + rc = ble_att_svr_build_find_type_value_rsp(conn_handle, cid, start_handle, end_handle, attr_type, rxom, &txom, &att_err); if (rc != 0) { @@ -1310,7 +1297,7 @@ ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_FIND_TYPE_VALUE_REQ, att_err, err_handle); return rc; @@ -1348,7 +1335,7 @@ static uint8_t * ble_att_svr_get_csfs(uint16_t conn_handle) { #endif static int -ble_att_svr_build_read_type_rsp(uint16_t conn_handle, +ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid, struct os_mbuf **rxom, @@ -1391,7 +1378,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, goto done; } - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); /* Find all matching attributes, writing a record for each. */ entry = NULL; @@ -1463,7 +1450,7 @@ done: } int -ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_TYPE) return BLE_HS_ENOTSUP; @@ -1524,7 +1511,7 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } #endif - rc = ble_att_svr_build_read_type_rsp(conn_handle, start_handle, end_handle, + rc = ble_att_svr_build_read_type_rsp(conn_handle, cid, start_handle, end_handle, &uuid.u, rxom, &txom, &att_err, &err_handle); if (rc != 0) { @@ -1534,13 +1521,13 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_TYPE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_TYPE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ) return BLE_HS_ENOTSUP; @@ -1597,13 +1584,13 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) } done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_BLOB) return BLE_HS_ENOTSUP; @@ -1665,13 +1652,13 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_BLOB_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_BLOB_REQ, att_err, err_handle); return rc; } static int -ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, +ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom, struct os_mbuf **out_txom, uint8_t *att_err, @@ -1682,7 +1669,7 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, uint16_t mtu; int rc; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_pkt(rxom, &txom, att_err); if (rc != 0) { @@ -1732,7 +1719,7 @@ done: } int -ble_att_svr_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) return BLE_HS_ENOTSUP; @@ -1763,18 +1750,18 @@ ble_att_svr_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_mult_rsp(conn_handle, rxom, &txom, &att_err, + rc = ble_att_svr_build_read_mult_rsp(conn_handle, cid, rxom, &txom, &att_err, &err_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) done : #endif - return ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_MULT_REQ, + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_MULT_REQ, att_err, err_handle); } static int -ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, +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, @@ -1787,7 +1774,7 @@ ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, struct os_mbuf *tmp = NULL; int rc; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_pkt(rxom, &txom, att_err); if (rc != 0) { @@ -1856,7 +1843,7 @@ done: } int -ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) +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) return BLE_HS_ENOTSUP; @@ -1887,13 +1874,13 @@ ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, rxom, &txom, &att_err, + rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, cid, rxom, &txom, &att_err, &err_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) done: #endif - return ble_att_svr_tx_rsp(conn_handle, rc, txom, + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_MULT_VAR_REQ, att_err, err_handle); } @@ -1962,7 +1949,7 @@ ble_att_svr_read_group_type_entry_write(struct os_mbuf *om, uint16_t mtu, * @return 0 on success; BLE_HS error code on failure. */ static int -ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, +ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *group_uuid, @@ -1992,7 +1979,7 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, entry = NULL; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); /* Just reuse the request buffer for the response. */ txom = *rxom; @@ -2134,7 +2121,7 @@ done: } int -ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_GROUP_TYPE) return BLE_HS_ENOTSUP; @@ -2203,9 +2190,10 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - rc = ble_att_svr_build_read_group_type_rsp(conn_handle, start_handle, - end_handle, &uuid.u, - rxom, &txom, &att_err, + rc = ble_att_svr_build_read_group_type_rsp(conn_handle, cid, + start_handle, end_handle, + &uuid.u, rxom, + &txom, &att_err, &err_handle); if (rc != 0) { goto done; @@ -2214,7 +2202,7 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_GROUP_TYPE_REQ, att_err, err_handle); return rc; @@ -2249,7 +2237,7 @@ done: } int -ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_WRITE) return BLE_HS_ENOTSUP; @@ -2309,13 +2297,13 @@ ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_WRITE_REQ, att_err, handle); return rc; } int -ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_WRITE_NO_RSP) return BLE_HS_ENOTSUP; @@ -2352,9 +2340,9 @@ ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom) } int -ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_signed_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { -#if !MYNEWT_VAL(BLE_ATT_SVR_SIGNED_WRITE) +#if !MYNEWT_VAL(BLE_ATT_SVR_SIGNED_WRITE) || MYNEWT_VAL(BLE_EATT_CHAN_NUM) return BLE_HS_ENOTSUP; #endif @@ -2727,7 +2715,7 @@ ble_att_svr_insert_prep_entry(uint16_t conn_handle, } int -ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) return BLE_HS_ENOTSUP; @@ -2817,13 +2805,13 @@ ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) return BLE_HS_ENOTSUP; @@ -2907,13 +2895,13 @@ done: ble_att_svr_prep_clear(&prep_list); } - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_NOTIFY) return BLE_HS_ENOTSUP; @@ -2955,6 +2943,67 @@ ble_att_svr_rx_notify(uint16_t conn_handle, 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 = 0; + 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) { + BLE_HS_LOG_ERROR("attr length (%d) > max (%d)", + attr_len, BLE_ATT_ATTR_MAX_LEN); + rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + goto done; + } + + tmp = os_msys_get_pkthdr(attr_len, 0); + if (!tmp) { + BLE_HS_LOG_ERROR("not enough resources, aborting"); + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + goto done; + } + + rc = os_mbuf_appendfrom(tmp, *rxom, 0, attr_len); + if (rc) { + BLE_HS_LOG_ERROR("not enough resources, aborting"); + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + goto done; + } + + ble_gap_notify_rx_event(conn_handle, handle, tmp, 0); + + os_mbuf_adj(*rxom, attr_len); + pkt_len = OS_MBUF_PKTLEN(*rxom); + } +done: + os_mbuf_free_chain(*rxom); + *rxom = NULL; + + return rc; +} + /** * @return 0 on success; nonzero on failure. */ @@ -2988,7 +3037,7 @@ done: } int -ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_INDICATE) return BLE_HS_ENOTSUP; @@ -3046,7 +3095,7 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_INDICATE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_INDICATE_REQ, att_err, handle); return rc; } diff --git a/nimble/host/src/ble_eatt.c b/nimble/host/src/ble_eatt.c new file mode 100644 index 000000000..3e27ae5c1 --- /dev/null +++ b/nimble/host/src/ble_eatt.c @@ -0,0 +1,601 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "syscfg/syscfg.h" + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + +#include +#include +#include "host/ble_hs_log.h" +#include "ble_att_cmd_priv.h" +#include "ble_hs_priv.h" +#include "ble_l2cap_priv.h" +#include "ble_eatt_priv.h" +#include "services/gatt/ble_svc_gatt.h" + +struct ble_eatt { + SLIST_ENTRY(ble_eatt) next; + uint16_t conn_handle; + struct ble_l2cap_chan *chan; + uint8_t client_op; + + /* Packet transmit queue */ + STAILQ_HEAD(, os_mbuf_pkthdr) eatt_tx_q; + + struct ble_npl_event setup_ev; + struct ble_npl_event wakeup_ev; +}; + +SLIST_HEAD(ble_eatt_list, ble_eatt); + +static struct ble_eatt_list g_ble_eatt_list; +static ble_eatt_att_rx_fn ble_eatt_att_rx_cb; + +#define BLE_EATT_DATABUF_SIZE ( \ + MYNEWT_VAL(BLE_EATT_MTU) + \ + 2 + \ + sizeof (struct os_mbuf_pkthdr) + \ + sizeof (struct os_mbuf)) + +#define BLE_EATT_MEMBLOCK_SIZE \ + (OS_ALIGN(BLE_EATT_DATABUF_SIZE, 4)) + +#define BLE_EATT_MEMPOOL_SIZE \ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1, BLE_EATT_MEMBLOCK_SIZE) +static os_membuf_t ble_eatt_conn_mem[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_EATT_CHAN_NUM), + sizeof(struct ble_eatt)) +]; +static struct os_mempool ble_eatt_conn_pool; +static os_membuf_t ble_eatt_sdu_coc_mem[BLE_EATT_MEMPOOL_SIZE]; +struct os_mbuf_pool ble_eatt_sdu_os_mbuf_pool; +static struct os_mempool ble_eatt_sdu_mbuf_mempool; + +static struct ble_gap_event_listener ble_eatt_listener; + +static struct ble_npl_event g_read_sup_cl_feat_ev; +static struct ble_npl_event g_read_sup_srv_feat_ev; + +static void ble_eatt_setup_cb(struct ble_npl_event *ev); +static void ble_eatt_start(uint16_t conn_handle); + +static struct ble_eatt * +ble_eatt_find_not_busy(uint16_t conn_handle) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if ((eatt->conn_handle == conn_handle) && !eatt->client_op && eatt->chan) { + return eatt; + } + } + return NULL; +} + +static struct ble_eatt * +ble_eatt_find_by_conn_handle(uint16_t conn_handle) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if (eatt->conn_handle == conn_handle) { + return eatt; + } + } + return NULL; + +} + +static struct ble_eatt * +ble_eatt_find_by_conn_handle_and_busy_op(uint16_t conn_handle, uint8_t op) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if (eatt->conn_handle == conn_handle && eatt->client_op == op) { + return eatt; + } + } + return NULL; + +} + +static struct ble_eatt * +ble_eatt_find(uint16_t conn_handle, uint16_t cid) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if ((eatt->conn_handle == conn_handle) && + (eatt->chan) && + (eatt->chan->scid == cid)) { + return eatt; + } + } + return NULL; + +} + +static int +ble_eatt_prepare_rx_sdu(struct ble_l2cap_chan *chan) +{ + int rc; + struct os_mbuf *om; + + om = os_mbuf_get_pkthdr(&ble_eatt_sdu_os_mbuf_pool, 0); + if (!om) { + BLE_EATT_LOG_ERROR("eatt: no memory for sdu\n"); + return BLE_HS_ENOMEM; + } + + rc = ble_l2cap_recv_ready(chan, om); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Failed to supply RX SDU conn_handle 0x%04x (status=%d)\n", + chan->conn_handle, rc); + os_mbuf_free_chain(om); + } + return rc; +} + +static void +ble_eatt_wakeup_cb(struct ble_npl_event *ev) +{ + struct ble_eatt *eatt; + struct os_mbuf *txom; + struct os_mbuf_pkthdr *omp; + struct ble_l2cap_chan_info info; + + eatt = ble_npl_event_get_arg(ev); + assert(eatt); + + omp = STAILQ_FIRST(&eatt->eatt_tx_q); + if (omp != NULL) { + STAILQ_REMOVE_HEAD(&eatt->eatt_tx_q, omp_next); + + txom = OS_MBUF_PKTHDR_TO_MBUF(omp); + ble_l2cap_get_chan_info(eatt->chan, &info); + ble_eatt_tx(eatt->conn_handle, info.dcid, txom); + } +} + +static struct ble_eatt * +ble_eatt_alloc(void) +{ + struct ble_eatt *eatt; + + eatt = os_memblock_get(&ble_eatt_conn_pool); + if (eatt) { + SLIST_INSERT_HEAD(&g_ble_eatt_list, eatt, next); + } else { + BLE_EATT_LOG_DEBUG("eatt: Failed to allocate new eatt context\n"); + return NULL; + } + + eatt->conn_handle = BLE_HS_CONN_HANDLE_NONE; + eatt->chan = NULL; + eatt->client_op = 0; + + STAILQ_INIT(&eatt->eatt_tx_q); + ble_npl_event_init(&eatt->setup_ev, ble_eatt_setup_cb, eatt); + ble_npl_event_init(&eatt->wakeup_ev, ble_eatt_wakeup_cb, eatt); + return eatt; +} + +static void +ble_eatt_free(struct ble_eatt *eatt) +{ + struct os_mbuf_pkthdr *omp; + + while ((omp = STAILQ_FIRST(&eatt->eatt_tx_q)) != NULL) { + STAILQ_REMOVE_HEAD(&eatt->eatt_tx_q, omp_next); + os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(omp)); + } + + SLIST_REMOVE(&g_ble_eatt_list, eatt, ble_eatt, next); + os_memblock_put(&ble_eatt_conn_pool, eatt); +} + +static int +ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg) +{ + struct ble_eatt *eatt = arg; + struct ble_gap_conn_desc desc; + uint8_t opcode; + int rc; + + switch (event->type) { + case BLE_L2CAP_EVENT_COC_CONNECTED: + BLE_EATT_LOG_DEBUG("eatt: Connected \n"); + if (event->connect.status) { + ble_eatt_free(eatt); + return 0; + } + eatt->chan = event->connect.chan; + ble_gap_eatt_event(event->connect.conn_handle, 0, event->connect.chan->scid); + break; + case BLE_L2CAP_EVENT_COC_DISCONNECTED: + BLE_EATT_LOG_DEBUG("eatt: Disconnected \n"); + ble_eatt_free(eatt); + ble_gap_eatt_event(event->disconnect.conn_handle, 1, event->disconnect.chan->scid); + break; + case BLE_L2CAP_EVENT_COC_ACCEPT: + BLE_EATT_LOG_DEBUG("eatt: Accept request\n"); + + eatt = ble_eatt_alloc(); + if (!eatt) { + return BLE_HS_ENOMEM; + } + eatt->conn_handle = event->accept.conn_handle; + event->accept.chan->cb_arg = eatt; + + rc = ble_eatt_prepare_rx_sdu(event->accept.chan); + if (rc) { + ble_eatt_free(eatt); + return rc; + } + break; + case BLE_L2CAP_EVENT_COC_TX_UNSTALLED: + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + break; + case BLE_L2CAP_EVENT_COC_DATA_RECEIVED: + assert(eatt->chan == event->receive.chan); + opcode = event->receive.sdu_rx->om_data[0]; + if (ble_att_is_response_op(opcode)) { + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + } else if (!ble_att_is_att_pdu_op(opcode)) { + /* As per BLE 5.4 Standard, Vol. 3, Part G, section 5.3.2 + * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: + * Channel Requirements): + * All packets sent on this L2CAP channel shall be Attribute PDUs. + * + * Disconnect peer with invalid behavior. + */ + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_EREJECT; + } + + assert (!ble_gap_conn_find(event->receive.conn_handle, &desc)); + /* As per BLE 5.4 Standard, Vol. 3, Part G, section 5.3.2 + * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: + * Channel Requirements): + * The channel shall be encrypted. + * + * Disconnect peer with invalid behavior - ATT PDU received before + * encryption. + */ + if (!desc.sec_state.encrypted) { + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_EREJECT; + } + + ble_eatt_att_rx_cb(event->receive.conn_handle, eatt->chan->scid, &event->receive.sdu_rx); + if (event->receive.sdu_rx) { + os_mbuf_free_chain(event->receive.sdu_rx); + event->receive.sdu_rx = NULL; + } + rc = ble_eatt_prepare_rx_sdu(event->receive.chan); + if (rc) { + /* Receiving L2CAP data is no longer possible, terminate connection */ + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_ENOMEM; + } + break; + default: + break; + } + + return 0; +} + +static void +ble_eatt_setup_cb(struct ble_npl_event *ev) +{ + struct ble_eatt *eatt; + struct os_mbuf *om; + int rc; + + eatt = ble_npl_event_get_arg(ev); + assert(eatt); + + om = os_mbuf_get_pkthdr(&ble_eatt_sdu_os_mbuf_pool, 0); + if (!om) { + ble_eatt_free(eatt); + BLE_EATT_LOG_ERROR("eatt: no memory for sdu\n"); + return; + } + + BLE_EATT_LOG_DEBUG("eatt: connecting eatt on conn_handle 0x%04x\n", eatt->conn_handle); + rc = ble_l2cap_enhanced_connect(eatt->conn_handle, BLE_EATT_PSM, + MYNEWT_VAL(BLE_EATT_MTU), 1, &om, ble_eatt_l2cap_event_fn, eatt); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Failed to connect EATT on conn_handle 0x%04x (status=%d)\n", + eatt->conn_handle, rc); + os_mbuf_free_chain(om); + ble_eatt_free(eatt); + } +} + +static int +ble_gatt_eatt_write_cl_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot write to Client Supported features on peer device\n"); + return 0; + } + + ble_eatt_start(conn_handle); + return 0; +} + +static int +ble_gatt_eatt_read_cl_uuid_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + uint8_t client_supported_feat; + int rc; + + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot find Client Supported features on peer device\n"); + return BLE_HS_EDONE; + } + + if (attr == NULL) { + BLE_EATT_LOG_ERROR("eatt: Invalid attribute \n"); + return BLE_HS_EDONE; + } + + if (error->status == 0) { + client_supported_feat = MYNEWT_VAL(BLE_CLIENT_SUPPORTED_FEATURES); + rc = ble_gattc_write_flat(conn_handle, attr->handle, &client_supported_feat, 1, + ble_gatt_eatt_write_cl_cb, NULL); + BLE_EATT_LOG_DEBUG("eatt: %s , write rc = %d \n", __func__, rc); + assert(rc == 0); + return 0; + } + + return BLE_HS_EDONE; +} + +static int +ble_gatt_eatt_read_uuid_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + uint8_t supported_features; + int rc; + + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot find Server Supported features on peer device\n"); + return BLE_HS_EDONE; + } + + if (attr == NULL) { + BLE_EATT_LOG_ERROR("eatt: Invalid attribute \n"); + return BLE_HS_EDONE; + } + + rc = os_mbuf_copydata(attr->om, 0, 1, &supported_features); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Cannot read srv supported features \n"); + return BLE_HS_EDONE; + } + + if (supported_features & 0x01) { + ble_npl_event_set_arg(&g_read_sup_cl_feat_ev, (void *)((uintptr_t) conn_handle)); + ble_npl_eventq_put(ble_hs_evq_get(), &g_read_sup_cl_feat_ev); + } + return BLE_HS_EDONE; +} + +static void +ble_gatt_eatt_read_svr_uuid(struct ble_npl_event *ev) +{ + uint16_t conn_handle; + + conn_handle = (uint16_t)((uintptr_t)(ble_npl_event_get_arg(ev))); + + ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16), + ble_gatt_eatt_read_uuid_cb, NULL); +} + +static void +ble_gatt_eatt_read_cl_uuid(struct ble_npl_event *ev) +{ + uint16_t conn_handle; + + conn_handle = (uint16_t)((uintptr_t)(ble_npl_event_get_arg(ev))); + + ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16), + ble_gatt_eatt_read_cl_uuid_cb, NULL); +} + +static int +ble_eatt_gap_event(struct ble_gap_event *event, void *arg) +{ + struct ble_eatt *eatt; + + switch (event->type) { + case BLE_GAP_EVENT_ENC_CHANGE: + if (event->enc_change.status != 0) { + return 0; + } + + /* Don't try to connect if already connected */ + if (ble_eatt_find_by_conn_handle(event->enc_change.conn_handle)) { + return 0; + } + + BLE_EATT_LOG_DEBUG("eatt: Encryption enabled, connecting EATT (conn_handle=0x%04x)\n", + event->enc_change.conn_handle); + + ble_npl_event_set_arg(&g_read_sup_srv_feat_ev, (void *)((uintptr_t)(event->enc_change.conn_handle))); + ble_npl_eventq_put(ble_hs_evq_get(), &g_read_sup_srv_feat_ev); + + break; + case BLE_GAP_EVENT_DISCONNECT: + eatt = ble_eatt_find_by_conn_handle(event->disconnect.conn.conn_handle); + assert(eatt == NULL); + break; + default: + break; + } + return 0; +} + +uint16_t +ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op) +{ + uint16_t default_cid; + struct ble_eatt * eatt; + + default_cid = ble_att_get_default_bearer_cid(conn_handle); + if (default_cid) { + eatt = ble_eatt_find(conn_handle, default_cid); + } else { + eatt = ble_eatt_find_not_busy(conn_handle); + } + if (!eatt) { + return BLE_L2CAP_CID_ATT; + } + + eatt->client_op = op; + return eatt->chan->scid; +} + + +void +ble_eatt_release_chan(uint16_t conn_handle, uint8_t op) +{ + struct ble_eatt * eatt; + + eatt = ble_eatt_find_by_conn_handle_and_busy_op(conn_handle, op); + if (!eatt) { + BLE_EATT_LOG_DEBUG("ble_eatt_release_chan:" + "EATT not found for conn_handle 0x%04x, operation 0x%02\n", conn_handle, op); + return; + } + + eatt->client_op = 0; +} + +int +ble_eatt_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom) +{ + struct ble_eatt *eatt; + int rc; + + BLE_EATT_LOG_DEBUG("eatt: %s, size %d ", __func__, OS_MBUF_PKTLEN(txom)); + eatt = ble_eatt_find(conn_handle, cid); + if (!eatt || !eatt->chan) { + BLE_EATT_LOG_ERROR("Eatt not available"); + rc = BLE_HS_ENOENT; + goto error; + } + + ble_att_truncate_to_mtu(eatt->chan, txom); + rc = ble_l2cap_send(eatt->chan, txom); + if (rc == 0) { + goto done; + } + + if (rc == BLE_HS_ESTALLED) { + BLE_EATT_LOG_DEBUG("ble_eatt_tx: Eatt stalled"); + } else if (rc == BLE_HS_EBUSY) { + BLE_EATT_LOG_DEBUG("ble_eatt_tx: Message queued"); + STAILQ_INSERT_HEAD(&eatt->eatt_tx_q, OS_MBUF_PKTHDR(txom), omp_next); + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + } else { + BLE_EATT_LOG_ERROR("eatt: %s, ERROR %d ", __func__, rc); + assert(0); + } +done: + return 0; + +error: + os_mbuf_free_chain(txom); + return rc; +} + +static void +ble_eatt_start(uint16_t conn_handle) +{ + struct ble_gap_conn_desc desc; + struct ble_eatt *eatt; + int rc; + + rc = ble_gap_conn_find(conn_handle, &desc); + assert(rc == 0); + if (desc.role != BLE_GAP_ROLE_MASTER) { + /* Let master to create ecoc. + */ + return; + } + + for (int i = 0; i < MYNEWT_VAL(BLE_EATT_CHAN_NUM); i++) { + eatt = ble_eatt_alloc(); + if (!eatt) { + return; + } + + eatt->conn_handle = conn_handle; + + /* Setup EATT */ + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->setup_ev); + eatt = NULL; + } +} + +void +ble_eatt_init(ble_eatt_att_rx_fn att_rx_cb) +{ + int rc; + + rc = os_mempool_init(&ble_eatt_sdu_mbuf_mempool, + MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1, + BLE_EATT_MEMBLOCK_SIZE, + ble_eatt_sdu_coc_mem, + "ble_eatt_sdu"); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = os_mbuf_pool_init(&ble_eatt_sdu_os_mbuf_pool, + &ble_eatt_sdu_mbuf_mempool, + BLE_EATT_MEMBLOCK_SIZE, + MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = os_mempool_init(&ble_eatt_conn_pool, MYNEWT_VAL(BLE_EATT_CHAN_NUM), + sizeof (struct ble_eatt), + ble_eatt_conn_mem, "ble_eatt_conn_pool"); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = ble_gap_event_listener_register(&ble_eatt_listener, ble_eatt_gap_event, NULL); + ble_l2cap_create_server(BLE_EATT_PSM, MYNEWT_VAL(BLE_EATT_MTU), ble_eatt_l2cap_event_fn, NULL); + + ble_npl_event_init(&g_read_sup_srv_feat_ev, ble_gatt_eatt_read_svr_uuid, NULL); + ble_npl_event_init(&g_read_sup_cl_feat_ev, ble_gatt_eatt_read_cl_uuid, NULL); + + ble_eatt_att_rx_cb = att_rx_cb; +} +#endif diff --git a/nimble/host/src/ble_eatt_priv.h b/nimble/host/src/ble_eatt_priv.h new file mode 100644 index 000000000..1797ce670 --- /dev/null +++ b/nimble/host/src/ble_eatt_priv.h @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "syscfg/syscfg.h" +#include "os/os_mbuf.h" +#include "host/ble_l2cap.h" + +#ifndef BLE_EATT_H_ +#define BLE_EATT_H_ + +typedef int (* ble_eatt_att_rx_fn)(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx_buf); + +#define BLE_EATT_PSM (0x0027) + +#define BLE_GATT_OP_SERVER 0xF1 +#define BLE_GATT_OP_DUMMY 0xF2 + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 +void ble_eatt_init(ble_eatt_att_rx_fn att_rx_fn); +uint16_t ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op); +void ble_eatt_release_chan(uint16_t conn_handle, uint8_t op); +int ble_eatt_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom); +#else +static inline void +ble_eatt_init(ble_eatt_att_rx_fn att_rx_fn) +{ +} + +static inline void +ble_eatt_release_chan(uint16_t conn_handle, uint8_t op) +{ + +} + +static inline uint16_t +ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op) +{ + return BLE_L2CAP_CID_ATT; +} + +#endif +#endif diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index ddea5f194..1fea884aa 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -7939,6 +7939,27 @@ ble_gap_end_test_evt(const void *buf, uint8_t len) ble_gap_event_listener_call(&event); } +/***************************************************************************** + * EATT * + *****************************************************************************/ +void +ble_gap_eatt_event(uint16_t conn_handle, uint8_t status, uint16_t cid) +{ +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_EATT; + + event.eatt.conn_handle = conn_handle; + event.eatt.status = status; + event.eatt.cid = cid; + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} + /***************************************************************************** * $preempt * *****************************************************************************/ diff --git a/nimble/host/src/ble_gap_priv.h b/nimble/host/src/ble_gap_priv.h index af474adbc..3d134dd64 100644 --- a/nimble/host/src/ble_gap_priv.h +++ b/nimble/host/src/ble_gap_priv.h @@ -148,6 +148,7 @@ int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp); void ble_gap_pairing_complete_event(uint16_t conn_handle, int status); void ble_gap_vs_hci_event(const void *buf, uint8_t len); int ble_gap_authorize_event(uint16_t conn_handle, uint16_t attr_handle, int is_read); +void ble_gap_eatt_event(uint16_t conn_handle, uint8_t status, uint16_t cid); int ble_gap_master_in_progress(void); void ble_gap_preempt(void); diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index 86a52ee25..941cdc146 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -68,6 +68,8 @@ STATS_SECT_START(ble_gattc_stats) STATS_SECT_ENTRY(write_reliable_fail) STATS_SECT_ENTRY(notify) STATS_SECT_ENTRY(notify_fail) + STATS_SECT_ENTRY(multi_notify) + STATS_SECT_ENTRY(multi_notify_fail) STATS_SECT_ENTRY(indicate) STATS_SECT_ENTRY(indicate_fail) STATS_SECT_ENTRY(proc_timeout) @@ -127,32 +129,32 @@ struct ble_gatts_conn { int ble_gattc_locked_by_cur_task(void); void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); -void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); -void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); -void ble_gattc_rx_read_type_adata(uint16_t conn_handle, +void ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status); +void ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu); +void ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata); -void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status); +void ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); -void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, 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, int status, +void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, 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); -void ble_gattc_rx_find_type_value_hinfo( - uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); -void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_write_rsp(uint16_t conn_handle); -void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, +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); +void ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, + struct ble_att_find_type_value_hinfo *hinfo); +void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int status); +void ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid); +void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, uint16_t handle, uint16_t offset, struct os_mbuf **rxom); -void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); -void ble_gatts_rx_indicate_rsp(uint16_t conn_handle); -void ble_gattc_rx_find_info_idata(uint16_t conn_handle, +void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status); +void ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid); +void ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, struct ble_att_find_info_idata *idata); -void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status); void ble_gattc_connection_txable(uint16_t conn_handle); void ble_gattc_connection_broken(uint16_t conn_handle); int32_t ble_gattc_timer(void); diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 0669b6c2f..ee1b149bc 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -110,6 +110,7 @@ struct ble_gattc_proc { uint32_t exp_os_ticks; uint16_t conn_handle; + uint16_t cid; uint8_t op; uint8_t flags; @@ -243,6 +244,7 @@ static ble_gattc_err_fn ble_gattc_read_err; static ble_gattc_err_fn ble_gattc_read_uuid_err; static ble_gattc_err_fn ble_gattc_read_long_err; static ble_gattc_err_fn ble_gattc_read_mult_err; +static ble_gattc_err_fn ble_gattc_read_mult_var_err; static ble_gattc_err_fn ble_gattc_write_err; static ble_gattc_err_fn ble_gattc_write_long_err; static ble_gattc_err_fn ble_gattc_write_reliable_err; @@ -260,6 +262,7 @@ static ble_gattc_err_fn * const ble_gattc_err_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = ble_gattc_read_uuid_err, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_err, [BLE_GATT_OP_READ_MULT] = ble_gattc_read_mult_err, + [BLE_GATT_OP_READ_MULT_VAR] = ble_gattc_read_mult_var_err, [BLE_GATT_OP_WRITE] = ble_gattc_write_err, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_err, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_err, @@ -295,6 +298,7 @@ ble_gattc_resume_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = NULL, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_resume, [BLE_GATT_OP_READ_MULT] = NULL, + [BLE_GATT_OP_READ_MULT_VAR] = NULL, [BLE_GATT_OP_WRITE] = NULL, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_resume, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_resume, @@ -318,6 +322,7 @@ static ble_gattc_tmo_fn ble_gattc_read_tmo; static ble_gattc_tmo_fn ble_gattc_read_uuid_tmo; static ble_gattc_tmo_fn ble_gattc_read_long_tmo; static ble_gattc_tmo_fn ble_gattc_read_mult_tmo; +static ble_gattc_tmo_fn ble_gattc_read_mult_var_tmo; static ble_gattc_tmo_fn ble_gattc_write_tmo; static ble_gattc_tmo_fn ble_gattc_write_long_tmo; static ble_gattc_tmo_fn ble_gattc_write_reliable_tmo; @@ -336,6 +341,7 @@ ble_gattc_tmo_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = ble_gattc_read_uuid_tmo, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_tmo, [BLE_GATT_OP_READ_MULT] = ble_gattc_read_mult_tmo, + [BLE_GATT_OP_READ_MULT_VAR] = ble_gattc_read_mult_var_tmo, [BLE_GATT_OP_WRITE] = ble_gattc_write_tmo, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_tmo, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_tmo, @@ -472,6 +478,8 @@ STATS_NAME_START(ble_gattc_stats) STATS_NAME(ble_gattc_stats, write_reliable_fail) STATS_NAME(ble_gattc_stats, notify) STATS_NAME(ble_gattc_stats, notify_fail) + STATS_NAME(ble_gattc_stats, multi_notify) + STATS_NAME(ble_gattc_stats, multi_notify_fail) STATS_NAME(ble_gattc_stats, indicate) STATS_NAME(ble_gattc_stats, indicate_fail) STATS_NAME(ble_gattc_stats, proc_timeout) @@ -653,6 +661,15 @@ ble_gattc_log_notify(uint16_t att_handle) BLE_HS_LOG(INFO, "att_handle=%d\n", att_handle); } +static void +ble_gattc_log_multi_notify(struct ble_gatt_notif * tuples, uint16_t num) +{ + ble_gattc_log_proc_init("multi handle notify; "); + for (int i = 0; i < num; i++) { + BLE_HS_LOG(INFO, "att_handle=%d", tuples[i].handle); + } +} + static void ble_gattc_log_indicate(uint16_t att_handle) { @@ -707,6 +724,14 @@ ble_gattc_proc_alloc(void) return proc; } +static void +ble_gattc_proc_prepare(struct ble_gattc_proc *proc, uint16_t conn_handle, uint8_t op) +{ + proc->conn_handle = conn_handle; + proc->op = op; + proc->cid = ble_eatt_get_available_chan_cid(conn_handle, op); +} + /** * Frees the specified proc entry. No-op if passed a null pointer. */ @@ -738,6 +763,12 @@ ble_gattc_proc_free(struct ble_gattc_proc *proc) break; } +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (proc->cid != BLE_L2CAP_CID_ATT) { + ble_eatt_release_chan(proc->conn_handle, proc->op); + } +#endif + #if MYNEWT_VAL(BLE_HS_DEBUG) memset(proc, 0xff, sizeof *proc); #endif @@ -858,6 +889,7 @@ typedef int ble_gattc_match_fn(struct ble_gattc_proc *proc, void *arg); struct ble_gattc_criteria_conn_op { uint16_t conn_handle; + uint16_t psm; uint8_t op; }; @@ -889,6 +921,28 @@ ble_gattc_proc_matches_conn_op(struct ble_gattc_proc *proc, void *arg) return 1; } +static int +ble_gattc_proc_matches_conn_cid_op(struct ble_gattc_proc *proc, void *arg) +{ + const struct ble_gattc_criteria_conn_op *criteria; + + criteria = arg; + + if (criteria->conn_handle != proc->conn_handle) { + return 0; + } + + if (criteria->psm != proc->cid) { + return 0; + } + + if (criteria->op != proc->op && criteria->op != BLE_GATT_OP_NONE) { + return 0; + } + + return 1; +} + struct ble_gattc_criteria_exp { ble_npl_time_t now; int32_t next_exp_in; @@ -918,6 +972,7 @@ ble_gattc_proc_matches_expired(struct ble_gattc_proc *proc, void *arg) struct ble_gattc_criteria_conn_rx_entry { uint16_t conn_handle; + uint16_t cid; const void *rx_entries; int num_rx_entries; const void *matching_rx_entry; @@ -931,7 +986,8 @@ ble_gattc_proc_matches_conn_rx_entry(struct ble_gattc_proc *proc, void *arg) criteria = arg; if (criteria->conn_handle != BLE_HS_CONN_HANDLE_NONE && - criteria->conn_handle != proc->conn_handle) { + criteria->conn_handle != proc->conn_handle && + criteria->cid != proc->cid) { return 0; } @@ -1010,12 +1066,26 @@ ble_gattc_extract_by_conn_op(uint16_t conn_handle, uint8_t op, int max_procs, ble_gattc_extract(ble_gattc_proc_matches_conn_op, &criteria, max_procs, dst_list); } +static void +ble_gattc_extract_by_conn_cid_op(uint16_t conn_handle, uint16_t psm, uint8_t op, + int max_procs, + struct ble_gattc_proc_list *dst_list) +{ + struct ble_gattc_criteria_conn_op criteria; + + criteria.conn_handle = conn_handle; + criteria.op = op; + criteria.psm = psm; + + ble_gattc_extract(ble_gattc_proc_matches_conn_cid_op, &criteria, max_procs, dst_list); +} + static struct ble_gattc_proc * -ble_gattc_extract_first_by_conn_op(uint16_t conn_handle, uint8_t op) +ble_gattc_extract_first_by_conn_cid_op(uint16_t conn_handle, uint16_t cid, uint8_t op) { struct ble_gattc_proc_list dst_list; - ble_gattc_extract_by_conn_op(conn_handle, op, 1, &dst_list); + ble_gattc_extract_by_conn_cid_op(conn_handle, cid, op, 1, &dst_list); return STAILQ_FIRST(&dst_list); } @@ -1050,7 +1120,7 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list) } static struct ble_gattc_proc * -ble_gattc_extract_with_rx_entry(uint16_t conn_handle, +ble_gattc_extract_with_rx_entry(uint16_t conn_handle, uint16_t cid, const void *rx_entries, int num_rx_entries, const void **out_rx_entry) { @@ -1058,6 +1128,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, struct ble_gattc_proc *proc; criteria.conn_handle = conn_handle; + criteria.cid = cid; criteria.rx_entries = rx_entries; criteria.num_rx_entries = num_rx_entries; criteria.matching_rx_entry = NULL; @@ -1075,6 +1146,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, * list and returned. * * @param conn_handle The connection handle to match against. + * @param cid Source CID of L2CAP channel used * @param rx_entries The array of rx entries corresponding to the * op code of the incoming response. * @param out_rx_entry On success, the address of the matching rx @@ -1083,9 +1155,9 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, * @return The matching proc entry on success; * null on failure. */ -#define BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, rx_entries, out_rx_entry) \ +#define BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, rx_entries, out_rx_entry) \ ble_gattc_extract_with_rx_entry( \ - (conn_handle), (rx_entries), \ + (conn_handle), (cid), (rx_entries), \ sizeof (rx_entries) / sizeof (rx_entries)[0], \ (const void **)(out_rx_entry)) @@ -1303,7 +1375,7 @@ ble_gattc_mtu_tx(struct ble_gattc_proc *proc) int rc; ble_hs_lock(); - rc = ble_att_conn_chan_find(proc->conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(proc->conn_handle, proc->cid, &conn, &chan); if (rc == 0) { mtu = chan->my_mtu; } @@ -1332,6 +1404,7 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg) proc->op = BLE_GATT_OP_MTU; proc->conn_handle = conn_handle; + proc->cid = BLE_L2CAP_CID_ATT; proc->mtu.cb = cb; proc->mtu.cb_arg = cb_arg; @@ -1408,7 +1481,7 @@ ble_gattc_disc_all_svcs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_group_type(proc->conn_handle, + rc = ble_att_clt_tx_read_group_type(proc->conn_handle, proc->cid, proc->disc_all_svcs.prev_handle + 1, 0xffff, &uuid.u); if (rc != 0) { @@ -1561,8 +1634,8 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_SVCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_SVCS); + proc->disc_all_svcs.prev_handle = 0x0000; proc->disc_all_svcs.cb = cb; proc->disc_all_svcs.cb_arg = cb_arg; @@ -1641,7 +1714,7 @@ ble_gattc_disc_svc_uuid_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); ble_uuid_flat(&proc->disc_svc_uuid.service_uuid.u, val); - rc = ble_att_clt_tx_find_type_value(proc->conn_handle, + rc = ble_att_clt_tx_find_type_value(proc->conn_handle, proc->cid, proc->disc_svc_uuid.prev_handle + 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE, val, @@ -1780,8 +1853,8 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, goto done; } - proc->op = BLE_GATT_OP_DISC_SVC_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_SVC_UUID); + ble_uuid_to_any(uuid, &proc->disc_svc_uuid.service_uuid); proc->disc_svc_uuid.prev_handle = 0x0000; proc->disc_svc_uuid.cb = cb; @@ -1862,7 +1935,7 @@ ble_gattc_find_inc_svcs_tx(struct ble_gattc_proc *proc) if (proc->find_inc_svcs.cur_start == 0) { /* Find the next included service. */ - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->find_inc_svcs.prev_handle + 1, proc->find_inc_svcs.end_handle, &uuid.u); if (rc != 0) { @@ -1870,7 +1943,7 @@ ble_gattc_find_inc_svcs_tx(struct ble_gattc_proc *proc) } } else { /* Read the UUID of the previously found service. */ - rc = ble_att_clt_tx_read(proc->conn_handle, + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->find_inc_svcs.cur_start); if (rc != 0) { return rc; @@ -2096,8 +2169,8 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_FIND_INC_SVCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_FIND_INC_SVCS); + proc->find_inc_svcs.prev_handle = start_handle - 1; proc->find_inc_svcs.end_handle = end_handle; proc->find_inc_svcs.cb = cb; @@ -2176,7 +2249,7 @@ ble_gattc_disc_all_chrs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->disc_all_chrs.prev_handle + 1, proc->disc_all_chrs.end_handle, &uuid.u); if (rc != 0) { @@ -2330,8 +2403,8 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_CHRS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_CHRS); + proc->disc_all_chrs.prev_handle = start_handle - 1; proc->disc_all_chrs.end_handle = end_handle; proc->disc_all_chrs.cb = cb; @@ -2410,7 +2483,7 @@ ble_gattc_disc_chr_uuid_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->disc_chr_uuid.prev_handle + 1, proc->disc_chr_uuid.end_handle, &uuid.u); if (rc != 0) { @@ -2575,8 +2648,8 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_CHR_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_CHR_UUID); + ble_uuid_to_any(uuid, &proc->disc_chr_uuid.chr_uuid); proc->disc_chr_uuid.prev_handle = start_handle - 1; proc->disc_chr_uuid.end_handle = end_handle; @@ -2655,7 +2728,7 @@ ble_gattc_disc_all_dscs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_find_info(proc->conn_handle, + rc = ble_att_clt_tx_find_info(proc->conn_handle, proc->cid, proc->disc_all_dscs.prev_handle + 1, proc->disc_all_dscs.end_handle); if (rc != 0) { @@ -2791,8 +2864,8 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_DSCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_DSCS); + proc->disc_all_dscs.chr_val_handle = start_handle; proc->disc_all_dscs.prev_handle = start_handle; proc->disc_all_dscs.end_handle = end_handle; @@ -2907,7 +2980,7 @@ ble_gattc_read_tx(struct ble_gattc_proc *proc) { int rc; - rc = ble_att_clt_tx_read(proc->conn_handle, proc->read.handle); + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->read.handle); if (rc != 0) { return rc; } @@ -2934,8 +3007,8 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_READ; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ); + proc->read.handle = attr_handle; proc->read.cb = cb; proc->read.cb_arg = cb_arg; @@ -3070,7 +3143,7 @@ ble_gattc_read_uuid_rx_complete(struct ble_gattc_proc *proc, int status) static int ble_gattc_read_uuid_tx(struct ble_gattc_proc *proc) { - return ble_att_clt_tx_read_type(proc->conn_handle, + return ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->read_uuid.start_handle, proc->read_uuid.end_handle, &proc->read_uuid.chr_uuid.u); @@ -3096,8 +3169,8 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_READ_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_UUID); + ble_uuid_to_any(uuid, &proc->read_uuid.chr_uuid); proc->read_uuid.start_handle = start_handle; proc->read_uuid.end_handle = end_handle; @@ -3180,12 +3253,12 @@ ble_gattc_read_long_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); if (proc->read_long.offset == 0) { - rc = ble_att_clt_tx_read(proc->conn_handle, proc->read_long.handle); + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->read_long.handle); if (rc != 0) { return rc; } } else { - rc = ble_att_clt_tx_read_blob(proc->conn_handle, + rc = ble_att_clt_tx_read_blob(proc->conn_handle, proc->cid, proc->read_long.handle, proc->read_long.offset); if (rc != 0) { @@ -3256,7 +3329,7 @@ ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc, int status, } /* Determine if this is the end of the attribute value. */ - mtu = ble_att_mtu(proc->conn_handle); + mtu = ble_att_mtu_by_cid(proc->conn_handle, proc->cid); if (mtu == 0) { /* No longer connected. */ return BLE_HS_EDONE; @@ -3297,8 +3370,8 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset, goto done; } - proc->op = BLE_GATT_OP_READ_LONG; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_LONG); + proc->read_long.handle = handle; proc->read_long.offset = offset; proc->read_long.cb = cb; @@ -3455,6 +3528,15 @@ ble_gattc_read_mult_tmo(struct ble_gattc_proc *proc) ble_gattc_read_mult_cb(proc, BLE_HS_ETIMEOUT, 0, 0); } +static void +ble_gattc_read_mult_var_tmo(struct ble_gattc_proc *proc) +{ + BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task()); + ble_gattc_dbg_assert_proc_not_inserted(proc); + + ble_gattc_read_mult_cb_var(proc, BLE_HS_ETIMEOUT, 0, 0); +} + /** * Handles an incoming ATT error response for the specified * read-multiple-characteristics proc. @@ -3467,12 +3549,24 @@ ble_gattc_read_mult_err(struct ble_gattc_proc *proc, int status, ble_gattc_read_mult_cb(proc, status, att_handle, NULL); } +/** + * Handles an incoming ATT error response for the specified + * read-multiple-variable-lengthcharacteristics proc. + */ +static void +ble_gattc_read_mult_var_err(struct ble_gattc_proc *proc, int status, + uint16_t att_handle) +{ + ble_gattc_dbg_assert_proc_not_inserted(proc); + ble_gattc_read_mult_cb_var(proc, status, att_handle, NULL); +} + static int 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, + rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->cid, proc->read_mult.handles, proc->read_mult.num_handles, proc->read_mult.variable); if (rc != 0) { return rc; @@ -3510,12 +3604,9 @@ ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles, goto done; } - if (variable) { - proc->op = BLE_GATT_OP_READ_MULT_VAR; - } else { - proc->op = BLE_GATT_OP_READ_MULT; - } - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, + variable ? BLE_GATT_OP_READ_MULT_VAR : 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; @@ -3573,15 +3664,18 @@ ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, #endif int rc; + uint16_t cid; STATS_INC(ble_gattc_stats, write_no_rsp); ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 0); - rc = ble_att_clt_tx_write_cmd(conn_handle, attr_handle, txom); + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_clt_tx_write_cmd(conn_handle, cid, attr_handle, txom); if (rc != 0) { STATS_INC(ble_gattc_stats, write); } + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); return rc; } @@ -3653,7 +3747,7 @@ ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, /* Converting the csrk to little endian */ swap_buf(csrk, value_sec.csrk, 16); - rc = ble_att_clt_tx_signed_write_cmd(conn_handle, attr_handle, + rc = ble_att_clt_tx_signed_write_cmd(conn_handle, BLE_L2CAP_CID_ATT, attr_handle, csrk, value_sec.sign_counter, txom); if (rc != 0) { goto err; @@ -3749,15 +3843,15 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE); + proc->write.att_handle = attr_handle; proc->write.cb = cb; proc->write.cb_arg = cb_arg; ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 1); - rc = ble_att_clt_tx_write_req(conn_handle, attr_handle, txom); + rc = ble_att_clt_tx_write_req(conn_handle, proc->cid, attr_handle, txom); txom = NULL; if (rc != 0) { goto done; @@ -3862,7 +3956,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) om = NULL; - max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + max_sz = ble_att_mtu_by_cid(proc->conn_handle, proc->cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; if (max_sz <= 0) { /* Not connected. */ rc = BLE_HS_ENOTCONN; @@ -3874,7 +3968,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) proc->write_long.attr.offset); if (write_len <= 0) { - rc = ble_att_clt_tx_exec_write(proc->conn_handle, + rc = ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_EXECUTE); goto done; } @@ -3894,7 +3988,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) goto done; } - rc = ble_att_clt_tx_prep_write(proc->conn_handle, + rc = ble_att_clt_tx_prep_write(proc->conn_handle, proc->cid, proc->write_long.attr.handle, proc->write_long.attr.offset, om); om = NULL; @@ -3938,9 +4032,9 @@ ble_gattc_write_long_err(struct ble_gattc_proc *proc, int status, */ if (proc->write_long.attr.offset > 0 && proc->write_long.attr.offset < - OS_MBUF_PKTLEN(proc->write_long.attr.om)) { + OS_MBUF_PKTLEN(proc->write_long.attr.om)) { - ble_att_clt_tx_exec_write(proc->conn_handle, + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_CANCEL); } @@ -4006,7 +4100,8 @@ ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc, rc = BLE_HS_EBADDATA; /* if data doesn't match up send cancel write */ - ble_att_clt_tx_exec_write(proc->conn_handle, BLE_ATT_EXEC_WRITE_F_CANCEL); + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, + BLE_ATT_EXEC_WRITE_F_CANCEL); goto err; } else { /* Send follow-up request. */ @@ -4067,8 +4162,8 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE_LONG; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_LONG); + proc->write_long.attr.handle = attr_handle; proc->write_long.attr.offset = offset; proc->write_long.attr.om = txom; @@ -4168,14 +4263,14 @@ ble_gattc_write_reliable_tx(struct ble_gattc_proc *proc) attr_idx = proc->write_reliable.cur_attr; if (attr_idx >= proc->write_reliable.num_attrs) { - rc = ble_att_clt_tx_exec_write(proc->conn_handle, + rc = ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_EXECUTE); goto done; } attr = proc->write_reliable.attrs + attr_idx; - max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + max_sz = ble_att_mtu_by_cid(proc->conn_handle, proc->cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; if (max_sz <= 0) { /* Not connected. */ rc = BLE_HS_ENOTCONN; @@ -4198,8 +4293,8 @@ ble_gattc_write_reliable_tx(struct ble_gattc_proc *proc) goto done; } - rc = ble_att_clt_tx_prep_write(proc->conn_handle, attr->handle, - attr->offset, om); + rc = ble_att_clt_tx_prep_write(proc->conn_handle, proc->cid, + attr->handle, attr->offset, om); om = NULL; if (rc != 0) { goto done; @@ -4242,7 +4337,7 @@ ble_gattc_write_reliable_err(struct ble_gattc_proc *proc, int status, */ if (proc->write_reliable.cur_attr < proc->write_reliable.num_attrs) { - ble_att_clt_tx_exec_write(proc->conn_handle, + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_CANCEL); } } @@ -4355,8 +4450,8 @@ ble_gattc_write_reliable(uint16_t conn_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE_RELIABLE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_RELIABLE); + proc->write_reliable.num_attrs = num_attrs; proc->write_reliable.cur_attr = 0; proc->write_reliable.cb = cb; @@ -4473,6 +4568,118 @@ done: return rc; } +int +ble_gatts_notify_multiple_custom(uint16_t conn_handle, + size_t chr_count, + struct ble_gatt_notif *tuples) +{ +#if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) + return BLE_HS_ENOTSUP; +#endif + + int rc = 0; + int i = 0; + uint16_t cur_chr_cnt = 0; + /* mtu = MTU - 1 octet (OP code) */ + uint16_t mtu = ble_att_mtu(conn_handle) - 1; + struct os_mbuf *txom; + struct ble_hs_conn *conn; + + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return ENOTCONN; + } + + STATS_INC(ble_gattc_stats, multi_notify); + ble_gattc_log_multi_notify(tuples, chr_count); + + /* Read missing values */ + for (i = 0; i < chr_count; i++) { + if (tuples->handle == 0) { + rc = BLE_HS_EINVAL; + goto done; + } + if (tuples[i].value == NULL) { + /* No custom attribute data; read the value from the specified + * attribute + */ + rc = ble_att_svr_read_local(tuples[i].handle, &tuples[i].value); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Attribute read failed (err=0x%02x), rc"); + goto done; + } + } + } + + /* If peer does not support fall back to multiple single value + * Notifications */ + if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) { + for (i = 0; i < chr_count; i++) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, tuples[i].value); + if (rc != 0) { + goto done; + } + } + goto done; + } + + for (i = 0; i < chr_count; i++) { + if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu && cur_chr_cnt < 2) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, + tuples[i].value); + if (rc != 0) { + goto done; + } + continue; + } else if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu) { + rc = ble_att_clt_tx_notify_mult(conn_handle, txom); + if (rc != 0) { + goto done; + } + cur_chr_cnt = 0; + /* buffer was consumed, allocate new one */ + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + } + + /* Handle */ + os_mbuf_append(txom, &tuples[i].handle, sizeof(uint16_t)); + + /* Length */ + os_mbuf_append(txom, &OS_MBUF_PKTLEN(tuples[i].value), + sizeof(uint16_t)); + + /* Value */ + os_mbuf_concat(txom, tuples[i].value); + cur_chr_cnt++; + } + + if (cur_chr_cnt == 1) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[chr_count].handle, + tuples[chr_count].value); + } else { + rc = ble_att_clt_tx_notify_mult(conn_handle, txom); + } + +done: + if (rc != 0) { + STATS_INC(ble_gattc_stats, multi_notify_fail); + } + + /* Tell the application that multiple notification transmissions were attempted. */ + for (i = 0; i < chr_count; i++) { + ble_gap_notify_tx_event(rc, conn_handle, tuples[i].handle, 0); + } + return rc; +} + /** * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. */ @@ -4608,8 +4815,8 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, goto done; } - proc->op = BLE_GATT_OP_INDICATE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_INDICATE); + proc->indicate.chr_val_handle = chr_val_handle; ble_gattc_log_indicate(chr_val_handle); @@ -4648,7 +4855,7 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, } } - rc = ble_att_clt_tx_indicate(conn_handle, chr_val_handle, txom); + rc = ble_att_clt_tx_indicate(conn_handle, proc->cid, chr_val_handle, txom); txom = NULL; if (rc != 0) { goto done; @@ -4709,12 +4916,12 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle) * procedure. */ void -ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status) +ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status) { struct ble_gattc_proc *proc; ble_gattc_err_fn *err_cb; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, BLE_GATT_OP_NONE); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_NONE); if (proc != NULL) { err_cb = ble_gattc_err_dispatch_get(proc->op); if (err_cb != NULL) { @@ -4729,11 +4936,13 @@ ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status) * GATT procedure. */ void -ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu) +ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu) { struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, BLE_GATT_OP_MTU); + assert(cid == BLE_L2CAP_CID_ATT); + + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, BLE_L2CAP_CID_ATT, BLE_GATT_OP_MTU); if (proc != NULL) { ble_gattc_mtu_cb(proc, status, 0, chan_mtu); ble_gattc_process_status(proc, BLE_HS_EDONE); @@ -4745,7 +4954,7 @@ ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu) * find-information-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_info_idata(uint16_t conn_handle, +ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, struct ble_att_find_info_idata *idata) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO @@ -4755,7 +4964,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_idata(proc, idata); @@ -4768,7 +4977,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, * find-information-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) +ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO return; @@ -4777,8 +4986,8 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_ALL_DSCS); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4790,7 +4999,7 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) * find-by-type-value-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, +ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, struct ble_att_find_type_value_hinfo *hinfo) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE @@ -4800,7 +5009,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_hinfo(proc, hinfo); @@ -4813,7 +5022,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, * find-by-type-value-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) +ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE return; @@ -4822,8 +5031,8 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_SVC_UUID); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4835,7 +5044,7 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) * to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_type_adata(uint16_t conn_handle, +ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE @@ -4846,7 +5055,7 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_read_type_elem_entries, &rx_entry); if (proc != NULL) { @@ -4860,7 +5069,7 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, * the appropriate active GATT procedure. */ void -ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) +ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE return; @@ -4871,7 +5080,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) int rc; proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY( - conn_handle, ble_gattc_rx_read_type_complete_entries, + conn_handle, cid, ble_gattc_rx_read_type_complete_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); @@ -4884,7 +5093,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) * read-by-group-type-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, +ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_group_type_adata *adata) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE @@ -4894,7 +5103,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_adata(proc, adata); @@ -4907,7 +5116,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, * read-by-group-type-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) +ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE return; @@ -4916,8 +5125,8 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_ALL_SVCS); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4929,7 +5138,7 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) * procedure. */ void -ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) +ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_READ return; @@ -4939,7 +5148,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_read_rsp_entries, &rx_entry); if (proc != NULL) { @@ -4953,7 +5162,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) * procedure. */ void -ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB @@ -4963,7 +5172,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_READ_LONG); if (proc != NULL) { rc = ble_gattc_read_long_rx_read_rsp(proc, status, om); @@ -4976,7 +5185,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, * GATT procedure. */ void -ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT @@ -4988,7 +5197,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, op = variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, op); + 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); @@ -5000,7 +5209,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, * procedure. */ void -ble_gattc_rx_write_rsp(uint16_t conn_handle) +ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid) { #if !NIMBLE_BLE_ATT_CLT_WRITE return; @@ -5008,7 +5217,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle) struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_WRITE); if (proc != NULL) { ble_gattc_write_cb(proc, 0, 0); @@ -5021,7 +5230,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle) * GATT procedure. */ void -ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, uint16_t handle, uint16_t offset, struct os_mbuf **om) { @@ -5033,7 +5242,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_prep_entries, &rx_entry); if (proc != NULL) { @@ -5047,7 +5256,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, * GATT procedure. */ void -ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) +ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return; @@ -5057,7 +5266,7 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_exec_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); @@ -5070,7 +5279,7 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) * active GATT procedure. */ void -ble_gatts_rx_indicate_rsp(uint16_t conn_handle) +ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return; @@ -5078,7 +5287,7 @@ ble_gatts_rx_indicate_rsp(uint16_t conn_handle) struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_INDICATE); if (proc != NULL) { ble_gatts_indicate_rx_rsp(proc); diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c index 1d5b17661..d15577279 100644 --- a/nimble/host/src/ble_hs.c +++ b/nimble/host/src/ble_hs.c @@ -787,10 +787,16 @@ ble_hs_init(void) SYSINIT_PANIC_ASSERT(rc == 0); #endif + #if NIMBLE_BLE_CONNECT rc = ble_l2cap_init(); SYSINIT_PANIC_ASSERT(rc == 0); +#endif + rc = ble_gap_init(); + SYSINIT_PANIC_ASSERT(rc == 0); + +#if NIMBLE_BLE_CONNECT rc = ble_att_init(); SYSINIT_PANIC_ASSERT(rc == 0); @@ -808,8 +814,6 @@ ble_hs_init(void) rc = ble_gatts_init(); SYSINIT_PANIC_ASSERT(rc == 0); #endif - rc = ble_gap_init(); - SYSINIT_PANIC_ASSERT(rc == 0); ble_hs_stop_init(); diff --git a/nimble/host/src/ble_hs_conn.c b/nimble/host/src/ble_hs_conn.c index 0af96f284..eb749c41a 100644 --- a/nimble/host/src/ble_hs_conn.c +++ b/nimble/host/src/ble_hs_conn.c @@ -194,6 +194,7 @@ ble_hs_conn_alloc(uint16_t conn_handle) } STAILQ_INIT(&conn->bhc_tx_q); + STAILQ_INIT(&conn->att_tx_q); STATS_INC(ble_hs_stats, conn_create); diff --git a/nimble/host/src/ble_hs_conn_priv.h b/nimble/host/src/ble_hs_conn_priv.h index 0e451194d..07773f2e3 100644 --- a/nimble/host/src/ble_hs_conn_priv.h +++ b/nimble/host/src/ble_hs_conn_priv.h @@ -102,6 +102,12 @@ struct ble_hs_conn { #if MYNEWT_VAL(BLE_PERIODIC_ADV) struct ble_hs_periodic_sync *psync; #endif + + STAILQ_HEAD(, os_mbuf_pkthdr) att_tx_q; + bool client_att_busy; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + uint16_t default_cid; +#endif }; struct ble_hs_conn_addrs { diff --git a/nimble/host/src/ble_hs_priv.h b/nimble/host/src/ble_hs_priv.h index c5781ccc9..cb97e5374 100644 --- a/nimble/host/src/ble_hs_priv.h +++ b/nimble/host/src/ble_hs_priv.h @@ -24,6 +24,7 @@ #include #include "ble_att_cmd_priv.h" #include "ble_att_priv.h" +#include "ble_eatt_priv.h" #include "ble_gap_priv.h" #include "ble_gatt_priv.h" #include "ble_hs_hci_priv.h" diff --git a/nimble/host/src/ble_l2cap_coc.c b/nimble/host/src/ble_l2cap_coc.c index 90d2a0573..f55d14da3 100644 --- a/nimble/host/src/ble_l2cap_coc.c +++ b/nimble/host/src/ble_l2cap_coc.c @@ -211,7 +211,7 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) sdu_len = get_le16((*om)->om_data); - BLE_HS_LOG(INFO, "First LE frame received %d, SDU len: %d\n", + BLE_HS_LOG(DEBUG, "First LE frame received %d, SDU len: %d\n", om_total, sdu_len + 2); /* We should receive payload of size sdu_len + 2 bytes of sdu_len field */ diff --git a/nimble/host/syscfg.yml b/nimble/host/syscfg.yml index eb1abdf41..6694ee4c6 100644 --- a/nimble/host/syscfg.yml +++ b/nimble/host/syscfg.yml @@ -277,6 +277,10 @@ syscfg.defs: description: > Enables sending and receiving of GATT indications. (0/1) value: 1 + BLE_GATT_NOTIFY_MULTIPLE: + description: > + Enables sending and receiving of GATT multi handle notifications. + value: 1 # GATT options. BLE_GATT_READ_MAX_ATTRS: @@ -299,6 +303,22 @@ syscfg.defs: due to memory exhaustion. (0/1) Units are milliseconds. (0/1) value: 1000 + # Enhanced ATT bearer options + BLE_EATT_CHAN_NUM: + description: > + Maximum number of supported EATT channels (in total). If set to 0 + EATT support it disabled. + value: 0 + restrictions: + - BLE_GATT_NOTIFY_MULTIPLE + - BLE_L2CAP_ENHANCED_COC + - 'BLE_L2CAP_COC_MAX_NUM >= BLE_EATT_CHAN_NUM' + + BLE_EATT_MTU: + description: > + MTU used for EATT channels. + value: 128 + # Supported server ATT commands. (0/1) BLE_ATT_SVR_FIND_INFO: description: > @@ -357,6 +377,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 @@ -467,11 +493,22 @@ syscfg.defs: description: 'Minimum level for the BLE host log.' value: 1 + BLE_EATT_LOG_MOD: + description: 'Numeric module ID to use for BLE EATT log messages.' + value: 27 + BLE_EATT_LOG_LVL: + description: 'Minimum level for the BLE EATT log.' + value: 1 + syscfg.logs: BLE_HS_LOG: module: MYNEWT_VAL(BLE_HS_LOG_MOD) level: MYNEWT_VAL(BLE_HS_LOG_LVL) + BLE_EATT_LOG: + module: MYNEWT_VAL(BLE_EATT_LOG_MOD) + level: MYNEWT_VAL(BLE_EATT_LOG_LVL) + syscfg.vals.BLE_MESH: BLE_SM_SC: 1 diff --git a/nimble/host/test/src/ble_att_clt_test.c b/nimble/host/test/src/ble_att_clt_test.c index 0b6d55d31..35d2e235d 100644 --- a/nimble/host/test/src/ble_att_clt_test.c +++ b/nimble/host/test/src/ble_att_clt_test.c @@ -67,9 +67,9 @@ ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle, uint16_t handle, om = ble_hs_test_util_om_from_flat(value, value_len); if (is_req) { - rc = ble_att_clt_tx_write_req(conn_handle, handle, om); + rc = ble_att_clt_tx_write_req(conn_handle, BLE_L2CAP_CID_ATT, handle, om); } else { - rc = ble_att_clt_tx_write_cmd(conn_handle, handle, om); + rc = ble_att_clt_tx_write_cmd(conn_handle, BLE_L2CAP_CID_ATT, handle, om); } TEST_ASSERT(rc == 0); } @@ -78,25 +78,35 @@ TEST_CASE_SELF(ble_att_clt_test_tx_find_info) { uint16_t conn_handle; int rc; + struct ble_hs_conn *conn; ble_hs_test_util_assert_mbufs_freed(NULL); conn_handle = ble_att_clt_test_misc_init(); + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); /*** Success. */ - rc = ble_att_clt_tx_find_info(conn_handle, 1, 0xffff); + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 1, 0xffff); TEST_ASSERT(rc == 0); /*** Error: start handle of 0. */ - rc = ble_att_clt_tx_find_info(conn_handle, 0, 0xffff); + /** In unit tests we don't are not receiving response - procedure will + * not complete. Reset `client_att_busy` flag so new request can be sent + */ + conn->client_att_busy = false; + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 0, 0xffff); TEST_ASSERT(rc == BLE_HS_EINVAL); /*** Error: start handle greater than end handle. */ - rc = ble_att_clt_tx_find_info(conn_handle, 500, 499); + conn->client_att_busy = false; + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 500, 499); TEST_ASSERT(rc == BLE_HS_EINVAL); /*** Success; start and end handles equal. */ - rc = ble_att_clt_tx_find_info(conn_handle, 500, 500); + conn->client_att_busy = false; + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 500, 500); TEST_ASSERT(rc == 0); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -175,9 +185,14 @@ ble_att_clt_test_case_tx_write_req_or_cmd(int is_req) uint16_t conn_handle; uint8_t value300[500] = { 0 }; uint8_t value5[5] = { 6, 7, 54, 34, 8 }; + struct ble_hs_conn *conn; conn_handle = ble_att_clt_test_misc_init(); + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + /*** 5-byte write. */ ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0x1234, value5, sizeof value5, is_req); @@ -185,6 +200,10 @@ ble_att_clt_test_case_tx_write_req_or_cmd(int is_req) is_req); /*** Overlong write; verify command truncated to ATT MTU. */ + /** In unit tests we are not receiving response - procedure will + * not complete. Reset `client_att_busy` flag so new request can be sent + */ + conn->client_att_busy = false; ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0xab83, value300, sizeof value300, is_req); ble_att_clt_test_misc_verify_tx_write(0xab83, value300, @@ -206,7 +225,7 @@ ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset, conn_handle = ble_att_clt_test_misc_init(); om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len); - rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om); + rc = ble_att_clt_tx_prep_write(conn_handle, BLE_L2CAP_CID_ATT, handle, offset, om); TEST_ASSERT(rc == 0); om = ble_hs_test_util_prev_tx_dequeue_pullup(); @@ -232,7 +251,7 @@ ble_att_clt_test_misc_exec_good(uint8_t flags) conn_handle = ble_att_clt_test_misc_init(); - rc = ble_att_clt_tx_exec_write(conn_handle, flags); + rc = ble_att_clt_tx_exec_write(conn_handle, BLE_L2CAP_CID_ATT, flags); TEST_ASSERT(rc == 0); om = ble_hs_test_util_prev_tx_dequeue_pullup(); @@ -256,7 +275,7 @@ ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset, om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len); - rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om); + rc = ble_att_clt_tx_prep_write(conn_handle, BLE_L2CAP_CID_ATT, handle, offset, om); TEST_ASSERT(rc == status); } @@ -287,11 +306,11 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read) conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ - rc = ble_att_clt_tx_read(conn_handle, 1); + rc = ble_att_clt_tx_read(conn_handle, BLE_L2CAP_CID_ATT, 1); TEST_ASSERT(rc == 0); /*** Error: handle of 0. */ - rc = ble_att_clt_tx_read(conn_handle, 0); + rc = ble_att_clt_tx_read(conn_handle, BLE_L2CAP_CID_ATT, 0); TEST_ASSERT(rc == BLE_HS_EINVAL); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -333,11 +352,11 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read_blob) conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ - rc = ble_att_clt_tx_read_blob(conn_handle, 1, 0); + rc = ble_att_clt_tx_read_blob(conn_handle, BLE_L2CAP_CID_ATT, 1, 0); TEST_ASSERT(rc == 0); /*** Error: handle of 0. */ - rc = ble_att_clt_tx_read_blob(conn_handle, 0, 0); + rc = ble_att_clt_tx_read_blob(conn_handle, BLE_L2CAP_CID_ATT, 0, 0); TEST_ASSERT(rc == BLE_HS_EINVAL); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -380,7 +399,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, false); + 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 +411,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, false); + 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); @@ -501,14 +520,14 @@ TEST_CASE_SELF(ble_att_clt_test_tx_exec_write) uint16_t conn_handle; int rc; - conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_CANCEL); ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_EXECUTE); /*** Success: nonzero == execute. */ - rc = ble_att_clt_tx_exec_write(conn_handle, 0x02); + conn_handle = ble_att_clt_test_misc_init(); + rc = ble_att_clt_tx_exec_write(conn_handle, BLE_L2CAP_CID_ATT, 0x02); TEST_ASSERT(rc == 0); ble_hs_test_util_assert_mbufs_freed(NULL); diff --git a/nimble/host/test/src/ble_att_svr_test.c b/nimble/host/test/src/ble_att_svr_test.c index 60ab14b4e..84394d6a5 100644 --- a/nimble/host/test/src/ble_att_svr_test.c +++ b/nimble/host/test/src/ble_att_svr_test.c @@ -24,6 +24,7 @@ #include "nimble/hci_common.h" #include "ble_hs_test.h" #include "host/ble_uuid.h" +#include "host/ble_l2cap.h" #include "ble_hs_test_util.h" static uint8_t *ble_att_svr_test_attr_r_1; @@ -478,7 +479,7 @@ ble_att_svr_test_misc_verify_all_read_mult( } static void -ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle) +ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle, uint16_t cid) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; @@ -487,7 +488,7 @@ ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, &conn, &chan); assert(rc == 0); my_mtu = chan->my_mtu; @@ -644,7 +645,7 @@ ble_att_svr_test_misc_mtu_exchange(uint16_t my_mtu, uint16_t peer_sent, buf, sizeof buf); TEST_ASSERT(rc == 0); - ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle); + ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle, BLE_L2CAP_CID_ATT); ble_hs_lock(); rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, @@ -1138,19 +1139,19 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) conn_handle = ble_att_svr_test_misc_init(128); /*** Start handle of 0. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 0, 0); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 0, 0); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 0, BLE_ATT_ERR_INVALID_HANDLE); /*** Start handle > end handle. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 101, 100); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 101, 100); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 101, BLE_ATT_ERR_INVALID_HANDLE); /*** No attributes. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 200, 300); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 200, 300); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND); @@ -1160,13 +1161,13 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) ble_att_svr_test_misc_attr_fn_r_1, NULL); TEST_ASSERT(rc == 0); - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 200, 300); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 200, 300); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND); /*** One 128-bit entry. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle1); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle1, handle1); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1181,7 +1182,7 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) ble_att_svr_test_misc_attr_fn_r_1, NULL); TEST_ASSERT(rc == 0); - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle2); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle1, handle2); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1199,7 +1200,7 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) ble_att_svr_test_misc_attr_fn_r_1, NULL); TEST_ASSERT(rc == 0); - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle3); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle1, handle3); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1213,7 +1214,7 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) } })); /*** Remaining 16-bit entry requested. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle3, handle3); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle3, handle3); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1936,13 +1937,13 @@ TEST_CASE_SELF(ble_att_svr_test_oom) TEST_ASSERT_FATAL(rc == 0); /* Ensure we were able to send a real response. */ - ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle); + ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle, BLE_L2CAP_CID_ATT); /*** Find information; always respond affirmatively, even when no mbufs. */ ble_hs_test_util_prev_tx_dequeue(); /* Receive a request. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 1, 100); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 1, 100); TEST_ASSERT_FATAL(rc == 0); /* Ensure we were able to send a real response. */ diff --git a/nimble/host/test/src/ble_gatt_conn_test.c b/nimble/host/test/src/ble_gatt_conn_test.c index 5cb94ce82..d74dd6fcf 100644 --- a/nimble/host/test/src/ble_gatt_conn_test.c +++ b/nimble/host/test/src/ble_gatt_conn_test.c @@ -385,6 +385,7 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) uint16_t attr_handle; uint16_t offset = 0; int rc; + struct ble_hs_conn *conn; ble_gatt_conn_test_util_init(); @@ -405,65 +406,92 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) /*** Schedule some GATT procedures. */ /* Connection 1. */ mtu_arg.exp_conn_handle = 1; + ble_hs_lock(); + conn = ble_hs_conn_find(1); + ble_hs_unlock(); + + /** In unit tests we are not receiving response - procedure will + * not complete. Reset `client_att_busy` flag so new request can be sent + */ + conn->client_att_busy = false; ble_gattc_exchange_mtu(1, ble_gatt_conn_test_mtu_cb, &mtu_arg); disc_all_svcs_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_disc_all_svcs(1, ble_gatt_conn_test_disc_all_svcs_cb, &disc_all_svcs_arg); TEST_ASSERT_FATAL(rc == 0); disc_svc_uuid_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_disc_svc_by_uuid(1, BLE_UUID16_DECLARE(0x1111), ble_gatt_conn_test_disc_svc_uuid_cb, &disc_svc_uuid_arg); TEST_ASSERT_FATAL(rc == 0); find_inc_svcs_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_find_inc_svcs(1, 1, 0xffff, ble_gatt_conn_test_find_inc_svcs_cb, &find_inc_svcs_arg); TEST_ASSERT_FATAL(rc == 0); disc_all_chrs_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_disc_all_chrs(1, 1, 0xffff, ble_gatt_conn_test_disc_all_chrs_cb, &disc_all_chrs_arg); TEST_ASSERT_FATAL(rc == 0); /* Connection 2. */ + ble_hs_lock(); + conn = ble_hs_conn_find(2); + ble_hs_unlock(); + disc_all_dscs_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_disc_all_dscs(2, 3, 0xffff, ble_gatt_conn_test_disc_all_dscs_cb, &disc_all_dscs_arg); disc_chr_uuid_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_disc_chrs_by_uuid(2, 2, 0xffff, BLE_UUID16_DECLARE(0x2222), ble_gatt_conn_test_disc_chr_uuid_cb, &disc_chr_uuid_arg); read_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_read(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE, ble_gatt_conn_test_read_cb, &read_arg); TEST_ASSERT_FATAL(rc == 0); read_uuid_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_read_by_uuid(2, 1, 0xffff, BLE_UUID16_DECLARE(0x3333), ble_gatt_conn_test_read_uuid_cb, &read_uuid_arg); TEST_ASSERT_FATAL(rc == 0); read_long_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_read_long(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE, offset, ble_gatt_conn_test_read_long_cb, &read_long_arg); TEST_ASSERT_FATAL(rc == 0); /* Connection 3. */ + ble_hs_lock(); + conn = ble_hs_conn_find(3); + ble_hs_unlock(); + read_mult_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_gattc_read_mult(3, ((uint16_t[3]){5,6,7}), 3, ble_gatt_conn_test_read_mult_cb, &read_mult_arg); TEST_ASSERT_FATAL(rc == 0); write_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_hs_test_util_gatt_write_flat( 3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE, ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value, @@ -471,6 +499,7 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) TEST_ASSERT_FATAL(rc == 0); write_long_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_hs_test_util_gatt_write_long_flat( 3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE, ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value, @@ -481,10 +510,12 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) attr.offset = 0; attr.om = os_msys_get_pkthdr(0, 0); write_rel_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_gattc_write_reliable( 3, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg); TEST_ASSERT_FATAL(rc == 0); + conn->client_att_busy = false; rc = ble_gatts_indicate(3, attr_handle); TEST_ASSERT_FATAL(rc == 0); @@ -528,6 +559,11 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) TEST_ASSERT(ble_gatt_conn_test_gap_event.type == 255); /* Connection 3. */ + /** This is required because of call ble_att_clt_tx_exec_write + * from ble_att_clt_tx_exec_write after broken connection - + * ble_gattc_fail_procs is called + */ + conn->client_att_busy = false; ble_gattc_connection_broken(3); TEST_ASSERT(mtu_arg.called == 1); TEST_ASSERT(disc_all_svcs_arg.called == 1); diff --git a/nimble/host/test/src/ble_gatt_disc_c_test.c b/nimble/host/test/src/ble_gatt_disc_c_test.c index e19db341b..d0034889f 100644 --- a/nimble/host/test/src/ble_gatt_disc_c_test.c +++ b/nimble/host/test/src/ble_gatt_disc_c_test.c @@ -25,6 +25,7 @@ #include "ble_hs_test.h" #include "host/ble_gatt.h" #include "host/ble_uuid.h" +#include "host/ble_l2cap.h" #include "ble_hs_test_util.h" struct ble_gatt_disc_c_test_char { @@ -50,8 +51,8 @@ ble_gatt_disc_c_test_init(void) } static int -ble_gatt_disc_c_test_misc_rx_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_c_test_char *chars) +ble_gatt_disc_c_test_misc_rx_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_c_test_char *chars) { struct ble_att_read_type_rsp rsp; uint8_t buf[1024]; @@ -86,14 +87,14 @@ ble_gatt_disc_c_test_misc_rx_rsp_once( if (chars[i].uuid->type == BLE_UUID_TYPE_16) { if (off + BLE_ATT_READ_TYPE_ADATA_SZ_16 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; } } else { if (off + BLE_ATT_READ_TYPE_ADATA_SZ_128 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; @@ -121,7 +122,7 @@ ble_gatt_disc_c_test_misc_rx_rsp_once( } static void -ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, +ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, uint16_t cid, uint16_t end_handle, struct ble_gatt_disc_c_test_char *chars) { @@ -130,7 +131,7 @@ ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, idx = 0; while (chars[idx].def_handle != 0) { - count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn_handle, + count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn_handle, cid, chars + idx); if (count == 0) { break; @@ -140,7 +141,8 @@ ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, if (chars[idx - 1].def_handle != end_handle) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, + BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, chars[idx - 1].def_handle); } @@ -229,7 +231,7 @@ ble_gatt_disc_c_test_misc_all(uint16_t start_handle, uint16_t end_handle, ble_gatt_disc_c_test_misc_cb, &num_left); TEST_ASSERT(rc == 0); - ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, chars); + ble_gatt_disc_c_test_misc_rx_rsp(2, BLE_L2CAP_CID_ATT, end_handle, chars); ble_gatt_disc_c_test_misc_verify_chars(chars, stop_after); } @@ -252,7 +254,7 @@ ble_gatt_disc_c_test_misc_uuid(uint16_t start_handle, uint16_t end_handle, &stop_after); TEST_ASSERT(rc == 0); - ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, rsp_chars); + ble_gatt_disc_c_test_misc_rx_rsp(2, BLE_L2CAP_CID_ATT, end_handle, rsp_chars); ble_gatt_disc_c_test_misc_verify_chars(ret_chars, 0); } @@ -574,7 +576,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs); + num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs); /* Make sure there are still undiscovered characteristics. */ TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1); @@ -598,7 +600,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs); + ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs + num_chrs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -617,7 +619,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); @@ -663,7 +665,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs); + num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs); /* Make sure there are still undiscovered characteristics. */ TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1); @@ -686,7 +688,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs); + ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs + num_chrs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -704,7 +706,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); diff --git a/nimble/host/test/src/ble_gatt_disc_d_test.c b/nimble/host/test/src/ble_gatt_disc_d_test.c index e405c86f1..acee2ef8d 100644 --- a/nimble/host/test/src/ble_gatt_disc_d_test.c +++ b/nimble/host/test/src/ble_gatt_disc_d_test.c @@ -49,8 +49,8 @@ ble_gatt_disc_d_test_init(void) } static int -ble_gatt_disc_d_test_misc_rx_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_d_test_dsc *dscs) +ble_gatt_disc_d_test_misc_rx_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_d_test_dsc *dscs) { struct ble_att_find_info_rsp rsp; uint8_t buf[1024]; @@ -77,14 +77,14 @@ ble_gatt_disc_d_test_misc_rx_rsp_once( if (dscs[i].dsc_uuid.u.type == BLE_UUID_TYPE_16) { if (off + BLE_ATT_FIND_INFO_IDATA_16_SZ > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; } } else { if (off + BLE_ATT_FIND_INFO_IDATA_128_SZ > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; @@ -104,7 +104,7 @@ ble_gatt_disc_d_test_misc_rx_rsp_once( off += ble_uuid_length(&dscs[i].dsc_uuid.u); } - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -113,6 +113,7 @@ ble_gatt_disc_d_test_misc_rx_rsp_once( static void ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle, + uint16_t cid, uint16_t end_handle, struct ble_gatt_disc_d_test_dsc *dscs) { @@ -121,7 +122,7 @@ ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle, idx = 0; while (dscs[idx].chr_val_handle != 0) { - count = ble_gatt_disc_d_test_misc_rx_rsp_once(conn_handle, dscs + idx); + count = ble_gatt_disc_d_test_misc_rx_rsp_once(conn_handle, cid, dscs + idx); if (count == 0) { break; } @@ -130,7 +131,8 @@ ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle, if (dscs[idx - 1].dsc_handle != end_handle) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_FIND_INFO_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, + BLE_ATT_OP_FIND_INFO_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, end_handle); } @@ -223,7 +225,7 @@ ble_gatt_disc_d_test_misc_all(uint16_t chr_val_handle, uint16_t end_handle, ble_gatt_disc_d_test_misc_cb, &num_left); TEST_ASSERT(rc == 0); - ble_gatt_disc_d_test_misc_rx_rsp(2, end_handle, dscs); + ble_gatt_disc_d_test_misc_rx_rsp(2, BLE_L2CAP_CID_ATT, end_handle, dscs); ble_gatt_disc_d_test_misc_verify_dscs(dscs, stop_after); } @@ -389,7 +391,7 @@ TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_dscs = ble_gatt_disc_d_test_misc_rx_rsp_once(1, dscs); + num_dscs = ble_gatt_disc_d_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, dscs); /* Make sure there are still undiscovered services. */ TEST_ASSERT_FATAL(num_dscs < sizeof dscs / sizeof dscs[0] - 1); @@ -412,7 +414,7 @@ TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_d_test_misc_rx_rsp_once(1, dscs + num_dscs); + ble_gatt_disc_d_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, dscs + num_dscs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -430,7 +432,7 @@ TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); diff --git a/nimble/host/test/src/ble_gatt_disc_s_test.c b/nimble/host/test/src/ble_gatt_disc_s_test.c index 3e7a30266..87735f7df 100644 --- a/nimble/host/test/src/ble_gatt_disc_s_test.c +++ b/nimble/host/test/src/ble_gatt_disc_s_test.c @@ -56,8 +56,8 @@ ble_gatt_disc_s_test_misc_svc_length(struct ble_gatt_disc_s_test_svc *service) } static int -ble_gatt_disc_s_test_misc_rx_all_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_all_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { struct ble_att_read_group_type_rsp rsp; uint8_t buf[1024]; @@ -86,14 +86,14 @@ ble_gatt_disc_s_test_misc_rx_all_rsp_once( if (services[i].uuid->type == BLE_UUID_TYPE_16) { if (off + BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; } } else { if (off + BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle,cid)) { /* Can't fit any more entries. */ break; @@ -110,7 +110,7 @@ ble_gatt_disc_s_test_misc_rx_all_rsp_once( off += ble_uuid_length(services[i].uuid); } - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -118,22 +118,22 @@ ble_gatt_disc_s_test_misc_rx_all_rsp_once( } static void -ble_gatt_disc_s_test_misc_rx_all_rsp( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_all_rsp(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { int count; int idx; idx = 0; while (services[idx].start_handle != 0) { - count = ble_gatt_disc_s_test_misc_rx_all_rsp_once(conn_handle, + count = ble_gatt_disc_s_test_misc_rx_all_rsp_once(conn_handle, cid, services + idx); idx += count; } if (services[idx - 1].end_handle != 0xffff) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, BLE_ATT_OP_READ_GROUP_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, services[idx - 1].start_handle); @@ -141,8 +141,8 @@ ble_gatt_disc_s_test_misc_rx_all_rsp( } static int -ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { uint8_t buf[1024]; int off; @@ -160,7 +160,7 @@ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( } if (off + BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; @@ -173,7 +173,7 @@ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( off += 2; } - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -181,22 +181,22 @@ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( } static void -ble_gatt_disc_s_test_misc_rx_uuid_rsp( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_uuid_rsp(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { int count; int idx; idx = 0; while (services[idx].start_handle != 0) { - count = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(conn_handle, + count = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(conn_handle, cid, services + idx); idx += count; } if (services[idx - 1].end_handle != 0xffff) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, BLE_ATT_OP_FIND_TYPE_VALUE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, services[idx - 1].start_handle); @@ -269,7 +269,7 @@ ble_gatt_disc_s_test_misc_good_all(struct ble_gatt_disc_s_test_svc *services) rc = ble_gattc_disc_all_svcs(2, ble_gatt_disc_s_test_misc_disc_cb, NULL); TEST_ASSERT(rc == 0); - ble_gatt_disc_s_test_misc_rx_all_rsp(2, services); + ble_gatt_disc_s_test_misc_rx_all_rsp(2, BLE_L2CAP_CID_ATT, services); ble_gatt_disc_s_test_misc_verify_services(services); } @@ -290,7 +290,7 @@ ble_gatt_disc_s_test_misc_good_uuid( ble_hs_test_util_verify_tx_disc_svc_uuid(services[0].uuid); - ble_gatt_disc_s_test_misc_rx_uuid_rsp(2, services); + ble_gatt_disc_s_test_misc_rx_uuid_rsp(2, BLE_L2CAP_CID_ATT, services); ble_gatt_disc_s_test_misc_verify_services(services); } @@ -425,7 +425,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_svcs = ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs); + num_svcs = ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, BLE_L2CAP_CID_ATT, svcs); /* Make sure there are still undiscovered services. */ TEST_ASSERT_FATAL(num_svcs < sizeof svcs / sizeof svcs[0] - 1); @@ -448,7 +448,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs + num_svcs); + ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, BLE_L2CAP_CID_ATT, svcs + num_svcs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -465,7 +465,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_GROUP_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); @@ -504,7 +504,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_svcs = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, svcs); + num_svcs = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, BLE_L2CAP_CID_ATT, svcs); /* Make sure there are still undiscovered services. */ TEST_ASSERT_FATAL(num_svcs < sizeof svcs / sizeof svcs[0] - 1); @@ -527,7 +527,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, svcs + num_svcs); + ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, BLE_L2CAP_CID_ATT, svcs + num_svcs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -545,7 +545,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_GROUP_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); @@ -579,7 +579,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_timeout) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs); + ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, BLE_L2CAP_CID_ATT, svcs); /* Keep trying to resume for 30 seconds, but never free any mbufs. Verify * procedure eventually times out. diff --git a/nimble/host/test/src/ble_gatt_find_s_test.c b/nimble/host/test/src/ble_gatt_find_s_test.c index 172bdd332..5f8075c9a 100644 --- a/nimble/host/test/src/ble_gatt_find_s_test.c +++ b/nimble/host/test/src/ble_gatt_find_s_test.c @@ -90,8 +90,8 @@ ble_gatt_find_s_test_misc_verify_incs( } static int -ble_gatt_find_s_test_misc_rx_read_type( - uint16_t conn_handle, struct ble_gatt_find_s_test_entry *entries) +ble_gatt_find_s_test_misc_rx_read_type(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_find_s_test_entry *entries) { struct ble_att_read_type_rsp rsp; uint8_t buf[1024]; @@ -134,14 +134,15 @@ ble_gatt_find_s_test_misc_rx_read_type( } if (i == 0) { - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, + BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 0); return 0; } ble_att_read_type_rsp_write(buf + 0, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -149,7 +150,7 @@ ble_gatt_find_s_test_misc_rx_read_type( } static void -ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, const ble_uuid_t *uuid) +ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, uint16_t cid, const ble_uuid_t *uuid) { uint8_t buf[17]; int rc; @@ -159,7 +160,7 @@ ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, const ble_uuid_t *uuid) buf[0] = BLE_ATT_OP_READ_RSP; ble_uuid_flat(uuid, buf + 1); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, 17); TEST_ASSERT(rc == 0); } @@ -200,7 +201,7 @@ ble_gatt_find_s_test_misc_verify_tx_read(uint16_t handle) } static void -ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, +ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, struct ble_gatt_find_s_test_entry *entries) { @@ -219,7 +220,7 @@ ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, idx = 0; while (1) { ble_gatt_find_s_test_misc_verify_tx_read_type(cur_start, end_handle); - num_found = ble_gatt_find_s_test_misc_rx_read_type(conn_handle, + num_found = ble_gatt_find_s_test_misc_rx_read_type(conn_handle, cid, entries + idx); if (num_found == 0) { break; @@ -229,7 +230,7 @@ ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, TEST_ASSERT(num_found == 1); ble_gatt_find_s_test_misc_verify_tx_read( entries[idx].start_handle); - ble_gatt_find_s_test_misc_rx_read(conn_handle, + ble_gatt_find_s_test_misc_rx_read(conn_handle, cid, entries[idx].uuid); } @@ -255,7 +256,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 5, 10, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 5, 10, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 6, .start_handle = 35, @@ -275,7 +276,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 34, 100, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 34, 100, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 36, .start_handle = 403, @@ -290,7 +291,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 34, 100, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 34, 100, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 36, .start_handle = 403, @@ -310,7 +311,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 1, 100, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 1, 100, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 36, .start_handle = 403, @@ -379,7 +380,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_find_s_test_misc_rx_read_type(1, incs); + ble_gatt_find_s_test_misc_rx_read_type(1, BLE_L2CAP_CID_ATT, incs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -402,11 +403,11 @@ TEST_CASE_SELF(ble_gatt_find_s_test_oom) * follow-up request, so there is always an mbuf available. */ /* XXX: Find a way to test this. */ - ble_gatt_find_s_test_misc_rx_read(1, incs[0].uuid); + ble_gatt_find_s_test_misc_rx_read(1, BLE_L2CAP_CID_ATT, incs[0].uuid); /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_find_s_test_misc_rx_read_type(1, incs + 1); + ble_gatt_find_s_test_misc_rx_read_type(1, BLE_L2CAP_CID_ATT, incs + 1); /* Verify the procedure succeeds after mbufs become available. */ rc = os_mbuf_free_chain(oms); @@ -414,9 +415,9 @@ TEST_CASE_SELF(ble_gatt_find_s_test_oom) os_time_advance(ticks_until); ble_gattc_timer(); - ble_gatt_find_s_test_misc_rx_read(1, incs[1].uuid); + ble_gatt_find_s_test_misc_rx_read(1, BLE_L2CAP_CID_ATT, incs[1].uuid); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); diff --git a/nimble/host/test/src/ble_gatt_read_test.c b/nimble/host/test/src/ble_gatt_read_test.c index 572b0bf1c..a22e5a559 100644 --- a/nimble/host/test/src/ble_gatt_read_test.c +++ b/nimble/host/test/src/ble_gatt_read_test.c @@ -160,7 +160,7 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle, } static void -ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle, +ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle, uint16_t cid, uint8_t att_op, const void *data, int data_len) { @@ -174,27 +174,28 @@ ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle, buf[0] = att_op; memcpy(buf + 1, data, data_len); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, 1 + data_len); TEST_ASSERT(rc == 0); } static void -ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle, +ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle, uint16_t cid, struct ble_hs_test_util_flat_attr *attr) { - ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, BLE_ATT_OP_READ_RSP, + ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, cid, + BLE_ATT_OP_READ_RSP, attr->value, attr->value_len); } static void -ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle, +ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle, uint16_t cid, uint8_t att_error, uint16_t err_handle) { /* Send the pending ATT Read Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, BLE_ATT_OP_READ_REQ, att_error, err_handle); } @@ -255,7 +256,7 @@ ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr *attr) rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_good(2, attr); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attr); TEST_ASSERT(ble_gatt_read_test_num_attrs == 1); TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2); @@ -278,7 +279,7 @@ ble_gatt_read_test_misc_verify_bad(uint8_t att_status, rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle); + ble_gatt_read_test_misc_rx_rsp_bad(2, BLE_L2CAP_CID_ATT, att_status, attr->handle); TEST_ASSERT(ble_gatt_read_test_num_attrs == 0); TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2); @@ -309,7 +310,8 @@ ble_gatt_read_test_misc_uuid_verify_good( while (1) { num_read = ble_gatt_read_test_misc_uuid_rx_rsp_good(2, attrs + idx); if (num_read == 0) { - ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_READ_TYPE_REQ, + ble_hs_test_util_rx_att_err_rsp(2, BLE_L2CAP_CID_ATT, + BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, start_handle); break; @@ -369,7 +371,7 @@ ble_gatt_read_test_misc_long_verify_good( } else { att_op = BLE_ATT_OP_READ_BLOB_RSP; } - ble_gatt_read_test_misc_rx_rsp_good_raw(2, att_op, + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, att_op, attr->value + off, chunk_sz); rem_len -= chunk_sz; off += chunk_sz; @@ -401,7 +403,7 @@ ble_gatt_read_test_misc_long_verify_bad( ble_gatt_read_test_long_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle); + ble_gatt_read_test_misc_rx_rsp_bad(2, BLE_L2CAP_CID_ATT, att_status, attr->handle); TEST_ASSERT(ble_gatt_read_test_num_attrs == 0); TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2); @@ -458,7 +460,7 @@ ble_gatt_read_test_misc_mult_verify_good( ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_MULT_RSP, + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_MULT_RSP, expected_value, off); TEST_ASSERT(ble_gatt_read_test_complete); @@ -488,7 +490,7 @@ ble_gatt_read_test_misc_mult_verify_bad( ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, err_handle); + ble_gatt_read_test_misc_rx_rsp_bad(2, BLE_L2CAP_CID_ATT, att_status, err_handle); TEST_ASSERT(ble_gatt_read_test_num_attrs == 0); TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2); @@ -801,9 +803,9 @@ TEST_CASE_SELF(ble_gatt_read_test_concurrent) rc = ble_gattc_read(2, attrs[2].handle, ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 0); - ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 1); - ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 2); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attrs + 0); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attrs + 1); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attrs + 2); TEST_ASSERT(ble_gatt_read_test_num_attrs == 3); @@ -852,8 +854,8 @@ TEST_CASE_SELF(ble_gatt_read_test_long_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ; - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP, + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_READ_RSP_BASE_SZ; + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_RSP, attr.value + off, chunk_sz); off += chunk_sz; @@ -875,8 +877,8 @@ TEST_CASE_SELF(ble_gatt_read_test_long_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ; - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP, + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_READ_RSP_BASE_SZ; + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_RSP, attr.value + off, chunk_sz); off += chunk_sz; @@ -897,7 +899,7 @@ TEST_CASE_SELF(ble_gatt_read_test_long_oom) ble_gattc_timer(); chunk_sz = attr.value_len - off; - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP, + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_RSP, attr.value + off, chunk_sz); off += chunk_sz; diff --git a/nimble/host/test/src/ble_gatt_write_test.c b/nimble/host/test/src/ble_gatt_write_test.c index caa8e5657..ea815c0d5 100644 --- a/nimble/host/test/src/ble_gatt_write_test.c +++ b/nimble/host/test/src/ble_gatt_write_test.c @@ -87,8 +87,8 @@ ble_gatt_write_test_rx_rsp(uint16_t conn_handle) } static void -ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle, - uint16_t offset, +ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t cid, + uint16_t attr_handle, uint16_t offset, const void *attr_data, uint16_t attr_data_len) { struct ble_att_prep_write_cmd rsp; @@ -102,19 +102,19 @@ ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle, memcpy(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, attr_data, attr_data_len); rc = ble_hs_test_util_l2cap_rx_payload_flat( - conn_handle, BLE_L2CAP_CID_ATT, buf, + conn_handle, cid, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len); TEST_ASSERT(rc == 0); } static void -ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle) +ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle, uint16_t cid) { uint8_t op; int rc; op = BLE_ATT_OP_EXEC_WRITE_RSP; - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, &op, 1); TEST_ASSERT(rc == 0); } @@ -129,10 +129,10 @@ ble_gatt_write_test_misc_long_good(int attr_len) ble_gatt_write_test_init(); - ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), + ble_hs_test_util_create_conn(2, ((uint8_t[]) {2,3,4,5,6,7,8,9}), NULL, NULL); - mtu = ble_att_mtu(2); + mtu = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT); rc = ble_hs_test_util_gatt_write_long_flat( 2, 100, ble_gatt_write_test_attr_value, attr_len, @@ -152,7 +152,7 @@ ble_gatt_write_test_misc_long_good(int attr_len) /* Receive Prep Write response. */ ble_gatt_write_test_rx_prep_rsp( - 2, 100, off, ble_gatt_write_test_attr_value + off, len); + 2, BLE_L2CAP_CID_ATT, 100, off, ble_gatt_write_test_attr_value + off, len); /* Verify callback hasn't gotten called. */ TEST_ASSERT(!ble_gatt_write_test_cb_called); @@ -164,13 +164,13 @@ ble_gatt_write_test_misc_long_good(int attr_len) ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); } -typedef void ble_gatt_write_test_long_fail_fn(uint16_t conn_handle, +typedef void ble_gatt_write_test_long_fail_fn(uint16_t conn_handle, uint16_t cid, int off, int len); static void @@ -185,9 +185,9 @@ ble_gatt_write_test_misc_long_bad(int attr_len, ble_gatt_write_test_init(); - ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), + ble_hs_test_util_create_conn(2, ((uint8_t[]) {2,3,4,5,6,7,8,9}), NULL, NULL); - mtu = ble_att_mtu(2); + mtu = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT); rc = ble_hs_test_util_gatt_write_long_flat( 2, 100, ble_gatt_write_test_attr_value, attr_len, @@ -214,9 +214,9 @@ ble_gatt_write_test_misc_long_bad(int attr_len, } if (!fail_now) { ble_gatt_write_test_rx_prep_rsp( - 2, 100, off, ble_gatt_write_test_attr_value + off, len); + 2, BLE_L2CAP_CID_ATT, 100, off, ble_gatt_write_test_attr_value + off, len); } else { - cb(2, off, len); + cb(2, BLE_L2CAP_CID_ATT, off, len); break; } @@ -233,38 +233,38 @@ ble_gatt_write_test_misc_long_bad(int attr_len, } static void -ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 99, off, ble_gatt_write_test_attr_value + off, + conn_handle, cid, 99, off, ble_gatt_write_test_attr_value + off, len); } static void -ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 100, off + 1, ble_gatt_write_test_attr_value + off, + conn_handle, cid, 100, off + 1, ble_gatt_write_test_attr_value + off, len); } static void -ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 100, off, ble_gatt_write_test_attr_value + off + 1, + conn_handle, cid, 100, off, ble_gatt_write_test_attr_value + off + 1, len); } static void -ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 100, off, ble_gatt_write_test_attr_value + off, + conn_handle, cid, 100, off, ble_gatt_write_test_attr_value + off, len - 1); } @@ -313,9 +313,9 @@ ble_gatt_write_test_misc_reliable_good( flat_attrs + num_attrs); } - ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), + ble_hs_test_util_create_conn(2, ((uint8_t[]) {2,3,4,5,6,7,8,9}), NULL, NULL); - mtu = ble_att_mtu(2); + mtu = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT); rc = ble_gattc_write_reliable(2, attrs, num_attrs, ble_gatt_write_test_reliable_cb_good, NULL); @@ -336,7 +336,7 @@ ble_gatt_write_test_misc_reliable_good( attr->value + off, len); /* Receive Prep Write response. */ - ble_gatt_write_test_rx_prep_rsp(2, attr->handle, off, + ble_gatt_write_test_rx_prep_rsp(2, BLE_L2CAP_CID_ATT, attr->handle, off, attr->value + off, len); /* Verify callback hasn't gotten called. */ @@ -353,7 +353,7 @@ ble_gatt_write_test_misc_reliable_good( ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); @@ -599,7 +599,7 @@ TEST_CASE_SELF(ble_gatt_write_test_long_queue_full) /* Receive Prep Write response. */ len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; ble_gatt_write_test_rx_prep_rsp( - 2, 100, off, ble_gatt_write_test_attr_value + off, len); + 2, BLE_L2CAP_CID_ATT, 100, off, ble_gatt_write_test_attr_value + off, len); /* Verify callback hasn't gotten called. */ TEST_ASSERT(!ble_gatt_write_test_cb_called); @@ -611,7 +611,8 @@ TEST_CASE_SELF(ble_gatt_write_test_long_queue_full) TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL); /* Receive queue full error. */ - ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_PREP_WRITE_REQ, + ble_hs_test_util_rx_att_err_rsp(2, BLE_L2CAP_CID_ATT, + BLE_ATT_OP_PREP_WRITE_REQ, BLE_ATT_ERR_PREPARE_QUEUE_FULL, 100); /* Verify callback was called. */ @@ -654,14 +655,14 @@ TEST_CASE_SELF(ble_gatt_write_test_long_oom) ble_gatt_write_test_cb_good, NULL); TEST_ASSERT_FATAL(rc == 0); - chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; ble_hs_test_util_verify_tx_prep_write(attr.handle, off, attr.value + off, chunk_sz); /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off, + ble_gatt_write_test_rx_prep_rsp(2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; @@ -688,7 +689,7 @@ TEST_CASE_SELF(ble_gatt_write_test_long_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); ble_gatt_write_test_rx_prep_rsp( - 2, attr.handle, off, attr.value + off, chunk_sz); + 2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; /* Ensure no follow-up request got sent. It should not have gotten sent @@ -711,7 +712,7 @@ TEST_CASE_SELF(ble_gatt_write_test_long_oom) ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); @@ -750,14 +751,14 @@ TEST_CASE_SELF(ble_gatt_write_test_reliable_oom) ble_gatt_write_test_reliable_cb_good, NULL); TEST_ASSERT_FATAL(rc == 0); - chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; ble_hs_test_util_verify_tx_prep_write(attr.handle, off, attr.value + off, chunk_sz); /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off, + ble_gatt_write_test_rx_prep_rsp(2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; @@ -784,7 +785,7 @@ TEST_CASE_SELF(ble_gatt_write_test_reliable_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); ble_gatt_write_test_rx_prep_rsp( - 2, attr.handle, off, attr.value + off, chunk_sz); + 2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; /* Ensure no follow-up request got sent. It should not have gotten sent @@ -807,7 +808,7 @@ TEST_CASE_SELF(ble_gatt_write_test_reliable_oom) ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); diff --git a/nimble/host/test/src/ble_hs_test_util.c b/nimble/host/test/src/ble_hs_test_util.c index c336ddf92..f5463b3ea 100644 --- a/nimble/host/test/src/ble_hs_test_util.c +++ b/nimble/host/test/src/ble_hs_test_util.c @@ -741,7 +741,7 @@ ble_hs_test_util_set_att_mtu(uint16_t conn_handle, uint16_t mtu) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); assert(rc == 0); chan->my_mtu = mtu; chan->peer_mtu = mtu; @@ -772,6 +772,7 @@ ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, uint16_t mtu) int ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle, + uint16_t cid, uint16_t start_handle, uint16_t end_handle) { @@ -784,7 +785,7 @@ ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle, ble_att_find_info_req_write(buf, sizeof buf, &req); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, sizeof buf); return rc; @@ -1070,7 +1071,7 @@ ble_hs_test_util_rx_att_indicate_req(uint16_t conn_handle, } void -ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, +ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint16_t cid, uint8_t req_op, uint8_t error_code, uint16_t err_handle) { struct ble_att_error_rsp rsp; @@ -1083,7 +1084,7 @@ ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, ble_att_error_rsp_write(buf, sizeof buf, &rsp); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, sizeof buf); TEST_ASSERT(rc == 0); } diff --git a/nimble/host/test/src/ble_hs_test_util.h b/nimble/host/test/src/ble_hs_test_util.h index 7a0aa3eb1..6d5d04c05 100644 --- a/nimble/host/test/src/ble_hs_test_util.h +++ b/nimble/host/test/src/ble_hs_test_util.h @@ -173,6 +173,7 @@ void ble_hs_test_util_set_att_mtu(uint16_t conn_handle, uint16_t mtu); int ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, uint16_t mtu); int ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle, + uint16_t cid, uint16_t start_handle, uint16_t end_handle); int ble_hs_test_util_rx_att_find_type_value_req(uint16_t conn_handle, @@ -228,8 +229,9 @@ int ble_hs_test_util_rx_att_indicate_req(uint16_t conn_handle, uint16_t attr_handle, void *attr_val, uint16_t attr_len); -void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, - uint8_t error_code, uint16_t err_handle); +void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint16_t cid, + uint8_t req_op, uint8_t error_code, + uint16_t err_handle); void ble_hs_test_util_verify_tx_prep_write(uint16_t attr_handle, uint16_t offset, const void *data, int data_len); diff --git a/nimble/host/test/syscfg.yml b/nimble/host/test/syscfg.yml index 031b6c8ba..cfb3a8178 100644 --- a/nimble/host/test/syscfg.yml +++ b/nimble/host/test/syscfg.yml @@ -30,3 +30,4 @@ syscfg.vals: BLE_VERSION: 52 BLE_L2CAP_ENHANCED_COC: 1 BLE_TRANSPORT_LL: custom + BLE_EATT_CHAN_NUM: 0 diff --git a/nimble/include/nimble/nimble_opt_auto.h b/nimble/include/nimble/nimble_opt_auto.h index 6326abf54..8b3fde02d 100644 --- a/nimble/include/nimble/nimble_opt_auto.h +++ b/nimble/include/nimble/nimble_opt_auto.h @@ -113,6 +113,10 @@ extern "C" { #define NIMBLE_BLE_ATT_CLT_INDICATE \ (MYNEWT_VAL(BLE_GATT_INDICATE)) +#undef NIMBLE_BLE_ATT_CLT_NOTIFY_MULT +#define NIMBLE_BLE_ATT_CLT_NOTIFY_MULT \ + (MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE)) + /** Security manager settings. */ #undef NIMBLE_BLE_SM diff --git a/porting/examples/linux/include/logcfg/logcfg.h b/porting/examples/linux/include/logcfg/logcfg.h index 89af35309..9872da0bd 100644 --- a/porting/examples/linux/include/logcfg/logcfg.h +++ b/porting/examples/linux/include/logcfg/logcfg.h @@ -8,6 +8,13 @@ #include "modlog/modlog.h" #include "log_common/log_common.h" +#define BLE_EATT_LOG_DEBUG(...) MODLOG_INFO(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__) #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__) diff --git a/porting/examples/linux/include/syscfg/syscfg.h b/porting/examples/linux/include/syscfg/syscfg.h index d089d7e60..d825fd01c 100644 --- a/porting/examples/linux/include/syscfg/syscfg.h +++ b/porting/examples/linux/include/syscfg/syscfg.h @@ -535,6 +535,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 @@ -575,6 +579,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -615,6 +635,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/examples/linux_blemesh/include/logcfg/logcfg.h b/porting/examples/linux_blemesh/include/logcfg/logcfg.h index 520c658c6..99afa084f 100644 --- a/porting/examples/linux_blemesh/include/logcfg/logcfg.h +++ b/porting/examples/linux_blemesh/include/logcfg/logcfg.h @@ -8,6 +8,13 @@ #include "modlog/modlog.h" #include "log_common/log_common.h" +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__) #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__) diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 1df8abaf8..377428467 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -536,6 +536,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 @@ -576,6 +580,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -616,6 +636,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/examples/nuttx/include/syscfg/syscfg.h b/porting/examples/nuttx/include/syscfg/syscfg.h index 51f8c44bf..a51319c09 100644 --- a/porting/examples/nuttx/include/syscfg/syscfg.h +++ b/porting/examples/nuttx/include/syscfg/syscfg.h @@ -615,6 +615,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/nimble/include/logcfg/logcfg.h b/porting/nimble/include/logcfg/logcfg.h index f2f227c89..14633c52f 100644 --- a/porting/nimble/include/logcfg/logcfg.h +++ b/porting/nimble/include/logcfg/logcfg.h @@ -166,4 +166,11 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #endif diff --git a/porting/nimble/include/syscfg/syscfg.h b/porting/nimble/include/syscfg/syscfg.h index cc8a60b37..158f3846a 100644 --- a/porting/nimble/include/syscfg/syscfg.h +++ b/porting/nimble/include/syscfg/syscfg.h @@ -538,6 +538,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 @@ -578,6 +582,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -618,6 +638,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/porting/npl/riot/include/logcfg/logcfg.h b/porting/npl/riot/include/logcfg/logcfg.h index 89af35309..4fe2ee015 100644 --- a/porting/npl/riot/include/logcfg/logcfg.h +++ b/porting/npl/riot/include/logcfg/logcfg.h @@ -8,6 +8,13 @@ #include "modlog/modlog.h" #include "log_common/log_common.h" +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__) #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__) diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index c90322eaa..a52b22c54 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -1406,6 +1406,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 @@ -1446,6 +1450,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -1486,6 +1506,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif