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