1212
1313#include <zephyr/bluetooth/bluetooth.h>
1414#include <zephyr/bluetooth/conn.h>
15-
16- static struct k_work work_adv_start ;
17- static uint8_t volatile conn_count ;
18- static uint8_t id_current ;
19- static bool volatile is_disconnecting ;
15+ #include <zephyr/bluetooth/gatt.h>
2016
2117static const struct bt_data ad [] = {
2218 BT_DATA_BYTES (BT_DATA_FLAGS , (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR )),
@@ -26,6 +22,116 @@ static const struct bt_data sd[] = {
2622 BT_DATA (BT_DATA_NAME_COMPLETE , CONFIG_BT_DEVICE_NAME , sizeof (CONFIG_BT_DEVICE_NAME ) - 1 ),
2723};
2824
25+ #if defined(CONFIG_BT_GATT_CLIENT )
26+ static void mtu_updated (struct bt_conn * conn , uint16_t tx , uint16_t rx )
27+ {
28+ printk ("Updated MTU: TX: %d RX: %d bytes\n" , tx , rx );
29+ }
30+
31+ static struct bt_gatt_cb gatt_callbacks = {
32+ .att_mtu_updated = mtu_updated
33+ };
34+
35+ static void mtu_exchange_cb (struct bt_conn * conn , uint8_t err ,
36+ struct bt_gatt_exchange_params * params )
37+ {
38+ printk ("%s: MTU exchange %s (%u)\n" , __func__ ,
39+ err == 0U ? "successful" : "failed" ,
40+ bt_gatt_get_mtu (conn ));
41+ }
42+
43+ static int mtu_exchange (struct bt_conn * conn )
44+ {
45+ static struct bt_gatt_exchange_params mtu_exchange_params ;
46+ int err ;
47+
48+ printk ("%s: Current MTU = %u\n" , __func__ , bt_gatt_get_mtu (conn ));
49+
50+ mtu_exchange_params .func = mtu_exchange_cb ;
51+
52+ printk ("%s: Exchange MTU...\n" , __func__ );
53+ err = bt_gatt_exchange_mtu (conn , & mtu_exchange_params );
54+ if (err ) {
55+ printk ("%s: MTU exchange failed (err %d)" , __func__ , err );
56+ }
57+
58+ return err ;
59+ }
60+
61+ static uint32_t last_write_rate ;
62+
63+ static void write_cmd_cb (struct bt_conn * conn , void * user_data )
64+ {
65+ static uint32_t cycle_stamp ;
66+ static uint32_t write_count ;
67+ static uint32_t write_rate ;
68+ static uint32_t write_len ;
69+ uint64_t delta ;
70+
71+ delta = k_cycle_get_32 () - cycle_stamp ;
72+ delta = k_cyc_to_ns_floor64 (delta );
73+
74+ if (delta == 0 ) {
75+ /* Skip division by zero */
76+ return ;
77+ }
78+
79+ /* if last data rx-ed was greater than 1 second in the past,
80+ * reset the metrics.
81+ */
82+ if (delta > (1U * NSEC_PER_SEC )) {
83+ printk ("%s: count= %u, len= %u, rate= %u bps.\n" , __func__ ,
84+ write_count , write_len , write_rate );
85+
86+ last_write_rate = write_rate ;
87+
88+ write_count = 0U ;
89+ write_len = 0U ;
90+ write_rate = 0U ;
91+ cycle_stamp = k_cycle_get_32 ();
92+ } else {
93+ uint16_t len ;
94+
95+ write_count ++ ;
96+
97+ /* Extract the 16-bit data length stored in user_data */
98+ len = (uint32_t )user_data & 0xFFFF ;
99+
100+ write_len += len ;
101+ write_rate = ((uint64_t )write_len << 3 ) * (1U * NSEC_PER_SEC ) /
102+ delta ;
103+ }
104+ }
105+
106+ int write_cmd (struct bt_conn * conn )
107+ {
108+ static uint8_t data [BT_ATT_MAX_ATTRIBUTE_LEN ] = {0U , };
109+ static uint16_t data_len ;
110+ int err ;
111+
112+ data_len = bt_gatt_get_mtu (conn ) - 3U ;
113+ if (data_len > BT_ATT_MAX_ATTRIBUTE_LEN ) {
114+ data_len = BT_ATT_MAX_ATTRIBUTE_LEN ;
115+ }
116+
117+ /* Pass the 16-bit data length value (instead of reference) in
118+ * user_data so that unique value is pass for each write callback.
119+ * Using handle 0x0001, we do not care if it is writable, we just want
120+ * to transmit the data across.
121+ */
122+ err = bt_gatt_write_without_response_cb (conn , 0x0001 , data , data_len ,
123+ false, write_cmd_cb ,
124+ (void * )((uint32_t )data_len ));
125+ if (err ) {
126+ printk ("%s: Write cmd failed (%d).\n" , __func__ , err );
127+ }
128+
129+ return err ;
130+ }
131+ #endif /* CONFIG_BT_GATT_CLIENT */
132+
133+ static uint8_t id_current ;
134+
29135static void adv_start (struct k_work * work )
30136{
31137 struct bt_le_adv_param adv_param = {
@@ -74,6 +180,10 @@ static void adv_start(struct k_work *work)
74180 printk ("Advertising successfully started\n" );
75181}
76182
183+ static struct k_work work_adv_start ;
184+ static uint8_t volatile conn_count ;
185+ static struct bt_conn * conn_connected ;
186+
77187static void connected (struct bt_conn * conn , uint8_t err )
78188{
79189 char addr [BT_ADDR_LE_STR_LEN ];
@@ -91,8 +201,18 @@ static void connected(struct bt_conn *conn, uint8_t err)
91201 bt_addr_le_to_str (bt_conn_get_dst (conn ), addr , sizeof (addr ));
92202
93203 printk ("Connected (%u): %s\n" , conn_count , addr );
204+
205+ if (!conn_connected ) {
206+ conn_connected = bt_conn_ref (conn );
207+ }
208+
209+ #if defined(CONFIG_BT_GATT_CLIENT )
210+ (void )mtu_exchange (conn );
211+ #endif /* CONFIG_BT_GATT_CLIENT */
94212}
95213
214+ static bool volatile is_disconnecting ;
215+
96216static void disconnected (struct bt_conn * conn , uint8_t reason )
97217{
98218 char addr [BT_ADDR_LE_STR_LEN ];
@@ -101,6 +221,11 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
101221
102222 printk ("Disconnected %s (reason 0x%02x)\n" , addr , reason );
103223
224+ if (conn == conn_connected ) {
225+ conn_connected = NULL ;
226+ bt_conn_unref (conn );
227+ }
228+
104229 if ((conn_count == 1U ) && is_disconnecting ) {
105230 is_disconnecting = false;
106231 k_work_submit (& work_adv_start );
@@ -114,7 +239,7 @@ static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
114239
115240 bt_addr_le_to_str (bt_conn_get_dst (conn ), addr , sizeof (addr ));
116241
117- printk ("LE conn param req: %s int (0x%04x, 0x%04x) lat %d to %d\n" ,
242+ printk ("LE conn param req: %s int (0x%04x, 0x%04x) lat %d to %d\n" ,
118243 addr , param -> interval_min , param -> interval_max , param -> latency ,
119244 param -> timeout );
120245
@@ -208,8 +333,9 @@ static struct bt_conn_cb conn_callbacks = {
208333#endif /* CONFIG_BT_USER_DATA_LEN_UPDATE */
209334};
210335
211- #if defined(CONFIG_BT_OBSERVER )
212- #define BT_LE_SCAN_PASSIVE_ALLOW_DUPILCATES \
336+ #if defined(CONFIG_BT_OBSERVER ) && \
337+ !defined(CONFIG_TEST_BSIM_BT_CONN_PARAM_OBSERVER_DISABLED )
338+ #define BT_LE_SCAN_PASSIVE_ALLOW_DUPLICATES \
213339 BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_PASSIVE, \
214340 BT_LE_SCAN_OPT_NONE, \
215341 BT_GAP_SCAN_FAST_INTERVAL, \
@@ -223,7 +349,9 @@ static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
223349 bt_addr_le_to_str (addr , addr_str , sizeof (addr_str ));
224350 printk ("Device found: %s (RSSI %d)\n" , addr_str , rssi );
225351}
226- #endif /* CONFIG_BT_OBSERVER */
352+ #endif /* CONFIG_BT_OBSERVER &&
353+ * !CONFIG_TEST_BSIM_BT_CONN_PARAM_OBSERVER_DISABLED
354+ */
227355
228356int init_peripheral (uint8_t iterations )
229357{
@@ -242,18 +370,25 @@ int init_peripheral(uint8_t iterations)
242370 bt_conn_auth_cb_register (& auth_callbacks );
243371#endif /* CONFIG_BT_SMP */
244372
373+ #if defined(CONFIG_BT_GATT_CLIENT )
374+ bt_gatt_cb_register (& gatt_callbacks );
375+ #endif /* CONFIG_BT_GATT_CLIENT */
376+
245377 printk ("Bluetooth initialized\n" );
246378
247- #if defined(CONFIG_BT_OBSERVER )
379+ #if defined(CONFIG_BT_OBSERVER ) && \
380+ !defined(CONFIG_TEST_BSIM_BT_CONN_PARAM_OBSERVER_DISABLED )
248381 printk ("Start continuous passive scanning..." );
249- err = bt_le_scan_start (BT_LE_SCAN_PASSIVE_ALLOW_DUPILCATES ,
382+ err = bt_le_scan_start (BT_LE_SCAN_PASSIVE_ALLOW_DUPLICATES ,
250383 device_found );
251384 if (err ) {
252385 printk ("Scan start failed (%d).\n" , err );
253386 return err ;
254387 }
255388 printk ("success.\n" );
256- #endif /* CONFIG_BT_OBSERVER */
389+ #endif /* CONFIG_BT_OBSERVER && \
390+ * !CONFIG_TEST_BSIM_BT_CONN_PARAM_OBSERVER_DISABLED
391+ */
257392
258393 k_work_init (& work_adv_start , adv_start );
259394 k_work_submit (& work_adv_start );
@@ -284,6 +419,26 @@ int init_peripheral(uint8_t iterations)
284419 printk ("Wait for disconnections...\n" );
285420 is_disconnecting = true;
286421 while (is_disconnecting ) {
422+ #if defined(CONFIG_BT_GATT_CLIENT )
423+ struct bt_conn * conn = NULL ;
424+
425+ if (conn_connected ) {
426+ /* Get a connection reference to ensure
427+ * that a reference is maintained in
428+ * case disconnected callback is called
429+ * while we perform GATT Write command.
430+ */
431+ conn = bt_conn_ref (conn_connected );
432+ }
433+
434+ if (conn ) {
435+ (void )write_cmd (conn );
436+ bt_conn_unref (conn );
437+
438+ continue ;
439+ }
440+ #endif /* CONFIG_BT_GATT_CLIENT */
441+
287442 k_sleep (K_MSEC (10 ));
288443 }
289444 printk ("All disconnected.\n" );
0 commit comments