1 /*
2  * Copyright (c) 2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 
9 #include <zephyr/bluetooth/bluetooth.h>
10 #include <zephyr/bluetooth/conn.h>
11 #include <zephyr/bluetooth/att.h>
12 #include <zephyr/bluetooth/gatt.h>
13 
14 #include <zephyr/settings/settings.h>
15 
16 #include <zephyr/logging/log.h>
17 
18 #include "testlib/adv.h"
19 #include "testlib/att.h"
20 #include "testlib/att_read.h"
21 #include "testlib/att_write.h"
22 #include "testlib/conn.h"
23 
24 #include "babblekit/flags.h"
25 #include "babblekit/sync.h"
26 #include "babblekit/testcase.h"
27 
28 #include "common.h"
29 
30 LOG_MODULE_REGISTER(client, LOG_LEVEL_DBG);
31 
32 DEFINE_FLAG_STATIC(client_security_changed_flag);
33 
34 static struct bt_conn_cb client_conn_cb;
35 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)36 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
37 {
38 	char addr_str[BT_ADDR_LE_STR_LEN];
39 
40 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
41 
42 	TEST_ASSERT(err == 0, "Security update failed: %s level %u err %d", addr_str, level, err);
43 
44 	LOG_DBG("Security changed: %s level %u", addr_str, level);
45 	SET_FLAG(client_security_changed_flag);
46 }
47 
init_client_conn_callbacks(void)48 static void init_client_conn_callbacks(void)
49 {
50 	int err;
51 
52 	client_conn_cb.connected = NULL;
53 	client_conn_cb.disconnected = NULL;
54 	client_conn_cb.security_changed = security_changed;
55 
56 	err = bt_conn_cb_register(&client_conn_cb);
57 	TEST_ASSERT(err == 0, "Failed to set client conn callbacks (err %d)", err);
58 }
59 
find_characteristic(struct bt_conn * conn,const struct bt_uuid * svc,const struct bt_uuid * chrc,uint16_t * chrc_value_handle)60 void find_characteristic(struct bt_conn *conn, const struct bt_uuid *svc,
61 			 const struct bt_uuid *chrc, uint16_t *chrc_value_handle)
62 {
63 	int err;
64 	uint16_t svc_handle;
65 	uint16_t svc_end_handle;
66 	uint16_t chrc_end_handle;
67 
68 	err = bt_testlib_gatt_discover_primary(&svc_handle, &svc_end_handle, conn, svc,
69 					       BT_ATT_FIRST_ATTRIBUTE_HANDLE,
70 					       BT_ATT_LAST_ATTRIBUTE_HANDLE);
71 	TEST_ASSERT(err == 0, "Failed to discover service: %d", err);
72 
73 	LOG_DBG("svc_handle: %u, svc_end_handle: %u", svc_handle, svc_end_handle);
74 
75 	err = bt_testlib_gatt_discover_characteristic(chrc_value_handle, &chrc_end_handle, NULL,
76 						      conn, chrc, (svc_handle + 1), svc_end_handle);
77 	TEST_ASSERT(err == 0, "Failed to get value handle: %d", err);
78 
79 	LOG_DBG("chrc_value_handle: %u, chrc_end_handle: %u", *chrc_value_handle, chrc_end_handle);
80 }
81 
client_procedure(void)82 void client_procedure(void)
83 {
84 	int err;
85 	struct bt_conn *conn;
86 	uint16_t handle;
87 
88 	char server_new_name[CONFIG_BT_DEVICE_NAME_MAX];
89 
90 	NET_BUF_SIMPLE_DEFINE(attr_value_buf, BT_ATT_MAX_ATTRIBUTE_LEN);
91 
92 	generate_name(server_new_name, CONFIG_BT_DEVICE_NAME_MAX);
93 
94 	TEST_START("client");
95 
96 	bk_sync_init();
97 
98 	err = bt_enable(NULL);
99 	TEST_ASSERT(err == 0, "Cannot enable Bluetooth (err %d)", err);
100 
101 	LOG_DBG("Bluetooth initialized");
102 
103 	init_client_conn_callbacks();
104 
105 	err = bt_testlib_adv_conn(&conn, BT_ID_DEFAULT, ADVERTISER_NAME);
106 	TEST_ASSERT(err == 0, "Failed to start connectable advertising (err %d)", err);
107 
108 	err = bt_testlib_att_exchange_mtu(conn);
109 	TEST_ASSERT(err == 0, "Failed to update MTU (err %d)", err);
110 
111 	find_characteristic(conn, BT_UUID_GAP, BT_UUID_GAP_DEVICE_NAME, &handle);
112 
113 	err = bt_testlib_att_read_by_handle_sync(&attr_value_buf, NULL, NULL, conn,
114 						 BT_ATT_CHAN_OPT_UNENHANCED_ONLY, handle, 0);
115 	TEST_ASSERT(err == 0, "Failed to read characteristic (err %d)", err);
116 
117 	LOG_DBG("Device Name of the server: %.*s", attr_value_buf.len, attr_value_buf.data);
118 
119 	err = bt_testlib_att_write(conn, BT_ATT_CHAN_OPT_UNENHANCED_ONLY, handle, server_new_name,
120 				   sizeof(server_new_name));
121 	TEST_ASSERT(err == BT_ATT_ERR_SUCCESS, "Got ATT error: %d", err);
122 
123 	bk_sync_send();
124 
125 	TEST_PASS("client");
126 }
127