nrf_gzp_device.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. /**
  2. * Copyright (c) 2009 - 2020, 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. #elif defined(__GNUC__)
  263. static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((section(".gzll_paring")))
  264. #else
  265. static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((at(GZP_PARAMS_DB_ADR)))
  266. #endif
  267. = {
  268. #define STATIC_INIT_VALUE 0xFFFFFFFF
  269. #define STATIC_INIT_COUNT (GZP_DEVICE_PARAMS_STORAGE_SIZE / 4)
  270. #define INIT_1 STATIC_INIT_VALUE,
  271. #define INIT_4 REP4(INIT_1)
  272. #define INIT_16 REP4(INIT_4)
  273. #define INIT_64 REP4(INIT_16)
  274. #define INIT_256 REP4(INIT_64)
  275. #define INIT_1024 REP4(INIT_256)
  276. #if (STATIC_INIT_COUNT == 256)
  277. INIT_256
  278. #elif (STATIC_INIT_COUNT == 1024)
  279. INIT_1024
  280. #else
  281. #error Gazell Pairing Library database not initialized properly!
  282. #endif
  283. }; ///< Database for storing keys.
  284. /** @} */
  285. /******************************************************************************/
  286. // Implementation: Device-specific API functions
  287. /******************************************************************************/
  288. void gzp_init()
  289. {
  290. gzp_id_req_pending = false;
  291. #ifndef GZP_NV_STORAGE_DISABLE
  292. (void)gzp_params_restore();
  293. #endif
  294. // Update radio parameters from gzp_system_address
  295. (void)gzp_update_radio_params(gzp_system_address);
  296. }
  297. void gzp_erase_pairing_data(void)
  298. {
  299. // Erase database flash page so that it can be later written to.
  300. nrf_nvmc_page_erase((uint32_t)database);
  301. }
  302. bool gzp_address_req_send()
  303. {
  304. //lint -save -e514 Unusual use of a Boolean expression (gzll_update_ok &= ...)
  305. uint8_t i;
  306. bool retval = false;
  307. bool success;
  308. uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH];
  309. uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
  310. uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
  311. nrf_gzll_tx_power_t temp_power;
  312. uint32_t temp_max_tx_attempts;
  313. bool gzll_update_ok = true;
  314. // Store parameters that are temporarily changed
  315. temp_max_tx_attempts = nrf_gzll_get_max_tx_attempts();
  316. temp_power = nrf_gzll_get_tx_power();
  317. // Modify parameters
  318. nrf_gzp_disable_gzll();
  319. nrf_gzll_set_max_tx_attempts(GZP_REQ_TX_TIMEOUT);
  320. gzll_update_ok &= nrf_gzll_set_tx_power(GZP_POWER);
  321. // Flush RX FIFO
  322. gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE);
  323. gzll_update_ok &= nrf_gzll_enable();
  324. // Build "request" packet
  325. address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_REQ;
  326. // Send a number of packets in order to broadcast that devices not within
  327. // close proximity must back off.
  328. for (i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++)
  329. {
  330. success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE);
  331. if (success)
  332. {
  333. nrf_gzp_flush_rx_fifo(GZP_PAIRING_PIPE);
  334. }
  335. else
  336. {
  337. break;
  338. }
  339. }
  340. gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT);
  341. // Send message for fetching pairing response from host.
  342. address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH;
  343. success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE);
  344. if (success && latest_tx_info.payload_received_in_ack)
  345. {
  346. // If pairing response received
  347. if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0)
  348. {
  349. rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; //dummy placeholder
  350. if (nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &rx_payload_length))
  351. {
  352. if (rx_payload[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_RESP)
  353. {
  354. memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
  355. gzll_update_ok &= gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]);
  356. #ifndef GZP_NV_STORAGE_DISABLE
  357. (void)gzp_params_store(false); // "False" indicates that only "system address" part of DB element will be stored
  358. #endif
  359. retval = true;
  360. }
  361. }
  362. }
  363. }
  364. else
  365. {
  366. gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT);
  367. }
  368. gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT);
  369. // Clean-up and restore parameters temporarily modified
  370. nrf_gzp_disable_gzll();
  371. gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE);
  372. gzll_update_ok &= nrf_gzll_flush_tx_fifo(GZP_PAIRING_PIPE);
  373. nrf_gzll_set_max_tx_attempts(temp_max_tx_attempts);
  374. gzll_update_ok &= nrf_gzll_set_tx_power(temp_power);
  375. gzll_update_ok &= nrf_gzll_enable();
  376. if (!gzll_update_ok)
  377. {
  378. /*
  379. The update of the Gazell parameters failed. Use nrf_gzll_get_error_code()
  380. to investigate the cause.
  381. */
  382. }
  383. return retval;
  384. //lint -restore
  385. }
  386. #ifndef GZP_CRYPT_DISABLE
  387. gzp_id_req_res_t gzp_id_req_send()
  388. {
  389. uint8_t tx_packet[GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH];
  390. uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
  391. gzp_tx_rx_trans_result_t trans_result;
  392. // If no ID request is pending, send new "ID request"
  393. if (!gzp_id_req_pending)
  394. {
  395. // Build "Host ID request packet"
  396. tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_REQ;
  397. // Generate new session token
  398. gzp_random_numbers_generate(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
  399. // Send "Host ID request"
  400. if (gzp_tx_packet(tx_packet, GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH, GZP_DATA_PIPE))
  401. {
  402. // Update session token if "Host ID request" was successfully transmitted
  403. gzp_crypt_set_session_token(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
  404. gzp_id_req_pending = true;
  405. return GZP_ID_RESP_PENDING;
  406. }
  407. }
  408. else // If "ID request is pending" send "fetch ID" packet
  409. {
  410. // Build "host ID fetch" packet
  411. tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_FETCH;
  412. gzp_add_validation_id(&tx_packet[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]);
  413. // Encrypt "host ID fetch" packet
  414. gzp_crypt_select_key(GZP_ID_EXCHANGE);
  415. gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
  416. trans_result = gzp_tx_rx_transaction(tx_packet, GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE);
  417. // If packet was successfully sent AND a response packet was received
  418. if (trans_result == GZP_TX_RX_SUCCESS)
  419. {
  420. // Validate response packet
  421. if (rx_packet[0] == (uint8_t)GZP_CMD_HOST_ID_FETCH_RESP)
  422. {
  423. gzp_crypt(&rx_packet[1], &rx_packet[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
  424. if (gzp_validate_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]))
  425. {
  426. switch (rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS])
  427. {
  428. case GZP_ID_RESP_PENDING:
  429. break;
  430. case GZP_ID_RESP_REJECTED:
  431. gzp_id_req_pending = false;
  432. break;
  433. case GZP_ID_RESP_GRANTED:
  434. gzp_set_host_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
  435. gzp_random_numbers_generate(dyn_key, GZP_DYN_KEY_LENGTH);
  436. gzp_crypt_set_dyn_key(dyn_key);
  437. #ifndef GZP_NV_STORAGE_DISABLE
  438. (void)gzp_params_store(true);
  439. #endif
  440. gzp_id_req_pending = false;
  441. break;
  442. default:
  443. break;
  444. }
  445. return (gzp_id_req_res_t)rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS];
  446. }
  447. else
  448. {
  449. gzp_id_req_pending = false;
  450. return GZP_ID_RESP_REJECTED;
  451. }
  452. }
  453. }
  454. }
  455. gzp_id_req_pending = false;
  456. return GZP_ID_RESP_FAILED;
  457. }
  458. void gzp_id_req_cancel()
  459. {
  460. gzp_id_req_pending = false;
  461. }
  462. bool gzp_crypt_data_send(const uint8_t *src, uint8_t length)
  463. {
  464. if (length <= GZP_ENCRYPTED_USER_DATA_MAX_LENGTH)
  465. {
  466. if (gzp_crypt_tx_transaction(src, length))
  467. {
  468. return true;
  469. }
  470. else
  471. {
  472. //print_string("GZP_CRYPT_TX failed\r\n");
  473. // Attempt key update if user data transmission failed
  474. // during normal operation (!gzp_id_req_pending)
  475. if (!gzp_id_req_pending)
  476. {
  477. //print_string("KEY UPDATE\r\n");
  478. if (gzp_key_update())
  479. {
  480. return gzp_crypt_tx_transaction(src, length);
  481. }
  482. }
  483. return false;
  484. }
  485. }
  486. else
  487. {
  488. return false;
  489. }
  490. }
  491. #endif
  492. /** @} */
  493. /******************************************************************************/
  494. // Implementation: Internal (static) functions
  495. /******************************************************************************/
  496. static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe)
  497. {
  498. tx_complete = false;
  499. tx_success = false;
  500. if (nrf_gzll_add_packet_to_tx_fifo(pipe,(uint8_t *)tx_packet, length))
  501. {
  502. while (tx_complete == false)
  503. {
  504. __WFI();
  505. }
  506. return tx_success;
  507. }
  508. else
  509. {
  510. return false;
  511. }
  512. }
  513. 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)
  514. {
  515. gzp_tx_rx_trans_result_t retval;
  516. uint8_t fetch_packet[GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH];
  517. bool tx_packet_success;
  518. bool fetch_success;
  519. uint32_t local_rx_length = GZP_MAX_ACK_PAYLOAD_LENGTH;
  520. uint32_t temp_lifetime;
  521. nrf_gzp_flush_rx_fifo(pipe);
  522. retval = GZP_TX_RX_FAILED_TO_SEND;
  523. (void)nrf_gzll_disable();
  524. while (nrf_gzll_is_enabled())
  525. {}
  526. temp_lifetime = nrf_gzll_get_sync_lifetime();
  527. (void)nrf_gzll_set_sync_lifetime(GZP_TX_RX_TRANS_DELAY * 3); // 3 = RXPERIOD * 2 + margin
  528. (void)nrf_gzll_enable();
  529. tx_packet_success = gzp_tx_packet(tx_packet, tx_length, pipe);
  530. if (tx_packet_success)
  531. {
  532. retval = GZP_TX_RX_NO_RESPONSE;
  533. nrf_gzp_flush_rx_fifo(pipe);
  534. fetch_packet[0] = (uint8_t)GZP_CMD_FETCH_RESP;
  535. gzp_tick_sleep_rx_periods(GZP_TX_RX_TRANS_DELAY);
  536. tx_packet_success = gzp_tx_packet(fetch_packet, GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe);
  537. if (tx_packet_success)
  538. {
  539. if (nrf_gzll_get_rx_fifo_packet_count(pipe))
  540. {
  541. local_rx_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
  542. fetch_success = nrf_gzll_fetch_packet_from_rx_fifo(pipe, rx_dst, &local_rx_length);
  543. }
  544. else
  545. {
  546. fetch_success = false;
  547. }
  548. if (fetch_success)
  549. {
  550. retval = GZP_TX_RX_SUCCESS;
  551. }
  552. else
  553. {
  554. //print_string("GZP_TX_FETCH_FAILED\r\n");
  555. }
  556. }
  557. else
  558. {
  559. //print_string("GZP_TX_FETCH_NO_ACK\r\n");
  560. }
  561. }
  562. (void)nrf_gzll_disable();
  563. while (nrf_gzll_is_enabled())
  564. {}
  565. (void)nrf_gzll_set_sync_lifetime(temp_lifetime);
  566. (void)nrf_gzll_enable();
  567. return retval;
  568. }
  569. #ifndef GZP_CRYPT_DISABLE
  570. static bool gzp_crypt_tx_transaction(const uint8_t *src, uint8_t length)
  571. {
  572. uint8_t tx_packet[GZP_MAX_FW_PAYLOAD_LENGTH];
  573. uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
  574. uint8_t tx_packet_length;
  575. gzp_tx_rx_trans_result_t result;
  576. tx_packet_length = length + (uint8_t)GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD;
  577. // Assemble tx packet
  578. tx_packet[0] = (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA;
  579. gzp_add_validation_id(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]);
  580. memcpy(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], (uint8_t*)src, length);
  581. // Encrypt tx packet
  582. if (gzp_id_req_pending)
  583. {
  584. gzp_crypt_select_key(GZP_ID_EXCHANGE);
  585. }
  586. else
  587. {
  588. gzp_crypt_select_key(GZP_DATA_EXCHANGE);
  589. }
  590. gzp_crypt(&tx_packet[1], &tx_packet[1], tx_packet_length - 1);
  591. // If packet was successfully sent AND a response packet was received
  592. result = gzp_tx_rx_transaction(tx_packet, tx_packet_length, rx_packet, NULL, GZP_DATA_PIPE);
  593. if (result == GZP_TX_RX_SUCCESS)
  594. {
  595. if (rx_packet[0] == (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA_RESP)
  596. {
  597. 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);
  598. // Validate response in order to know whether packet was correctly decrypted by host
  599. if (gzp_validate_id(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]))
  600. {
  601. // Update session token if normal operation (!gzp_id_req_pending)
  602. if (!gzp_id_req_pending)
  603. {
  604. gzp_crypt_set_session_token(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
  605. }
  606. return true;
  607. }
  608. else
  609. {
  610. //print_string("GZP_CRYPT_TX_TRANS: Validation ID bad\r\n");
  611. return false;
  612. }
  613. }
  614. else
  615. {
  616. //print_string("GZP_CRYPT_TX_TRANS: Bad CMD. \r\n");
  617. return false;
  618. }
  619. }
  620. else
  621. {
  622. //print_string("GZP_CRYPT_TX_TRANS: gzp_tx_rx_trans not SUCCESS\r\n");
  623. return false;
  624. }
  625. }
  626. static bool gzp_key_update(void)
  627. {
  628. uint8_t tx_packet[GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH], rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
  629. // Send "prepare packet" to get session token to be used for key update
  630. tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE;
  631. // If packet was successfully sent AND a response packet was received
  632. if (gzp_tx_rx_transaction(tx_packet, GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
  633. {
  634. if (rx_packet[0] == (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP)
  635. {
  636. gzp_crypt_set_session_token(&rx_packet[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
  637. // Build "key update" packet
  638. tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE;
  639. gzp_add_validation_id(&tx_packet[GZP_CMD_KEY_UPDATE_VALIDATION_ID]);
  640. gzp_random_numbers_generate(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY], GZP_DYN_KEY_LENGTH);
  641. gzp_crypt_set_dyn_key(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY]);
  642. // Encrypt "key update packet"
  643. gzp_crypt_select_key(GZP_KEY_EXCHANGE);
  644. gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
  645. // Send "key update" packet
  646. if (gzp_tx_packet(tx_packet, GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH, GZP_DATA_PIPE))
  647. {
  648. return true;
  649. }
  650. }
  651. }
  652. return false;
  653. }
  654. #endif
  655. void gzp_set_host_id(const uint8_t * id)
  656. {
  657. memcpy(gzp_host_id, id, GZP_HOST_ID_LENGTH);
  658. }
  659. void gzp_get_host_id(uint8_t * dst_id)
  660. {
  661. memcpy(dst_id, gzp_host_id, GZP_HOST_ID_LENGTH);
  662. }
  663. static void gzp_params_db_add(const uint8_t* src_element, uint8_t index)
  664. {
  665. nrf_nvmc_write_bytes((GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE)), src_element, (uint32_t)GZP_PARAMS_DB_ELEMENT_SIZE);
  666. }
  667. static void gzp_params_db_read(uint8_t* dst_element, uint8_t index)
  668. {
  669. memcpy(dst_element,(uint8_t*)(GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE)), GZP_PARAMS_DB_ELEMENT_SIZE);
  670. }
  671. static void gzp_index_db_add(uint8_t val)
  672. {
  673. int16_t i;
  674. uint8_t temp_val;
  675. uint32_t addr;
  676. // Search for unwritten loacation in index DB
  677. for (i = 0; i < GZP_INDEX_DB_SIZE; i++)
  678. {
  679. temp_val = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
  680. // Lower nibble
  681. if (i != (GZP_INDEX_DB_SIZE - 1))
  682. {
  683. if ((temp_val & 0x0f) == 0x0f)
  684. {
  685. temp_val = (temp_val & 0xf0) | val;
  686. break;
  687. }
  688. // Upper nibble
  689. else if ((temp_val & 0xf0) == 0xf0)
  690. {
  691. temp_val = (temp_val & 0x0f) | (val << 4);
  692. break;
  693. }
  694. }
  695. else
  696. {
  697. temp_val = (GZP_PARAMS_DB_MAX_ENTRIES << 4) | val;
  698. break;
  699. }
  700. }
  701. // Write index DB
  702. addr = (GZP_INDEX_DB_ADR + i);
  703. nrf_nvmc_write_byte(addr, temp_val);
  704. }
  705. static uint8_t gzp_index_db_read()
  706. {
  707. uint8_t retval;
  708. int16_t i;
  709. // Search for previously written location
  710. for (i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
  711. {
  712. retval = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
  713. if (retval != 0xff)
  714. {
  715. break;
  716. }
  717. }
  718. if (retval == 0xff)
  719. {
  720. retval = GZP_PARAMS_DB_MAX_ENTRIES; // index db empty
  721. }
  722. else if ((retval & 0xf0) != 0xf0)
  723. {
  724. retval >>= 4;
  725. }
  726. else
  727. {
  728. retval &= 0x0f;
  729. }
  730. return retval;
  731. }
  732. int8_t gzp_get_pairing_status(void)
  733. {
  734. uint8_t db_byte;
  735. int8_t db_index;
  736. int16_t i;
  737. uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
  738. uint8_t default_host_id[GZP_HOST_ID_LENGTH];
  739. db_index = -2;
  740. // Populate default Host ID with F's.
  741. for (i=0; i< GZP_HOST_ID_LENGTH; i++)
  742. {
  743. default_host_id[i] = 0xFF;
  744. }
  745. // Search for previously written location
  746. for (i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
  747. {
  748. db_byte = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
  749. // Check if idx has been written to
  750. if (db_byte != 0xff)
  751. {
  752. // Convert 4-bit nibble to index
  753. if ((db_byte & 0xf0) != 0xf0)
  754. {
  755. db_byte = (db_byte >> 4) & 0x0f;
  756. }
  757. else
  758. {
  759. db_byte = db_byte & 0x0f;
  760. }
  761. // Retrieve database entry
  762. gzp_params_db_read(temp_element, db_byte);
  763. // Check if database entry is all F's
  764. if ( memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], default_host_id, GZP_HOST_ID_LENGTH) != 0)
  765. {
  766. db_index = db_byte;
  767. }
  768. else
  769. {
  770. db_index = -1;
  771. }
  772. break;
  773. }
  774. }
  775. return db_index;
  776. }
  777. static bool gzp_index_db_full()
  778. {
  779. #if (GZP_INDEX_DB_SIZE != 0)
  780. return ((*(uint8_t*)(GZP_INDEX_DB_ADR + (GZP_INDEX_DB_SIZE - 1)) != 0xff));
  781. #else
  782. return true;
  783. #endif
  784. }
  785. //lint -save -e506 Constant value boolean
  786. static bool gzp_index_db_empty()
  787. {
  788. #if (GZP_INDEX_DB_SIZE != 0)
  789. return ((GZP_INDEX_DB_SIZE == 0) || ((*(uint8_t*)(GZP_INDEX_DB_ADR)) == 0xff));
  790. #else
  791. return true;
  792. #endif
  793. }
  794. //lint -restore
  795. static bool gzp_array_is_set(const uint8_t* src, uint8_t length)
  796. {
  797. uint8_t i;
  798. for (i = 0; i < length; i++)
  799. {
  800. if (*(src++) != 0xff)
  801. {
  802. return false;
  803. }
  804. }
  805. return true;
  806. }
  807. static bool gzp_params_store(bool store_all)
  808. {
  809. uint8_t i;
  810. bool write_index_db = false;
  811. bool write_param_db = false;
  812. uint8_t new_db_index = 0;
  813. uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
  814. // Search param DB to see if current setup exists
  815. if (store_all)
  816. {
  817. // Search for: Current system address and host ID exists
  818. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  819. {
  820. gzp_params_db_read(temp_element, i);
  821. 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))
  822. {
  823. write_index_db = true;
  824. new_db_index = i;
  825. break; // System address + host_id allready exists in database
  826. }
  827. }
  828. // Search for: Current system address and cleared host ID
  829. if (!write_index_db)
  830. {
  831. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  832. {
  833. gzp_params_db_read(temp_element, i);
  834. if (((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0) && \
  835. (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], GZP_HOST_ID_LENGTH)))
  836. {
  837. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
  838. new_db_index = i;
  839. write_index_db = true;
  840. write_param_db = true;
  841. break;
  842. }
  843. }
  844. }
  845. // Search for: Cleared system address and cleared host ID
  846. if (!write_index_db)
  847. {
  848. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  849. {
  850. gzp_params_db_read(temp_element, i);
  851. if (gzp_array_is_set(temp_element, GZP_PARAMS_DB_ELEMENT_SIZE))
  852. {
  853. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
  854. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
  855. new_db_index = i;
  856. write_index_db = true;
  857. write_param_db = true;
  858. break;
  859. }
  860. }
  861. }
  862. }
  863. else
  864. {
  865. // Search for: System address + any host ID
  866. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  867. {
  868. gzp_params_db_read(temp_element, i);
  869. if ((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0)
  870. {
  871. //memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
  872. write_index_db = true;
  873. new_db_index = i;
  874. break;
  875. }
  876. }
  877. // Search for: System address cleared
  878. if (!write_index_db)
  879. {
  880. for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
  881. {
  882. gzp_params_db_read(temp_element, i);
  883. if (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH))
  884. {
  885. memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
  886. write_index_db = true;
  887. write_param_db = true;
  888. new_db_index = i;
  889. break;
  890. }
  891. }
  892. }
  893. }
  894. if (write_param_db)
  895. {
  896. gzp_params_db_add(temp_element, new_db_index);
  897. }
  898. if (write_index_db)
  899. {
  900. if (!gzp_index_db_full() && (new_db_index != gzp_index_db_read()) && (new_db_index != GZP_PARAMS_DB_MAX_ENTRIES))
  901. {
  902. gzp_index_db_add(new_db_index);
  903. return true;
  904. }
  905. }
  906. return false;
  907. }
  908. static bool gzp_params_restore(void)
  909. {
  910. uint8_t i;
  911. uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
  912. if (!gzp_index_db_full() && !gzp_index_db_empty())
  913. {
  914. i = gzp_index_db_read();
  915. if (i < GZP_PARAMS_DB_MAX_ENTRIES)
  916. {
  917. gzp_params_db_read(temp_element, i);
  918. memcpy(gzp_system_address, &temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
  919. gzp_set_host_id(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID]);
  920. return true;
  921. }
  922. }
  923. return false;
  924. }
  925. void gzp_delay_rx_periods(uint32_t rx_periods)
  926. {
  927. nrf_delay_us(rx_periods * 2 * nrf_gzll_get_timeslot_period());
  928. }
  929. void gzp_tick_sleep_rx_periods(uint32_t rx_periods)
  930. {
  931. nrf_gzll_clear_tick_count();
  932. while (nrf_gzll_get_tick_count() < 2 * rx_periods)
  933. {
  934. __WFI();
  935. }
  936. }
  937. void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
  938. {
  939. latest_tx_info = tx_info;
  940. tx_complete = true;
  941. tx_success = true;
  942. }
  943. void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
  944. {
  945. latest_tx_info = tx_info;
  946. tx_complete = true;
  947. tx_success = false;
  948. }
  949. bool nrf_gzp_tx_complete(void)
  950. {
  951. return tx_complete;
  952. }
  953. bool nrf_gzp_tx_success(void)
  954. {
  955. return tx_success;
  956. }
  957. void nrf_gzp_reset_tx_complete()
  958. {
  959. tx_complete = false;
  960. }
  961. void nrf_gzp_reset_tx_success()
  962. {
  963. tx_success = false;
  964. }
  965. void nrf_gzll_disabled(void)
  966. {
  967. }
  968. void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
  969. {
  970. }
  971. /** @} */
  972. /** @} */