nrf_gzp_device.c 36 KB

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