Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bluetooth: services: ras: rreq: Add feature read functionality #19755

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions include/bluetooth/services/ras.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,20 @@ typedef void (*bt_ras_rreq_rd_overwritten_cb_t)(struct bt_conn *conn, uint16_t r
typedef void (*bt_ras_rreq_ranging_data_get_complete_t)(struct bt_conn *conn,
uint16_t ranging_counter, int err);

/** @brief RAS features read callback.
*
* @param[in] conn Connection Object.
* @param[in] feature_bits Bit 0 set if Real-time Ranging Data supported
* Bit 1 set if Retrieve Lost Ranging Data Segments supported
* Bit 2 set if Abort Operation supported
* Bit 3 set if Filter Ranging Data supported
* All other bits are RFU.
* @param[in] err Error code, 0 if the features were read successfully. Otherwise a
* negative error code.
*/
typedef void (*bt_ras_rreq_features_read_cb_t)(struct bt_conn *conn, uint32_t feature_bits,
int err);

/** @brief Allocate a RREQ context and assign GATT handles. Takes a reference to the connection.
*
* @note RREQ context will be freed automatically on disconnect.
Expand Down Expand Up @@ -486,6 +500,19 @@ int bt_ras_rreq_rd_overwritten_subscribe(struct bt_conn *conn, bt_ras_rreq_rd_ov
*/
int bt_ras_rreq_rd_overwritten_unsubscribe(struct bt_conn *conn);

/** @brief Read supported RAS features from peer.
*
* @note Calling from BT RX thread may return an error as bt_gatt_read will not block if
* there are no available TX buffers.
*
* @param[in] conn Connection Object, which already has associated RREQ context.
* @param[in] cb Features read callback.
*
* @retval 0 If the operation was successful.
* Otherwise, a negative error code is returned.
*/
int bt_ras_rreq_read_features(struct bt_conn *conn, bt_ras_rreq_features_read_cb_t cb);

/** @brief Provide step header for each step back to the user.
*
* @param[in] subevent_header Subevent header data.
Expand Down
104 changes: 104 additions & 0 deletions subsys/bluetooth/services/ras/rreq/ras_rreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,18 @@ struct bt_ras_rd_overwritten {
bt_ras_rreq_rd_overwritten_cb_t cb;
};

struct bt_ras_features_read {
struct bt_gatt_read_params read_params;
bt_ras_rreq_features_read_cb_t cb;
};

static struct bt_ras_rreq {
struct bt_conn *conn;
struct bt_ras_rreq_cp cp;
struct bt_ras_on_demand_rd on_demand_rd;
struct bt_ras_rd_ready rd_ready;
struct bt_ras_rd_overwritten rd_overwritten;
struct bt_ras_features_read features_read;
} rreq_pool[CONFIG_BT_RAS_RREQ_MAX_ACTIVE_CONN];

static struct bt_ras_rreq *ras_rreq_find(struct bt_conn *conn)
Expand Down Expand Up @@ -481,6 +487,69 @@ static int ras_cp_subscribe_params_populate(struct bt_gatt_dm *dm, struct bt_ras
return 0;
}

static uint8_t feature_read_cb(struct bt_conn *conn, uint8_t err,
struct bt_gatt_read_params *params, const void *data,
uint16_t length)
{
struct bt_ras_rreq *rreq = ras_rreq_find(conn);

if (rreq == NULL) {
return BT_GATT_ITER_STOP;
}

if (!rreq->features_read.cb) {
LOG_ERR("No read callback present");
return BT_GATT_ITER_STOP;
}

if (err) {
LOG_ERR("Read value error: %d", err);
rreq->features_read.cb(conn, 0, err);
return BT_GATT_ITER_STOP;
}

if (!data || length != sizeof(uint32_t)) {
rreq->features_read.cb(conn, 0, -EMSGSIZE);
return BT_GATT_ITER_STOP;
}

struct net_buf_simple feature_buf;

net_buf_simple_init_with_data(&feature_buf, (uint8_t *)data, length);
uint16_t feature_bits = net_buf_simple_pull_le32(&feature_buf);

rreq->features_read.cb(conn, feature_bits, err);

rreq->features_read.cb = NULL;

return BT_GATT_ITER_STOP;
}

static int ras_read_features_params_populate(struct bt_gatt_dm *dm, struct bt_ras_rreq *rreq)
{
const struct bt_gatt_dm_attr *gatt_chrc;
const struct bt_gatt_dm_attr *gatt_desc;

/* RAS Features (Mandatory) */
gatt_chrc = bt_gatt_dm_char_by_uuid(dm, BT_UUID_RAS_FEATURES);
if (!gatt_chrc) {
LOG_WRN("Could not locate mandatory RAS Features characteristic");
return -EINVAL;
}

gatt_desc = bt_gatt_dm_desc_by_uuid(dm, gatt_chrc, BT_UUID_RAS_FEATURES);
if (!gatt_desc) {
LOG_WRN("Could not locate mandatory RAS Features descriptor");
return -EINVAL;
}
rreq->features_read.read_params.single.handle = gatt_desc->handle;
rreq->features_read.read_params.func = feature_read_cb;
rreq->features_read.read_params.handle_count = 1;
rreq->features_read.read_params.single.offset = 0;

return 0;
}

int bt_ras_rreq_cp_subscribe(struct bt_conn *conn)
{
int err;
Expand Down Expand Up @@ -824,6 +893,41 @@ int bt_ras_rreq_alloc_and_assign_handles(struct bt_gatt_dm *dm, struct bt_conn *
return err;
}

err = ras_read_features_params_populate(dm, rreq);
if (err) {
bt_ras_rreq_free(conn);
return err;
}

return 0;
}

int bt_ras_rreq_read_features(struct bt_conn *conn, bt_ras_rreq_features_read_cb_t cb)
{
int err;

if (cb == NULL || conn == NULL) {
return -EINVAL;
}

struct bt_ras_rreq *rreq = ras_rreq_find(conn);

if (rreq == NULL) {
return -EINVAL;
}

if (rreq->features_read.cb) {
return -EBUSY;
}

rreq->features_read.cb = cb;

err = bt_gatt_read(conn, &rreq->features_read.read_params);
if (err) {
rreq->features_read.cb = NULL;
return err;
}

return 0;
}

Expand Down
Loading