1 /* Copyright (c) 2023 Nordic Semiconductor ASA
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <stdint.h>
6 #include <zephyr/bluetooth/att.h>
7 #include <zephyr/bluetooth/bluetooth.h>
8 #include <zephyr/bluetooth/conn.h>
9 #include <zephyr/bluetooth/gatt.h>
10 #include <zephyr/bluetooth/l2cap.h>
11 #include <zephyr/bluetooth/uuid.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/logging/log_core.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/sys/__assert.h>
16 #include <zephyr/sys/util.h>
17 
18 LOG_MODULE_REGISTER(bt_testlib_att_write, LOG_LEVEL_DBG);
19 
20 struct bt_testlib_att_write_closure {
21 	uint8_t att_err;
22 	struct bt_gatt_write_params params;
23 	struct k_mutex lock;
24 	struct k_condvar done;
25 };
26 
att_write_cb(struct bt_conn * conn,uint8_t att_err,struct bt_gatt_write_params * params)27 static void att_write_cb(struct bt_conn *conn, uint8_t att_err, struct bt_gatt_write_params *params)
28 {
29 	struct bt_testlib_att_write_closure *ctx =
30 		CONTAINER_OF(params, struct bt_testlib_att_write_closure, params);
31 
32 	k_mutex_lock(&ctx->lock, K_FOREVER);
33 
34 	ctx->att_err = att_err;
35 
36 	k_condvar_signal(&ctx->done);
37 	k_mutex_unlock(&ctx->lock);
38 }
39 
bt_testlib_att_write(struct bt_conn * conn,enum bt_att_chan_opt bearer,uint16_t handle,uint8_t * data,uint16_t size)40 int bt_testlib_att_write(struct bt_conn *conn, enum bt_att_chan_opt bearer, uint16_t handle,
41 			 uint8_t *data, uint16_t size)
42 {
43 	int api_err;
44 	struct bt_testlib_att_write_closure ctx_val = {.params = {
45 							       .handle = handle,
46 							       .offset = 0,
47 							       .func = att_write_cb,
48 							       .data = data,
49 							       .length = size,
50 						       }};
51 	struct bt_testlib_att_write_closure *const ctx = &ctx_val;
52 
53 	k_mutex_init(&ctx->lock);
54 	k_condvar_init(&ctx->done);
55 
56 	__ASSERT_NO_MSG(conn);
57 	__ASSERT_NO_MSG(
58 		IN_RANGE(handle, BT_ATT_FIRST_ATTRIBUTE_HANDLE, BT_ATT_LAST_ATTRIBUTE_HANDLE));
59 
60 	k_mutex_lock(&ctx->lock, K_FOREVER);
61 
62 	api_err = bt_gatt_write(conn, &ctx->params);
63 
64 	if (!api_err) {
65 		k_condvar_wait(&ctx->done, &ctx->lock, K_FOREVER);
66 	}
67 
68 	k_mutex_unlock(&ctx->lock);
69 
70 	if (api_err) {
71 		__ASSERT_NO_MSG(api_err < 0);
72 		return api_err;
73 	}
74 	__ASSERT_NO_MSG(ctx->att_err >= 0);
75 	return ctx->att_err;
76 }
77