1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2015-2016 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/types.h>
10 #include <stddef.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <zephyr/sys/printk.h>
14 #include <zephyr/sys/util.h>
15 #include <zephyr/sys/byteorder.h>
16 #include <zephyr/kernel.h>
17
18 #include <zephyr/bluetooth/bluetooth.h>
19 #include <zephyr/bluetooth/hci.h>
20 #include <zephyr/bluetooth/conn.h>
21 #include <zephyr/bluetooth/uuid.h>
22 #include <zephyr/bluetooth/gatt.h>
23
24 #define NUMBER_OF_SLOTS 1
25 #define EDS_VERSION 0x00
26 #define EDS_URL_READ_OFFSET 2
27 #define EDS_URL_WRITE_OFFSET 4
28 #define EDS_IDLE_TIMEOUT K_SECONDS(30)
29
30 /* Idle timer */
31 struct k_work_delayable idle_work;
32
33 static const struct bt_data ad[] = {
34 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
35 /* Eddystone Service UUID a3c87500-8ed3-4bdf-8a39-a01bebede295 */
36 BT_DATA_BYTES(BT_DATA_UUID128_ALL,
37 0x95, 0xe2, 0xed, 0xeb, 0x1b, 0xa0, 0x39, 0x8a,
38 0xdf, 0x4b, 0xd3, 0x8e, 0x00, 0x75, 0xc8, 0xa3),
39 };
40
41 /* Eddystone Service Variables */
42 /* Service UUID a3c87500-8ed3-4bdf-8a39-a01bebede295 */
43 static struct bt_uuid_128 eds_uuid = BT_UUID_INIT_128(
44 BT_UUID_128_ENCODE(0xa3c87500, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
45
46 /* Characteristic UUID a3c87501-8ed3-4bdf-8a39-a01bebede295 */
47 static struct bt_uuid_128 eds_caps_uuid = BT_UUID_INIT_128(
48 BT_UUID_128_ENCODE(0xa3c87501, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
49
50 /* Characteristic UUID a3c87502-8ed3-4bdf-8a39-a01bebede295 */
51 static struct bt_uuid_128 eds_slot_uuid = BT_UUID_INIT_128(
52 BT_UUID_128_ENCODE(0xa3c87502, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
53
54 /* Characteristic UUID a3c87503-8ed3-4bdf-8a39-a01bebede295 */
55 static struct bt_uuid_128 eds_intv_uuid = BT_UUID_INIT_128(
56 BT_UUID_128_ENCODE(0xa3c87503, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
57
58 /* Characteristic UUID a3c87504-8ed3-4bdf-8a39-a01bebede295 */
59 static struct bt_uuid_128 eds_tx_uuid = BT_UUID_INIT_128(
60 BT_UUID_128_ENCODE(0xa3c87504, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
61
62 /* Characteristic UUID a3c87505-8ed3-4bdf-8a39-a01bebede295 */
63 static struct bt_uuid_128 eds_adv_tx_uuid = BT_UUID_INIT_128(
64 BT_UUID_128_ENCODE(0xa3c87505, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
65
66 /* Characteristic UUID a3c87506-8ed3-4bdf-8a39-a01bebede295 */
67 static struct bt_uuid_128 eds_lock_uuid = BT_UUID_INIT_128(
68 BT_UUID_128_ENCODE(0xa3c87506, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
69
70 /* Characteristic UUID a3c87507-8ed3-4bdf-8a39-a01bebede295 */
71 static struct bt_uuid_128 eds_unlock_uuid = BT_UUID_INIT_128(
72 BT_UUID_128_ENCODE(0xa3c87507, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
73
74 /* Characteristic UUID a3c87508-8ed3-4bdf-8a39-a01bebede295 */
75 static struct bt_uuid_128 eds_ecdh_uuid = BT_UUID_INIT_128(
76 BT_UUID_128_ENCODE(0xa3c87508, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
77
78 /* Characteristic UUID a3c87509-8ed3-4bdf-8a39-a01bebede295 */
79 static struct bt_uuid_128 eds_eid_uuid = BT_UUID_INIT_128(
80 BT_UUID_128_ENCODE(0xa3c87509, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
81
82 /* Characteristic UUID a3c8750a-8ed3-4bdf-8a39-a01bebede295 */
83 static struct bt_uuid_128 eds_data_uuid = BT_UUID_INIT_128(
84 BT_UUID_128_ENCODE(0xa3c8750a, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
85
86 /* Characteristic UUID a3c8750b-8ed3-4bdf-8a39-a01bebede295 */
87 static struct bt_uuid_128 eds_reset_uuid = BT_UUID_INIT_128(
88 BT_UUID_128_ENCODE(0xa3c8750b, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
89
90 /* Characteristic UUID a3c8750c-8ed3-4bdf-8a39-a01bebede295 */
91 static struct bt_uuid_128 eds_connectable_uuid = BT_UUID_INIT_128(
92 BT_UUID_128_ENCODE(0xa3c8750c, 0x8ed3, 0x4bdf, 0x8a39, 0xa01bebede295));
93
94 enum {
95 EDS_TYPE_UID = 0x00,
96 EDS_TYPE_URL = 0x10,
97 EDS_TYPE_TLM = 0x20,
98 EDS_TYPE_EID = 0x30,
99 EDS_TYPE_NONE = 0xff,
100 };
101
102 enum {
103 EDS_SLOT_UID = sys_cpu_to_be16(BIT(0)),
104 EDS_SLOT_URL = sys_cpu_to_be16(BIT(1)),
105 EDS_SLOT_TLM = sys_cpu_to_be16(BIT(2)),
106 EDS_SLOT_EID = sys_cpu_to_be16(BIT(3)),
107 };
108
109 struct eds_capabilities {
110 uint8_t version;
111 uint8_t slots;
112 uint8_t uids;
113 uint8_t adv_types;
114 uint16_t slot_types;
115 uint8_t tx_power;
116 } __packed;
117
118 static struct eds_capabilities eds_caps = {
119 .version = EDS_VERSION,
120 .slots = NUMBER_OF_SLOTS,
121 .slot_types = EDS_SLOT_URL, /* TODO: Add support for other slot types */
122 };
123
124 uint8_t eds_active_slot;
125
126 enum {
127 EDS_LOCKED = 0x00,
128 EDS_UNLOCKED = 0x01,
129 EDS_UNLOCKED_NO_RELOCKING = 0x02,
130 };
131
132 struct eds_slot {
133 uint8_t type;
134 uint8_t state;
135 uint8_t connectable;
136 uint16_t interval;
137 uint8_t tx_power;
138 uint8_t adv_tx_power;
139 uint8_t lock[16];
140 uint8_t challenge[16];
141 struct bt_data ad[3];
142 };
143
144 static struct eds_slot eds_slots[NUMBER_OF_SLOTS] = {
145 [0 ... (NUMBER_OF_SLOTS - 1)] = {
146 .type = EDS_TYPE_NONE, /* Start as disabled */
147 .state = EDS_UNLOCKED, /* Start unlocked */
148 .interval = sys_cpu_to_be16(BT_GAP_ADV_FAST_INT_MIN_2),
149 .lock = { 'Z', 'e', 'p', 'h', 'y', 'r', ' ', 'E', 'd', 'd',
150 'y', 's', 't', 'o', 'n', 'e' },
151 .challenge = {},
152 .ad = {
153 BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
154 BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe),
155 BT_DATA_BYTES(BT_DATA_SVC_DATA16,
156 0xaa, 0xfe, /* Eddystone UUID */
157 0x10, /* Eddystone-URL frame type */
158 0x00, /* Calibrated Tx power at 0m */
159 0x00, /* URL Scheme Prefix http://www. */
160 'z', 'e', 'p', 'h', 'y', 'r',
161 'p', 'r', 'o', 'j', 'e', 'c', 't',
162 0x08) /* .org */
163 },
164 },
165 };
166
read_caps(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)167 static ssize_t read_caps(struct bt_conn *conn, const struct bt_gatt_attr *attr,
168 void *buf, uint16_t len, uint16_t offset)
169 {
170 const struct eds_capabilities *caps = attr->user_data;
171
172 return bt_gatt_attr_read(conn, attr, buf, len, offset, caps,
173 sizeof(*caps));
174 }
175
read_slot(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)176 static ssize_t read_slot(struct bt_conn *conn, const struct bt_gatt_attr *attr,
177 void *buf, uint16_t len, uint16_t offset)
178 {
179 return bt_gatt_attr_read(conn, attr, buf, len, offset,
180 &eds_active_slot, sizeof(eds_active_slot));
181 }
182
write_slot(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)183 static ssize_t write_slot(struct bt_conn *conn,
184 const struct bt_gatt_attr *attr, const void *buf,
185 uint16_t len, uint16_t offset, uint8_t flags)
186 {
187 uint8_t value;
188
189 if (offset + len > sizeof(value)) {
190 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
191 }
192
193 memcpy(&value, buf, len);
194
195 if (value + 1 > NUMBER_OF_SLOTS) {
196 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
197 }
198
199 eds_active_slot = value;
200
201 return len;
202 }
203
read_tx_power(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)204 static ssize_t read_tx_power(struct bt_conn *conn,
205 const struct bt_gatt_attr *attr,
206 void *buf, uint16_t len, uint16_t offset)
207 {
208 struct eds_slot *slot = &eds_slots[eds_active_slot];
209
210 if (slot->state == EDS_LOCKED) {
211 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
212 }
213
214 return bt_gatt_attr_read(conn, attr, buf, len, offset, &slot->tx_power,
215 sizeof(slot->tx_power));
216 }
217
write_tx_power(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)218 static ssize_t write_tx_power(struct bt_conn *conn,
219 const struct bt_gatt_attr *attr,
220 const void *buf, uint16_t len, uint16_t offset,
221 uint8_t flags)
222 {
223 struct eds_slot *slot = &eds_slots[eds_active_slot];
224
225 if (slot->state == EDS_LOCKED) {
226 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
227 }
228
229 if (offset + len > sizeof(slot->tx_power)) {
230 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
231 }
232
233 memcpy(&slot->tx_power, buf, len);
234
235 return len;
236 }
237
read_adv_tx_power(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)238 static ssize_t read_adv_tx_power(struct bt_conn *conn,
239 const struct bt_gatt_attr *attr,
240 void *buf, uint16_t len, uint16_t offset)
241 {
242 struct eds_slot *slot = &eds_slots[eds_active_slot];
243
244 if (slot->state == EDS_LOCKED) {
245 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
246 }
247
248 return bt_gatt_attr_read(conn, attr, buf, len, offset, &slot->tx_power,
249 sizeof(slot->tx_power));
250 }
251
write_adv_tx_power(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)252 static ssize_t write_adv_tx_power(struct bt_conn *conn,
253 const struct bt_gatt_attr *attr,
254 const void *buf, uint16_t len,
255 uint16_t offset,
256 uint8_t flags)
257 {
258 struct eds_slot *slot = &eds_slots[eds_active_slot];
259
260 if (slot->state == EDS_LOCKED) {
261 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
262 }
263
264 if (offset + len > sizeof(slot->adv_tx_power)) {
265 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
266 }
267
268 memcpy(&slot->adv_tx_power, buf, len);
269
270 return len;
271 }
272
read_interval(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)273 static ssize_t read_interval(struct bt_conn *conn,
274 const struct bt_gatt_attr *attr,
275 void *buf, uint16_t len, uint16_t offset)
276 {
277 struct eds_slot *slot = &eds_slots[eds_active_slot];
278
279 if (slot->state == EDS_LOCKED) {
280 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
281 }
282
283 return bt_gatt_attr_read(conn, attr, buf, len, offset, &slot->interval,
284 sizeof(slot->interval));
285 }
286
read_lock(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)287 static ssize_t read_lock(struct bt_conn *conn, const struct bt_gatt_attr *attr,
288 void *buf, uint16_t len, uint16_t offset)
289 {
290 struct eds_slot *slot = &eds_slots[eds_active_slot];
291
292 return bt_gatt_attr_read(conn, attr, buf, len, offset, &slot->state,
293 sizeof(slot->state));
294 }
295
write_lock(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)296 static ssize_t write_lock(struct bt_conn *conn,
297 const struct bt_gatt_attr *attr, const void *buf,
298 uint16_t len, uint16_t offset, uint8_t flags)
299 {
300 struct eds_slot *slot = &eds_slots[eds_active_slot];
301 uint8_t value;
302
303 if (slot->state == EDS_LOCKED) {
304 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
305 }
306
307 if (offset) {
308 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
309 }
310
311 /* Write 1 byte to lock or 17 bytes to transition to a new lock state */
312 if (len != 1U) {
313 /* TODO: Allow setting new lock code, using AES-128-ECB to
314 * decrypt with the existing lock code and set the unencrypted
315 * value as the new code.
316 */
317 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
318 }
319
320 memcpy(&value, buf, sizeof(value));
321
322 if (value > EDS_UNLOCKED_NO_RELOCKING) {
323 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
324 }
325
326 slot->state = value;
327
328 return len;
329 }
330
read_unlock(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)331 static ssize_t read_unlock(struct bt_conn *conn,
332 const struct bt_gatt_attr *attr,
333 void *buf, uint16_t len, uint16_t offset)
334 {
335 struct eds_slot *slot = &eds_slots[eds_active_slot];
336
337 if (slot->state != EDS_LOCKED) {
338 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
339 }
340
341 /* returns a 128-bit challenge token. This token is for one-time use
342 * and cannot be replayed.
343 */
344 if (bt_rand(slot->challenge, sizeof(slot->challenge))) {
345 return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
346 }
347
348 return bt_gatt_attr_read(conn, attr, buf, len, offset, slot->challenge,
349 sizeof(slot->challenge));
350 }
351
write_unlock(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)352 static ssize_t write_unlock(struct bt_conn *conn,
353 const struct bt_gatt_attr *attr, const void *buf,
354 uint16_t len, uint16_t offset, uint8_t flags)
355 {
356 struct eds_slot *slot = &eds_slots[eds_active_slot];
357
358 if (slot->state != EDS_LOCKED) {
359 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
360 }
361
362 /* TODO: accepts a 128-bit encrypted value that verifies the client
363 * knows the beacon's lock code.
364 */
365
366 return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED);
367 }
368
369 static uint8_t eds_ecdh[32] = {}; /* TODO: Add ECDH key */
370
read_ecdh(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)371 static ssize_t read_ecdh(struct bt_conn *conn, const struct bt_gatt_attr *attr,
372 void *buf, uint16_t len, uint16_t offset)
373 {
374 uint8_t *value = attr->user_data;
375
376 return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
377 sizeof(eds_ecdh));
378 }
379
380 static uint8_t eds_eid[16] = {}; /* TODO: Add EID key */
381
read_eid(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)382 static ssize_t read_eid(struct bt_conn *conn, const struct bt_gatt_attr *attr,
383 void *buf, uint16_t len, uint16_t offset)
384 {
385 uint8_t *value = attr->user_data;
386
387 return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
388 sizeof(eds_eid));
389 }
390
read_adv_data(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)391 static ssize_t read_adv_data(struct bt_conn *conn,
392 const struct bt_gatt_attr *attr, void *buf,
393 uint16_t len, uint16_t offset)
394 {
395 struct eds_slot *slot = &eds_slots[eds_active_slot];
396
397 if (slot->state == EDS_LOCKED) {
398 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
399 }
400
401 /* If the slot is currently not broadcasting, reading the slot data
402 * shall return either an empty array or a single byte of 0x00.
403 */
404 if (slot->type == EDS_TYPE_NONE) {
405 return 0;
406 }
407
408 return bt_gatt_attr_read(conn, attr, buf, len, offset,
409 slot->ad[2].data + EDS_URL_READ_OFFSET,
410 slot->ad[2].data_len - EDS_URL_READ_OFFSET);
411 }
412
eds_slot_restart(struct eds_slot * slot,uint8_t type)413 static int eds_slot_restart(struct eds_slot *slot, uint8_t type)
414 {
415 int err;
416 char addr_s[BT_ADDR_LE_STR_LEN];
417 bt_addr_le_t addr = {0};
418
419 /* Restart advertising */
420 bt_le_adv_stop();
421
422 if (type == EDS_TYPE_NONE) {
423 struct bt_le_oob oob;
424
425 /* Restore connectable if slot */
426 if (bt_le_oob_get_local(BT_ID_DEFAULT, &oob) == 0) {
427 addr = oob.addr;
428 }
429
430 err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad),
431 NULL, 0);
432 } else {
433 size_t count = 1;
434
435 bt_id_get(&addr, &count);
436 err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, slot->ad,
437 ARRAY_SIZE(slot->ad), NULL, 0);
438 }
439
440 if (err) {
441 printk("Advertising failed to start (err %d)\n", err);
442 return err;
443 }
444
445 bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s));
446 printk("Advertising as %s\n", addr_s);
447
448 slot->type = type;
449
450 return 0;
451 }
452
write_adv_data(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)453 static ssize_t write_adv_data(struct bt_conn *conn,
454 const struct bt_gatt_attr *attr,
455 const void *buf, uint16_t len, uint16_t offset,
456 uint8_t flags)
457 {
458 struct eds_slot *slot = &eds_slots[eds_active_slot];
459 uint8_t type;
460
461 if (slot->state == EDS_LOCKED) {
462 return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
463 }
464
465 if (offset) {
466 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
467 }
468
469 /* Writing an empty array, clears the slot and stops Tx. */
470 if (!len) {
471 eds_slot_restart(slot, EDS_TYPE_NONE);
472 return len;
473 }
474
475 /* Write length: 17 bytes (UID), 19 bytes (URL), 1 byte (TLM), 34 or
476 * 18 bytes (EID)
477 */
478 if (len > 19) {
479 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
480 }
481
482 memcpy(&type, buf, sizeof(type));
483
484 switch (type) {
485 case EDS_TYPE_URL:
486 /* written data is just the frame type and any ID-related
487 * information, and doesn't include the Tx power since that is
488 * controlled by characteristics 4 (Radio Tx Power) and
489 * 5 (Advertised Tx Power).
490 */
491 slot->ad[2].data_len = MIN(slot->ad[2].data_len,
492 len + EDS_URL_WRITE_OFFSET);
493 memcpy((uint8_t *) slot->ad[2].data + EDS_URL_WRITE_OFFSET, buf,
494 slot->ad[2].data_len - EDS_URL_WRITE_OFFSET);
495
496 /* Restart slot */
497 if (eds_slot_restart(slot, type) < 0) {
498 return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
499 }
500
501 return len;
502 case EDS_TYPE_UID:
503 case EDS_TYPE_TLM:
504 case EDS_TYPE_EID:
505 default:
506 /* TODO: Add support for other types. */
507 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
508 }
509 }
510
write_reset(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)511 static ssize_t write_reset(struct bt_conn *conn,
512 const struct bt_gatt_attr *attr,
513 const void *buf, uint16_t len, uint16_t offset,
514 uint8_t flags)
515 {
516 /* TODO: Power cycle or reload for storage the values */
517 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
518 }
519
read_connectable(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)520 static ssize_t read_connectable(struct bt_conn *conn,
521 const struct bt_gatt_attr *attr, void *buf,
522 uint16_t len, uint16_t offset)
523 {
524 uint8_t connectable = 0x01;
525
526 /* Returning a non-zero value indicates that the beacon is capable
527 * of becoming non-connectable
528 */
529 return bt_gatt_attr_read(conn, attr, buf, len, offset,
530 &connectable, sizeof(connectable));
531 }
532
write_connectable(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)533 static ssize_t write_connectable(struct bt_conn *conn,
534 const struct bt_gatt_attr *attr,
535 const void *buf, uint16_t len, uint16_t offset,
536 uint8_t flags)
537 {
538 struct eds_slot *slot = &eds_slots[eds_active_slot];
539
540 if (slot->state == EDS_LOCKED) {
541 return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
542 }
543
544 if (offset) {
545 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
546 }
547
548 if (len > sizeof(slot->connectable)) {
549 return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
550 }
551
552 /* If any non-zero value is written, the beacon shall remain in its
553 * connectable state until any other value is written.
554 */
555 memcpy(&slot->connectable, buf, len);
556
557 return len;
558 }
559
560 /* Eddystone Configuration Service Declaration */
561 BT_GATT_SERVICE_DEFINE(eds_svc,
562 BT_GATT_PRIMARY_SERVICE(&eds_uuid),
563 /* Capabilities: Readable only when unlocked. Never writable. */
564 BT_GATT_CHARACTERISTIC(&eds_caps_uuid.uuid, BT_GATT_CHRC_READ,
565 BT_GATT_PERM_READ, read_caps, NULL, &eds_caps),
566 /* Active slot: Must be unlocked for both read and write. */
567 BT_GATT_CHARACTERISTIC(&eds_slot_uuid.uuid,
568 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
569 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
570 read_slot, write_slot, NULL),
571 /* Advertising Interval: Must be unlocked for both read and write. */
572 BT_GATT_CHARACTERISTIC(&eds_intv_uuid.uuid, BT_GATT_CHRC_READ,
573 BT_GATT_PERM_READ, read_interval, NULL, NULL),
574 /* Radio TX Power: Must be unlocked for both read and write. */
575 BT_GATT_CHARACTERISTIC(&eds_tx_uuid.uuid,
576 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
577 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
578 read_tx_power, write_tx_power, NULL),
579 /* Advertised TX Power: Must be unlocked for both read and write. */
580 BT_GATT_CHARACTERISTIC(&eds_adv_tx_uuid.uuid,
581 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
582 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
583 read_adv_tx_power, write_adv_tx_power, NULL),
584 /* Lock State:
585 * Readable in locked or unlocked state.
586 * Writeable only in unlocked state.
587 */
588 BT_GATT_CHARACTERISTIC(&eds_lock_uuid.uuid,
589 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
590 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
591 read_lock, write_lock, NULL),
592 /* Unlock:
593 * Readable only in locked state.
594 * Writeable only in locked state.
595 */
596 BT_GATT_CHARACTERISTIC(&eds_unlock_uuid.uuid,
597 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
598 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
599 read_unlock, write_unlock, NULL),
600 /* Public ECDH Key: Readable only in unlocked state. Never writable. */
601 BT_GATT_CHARACTERISTIC(&eds_ecdh_uuid.uuid, BT_GATT_CHRC_READ,
602 BT_GATT_PERM_READ, read_ecdh, NULL, &eds_ecdh),
603 /* EID Identity Key:Readable only in unlocked state. Never writable. */
604 BT_GATT_CHARACTERISTIC(&eds_eid_uuid.uuid, BT_GATT_CHRC_READ,
605 BT_GATT_PERM_READ, read_eid, NULL, eds_eid),
606 /* ADV Slot Data: Must be unlocked for both read and write. */
607 BT_GATT_CHARACTERISTIC(&eds_data_uuid.uuid,
608 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
609 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
610 read_adv_data, write_adv_data, NULL),
611 /* ADV Factory Reset: Must be unlocked for write. */
612 BT_GATT_CHARACTERISTIC(&eds_reset_uuid.uuid, BT_GATT_CHRC_WRITE,
613 BT_GATT_PERM_WRITE, NULL, write_reset, NULL),
614 /* ADV Remain Connectable: Must be unlocked for write. */
615 BT_GATT_CHARACTERISTIC(&eds_connectable_uuid.uuid,
616 BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
617 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
618 read_connectable, write_connectable, NULL),
619 );
620
bt_ready(int err)621 static void bt_ready(int err)
622 {
623 char addr_s[BT_ADDR_LE_STR_LEN];
624 struct bt_le_oob oob;
625
626 if (err) {
627 printk("Bluetooth init failed (err %d)\n", err);
628 return;
629 }
630
631 printk("Bluetooth initialized\n");
632
633 /* Start advertising */
634 err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
635 if (err) {
636 printk("Advertising failed to start (err %d)\n", err);
637 return;
638 }
639
640 /* Restore connectable if slot */
641 bt_le_oob_get_local(BT_ID_DEFAULT, &oob);
642 bt_addr_le_to_str(&oob.addr, addr_s, sizeof(addr_s));
643 printk("Initial advertising as %s\n", addr_s);
644
645 k_work_schedule(&idle_work, EDS_IDLE_TIMEOUT);
646
647 printk("Configuration mode: waiting connections...\n");
648 }
649
idle_timeout(struct k_work * work)650 static void idle_timeout(struct k_work *work)
651 {
652 if (eds_slots[eds_active_slot].type == EDS_TYPE_NONE) {
653 printk("Switching to Beacon mode %u.\n", eds_active_slot);
654 eds_slot_restart(&eds_slots[eds_active_slot], EDS_TYPE_URL);
655 }
656 }
657
connected(struct bt_conn * conn,uint8_t err)658 static void connected(struct bt_conn *conn, uint8_t err)
659 {
660 if (err) {
661 printk("Connection failed (err 0x%02x)\n", err);
662 } else {
663 printk("Connected\n");
664 k_work_cancel_delayable(&idle_work);
665 }
666 }
667
disconnected(struct bt_conn * conn,uint8_t reason)668 static void disconnected(struct bt_conn *conn, uint8_t reason)
669 {
670 struct eds_slot *slot = &eds_slots[eds_active_slot];
671
672 printk("Disconnected (reason 0x%02x)\n", reason);
673
674 if (!slot->connectable) {
675 k_work_reschedule(&idle_work, K_NO_WAIT);
676 }
677 }
678
679 BT_CONN_CB_DEFINE(conn_callbacks) = {
680 .connected = connected,
681 .disconnected = disconnected,
682 };
683
main(void)684 int main(void)
685 {
686 int err;
687
688 k_work_init_delayable(&idle_work, idle_timeout);
689
690 /* Initialize the Bluetooth Subsystem */
691 err = bt_enable(bt_ready);
692 if (err) {
693 printk("Bluetooth init failed (err %d)\n", err);
694 }
695 return 0;
696 }
697