app_main.c 22 KB

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