Skip to content

Commit 406662a

Browse files
nimble/host: add gatts method for async authorization
This method can be used for asynchronous authorization. It can be used by application to trigger access callback of characteristic and send ATT response, in case where ble_att_svr_rx_foo returns with BLE_HS_EPENDING without triggering att response. Move ble_att_svr_tx_rsp and ble_att_svr_build_write_rsp declaration to ble_att_priv.h
1 parent 2bb83e8 commit 406662a

File tree

3 files changed

+121
-1
lines changed

3 files changed

+121
-1
lines changed

nimble/host/include/host/ble_gatt.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,24 @@ int ble_gatts_start(void);
12141214
*/
12151215
int ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_feat, uint8_t len);
12161216

1217+
/**
1218+
* Handles authorization of pending ATT request. If the specified attribute
1219+
* handle is found on pending_attr_list, the operation is performed by calling
1220+
* the registered access callback and ATT response is issued.
1221+
*
1222+
* @param conn_handle The connection over which to authorize a
1223+
* pending ATT procedure
1224+
* @param attr_handle The Handle of characteristic to perform att
1225+
* procedure on.
1226+
* @param authorize Whether to authorize a procedure
1227+
*
1228+
* @return 0 on success;
1229+
* BLE_HS_EAUTHOR if no matching attribute is
1230+
* found on pending_attr_list.
1231+
*/
1232+
int ble_gatts_pending_req_auth(uint16_t conn_handle, uint16_t attr_handle,
1233+
int authorize);
1234+
12171235
#ifdef __cplusplus
12181236
}
12191237
#endif

nimble/host/src/ble_att_priv.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ struct pending_attr {
131131
struct ble_att_svr_entry *entry;
132132
uint16_t offset;
133133
struct os_mbuf *om;
134-
uint16_t opcode;
134+
uint16_t access_opcode;
135+
uint8_t att_opcode;
135136
};
136137

137138
SLIST_HEAD(pending_attr_list_head, pending_attr);
@@ -238,6 +239,15 @@ void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle);
238239
int ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom,
239240
uint8_t req_op, uint16_t handle,
240241
uint8_t error_code);
242+
243+
int ble_att_svr_tx_rsp(uint16_t conn_handle, uint16_t cid, int hs_status,
244+
struct os_mbuf *om, uint8_t att_op,
245+
uint8_t err_status, uint16_t err_handle);
246+
int ble_att_svr_build_write_rsp(struct os_mbuf **rxom,
247+
struct os_mbuf**out_txom, uint8_t *att_err);
248+
int ble_att_svr_insert_prep_entry(uint16_t conn_handle, uint16_t handle,
249+
uint16_t offset, const struct os_mbuf *rxom,
250+
uint8_t *out_att_err);
241251
/*** $clt */
242252

243253
/** An information-data entry in a find information response. */

nimble/host/src/ble_gatts.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,98 @@ ble_gatts_find_dsc(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid,
20342034
}
20352035
}
20362036

2037+
int ble_gatts_pending_req_auth(uint16_t conn_handle, uint16_t attr_handle,
2038+
int authorize)
2039+
{
2040+
struct pending_attr *attr;
2041+
struct pending_attr *pend_attr;
2042+
ble_att_svr_access_fn *access_cb;
2043+
int rc;
2044+
uint8_t att_err = 0;
2045+
struct os_mbuf *txom;
2046+
struct ble_att_prep_write_cmd *req;
2047+
2048+
/* Silence warnings */
2049+
rc = 0;
2050+
pend_attr = NULL;
2051+
txom = NULL;
2052+
2053+
ble_hs_lock();
2054+
SLIST_FOREACH(attr, &pending_attr_list, next) {
2055+
if (attr->conn_handle == conn_handle &&
2056+
attr->entry->ha_handle_id == attr_handle) {
2057+
pend_attr = attr;
2058+
SLIST_REMOVE(&pending_attr_list, attr, pending_attr, next);
2059+
}
2060+
}
2061+
ble_hs_unlock();
2062+
2063+
if (!pend_attr) {
2064+
/* No matching attribute was found on pending_attr_list */
2065+
return BLE_HS_ENOENT;
2066+
}
2067+
2068+
if (pend_attr->att_opcode == BLE_ATT_OP_WRITE_REQ) {
2069+
rc = ble_att_svr_build_write_rsp(&pend_attr->om, &txom, &att_err);
2070+
if (rc != 0) {
2071+
goto done;
2072+
}
2073+
}
2074+
2075+
if (!authorize) {
2076+
att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
2077+
rc = BLE_HS_EAUTHOR;
2078+
goto done;
2079+
}
2080+
2081+
/* Prepare write request */
2082+
if (pend_attr->att_opcode == BLE_ATT_OP_PREP_WRITE_REQ) {
2083+
req = (struct ble_att_prep_write_cmd *)(pend_attr)->om->om_data;
2084+
ble_hs_lock();
2085+
rc = ble_att_svr_insert_prep_entry(conn_handle,
2086+
le16toh(req->bapc_handle),
2087+
le16toh(req->bapc_offset),
2088+
pend_attr->om, &att_err);
2089+
ble_hs_unlock();
2090+
if (rc != 0) {
2091+
goto done;
2092+
}
2093+
// txom = pend_attr->om;
2094+
// pend_attr->rxom = NULL;
2095+
os_mbuf_prepend(pend_attr->om, 1);
2096+
pend_attr->om->om_data[0] = BLE_ATT_OP_PREP_WRITE_RSP;
2097+
rc = 0;
2098+
goto done;
2099+
}
2100+
2101+
if (authorize) {
2102+
access_cb = pend_attr->entry->ha_cb;
2103+
rc = access_cb(pend_attr->conn_handle, pend_attr->entry->ha_handle_id,
2104+
pend_attr->access_opcode, pend_attr->offset,
2105+
&pend_attr->om, pend_attr->entry->ha_cb_arg);
2106+
}
2107+
2108+
if (rc != 0 ) {
2109+
att_err = rc;
2110+
rc = BLE_HS_EAPP;
2111+
}
2112+
2113+
if (pend_attr->att_opcode == BLE_ATT_OP_WRITE_REQ) {
2114+
/* read reuses the request buffer for the response */
2115+
ble_att_svr_tx_rsp(conn_handle, BLE_L2CAP_CID_ATT, rc, txom,
2116+
pend_attr->att_opcode, att_err, attr_handle);
2117+
return 0;
2118+
}
2119+
2120+
/* TODO: don't use BLE_L2CAP_CID_ATT, find a way to get cid */
2121+
done:
2122+
/* Write does not reuse request buffer for the response */
2123+
ble_att_svr_tx_rsp(conn_handle, BLE_L2CAP_CID_ATT, rc, pend_attr->om,
2124+
pend_attr->att_opcode, att_err, attr_handle);
2125+
2126+
return 0;
2127+
}
2128+
20372129
int
20382130
ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs)
20392131
{

0 commit comments

Comments
 (0)