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