tile_features.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /**
  2. * NOTICE
  3. *
  4. * Copyright 2020 Tile Inc. All Rights Reserved.
  5. * All code or other information included in the accompanying files ("Tile Source Material")
  6. * is PROPRIETARY information of Tile Inc. ("Tile") and access and use of the Tile Source Material
  7. * is subject to these terms. The Tile Source Material may only be used for demonstration purposes,
  8. * and may not be otherwise distributed or made available to others, including for commercial purposes.
  9. * Without limiting the foregoing , you understand and agree that no production use
  10. * of the Tile Source Material is allowed without a Tile ID properly obtained under a separate
  11. * agreement with Tile.
  12. * You also understand and agree that Tile may terminate the limited rights granted under these terms
  13. * at any time in its discretion.
  14. * All Tile Source Material is provided AS-IS without warranty of any kind.
  15. * Tile does not warrant that the Tile Source Material will be error-free or fit for your purposes.
  16. * Tile will not be liable for any damages resulting from your use of or inability to use
  17. * the Tile Source Material.
  18. *
  19. * Support: firmware_support@tile.com
  20. */
  21. /**
  22. * @file tile_features.c
  23. * @brief Support for features in Tile Lib
  24. */
  25. #include "sdk_common.h"
  26. #if NRF_MODULE_ENABLED(TILE_SUPPORT)
  27. #include "nrf_drv_rng.h"
  28. #include "ble.h"
  29. #include "ble_hci.h"
  30. #include "nrf_delay.h"
  31. #include "app_timer.h"
  32. #include "app_scheduler.h"
  33. #include "app_button.h"
  34. #include <string.h>
  35. #include "nrf_log.h"
  36. #include "nrf_log_ctrl.h"
  37. // TileLib includes
  38. #include "tile_config.h"
  39. #include "tile_features.h"
  40. #include "tile_lib.h"
  41. #include "drivers/tile_gap_driver.h"
  42. #include "drivers/tile_timer_driver.h"
  43. #include "drivers/tile_button_driver.h"
  44. #include "drivers/tile_random_driver.h"
  45. #include "modules/tile_tdi_module.h"
  46. #include "modules/tile_toa_module.h"
  47. #include "modules/tile_tmd_module.h"
  48. #include "modules/tile_tpi_module.h"
  49. #include "modules/tile_tdt_module.h"
  50. #include "modules/tile_tdg_module.h"
  51. #include "tile_storage/tile_storage.h"
  52. #include "tile_player/tile_player.h"
  53. #include "tile_assert/tile_assert.h"
  54. #include "tile_bdaddr/tile_bdaddr.h"
  55. /*******************************************************************************
  56. * Global variables
  57. ******************************************************************************/
  58. tile_ble_env_t tile_ble_env;
  59. app_timer_id_t tile_timer_id[TILE_MAX_TIMERS];
  60. const char tile_model_number[] = TILE_MODEL_NUMBER;
  61. const char tile_hw_version[] = TILE_HARDWARE_VERSION;
  62. /*******************************************************************************
  63. * Local variables
  64. ******************************************************************************/
  65. static toa_channel_t tile_toa_channels[NUM_TOA_CHANNELS] __attribute__((section("retention_mem_area0"), zero_init));
  66. static uint8_t toa_queue_buffer[TOA_QUEUE_BUFFER_SIZE];
  67. /*******************************************************************************
  68. * Forward declarations
  69. ******************************************************************************/
  70. void advertising_update(void);
  71. /* gap module*/
  72. static int tile_disconnect(void);
  73. /* timer module*/
  74. static int tile_timer_start(uint8_t timer_id, uint32_t duration);
  75. static int tile_timer_cancel(uint8_t timer_id);
  76. /* random module*/
  77. static int tile_random_bytes(uint8_t *dst, uint8_t len);
  78. /* toa module*/
  79. static int tile_send_toa_response(uint8_t *data, uint16_t len);
  80. static int tile_associate(uint8_t* tile_id, uint8_t* tile_auth_key, uint8_t* authorization_type);
  81. /* tmd module*/
  82. static int tile_mode_set(uint8_t mode);
  83. static int tile_mode_get(uint8_t *mode);
  84. /* tdg module*/
  85. static int tile_get_diagnostics_cb(void);
  86. /* song module*/
  87. // Refer tile_player.c
  88. /* test module*/
  89. static void test_process_reboot(uint8_t reboot_type);
  90. static void test_process_storage(uint8_t test_type, uint8_t *payload, uint8_t payload_length);
  91. static int test_process(uint8_t code, uint8_t *data, uint8_t datalen);
  92. /* button driver */
  93. int tile_read_button_state(uint8_t *button_state);
  94. static void tile_hdc_cb(void);
  95. static int tile_hdc_config_written(tdt_config_t *config);
  96. /* TPI module */
  97. static int tile_tileID_counter_updated(void);
  98. /*******************************************************************************
  99. * Defines & types
  100. ******************************************************************************/
  101. /*******************************************************************************
  102. * Tile configuration structures
  103. ******************************************************************************/
  104. /* gap register struct */
  105. static struct tile_gap_driver gap_driver =
  106. {
  107. .gap_disconnect = tile_disconnect,
  108. .auth_disconnect_count = &tile_persist.unchecked.s.auth_disconnect_count,
  109. };
  110. /* timer driver struct */
  111. struct tile_timer_driver timer_driver =
  112. {
  113. .start = tile_timer_start,
  114. .cancel = tile_timer_cancel,
  115. };
  116. /* random driver struct */
  117. static struct tile_random_driver random_driver =
  118. {
  119. .random_bytes = tile_random_bytes,
  120. };
  121. /* device information struct */
  122. struct tile_tdi_module tdi_module =
  123. {
  124. .tile_id = tile_persist.checked.s.tile_id,
  125. .model_number = tile_persist.checked.s.model_number,
  126. .hardware_version = tile_persist.checked.s.hardware_version,
  127. .bdaddr = bdaddr, // RAM Variable, Not stored in Flash
  128. .firmware_version = TILE_FIRMWARE_VERSION,
  129. };
  130. /* tile over the air struct */
  131. struct tile_toa_module toa_module =
  132. {
  133. .tile_id = tile_persist.checked.s.tile_id,
  134. .auth_key = tile_persist.checked.s.tile_auth_key,
  135. .channels = tile_toa_channels,
  136. .queue = toa_queue_buffer,
  137. .queue_size = TOA_QUEUE_BUFFER_SIZE,
  138. .num_channels = NUM_TOA_CHANNELS,
  139. .mic_failure_count = &tile_persist.unchecked.s.micFailures,
  140. .auth_failure_count = &tile_persist.unchecked.s.auth_fail_count,
  141. .channel_open_count = &tile_persist.unchecked.s.toa_channel_open_count,
  142. .authenticate_count = &tile_persist.unchecked.s.toa_authenticate_count,
  143. .tka_closed_channel_count = &tile_persist.unchecked.s.tka_closed_channel_count,
  144. .send_response = tile_send_toa_response,
  145. .associate = tile_associate
  146. };
  147. /* tile mode struct */
  148. struct tile_tmd_module tmd_module =
  149. {
  150. .get = tile_mode_get,
  151. .set = tile_mode_set,
  152. };
  153. /* tile mode struct */
  154. static struct tile_tdg_module tdg_module =
  155. {
  156. .get_diagnostics = tile_get_diagnostics_cb,
  157. };
  158. /* tile song module struct */
  159. static struct tile_song_module song_module =
  160. {
  161. .play = PlaySong,
  162. .stop = StopSong
  163. };
  164. /* tile test module struct */
  165. static struct tile_test_module test_module =
  166. {
  167. .process = test_process,
  168. };
  169. /* tile button driver struct */
  170. static struct tile_button_driver button_driver =
  171. {
  172. .read_state = tile_read_button_state,
  173. };
  174. struct tile_tpi_module tpi_module =
  175. {
  176. .tileID_key = tile_persist.checked.s.tileIDkey,
  177. .hashed_tileID = tile_env.hashedTileID,
  178. .tileID_counter = &tile_persist.unchecked.s.tileIDcounter,
  179. .tileID_counter_updated = tile_tileID_counter_updated,
  180. };
  181. /* tile double tap struct */
  182. struct tile_tdt_module tdt_module =
  183. {
  184. .hdc_status = TDT_HDC_STATUS_NORMAL,
  185. .single_tap = NULL,
  186. .long_tap = NULL,
  187. .double_tap_detect = NULL,
  188. .double_tap_notify = NULL,
  189. .double_tap_failure2 = NULL,
  190. .hdc_cb = tile_hdc_cb,
  191. .config_written = tile_hdc_config_written,
  192. };
  193. /*******************************************************************************
  194. * Functions
  195. ******************************************************************************/
  196. void tile_features_init(void)
  197. {
  198. /****************************************************************/
  199. /**** Minimum Features required for TileLib Interoperability ****/
  200. /****************************************************************/
  201. /* Initialize GAP driver */
  202. (void) tile_gap_register(&gap_driver);
  203. /* Initialize timer driver */
  204. (void) tile_timer_register(&timer_driver);
  205. /* Initialize random driver */
  206. (void) tile_random_register(&random_driver);
  207. /* Initialize device information module */
  208. /* Obtain default Bdaddr from device register at 0x100000A4*/
  209. get_default_macAddr();
  210. set_new_macAddr();
  211. (void) tile_tdi_register(&tdi_module);
  212. /* Initialize tile over the air module */
  213. (void) tile_toa_register(&toa_module);
  214. /* Initialize tile mode module */
  215. (void) tile_tmd_register(&tmd_module);
  216. /* Initialize button driver module */
  217. (void) tile_button_register(&button_driver);
  218. /* Initialize tile PrivateID module */
  219. (void) tile_tpi_register(&tpi_module);
  220. /* Initialize tile double tap module */
  221. memcpy(&tdt_module.config, &tile_checked->tdt_configuration, sizeof(tdt_config_t));
  222. (void) tile_tdt_register(&tdt_module);
  223. /****************************************************************/
  224. /**** Additional Features ****/
  225. /****************************************************************/
  226. /* Initialize tile diagnbostics module */
  227. (void) tile_tdg_register(&tdg_module);
  228. /* Initialize song module */
  229. (void) tile_song_register(&song_module);
  230. /* Initialize test module */
  231. (void) tile_test_register(&test_module);
  232. }
  233. /*******************************************************************************
  234. * Callback functions for Tile Lib
  235. ******************************************************************************/
  236. /***************************** gap module *******************************/
  237. /**
  238. * @brief Disconnect current connection
  239. */
  240. static int tile_disconnect(void)
  241. {
  242. if(BLE_CONN_HANDLE_INVALID == tile_ble_env.conn_handle)
  243. {
  244. return TILE_ERROR_ILLEGAL_OPERATION;
  245. }
  246. (void) sd_ble_gap_disconnect(tile_ble_env.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  247. return TILE_ERROR_SUCCESS;
  248. }
  249. /**
  250. * @brief Update the TileID Char
  251. */
  252. void tile_update_tileID_char(void)
  253. {
  254. ret_code_t err_code;
  255. ble_gatts_value_t gatts_value;
  256. // Initialize value struct.
  257. memset(&gatts_value, 0, sizeof(gatts_value));
  258. gatts_value.len = TILE_ID_LEN;
  259. gatts_value.offset = 0;
  260. gatts_value.p_value = tile_persist.checked.s.tile_id;
  261. // Update database
  262. err_code = sd_ble_gatts_value_set(tile_ble_env.conn_handle, tile_ble_env.service.characteristic_handles[TILE_ID_CHAR], &gatts_value);
  263. APP_ERROR_CHECK(err_code);
  264. return;
  265. }
  266. /************************************************************************/
  267. /***************************** timer module *****************************/
  268. /**
  269. * @brief Start a Tile timer
  270. *
  271. * @param[in] timer_id ID for timer, as specified by Tile Lib
  272. * @param[in] duration Duration (in 10ms increments) for the timer
  273. */
  274. static int tile_timer_start(uint8_t timer_id, uint32_t duration)
  275. {
  276. ret_code_t err_code;
  277. if(duration < 1)
  278. {
  279. duration++;
  280. }
  281. /* The new timer takes priority, so stop any existing timer */
  282. err_code = app_timer_stop(tile_timer_id[timer_id]);
  283. APP_ERROR_CHECK(err_code);
  284. err_code = app_timer_start(tile_timer_id[timer_id], APP_TIMER_TICKS((uint64_t) duration * 10), (void *)(uint32_t)timer_id);
  285. APP_ERROR_CHECK(err_code);
  286. return TILE_ERROR_SUCCESS;
  287. }
  288. /**
  289. * @brief Cancel a Tile timer
  290. *
  291. * @param[in] timer_id ID for timer, as specified by Tile Lib
  292. */
  293. static int tile_timer_cancel(uint8_t timer_id)
  294. {
  295. uint32_t err_code = app_timer_stop(tile_timer_id[timer_id]);
  296. err_code = (err_code == NRF_SUCCESS) ? TILE_ERROR_SUCCESS : err_code;
  297. return (int) err_code;
  298. }
  299. /************************************************************************/
  300. /****************************random module *******************************/
  301. /**
  302. * @brief Generate some random bytes
  303. *
  304. * @param[out] dst Destination address for the random bytes
  305. * @param[in] len Number of bytes requested
  306. */
  307. static int tile_random_bytes(uint8_t *dst, uint8_t len)
  308. {
  309. uint8_t num;
  310. uint32_t err_code;
  311. /* Check if enough random bytes are available */
  312. nrf_drv_rng_bytes_available(&num);
  313. while(num < len)
  314. {
  315. /* Wait for enough random bytes to be available */
  316. nrf_delay_us(200);
  317. nrf_drv_rng_bytes_available(&num);
  318. }
  319. /* Copy over random bytes */
  320. err_code = nrf_drv_rng_rand(dst, len);
  321. err_code = (err_code == NRF_SUCCESS) ? TILE_ERROR_SUCCESS : err_code;
  322. return (int) err_code;
  323. }
  324. /************************************************************************/
  325. /***************************** tpi module *******************************/
  326. /**
  327. * @brief Update TileID counter for TPI generation
  328. *
  329. * @param[out] int TILE_ERROR_TYPE
  330. */
  331. static int tile_tileID_counter_updated(void)
  332. {
  333. if((BLE_CONN_HANDLE_INVALID == tile_ble_env.conn_handle))
  334. {
  335. advertising_update();
  336. }
  337. return TILE_ERROR_SUCCESS;
  338. }
  339. /************************************************************************/
  340. /***************************** toa module *******************************/
  341. /**
  342. * @brief Send notification on a characteristic in TOA_RSP
  343. *
  344. * @param[in] data Data to set attribute to.
  345. * @param[in] len Length of data.
  346. */
  347. static int tile_send_toa_response(uint8_t *data, uint16_t len)
  348. {
  349. ret_code_t err_code;
  350. if(BLE_CONN_HANDLE_INVALID == tile_ble_env.conn_handle)
  351. {
  352. return TILE_ERROR_ILLEGAL_OPERATION;
  353. }
  354. uint16_t handle = tile_ble_env.service.characteristic_handles[TILE_TOA_RSP_CHAR];
  355. ble_gatts_hvx_params_t hvx_params =
  356. {
  357. .handle = handle,
  358. .type = BLE_GATT_HVX_NOTIFICATION,
  359. .offset = 0,
  360. .p_len = &len,
  361. .p_data = data
  362. };
  363. err_code = sd_ble_gatts_hvx(tile_ble_env.conn_handle, &hvx_params);
  364. APP_ERROR_CHECK(err_code);
  365. return TILE_ERROR_SUCCESS;
  366. };
  367. /**
  368. * @brief Set the new Tile Id/Auth Key during Commissioning Process if in Shipping Modes
  369. */
  370. static int tile_associate(uint8_t* tile_id, uint8_t* tile_auth_key, uint8_t* authorization_type)
  371. {
  372. int retcode = TOA_ERROR_OK;
  373. #ifdef INTERIM_TILE_ID
  374. if(TILE_MODE_SHIPPING == tile_checked->mode)
  375. {
  376. memcpy(tile_checked->tile_id, tile_id, sizeof(tile_checked->tile_id));
  377. memcpy(tile_checked->tile_auth_key, tile_auth_key, sizeof(tile_checked->tile_auth_key));
  378. // Update the TileID Char
  379. tile_update_tileID_char();
  380. NRF_LOG_INFO("tile_associate in Shipping Mode Successful\r\n");
  381. }
  382. else // Do not allow to set new Tile id/Auth key for an already Activated Tile. We should never come here ideally
  383. {
  384. retcode = TOA_RSP_SERVICE_UNAVAILABLE;
  385. NRF_LOG_INFO("tile_associate in Activated Mode Not Allowed, returning TOA_RSP_SERVICE_UNAVAILABLE \r\n");
  386. }
  387. return retcode;
  388. #else
  389. return retcode;
  390. #endif
  391. }
  392. /************************************************************************/
  393. /***************************** mode module *******************************/
  394. /**
  395. * @brief Set the mode of the device.
  396. *
  397. * @param[in] mode Mode, as specified by the TMD module.
  398. */
  399. static int tile_mode_set(uint8_t mode)
  400. {
  401. if(TILE_MODE_ACTIVATED != mode)
  402. {
  403. /* Disregard any mode besides Shipping and Activated
  404. * If mode being set is not Activated, Make it Shipping
  405. */
  406. mode = TILE_MODE_SHIPPING;
  407. /* When the Tile is not activated, the Interim TileID, Key is used. */
  408. memcpy(tile_checked->tile_id, interim_tile_id, 8);
  409. memcpy(tile_checked->tile_auth_key, interim_tile_key, 16);
  410. // Update the TileID Char
  411. tile_update_tileID_char();
  412. }
  413. tile_checked->mode = mode;
  414. set_new_macAddr();
  415. // tile_set_params_for_mode();
  416. tile_store_app_data();
  417. return TILE_ERROR_SUCCESS;
  418. }
  419. /**
  420. * @brief Get the current mode of the device.
  421. *
  422. * @param[out] mode Mode, as specified by the TMD module.
  423. */
  424. static int tile_mode_get(uint8_t *mode)
  425. {
  426. *mode = tile_checked->mode;
  427. return TILE_ERROR_SUCCESS;
  428. }
  429. /************************************************************************/
  430. /***************************** tdg module *******************************/
  431. static int tile_get_diagnostics_cb(void)
  432. {
  433. uint8_t version = DIAGNOSTIC_VERSION;
  434. (void) tdg_add_data(&version, 1);
  435. (void) tdg_add_data(&tile_checked->mode, 1);
  436. (void) tdg_add_data(&tile_unchecked->reset_count, 1);
  437. (void) tdg_add_data(&tile_unchecked->piezoMs, 4);
  438. (void) tdg_add_data(&tile_unchecked->connection_count, 3);
  439. (void) tdg_add_data(&tile_unchecked->auth_fail_count, 1);
  440. (void) tdg_add_data(&tile_unchecked->micFailures, 1);
  441. (void) tdg_add_data(&tile_unchecked->disconnect_count, 3);
  442. (void) tdg_add_data(&tile_unchecked->toa_channel_open_count, 3);
  443. (void) tdg_add_data(&tile_unchecked->toa_authenticate_count, 3);
  444. (void) tdg_add_data(&tile_unchecked->tka_closed_channel_count, 2);
  445. (void) tdg_add_data(&tile_unchecked->auth_disconnect_count, 2);
  446. (void) tdg_finish();
  447. return TILE_ERROR_SUCCESS;
  448. }
  449. /************************************************************************/
  450. /***************************** song module ******************************/
  451. // Refer tile_player.c
  452. /************************************************************************/
  453. void tile_button_was_pressed(void)
  454. {
  455. /* Abort SONG if Find Song is currently playing*/
  456. if (CheckFindSong())
  457. {
  458. (void) StopSong();
  459. }
  460. if(TILE_MODE_ACTIVATED == tile_checked->mode)
  461. {
  462. // Forward to TileLib
  463. (void) tile_button_pressed();
  464. }
  465. else
  466. {
  467. /* Play the right Song according to Mode */
  468. if(TILE_MODE_SHIPPING == tile_checked->mode)
  469. {
  470. (void) PlaySong(TILE_SONG_WAKEUP_PART, 3, TILE_SONG_DURATION_ONCE);
  471. }
  472. }
  473. }
  474. int tile_read_button_state(uint8_t *button_state)
  475. {
  476. bool is_button_pushed = app_button_is_pushed(0);
  477. /* pin is pulled high */
  478. if(true == is_button_pushed)
  479. {
  480. *button_state = TILE_BUTTON_PRESSED;
  481. }
  482. else
  483. {
  484. *button_state = TILE_BUTTON_RELEASED;
  485. }
  486. return TILE_ERROR_SUCCESS;
  487. };
  488. void tile_hdc_cb(void)
  489. {
  490. /* Currently Disconnected, Update Advertising Data and Parameters based on the TDT State */
  491. if(BLE_CONN_HANDLE_INVALID == tile_ble_env.conn_handle)
  492. {
  493. advertising_update();
  494. }
  495. };
  496. int tile_hdc_config_written(tdt_config_t *config)
  497. {
  498. return TILE_ERROR_SUCCESS;
  499. };
  500. /***************************** test module ******************************/
  501. static int test_process(uint8_t code, uint8_t *data, uint8_t datalen)
  502. {
  503. switch(code) {
  504. case TEST_CMD_REBOOT:
  505. test_process_reboot(data[0]);
  506. break;
  507. case TEST_CMD_STORAGE:
  508. test_process_storage(data[0], data+1, datalen-1);
  509. break;
  510. default:
  511. break;
  512. }
  513. return TILE_ERROR_SUCCESS;
  514. }
  515. static void test_process_reboot(uint8_t reboot_type)
  516. {
  517. switch(reboot_type) {
  518. case TEST_CMD_REBOOT_RESET:
  519. (void) sd_nvic_SystemReset();
  520. break;
  521. case TEST_CMD_REBOOT_WATCHDOG:
  522. while(1);
  523. //break;
  524. case TEST_CMD_REBOOT_MEMORY_FAULT:
  525. *((uint8_t*)0xFFFFFFFF) = 0;
  526. break;
  527. case TEST_CMD_REBOOT_OTHER:
  528. /* ? */
  529. break;
  530. case TEST_CMD_REBOOT_ASSERT:
  531. TILE_ASSERT(0);
  532. /* TODO */
  533. break;
  534. case TEST_CMD_REBOOT_DURING_FLASH:
  535. /* TODO */
  536. break;
  537. }
  538. }
  539. static void test_process_storage(uint8_t test_type, uint8_t *payload, uint8_t payload_length)
  540. {
  541. /* TODO */
  542. }
  543. /************************************************************************/
  544. #endif // NRF_MODULE_ENABLED(TILE_SUPPORT)