1 /*
2 * Copyright (c) 2025 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <stdbool.h>
9
10 #include <zephyr/kernel.h>
11
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/conn.h>
14 #include <zephyr/bluetooth/gatt.h>
15 #include <zephyr/bluetooth/uuid.h>
16
17 #include <zephyr/settings/settings.h>
18
19 #include <zephyr/logging/log.h>
20
21 #include <zephyr/sys/util.h>
22
23 #include "testlib/conn.h"
24 #include "testlib/scan.h"
25
26 #include "babblekit/flags.h"
27 #include "babblekit/sync.h"
28 #include "babblekit/testcase.h"
29
30 #include "common.h"
31
32 LOG_MODULE_REGISTER(server, LOG_LEVEL_DBG);
33
34 DEFINE_FLAG_STATIC(security_changed_flag);
35
36 static struct bt_conn_cb server_conn_cb;
37
memeq(const void * m1,size_t len1,const void * m2,size_t len2)38 static inline bool memeq(const void *m1, size_t len1, const void *m2, size_t len2)
39 {
40 int ret;
41
42 if (len1 != len2) {
43 return false;
44 }
45
46 ret = memcmp(m1, m2, len1);
47
48 return ret == 0;
49 }
50
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)51 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
52 {
53 char addr_str[BT_ADDR_LE_STR_LEN];
54
55 bt_addr_le_to_str(bt_conn_get_dst(conn), addr_str, sizeof(addr_str));
56
57 TEST_ASSERT(err == 0, "Security update failed: %s level %u err %d", addr_str, level, err);
58
59 LOG_DBG("Security changed: %s level %u", addr_str, level);
60 SET_FLAG(security_changed_flag);
61 }
62
init_server_conn_callbacks(void)63 static void init_server_conn_callbacks(void)
64 {
65 int err;
66
67 server_conn_cb.connected = NULL;
68 server_conn_cb.disconnected = NULL;
69 server_conn_cb.security_changed = security_changed;
70 server_conn_cb.identity_resolved = NULL;
71
72 err = bt_conn_cb_register(&server_conn_cb);
73 TEST_ASSERT(err == 0, "Failed to set server conn callbacks (err %d)", err);
74 }
75
connect_and_set_security(struct bt_conn ** conn)76 static void connect_and_set_security(struct bt_conn **conn)
77 {
78 int err;
79 bt_addr_le_t client = {};
80
81 err = bt_testlib_scan_find_name(&client, ADVERTISER_NAME);
82 TEST_ASSERT(err == 0, "Failed to start scan (err %d)", err);
83
84 err = bt_testlib_connect(&client, conn);
85 TEST_ASSERT(err == 0, "Failed to initiate connection (err %d)", err);
86
87 err = bt_conn_set_security(*conn, BT_SECURITY_L2);
88 TEST_ASSERT(err == 0, "Failed to set security (err %d)", err);
89
90 WAIT_FOR_FLAG(security_changed_flag);
91 }
92
server_procedure(void)93 void server_procedure(void)
94 {
95 /* Test purpose:
96 *
97 * Verifies that writing to the GAP Device Name characteristic correctly
98 * update the device name.
99 *
100 * Two devices:
101 * - `server`: GATT server, connect and elevate security
102 * - `client`: GATT client, when connected will look for the GAP Device
103 * Name characteristic handle and then will send a GATT write with a
104 * new name
105 *
106 * [verdict]
107 * - the server device name has been updated by the client
108 */
109
110 int err;
111 struct bt_conn *conn = NULL;
112
113 bool names_are_matching;
114
115 uint8_t expected_name[CONFIG_BT_DEVICE_NAME_MAX];
116
117 /* add one for the null character */
118 char original_name[CONFIG_BT_DEVICE_NAME_MAX + 1];
119 char new_name[CONFIG_BT_DEVICE_NAME_MAX + 1];
120
121 const char *name;
122
123 generate_name(expected_name, CONFIG_BT_DEVICE_NAME_MAX);
124
125 TEST_START("server");
126
127 bk_sync_init();
128
129 err = bt_enable(NULL);
130 TEST_ASSERT(err == 0, "Cannot enable Bluetooth (err %d)", err);
131
132 LOG_DBG("Bluetooth initialized");
133
134 err = bt_set_name("Server Super Name");
135 TEST_ASSERT(err == 0, "Failed to set the name (err %d)", err);
136
137 name = bt_get_name();
138 memcpy(original_name, name, strlen(name) + 1);
139
140 init_server_conn_callbacks();
141
142 connect_and_set_security(&conn);
143
144 /* wait for client to do gatt write */
145 bk_sync_wait();
146
147 name = bt_get_name();
148 memcpy(new_name, name, strlen(name) + 1);
149
150 LOG_DBG("Original Device Name: %s", original_name);
151 LOG_DBG("New Device Name: %s", new_name);
152
153 names_are_matching =
154 memeq(expected_name, sizeof(expected_name), new_name, strlen(new_name));
155 TEST_ASSERT(names_are_matching,
156 "The name of the server doesn't match the one set by the client (server name: "
157 "`%s`, expected name: `%.*s`)",
158 new_name, sizeof(expected_name), expected_name);
159
160 TEST_PASS("server");
161 }
162