1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 
10 #include <string.h>
11 
12 #include <zephyr/settings/settings.h>
13 
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/gatt.h>
16 #include <zephyr/drivers/sensor.h>
17 #include <zephyr/bluetooth/hci.h>
18 
19 #include "mesh.h"
20 #include "board.h"
21 
22 static const struct bt_data ad[] = {
23 	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
24 };
25 
26 static const struct bt_data sd[] = {
27 	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
28 };
29 
read_name(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)30 static ssize_t read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
31 			 void *buf, uint16_t len, uint16_t offset)
32 {
33 	const char *value = bt_get_name();
34 
35 	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
36 				 strlen(value));
37 }
38 
write_name(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)39 static ssize_t write_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
40 			  const void *buf, uint16_t len, uint16_t offset,
41 			  uint8_t flags)
42 {
43 	char name[CONFIG_BT_DEVICE_NAME_MAX];
44 	int err;
45 
46 	if (offset) {
47 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
48 	}
49 
50 	if (len >= CONFIG_BT_DEVICE_NAME_MAX) {
51 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
52 	}
53 
54 	memcpy(name, buf, len);
55 	name[len] = '\0';
56 
57 	err = bt_set_name(name);
58 	if (err) {
59 		return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
60 	}
61 
62 	board_refresh_display();
63 
64 	return len;
65 }
66 
67 static const struct bt_uuid_128 name_uuid = BT_UUID_INIT_128(
68 	BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef0));
69 
70 static const struct bt_uuid_128 name_enc_uuid = BT_UUID_INIT_128(
71 	BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef1));
72 
73 #define CPF_FORMAT_UTF8 0x19
74 
75 static const struct bt_gatt_cpf name_cpf = {
76 	.format = CPF_FORMAT_UTF8,
77 };
78 
79 /* Vendor Primary Service Declaration */
80 BT_GATT_SERVICE_DEFINE(name_svc,
81 	/* Vendor Primary Service Declaration */
82 	BT_GATT_PRIMARY_SERVICE(&name_uuid),
83 	BT_GATT_CHARACTERISTIC(&name_enc_uuid.uuid,
84 			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
85 			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT,
86 			       read_name, write_name, NULL),
87 	BT_GATT_CUD("Badge Name", BT_GATT_PERM_READ),
88 	BT_GATT_CPF(&name_cpf),
89 );
90 
passkey_display(struct bt_conn * conn,unsigned int passkey)91 static void passkey_display(struct bt_conn *conn, unsigned int passkey)
92 {
93 	char buf[20];
94 
95 	snprintk(buf, sizeof(buf), "Passkey:\n%06u", passkey);
96 
97 	printk("%s\n", buf);
98 	board_show_text(buf, false, K_FOREVER);
99 }
100 
passkey_cancel(struct bt_conn * conn)101 static void passkey_cancel(struct bt_conn *conn)
102 {
103 	printk("Cancel\n");
104 }
105 
pairing_complete(struct bt_conn * conn,bool bonded)106 static void pairing_complete(struct bt_conn *conn, bool bonded)
107 {
108 	printk("Pairing Complete\n");
109 	board_show_text("Pairing Complete", false, K_SECONDS(2));
110 }
111 
pairing_failed(struct bt_conn * conn,enum bt_security_err reason)112 static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
113 {
114 	printk("Pairing Failed (%d)\n", reason);
115 	board_show_text("Pairing Failed", false, K_SECONDS(2));
116 }
117 
118 const struct bt_conn_auth_cb auth_cb = {
119 	.passkey_display = passkey_display,
120 	.cancel = passkey_cancel,
121 };
122 
123 static struct bt_conn_auth_info_cb auth_info_cb = {
124 	.pairing_complete = pairing_complete,
125 	.pairing_failed = pairing_failed,
126 };
127 
connected(struct bt_conn * conn,uint8_t err)128 static void connected(struct bt_conn *conn, uint8_t err)
129 {
130 	printk("Connected (err 0x%02x)\n", err);
131 
132 	if (err) {
133 		board_show_text("Connection failed", false, K_SECONDS(2));
134 	} else {
135 		board_show_text("Connected", false, K_FOREVER);
136 	}
137 }
138 
disconnected(struct bt_conn * conn,uint8_t reason)139 static void disconnected(struct bt_conn *conn, uint8_t reason)
140 {
141 	printk("Disconnected, reason 0x%02x %s\n", reason, bt_hci_err_to_str(reason));
142 
143 	if (strcmp(CONFIG_BT_DEVICE_NAME, bt_get_name()) &&
144 	    !mesh_is_initialized()) {
145 		/* Mesh will take over advertising control */
146 		bt_le_adv_stop();
147 		mesh_start();
148 	} else {
149 		board_show_text("Disconnected", false, K_SECONDS(2));
150 	}
151 }
152 
153 BT_CONN_CB_DEFINE(conn_cb) = {
154 	.connected = connected,
155 	.disconnected = disconnected,
156 };
157 
bt_ready(int err)158 static void bt_ready(int err)
159 {
160 	if (err) {
161 		printk("Bluetooth init failed (err %d)\n", err);
162 		return;
163 	}
164 
165 	printk("Bluetooth initialized\n");
166 
167 	err = mesh_init();
168 	if (err) {
169 		printk("Initializing mesh failed (err %d)\n", err);
170 		return;
171 	}
172 
173 	printk("Mesh initialized\n");
174 
175 	bt_conn_auth_cb_register(&auth_cb);
176 	bt_conn_auth_info_cb_register(&auth_info_cb);
177 
178 	if (IS_ENABLED(CONFIG_SETTINGS)) {
179 		settings_load();
180 	}
181 
182 	if (!mesh_is_initialized()) {
183 		/* Start advertising */
184 		err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd,
185 				      ARRAY_SIZE(sd));
186 		if (err) {
187 			printk("Advertising failed to start (err %d)\n", err);
188 			return;
189 		}
190 	} else {
191 		printk("Already provisioned\n");
192 	}
193 
194 	board_refresh_display();
195 
196 	printk("Board started\n");
197 }
198 
main(void)199 int main(void)
200 {
201 	int err;
202 
203 	err = board_init();
204 	if (err) {
205 		printk("board init failed (err %d)\n", err);
206 		return 0;
207 	}
208 
209 	printk("Starting Board Demo\n");
210 
211 	/* Initialize the Bluetooth Subsystem */
212 	err = bt_enable(bt_ready);
213 	if (err) {
214 		printk("Bluetooth init failed (err %d)\n", err);
215 		return 0;
216 	}
217 
218 	err = periphs_init();
219 	if (err) {
220 		printk("peripherals initialization failed (err %d)\n", err);
221 		return 0;
222 	}
223 	return 0;
224 }
225