1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 
10 #include <zephyr/bluetooth/bluetooth.h>
11 #include <zephyr/bluetooth/conn.h>
12 #include <zephyr/bluetooth/gatt.h>
13 #include <zephyr/bluetooth/hci.h>
14 
15 extern int mtu_exchange(struct bt_conn *conn);
16 extern int write_cmd(struct bt_conn *conn);
17 extern struct bt_conn *conn_connected;
18 extern uint32_t last_write_rate;
19 extern void (*start_scan_func)(void);
20 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)21 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
22 			 struct net_buf_simple *ad)
23 {
24 	char dev[BT_ADDR_LE_STR_LEN];
25 	struct bt_conn *conn;
26 	int err;
27 
28 	bt_addr_le_to_str(addr, dev, sizeof(dev));
29 	printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
30 	       dev, type, ad->len, rssi);
31 
32 	/* We're only interested in connectable events */
33 	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
34 	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
35 		return;
36 	}
37 
38 	/* connect only to devices in close proximity */
39 	if (rssi < -50) {
40 		return;
41 	}
42 
43 	err = bt_le_scan_stop();
44 	if (err) {
45 		printk("%s: Stop LE scan failed (err %d)\n", __func__, err);
46 		return;
47 	}
48 
49 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
50 				BT_LE_CONN_PARAM_DEFAULT, &conn);
51 	if (err) {
52 		printk("%s: Create conn failed (err %d)\n", __func__, err);
53 		start_scan_func();
54 	} else {
55 		bt_conn_unref(conn);
56 	}
57 }
58 
start_scan(void)59 static void start_scan(void)
60 {
61 	int err;
62 
63 	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
64 	if (err) {
65 		printk("%s: Scanning failed to start (err %d)\n", __func__,
66 		       err);
67 		return;
68 	}
69 
70 	printk("%s: Scanning successfully started\n", __func__);
71 }
72 
mtu_updated(struct bt_conn * conn,uint16_t tx,uint16_t rx)73 void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
74 {
75 	printk("Updated MTU: TX: %d RX: %d bytes\n", tx, rx);
76 }
77 
78 static struct bt_gatt_cb gatt_callbacks = {
79 	.att_mtu_updated = mtu_updated
80 };
81 
central_gatt_write(uint32_t count)82 uint32_t central_gatt_write(uint32_t count)
83 {
84 	int err;
85 
86 	err = bt_enable(NULL);
87 	if (err) {
88 		printk("Bluetooth init failed (err %d)\n", err);
89 		return 0U;
90 	}
91 	printk("Bluetooth initialized\n");
92 
93 	bt_gatt_cb_register(&gatt_callbacks);
94 
95 	conn_connected = NULL;
96 	last_write_rate = 0U;
97 
98 	start_scan_func = start_scan;
99 	start_scan_func();
100 
101 	while (true) {
102 		struct bt_conn *conn = NULL;
103 
104 		if (conn_connected) {
105 			/* Get a connection reference to ensure that a
106 			 * reference is maintained in case disconnected
107 			 * callback is called while we perform GATT Write
108 			 * command.
109 			 */
110 			conn = bt_conn_ref(conn_connected);
111 		}
112 
113 		if (conn) {
114 			(void)write_cmd(conn);
115 			bt_conn_unref(conn);
116 
117 			if (count) {
118 				count--;
119 				if (!count) {
120 					break;
121 				}
122 			}
123 
124 			k_yield();
125 		} else {
126 			k_sleep(K_SECONDS(1));
127 		}
128 	}
129 
130 	return last_write_rate;
131 }
132