nrf_gzp_device.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. /**
  2. * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. /**
  41. * @file
  42. * @brief Implementation of Gazell Pairing Library (gzp), Device functions.
  43. * @defgroup gzp_source_device Gazell Pairing Device implementation.
  44. * @{
  45. * @ingroup gzp_04_source
  46. */
  47. #include <stdint.h>
  48. #include <stdbool.h>
  49. #include <string.h>
  50. #include "nrf_gzll.h"
  51. #include "nrf_gzp.h"
  52. #include "nrf_delay.h"
  53. #include "nrf_nvmc.h"
  54. #define SOURCE_FILE NRF_SOURCE_FILE_GZP_DEVICE ///< File identifer for asserts.
  55. /******************************************************************************/
  56. /** @name Misc. defines
  57. * @{ */
  58. /******************************************************************************/
  59. #define GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS 0 ///< System address position.
  60. #define GZP_PARAMS_DB_ELEMENT_HOST_ID (GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS + GZP_SYSTEM_ADDRESS_WIDTH) ///< Host ID position
  61. #define GZP_PARAMS_DB_ELEMENT_SIZE (GZP_SYSTEM_ADDRESS_WIDTH + GZP_HOST_ID_LENGTH)///< Total size
  62. #define GZP_PARAMS_DB_MAX_ENTRIES 14 ///< Maximum allowed entries in the database.
  63. /** @} */
  64. /******************************************************************************/
  65. /** @name Derived parameters
  66. * @{ */
  67. /******************************************************************************/
  68. //lint -esym(40, GZP_PARAMS_STORAGE_ADR) "Undeclare identifier"
  69. #define GZP_PARAMS_DB_ADR GZP_PARAMS_STORAGE_ADR ///<
  70. #define GZP_PARAMS_DB_SIZE (GZP_PARAMS_DB_MAX_ENTRIES * GZP_PARAMS_DB_ELEMENT_SIZE) ///<
  71. #define GZP_INDEX_DB_ADR (GZP_PARAMS_STORAGE_ADR + GZP_PARAMS_DB_SIZE) ///<
  72. #define GZP_INDEX_DB_SIZE (GZP_DEVICE_PARAMS_STORAGE_SIZE - GZP_PARAMS_DB_SIZE) ///<
  73. #if (GZP_DEVICE_PARAMS_STORAGE_SIZE < GZP_PARAMS_DB_SIZE)
  74. #error GZP_DEVICE_PARAMS_STORAGE_SIZE must be greater or equal to GZP_PAIRING_PARAMS_DB_SIZE
  75. #elif (GZP_DEVICE_PARAMS_STORAGE_SIZE == GZP_PARAMS_DB_SIZE )
  76. #warning GZP_DEVICE_PARAMS_STORAGE_SIZE to low to be able store any pairing parameters NV memory
  77. #endif
  78. /** @} */
  79. /******************************************************************************/
  80. /** @name Typedefs
  81. * @{ */
  82. /******************************************************************************/
  83. /**
  84. * Possible return values for the function gzp_tx_rx_transaction()
  85. */
  86. typedef enum
  87. {
  88. GZP_TX_RX_SUCCESS, ///< ACK received. Transaction successful.
  89. GZP_TX_RX_FAILED_TO_SEND, ///<
  90. GZP_TX_RX_NO_RESPONSE ///<
  91. } gzp_tx_rx_trans_result_t;
  92. /** @} */
  93. /******************************************************************************/
  94. /** @name Internal variables
  95. * @{ */
  96. /******************************************************************************/
  97. static uint8_t gzp_system_address[GZP_SYSTEM_ADDRESS_WIDTH]; ///<
  98. static uint8_t gzp_host_id[GZP_HOST_ID_LENGTH]; ///<
  99. static uint8_t dyn_key[GZP_DYN_KEY_LENGTH];
  100. static bool gzp_id_req_pending = false;
  101. /** @} */
  102. /******************************************************************************/
  103. /** @name Internal (static) function prototypes
  104. * @{ */
  105. /******************************************************************************/
  106. /**
  107. * Function for sending an encrypted packet.
  108. *
  109. * The function waits for the transmission to complete.
  110. *
  111. * @param tx_packet Pointer to the packet to be sent.
  112. * @param length Length of the packet to be sent.
  113. * @param pipe Pipe on which the packet should be sent.
  114. *
  115. * @retval true If the transmission succeeded.
  116. * @retval false If the transmission failed (timed out).
  117. */
  118. static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe);
  119. /**
  120. * Function sending the packet *tx_packet and a subsequent packet fetching the response
  121. * to *tx_packet.
  122. *
  123. * @param tx_packet is a pointer to the packet to be sent.
  124. * @param tx_length is the length of the packet to be sent.
  125. * @param rx_dst is a pointer to where the received response packet should be stored.
  126. * @param rx_length is a pointer to where the length of the received packet should be stored.
  127. * @param pipe is the pipe on which the packet should be sent.
  128. *
  129. * @return result of the transaction.
  130. */
  131. static gzp_tx_rx_trans_result_t gzp_tx_rx_transaction(const uint8_t *tx_packet, uint8_t tx_length, uint8_t *rx_dst, uint32_t *rx_length, uint8_t pipe);
  132. /**
  133. * Function for sending an encrypted packet. The function detects whether the correct
  134. * key was used, and attempts to send a "key update" to the host if the wrong key was being
  135. * used.
  136. * @param tx_packet is a pointer to the packet to be sent.
  137. * @param length is the length of the packet to be sent.
  138. * @retval true if transmission succeeded and packet was decrypted correctly by host.
  139. * @retval false if transmission failed or packet was not decrypted correctly by host.
  140. */
  141. static bool gzp_crypt_tx_transaction(const uint8_t *tx_packet, uint8_t length);
  142. /**
  143. * Function updateing the "dynamic key" and sending a "key update" to the host.
  144. *
  145. * @retval true if key update succeeded.
  146. * @retval false if if key update failed.
  147. */
  148. static bool gzp_key_update(void);
  149. /**
  150. * Function for adding an element to "parameters data base" in non volatile (NV) memory. An element is
  151. * GZP_PARAMS_ELEMENT_SYSTEM_ADDRESS bytes long, holding the "system address" and "host ID".
  152. *
  153. * The "parameters data base" can store up to GZP_DEVICE_PAIRING_PARAMS_DB_MAX_ENTRIES
  154. * elements.
  155. *
  156. * @param src_element is a pointer to the element.
  157. * @param index is a number between 0 and (GZP_PARAMS_DB_MAX_ENTRIES - 1)
  158. * selecting the location in which the element will be stored.
  159. */
  160. static void gzp_params_db_add(const uint8_t *src_element, uint8_t index);
  161. /**
  162. * Function for reading an element from "parameters data base" in non volatile (NV) memory. An element is
  163. * GZP_PARAMS_ELEMENT_SYSTEM_ADDRESS bytes long, holding the "system address" and "host ID".
  164. *
  165. * @param dst_element is a pointer where the read element should be stored.
  166. * @param index is a number between 0 and (GZP_PARAMS_DB_MAX_ENTRIES - 1).
  167. * selecting the location that should be read.
  168. */
  169. static void gzp_params_db_read(uint8_t* dst_element, uint8_t index);
  170. /**
  171. * Function for writing an index to the "index data base" in non volatile (NV) memory.
  172. *
  173. * @param index is the index to be written to the data base.
  174. */
  175. static void gzp_index_db_add(uint8_t index);
  176. /**
  177. * Function for reading the index previously written to the "index data base" in NV memory.
  178. *
  179. * @return
  180. */
  181. static uint8_t gzp_index_db_read(void);
  182. /**
  183. * Check "index data base" is full.
  184. *
  185. * @retval true
  186. * @retval false
  187. */
  188. static bool gzp_index_db_full(void);
  189. /**
  190. * Function returning @b true if the "index data base" is empty.
  191. *
  192. * @retval true
  193. * @retval false
  194. */
  195. static bool gzp_index_db_empty(void);
  196. /**
  197. * Function returning @b true if array contains only 1s (0xff).
  198. *
  199. * @param *src is a pointer to the array to be evaluated.
  200. * @param length is the length of the array to be evaluated.
  201. *
  202. * @retval true
  203. * @retval false
  204. */
  205. static bool gzp_array_is_set(const uint8_t* src, uint8_t length);
  206. /**
  207. * Function for storing the current "system address" and "host ID" in NV memory.
  208. *
  209. * @param store_all selects whether only "system address" or both "system address" and
  210. * "host ID" should be stored.
  211. * @arg true selects that both should be stored.
  212. * @arg false selects that only "system address" should be stored.
  213. *
  214. * @retval true
  215. * @retval false
  216. */
  217. static bool gzp_params_store(bool store_all);
  218. /**
  219. * Restore the "system address" and "host ID" from NV memory.
  220. * @retval true
  221. * @retval false
  222. */
  223. static bool gzp_params_restore(void);
  224. /**
  225. * Delay function. Will add a delay equal to GZLL_RX_PERIOD * rx_periods [us].
  226. *
  227. * @param rx_periods
  228. */
  229. void gzp_delay_rx_periods(uint32_t rx_periods);
  230. /**
  231. * Delay function. Will add a delay equal to GZLL_RX_PERIOD * rx_periods [us] using the
  232. * gazell timer and not a delay loop.
  233. *
  234. * @param rx_periods
  235. */
  236. void gzp_tick_sleep_rx_periods(uint32_t rx_periods);
  237. /*
  238. * Print debug string. By default does nothing.
  239. *
  240. * If GZP_DEBUG is defined then the print string function is required to
  241. * be implemented.
  242. */
  243. void print_string(char* p_expr);
  244. /** @} */
  245. /******************************************************************************/
  246. /** @name Internal (static) variables
  247. * @{ */
  248. /******************************************************************************/
  249. static nrf_gzll_device_tx_info_t latest_tx_info; ///< Information about the last TX attempt, e.g. RSSI of ACK.
  250. static volatile bool tx_complete; ///< Flag to indicate whether a GZLL TX attempt has completed.
  251. static bool tx_success; ///< Flag to indicate whether a GZLL TX attempt was successful.
  252. // Define Macro to make array initialization nicer
  253. #define REP4(X) X X X X
  254. #if defined(__ICCARM__)
  255. #if GZP_PARAMS_DB_ADR == 0x1000
  256. static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data"
  257. #elif GZP_PARAMS_DB_ADR == 0x15000
  258. static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data_sd"
  259. #else
  260. #error
  261. #endif
  262. #else
  263. static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((at(GZP_PARAMS_DB_ADR)))
  264. #endif
  265. = {
  266. #define STATIC_INIT_VALUE 0xFFFFFFFF
  267. #define STATIC_INIT_COUNT (GZP_DEVICE_PARAMS_STORAGE_SIZE / 4)
  268. #define INIT_1 STATIC_INIT_VALUE,
  269. #define INIT_4 REP4(INIT_1)
  270. #define INIT_16 REP4(INIT_4)
  271. #define INIT_64 REP4(INIT_16)
  272. #define INIT_256 REP4(INIT_64)
  273. #define INIT_1024 REP4(INIT_256)
  274. #if (STATIC_INIT_COUNT == 256)
  275. INIT_256
  276. #elif (STATIC_INIT_COUNT == 1024)
  277. INIT_1024
  278. #else
  279. #error Gazell Pairing Library database not initialized properly!
  280. #endif
  281. }; ///< Database for storing keys.
  282. /** @} */
  283. /******************************************************************************/
  284. // Implementation: Device-specific API functions
  285. /******************************************************************************/
  286. void gzp_init()
  287. {
  288. gzp_id_req_pending = false;
  289. #ifndef GZP_NV_STORAGE_DISABLE
  290. (void)gzp_params_restore();
  291. #endif
  292. // Update radio parameters from gzp_system_address
  293. (void)gzp_update_radio_params(gzp_system_address);
  294. }
  295. void gzp_erase_pairing_data(void)
  296. {
  297. // Erase database flash page so that it can be later written to.
  298. nrf_nvmc_page_erase((uint32_t)database);
  299. }
  300. bool gzp_address_req_send()
  301. {
  302. //lint -save -e514 Unusual use of a Boolean expression (gzll_update_ok &= ...)
  303. uint8_t i;
  304. bool retval = false;
  305. bool success;
  306. uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH];
  307. uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
  308. uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
  309. nrf_gzll_tx_power_t temp_power;
  310. uint32_t temp_max_tx_attempts;
  311. bool gzll_update_ok = true;
  312. // Store parameters that are temporarily changed
  313. temp_max_tx_attempts = nrf_gzll_get_max_tx_attempts();
  314. temp_power = nrf_gzll_get_tx_power();
  315. // Modify parameters
  316. nrf_gzp_disable_gzll();
  317. nrf_gzll_set_max_tx_attempts(GZP_REQ_TX_TIMEOUT);
  318. gzll_update_ok &= nrf_gzll_set_tx_power(GZP_POWER);
  319. // Flush RX FIFO
  320. gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE);
  321. gzll_update_ok &= nrf_gzll_enable();
  322. // Build "request" packet
  323. address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_REQ;
  324. // Send a number of packets in order to broadcast that devices not within
  325. // close proximity must back off.
  326. for (i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++)
  327. {
  328. success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE);
  329. if (success)
  330. {
  331. nrf_gzp_flush_rx_fifo(GZP_PAIRING_PIPE);
  332. }
  333. else
  334. {
  335. break;
  336. }
  337. }
  338. gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT);
  339. // Send message for fetching pairing response from host.
  340. address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH;
  341. success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE);
  342. if (success && latest_tx_info.payload_received_in_ack)
  343. {
  344. // If pairing response received
  345. if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0)
  346. {
  347. rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; //dummy placeholder
  348. if (nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &rx_payload_length))
  349. {
  350. if (rx_payload[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_RESP)
  351. {
  352. memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
  353. gzll_update_ok &= gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]);
  354. #ifndef GZP_NV_STORAGE_DISABLE
  355. (void)gzp_params_store(false); // "False" indicates that only "system address" part of DB element will be stored
  356. #endif
  357. retval = true;
  358. }
  359. }
  360. }
  361. }
  362. else
  363. {
  364. gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT);
  365. }
  366. gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT);
  367. // Clean-up and restore parameters temporarily modified
  368. nrf_gzp_disable_gzll();
  369. gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE);
  370. gzll_update_ok &= nrf_gzll_flush_tx_fifo(GZP_PAIRING_PIPE);
  371. nrf_gzll_set_max_tx_attempts(temp_max_tx_attempts);
  372. gzll_update_ok &= nrf_gzll_set_tx_power(temp_power);
  373. gzll_update_ok &= nrf_gzll_enable();
  374. if (!gzll_update_ok)
  375. {
  376. /*
  377. The update of the Gazell parameters failed. Use nrf_gzll_get_error_code()
  378. to investigate the cause.
  379. */
  380. }
  381. return retval;
  382. //lint -restore
  383. }
  384. #ifndef GZP_CRYPT_DISABLE
  385. gzp_id_req_res_t gzp_id_req_send()
  386. {
  387. uint8_t tx_packet[GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH];
  388. uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
  389. gzp_tx_rx_trans_result_t trans_result;
  390. // If no ID request is pending, send new "ID request"
  391. if (!gzp_id_req_pending)
  392. {
  393. // Build "Host ID request packet"
  394. tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_REQ;
  395. // Generate new session token
  396. gzp_random_numbers_generate(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
  397. // Send "Host ID request"
  398. if (gzp_tx_packet(tx_packet, GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH, GZP_DATA_PIPE))
  399. {
  400. // Update session token if "Host ID request" was successfully transmitted
  401. gzp_crypt_set_session_token(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
  402. gzp_id_req_pending = true;
  403. return GZP_ID_RESP_PENDING;
  404. }
  405. }
  406. else // If "ID request is pending" send "fetch ID" packet
  407. {
  408. // Build "host ID fetch" packet
  409. tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_FETCH;
  410. gzp_add_validation_id(&tx_packet[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]);
  411. // Encrypt "host ID fetch" packet
  412. gzp_crypt_select_key(GZP_ID_EXCHANGE);
  413. gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
  414. trans_result = gzp_tx_rx_transaction(tx_packet, GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE);
  415. // If packet was successfully sent AND a response packet was received
  416. if (trans_result == GZP_TX_RX_SUCCESS)
  417. {
  418. // Validate response packet
  419. if (rx_packet[0] == (uint8_t)GZP_CMD_HOST_ID_FETCH_RESP)
  420. {
  421. gzp_crypt(&rx_packet[1], &rx_packet[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
  422. if (gzp_validate_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]))
  423. {
  424. switch (rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS])
  425. {
  426. case GZP_ID_RESP_PENDING:
  427. break;
  428. case GZP_ID_RESP_REJECTED:
  429. gzp_id_req_pending = false;
  430. break;
  431. case GZP_ID_RESP_GRANTED:
  432. gzp_set_host_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
  433. gzp_random_numbers_generate(dyn_key, GZP_DYN_KEY_LENGTH);
  434. gzp_crypt_set_dyn_key(dyn_key);
  435. #ifndef GZP_NV_STORAGE_DISABLE
  436. (void)gzp_params_store(true);
  437. #endif
  438. gzp_id_req_pending = false;
  439. break;
  440. default:
  441. break;
  442. }
  443. return (gzp_id_req_res_t)rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS];
  444. }
  445. else
  446. {
  447. gzp_id_req_pending = false;
  448. return GZP_ID_RESP_REJECTED;
  449. }
  450. }
  451. }
  452. }
  453. gzp_id_req_pending = false;
  454. return GZP_ID_RESP_FAILED;
  455. }
  456. void gzp_id_req_cancel()
  457. {
  458. gzp_id_req_pending = false;
  459. }
  460. bool gzp_crypt_data_send(const uint8_t *src, uint8_t length)
  461. {
  462. if (length <= GZP_ENCRYPTED_USER_DATA_MAX_LENGTH)
  463. {
  464. if (gzp_crypt_tx_transaction(src, length))
  465. {
  466. return true;
  467. }
  468. else
  469. {
  470. //print_string("GZP_CRYPT_TX failed\r\n");
  471. // Attempt key update if user data transmission failed
  472. // during normal operation (!gzp_id_req_pending)
  473. if (!gzp_id_req_pending)
  474. {
  475. //print_string("KEY UPDATE\r\n");
  476. if (gzp_key_update())
  477. {
  478. return gzp_crypt_tx_transaction(src, length);
  479. }
  480. }
  481. return false;
  482. }
  483. }
  484. else
  485. {
  486. return false;
  487. }
  488. }
  489. #endif
  490. /** @} */
  491. /******************************************************************************/
  492. // Implementation: Internal (static) functions
  493. /******************************************************************************/
  494. static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe)
  495. {
  496. tx_complete = false;
  497. tx_success = false;
  498. if (nrf_gzll_add_packet_to_tx_fifo(pipe,(uint8_t *)tx_packet, length))
  499. {
  500. while (tx_complete == false)
  501. {
  502. __WFI();
  503. }
  504. return tx_success;
  505. }
  506. else
  507. {
  508. return false;
  509. }
  510. }
  511. static gzp_tx_rx_trans_result_t gzp_tx_rx_transaction(const uint8_t *tx_packet, uint8_t tx_length, uint8_t *rx_dst, uint32_t *rx_length, uint8_t pipe)
  512. {
  513. gzp_tx_rx_trans_result_t retval;
  514. uint8_t fetch_packet[GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH];
  515. bool tx_packet_success;
  516. bool fetch_success;
  517. uint32_t local_rx_length = GZP_MAX_ACK_PAYLOAD_LENGTH;
  518. uint32_t temp_lifetime;
  519. nrf_gzp_flush_rx_fifo(pipe);
  520. retval = GZP_TX_RX_FAILED_TO_SEND;
  521. (void)nrf_gzll_disable();
  522. while (nrf_gzll_is_enabled())
  523. {}
  524. temp_lifetime = nrf_gzll_get_sync_lifetime();
  525. (void)nrf_gzll_set_sync_lifetime(GZP_TX_RX_TRANS_DELAY * 3); // 3 = RXPERIOD * 2 + margin
  526. (void)nrf_gzll_enable();
  527. tx_packet_success = gzp_tx_packet(tx_packet, tx_length, pipe);
  528. if (tx_packet_success)
  529. {
  530. retval = GZP_TX_RX_NO_RESPONSE;
  531. nrf_gzp_flush_rx_fifo(pipe);
  532. fetch_packet[0] = (uint8_t)GZP_CMD_FETCH_RESP;
  533. gzp_tick_sleep_rx_periods(GZP_TX_RX_TRANS_DELAY);
  534. tx_packet_success = gzp_tx_packet(fetch_packet, GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe);
  535. if (tx_packet_success)
  536. {
  537. if (nrf_gzll_get_rx_fifo_packet_count(pipe))
  538. {
  539. local_rx_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
  540. fetch_success = nrf_gzll_fetch_packet_from_rx_fifo(pipe, rx_dst, &local_rx_length);
  541. }
  542. else
  543. {
  544. fetch_success = false;
  545. }
  546. if (fetch_success)
  547. {
  548. retval = GZP_TX_RX_SUCCESS;
  549. }
  550. else
  551. {
  552. //print_string("GZP_TX_FETCH_FAILED\r\n");
  553. }
  554. }
  555. else
  556. {
  557. //print_string("GZP_TX_FETCH_NO_ACK\r\n");
  558. }
  559. }
  560. (void)nrf_gzll_disable();
  561. while (nrf_gzll_is_enabled())
  562. {}
  563. (void)nrf_gzll_set_sync_lifetime(temp_lifetime);
  564. (void)nrf_gzll_enable();
  565. return retval;
  566. }
  567. #ifndef GZP_CRYPT_DISABLE
  568. static bool gzp_crypt_tx_transaction(const uint8_t *src, uint8_t length)
  569. {
  570. uint8_t tx_packet[GZP_MAX_FW_PAYLOAD_LENGTH];
  571. uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
  572. uint8_t tx_packet_length;
  573. gzp_tx_rx_trans_result_t result;
  574. tx_packet_length = length + (uint8_t)GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD;
  575. // Assemble tx packet
  576. tx_packet[0] = (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA;
  577. gzp_add_validation_id(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]);
  578. memcpy(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], (uint8_t*)src, length);
  579. // Encrypt tx packet
  580. if (gzp_id_req_pending)
  581. {
  582. gzp_crypt_select_key(GZP_ID_EXCHANGE);
  583. }
  584. else
  585. {
  586. gzp_crypt_select_key(GZP_DATA_EXCHANGE);
  587. }
  588. gzp_crypt(&tx_packet[1], &tx_packet[1], tx_packet_length - 1);
  589. // If packet was successfully sent AND a response packet was received
  590. result = gzp_tx_rx_transaction(tx_packet, tx_packet_length, rx_packet, NULL, GZP_DATA_PIPE);
  591. if (result == GZP_TX_RX_SUCCESS)
  592. {
  593. if (rx_packet[0] == (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA_RESP)
  594. {
  595. gzp_crypt(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], &rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], GZP_VALIDATION_ID_LENGTH);
  596. // Validate response in order to know whether packet was correctly decrypted by host
  597. if (gzp_validate_id(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]))
  598. {
  599. // Update session token if normal operation (!gzp_id_req_pending)
  600. if (!gzp_id_req_pending)
  601. {
  602. gzp_crypt_set_session_token(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
  603. }
  604. return true;
  605. }
  606. else
  607. {
  608. //print_string("GZP_CRYPT_TX_TRANS: Validation ID bad\r\n");
  609. return false;
  610. }
  611. }
  612. else
  613. {
  614. //print_string("GZP_CRYPT_TX_TRANS: Bad CMD. \r\n");
  615. return false;
  616. }
  617. }
  618. else
  619. {
  620. //print_string("GZP_CRYPT_TX_TRANS: gzp_tx_rx_trans not SUCCESS\r\n");
  621. return false;
  622. }
  623. }
  624. static bool gzp_key_update(void)
  625. {
  626. uint8_t tx_packet[GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH], rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
  627. // Send "prepare packet" to get session token to be used for key update
  628. tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE;
  629. // If packet was successfully sent AND a response packet was received
  630. if (gzp_tx_rx_transaction(tx_packet, GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
  631. {
  632. if (rx_packet[0] == (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP)
  633. {
  634. gzp_crypt_set_session_token(&rx_packet[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
  635. // Build "key update" packet
  636. tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE;
  637. gzp_add_validation_id(&tx_packet[GZP_CMD_KEY_UPDATE_VALIDATION_ID]);
  638. gzp_random_numbers_generate(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY], GZP_DYN_KEY_LENGTH);
  639. gzp_crypt_set_dyn_key(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY]);
  640. // Encrypt "key update packet"
  641. gzp_crypt_select_key(GZP_KEY_EXCHANGE);
  642. gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
  643. // Send "key update" packet
  644. if (gzp_tx_packet(tx_packet, GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH, GZP_DATA_PIPE))
  645. {
  646. return true;
  647. }
  648. }
  649. }
  650. return false;
  651. }
  652. #endif
  653. void gzp_set_host_id(const uint8_t * id)
  654. {
  655. memcpy(gzp_host_id, id, GZP_HOST_ID_LENGTH);
  656. }
  657. void gzp_get_host_id(uint8_t * dst_id)
  658. {
  659. memcpy(dst_id, gzp_host_id, GZP_HOST_ID_LENGTH);
  660. }
  661. static void gzp_params_db_add(const uint8_t* src_element, uint8_t index)
  662. {
  663. nrf_nvmc_write_bytes((GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE)), src_element, (uint32_t)GZP_PARAMS_DB_ELEMENT_SIZE);
  664. }
  665. static void gzp_params_db_read(uint8_t* dst_element, uint8_t index)
  666. {
  667. memcpy(dst_element,(uint8_t*)(GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE)), GZP_PARAMS_DB_ELEMENT_SIZE);
  668. }
  669. static void gzp_index_db_add(uint8_t val)
  670. {
  671. int16_t i;
  672. uint8_t temp_val;
  673. uint32_t addr;
  674. // Search for unwritten loacation in index DB
  675. for (i = 0; i < GZP_INDEX_DB_SIZE; i++)
  676. {
  677. temp_val = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
  678. // Lower nibble
  679. if (i != (GZP_INDEX_DB_SIZE - 1))
  680. {
  681. if ((temp_val & 0x0f) == 0x0f)
  682. {
  683. temp_val = (temp_val & 0xf0) | val;
  684. break;
  685. }
  686. // Upper nibble
  687. else if ((temp_val & 0xf0) == 0xf0)
  688. {
  689. temp_val = (temp_val & 0x0f) | (val << 4);
  690. break;
  691. }
  692. }
  693. else
  694. {
  695. temp_val = (GZP_PARAMS_DB_MAX_ENTRIES << 4) | val;
  696. break;
  697. }
  698. }
  699. // Write index DB
  700. addr = (GZP_INDEX_DB_ADR + i);
  701. nrf_nvmc_write_byte(addr, temp_val);
  702. }
  703. static uint8_t gzp_index_db_read()
  704. {
  705. uint8_t retval;
  706. int16_t i;
  707. // Search for previously written location
  708. for (i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
  709. {
  710. retval = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
  711. if (retval != 0xff)
  712. {
  713. break;
  714. }
  715. }
  716. if (retval == 0xff)
  717. {
  718. retval = GZP_PARAMS_DB_MAX_ENTRIES; // index db empty
  719. }
  720. else if ((retval & 0xf0) != 0xf0)
  721. {
  722. retval >>= 4;
  723. }
  724. else
  725. {
  726. retval &= 0x0f;
  727. }
  728. return retval;
  729. }
  730. int8_t gzp_get_pairing_status(void)
  731. {
  732. uint8_t db_byte;
  733. int8_t db_index;
  734. int16_t i;
  735. uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
  736. uint8_t default_host_id[GZP_HOST_ID_LENGTH];
  737. db_index = -2;
  738. // Populate default Host ID with F's.
  739. for (i=0; i< GZP_HOST_ID_LENGTH; i++)
  740. {
  741. default_host_id[i] = 0xFF;
  742. }
  743. // Search for previously written location
  744. for (i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
  745. {
  746. db_byte = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
  747. // Check if idx has been written to
  748. if (db_byte != 0xff)
  749. {
  750. // Convert 4-bit nibble to index
  751. if ((db_byte & 0xf0) != 0xf0)
  752. {
  753. db_byte = (db_byte >> 4) & 0x0f;
  754. }
  755. else
  756. {
  757. db_byte = db_byte & 0x0f;
  758. }
  759. // Retrieve database entry
  760. gzp_params_db_read(temp_element, db_byte);
  761. // Check if database entry is all F's
  762. if ( memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], default_host_id, GZP_HOST_ID_LENGTH) != 0)
  763. {
  764. db_index = db_byte;
  765. }
  766. else
  767. {
  768. db_index = -1;
  769. }
  770. break;
  771. }
  772. }
  773. return db_index;
  774. }
  775. static bool gzp_index_db_full()
  776. {
  777. #if (GZP_INDEX_DB_SIZE != 0)
  778. return ((*(uint8_t*)(GZP_INDEX_DB_ADR + (GZP_INDEX_DB_SIZE - 1)) != 0xff));
  779. #else
  780. return true;
  781. #endif
  782. }
  783. //lint -save -e506 Constant value boolean
  784. static bool gzp_index_db_empty()
  785. {
  786. #if (GZP_INDEX_DB_SIZE != 0)
  787. return ((GZP_INDEX_DB_SIZE == 0) || ((*(uint8_t*)(GZP_INDEX_DB_ADR)) == 0xff));
  788. #else
  789. return true;
  790. #endif
  791. }
  792. //lint -restore
  793. static bool gzp_array_is_set(const uint8_t* src, uint8_t length)
  794. {
  795. uint8_t i;
  796. for (i = 0; i < length; i++)
  797. {
  798. if (*(src++) != 0xff)
  799. {
  800. return false;
  801. }
  802. }
  803. return true;
  804. }
  805. static bool gzp_params_store(bool store_all)
  806. {
  807. uint8_t i;
  808. bool write_index_db = false;
  809. bool write_param_db = false;
  810. uint8_t new_db_index = 0;
  811. uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
  812. // Search param DB to see if current setup exists
  813. if (store_all)
  814. {
  815. // Search for: Current system address and host ID exists
  816. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  817. {
  818. gzp_params_db_read(temp_element, i);
  819. if (((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0) && ((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH)) == 0))
  820. {
  821. write_index_db = true;
  822. new_db_index = i;
  823. break; // System address + host_id allready exists in database
  824. }
  825. }
  826. // Search for: Current system address and cleared host ID
  827. if (!write_index_db)
  828. {
  829. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  830. {
  831. gzp_params_db_read(temp_element, i);
  832. if (((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0) && \
  833. (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], GZP_HOST_ID_LENGTH)))
  834. {
  835. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
  836. new_db_index = i;
  837. write_index_db = true;
  838. write_param_db = true;
  839. break;
  840. }
  841. }
  842. }
  843. // Search for: Cleared system address and cleared host ID
  844. if (!write_index_db)
  845. {
  846. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  847. {
  848. gzp_params_db_read(temp_element, i);
  849. if (gzp_array_is_set(temp_element, GZP_PARAMS_DB_ELEMENT_SIZE))
  850. {
  851. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
  852. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
  853. new_db_index = i;
  854. write_index_db = true;
  855. write_param_db = true;
  856. break;
  857. }
  858. }
  859. }
  860. }
  861. else
  862. {
  863. // Search for: System address + any host ID
  864. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  865. {
  866. gzp_params_db_read(temp_element, i);
  867. if ((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0)
  868. {
  869. //memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
  870. write_index_db = true;
  871. new_db_index = i;
  872. break;
  873. }
  874. }
  875. // Search for: System address cleared
  876. if (!write_index_db)
  877. {
  878. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  879. {
  880. gzp_params_db_read(temp_element, i);
  881. if (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH))
  882. {
  883. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
  884. write_index_db = true;
  885. write_param_db = true;
  886. new_db_index = i;
  887. break;
  888. }
  889. }
  890. }
  891. }
  892. if (write_param_db)
  893. {
  894. gzp_params_db_add(temp_element, new_db_index);
  895. }
  896. if (write_index_db)
  897. {
  898. if (!gzp_index_db_full() && (new_db_index != gzp_index_db_read()) && (new_db_index != GZP_PARAMS_DB_MAX_ENTRIES))
  899. {
  900. gzp_index_db_add(new_db_index);
  901. return true;
  902. }
  903. }
  904. return false;
  905. }
  906. static bool gzp_params_restore(void)
  907. {
  908. uint8_t i;
  909. uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
  910. if (!gzp_index_db_full() && !gzp_index_db_empty())
  911. {
  912. i = gzp_index_db_read();
  913. if (i < GZP_PARAMS_DB_MAX_ENTRIES)
  914. {
  915. gzp_params_db_read(temp_element, i);
  916. memcpy(gzp_system_address, &temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
  917. gzp_set_host_id(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID]);
  918. return true;
  919. }
  920. }
  921. return false;
  922. }
  923. void gzp_delay_rx_periods(uint32_t rx_periods)
  924. {
  925. nrf_delay_us(rx_periods * 2 * nrf_gzll_get_timeslot_period());
  926. }
  927. void gzp_tick_sleep_rx_periods(uint32_t rx_periods)
  928. {
  929. nrf_gzll_clear_tick_count();
  930. while (nrf_gzll_get_tick_count() < 2 * rx_periods)
  931. {
  932. __WFI();
  933. }
  934. }
  935. void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
  936. {
  937. latest_tx_info = tx_info;
  938. tx_complete = true;
  939. tx_success = true;
  940. }
  941. void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
  942. {
  943. latest_tx_info = tx_info;
  944. tx_complete = true;
  945. tx_success = false;
  946. }
  947. bool nrf_gzp_tx_complete(void)
  948. {
  949. return tx_complete;
  950. }
  951. bool nrf_gzp_tx_success(void)
  952. {
  953. return tx_success;
  954. }
  955. void nrf_gzp_reset_tx_complete()
  956. {
  957. tx_complete = false;
  958. }
  959. void nrf_gzp_reset_tx_success()
  960. {
  961. tx_success = false;
  962. }
  963. void nrf_gzll_disabled(void)
  964. {
  965. }
  966. void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
  967. {
  968. }
  969. /** @} */
  970. /** @} */