static gzp_tx_rx_trans_result_t gzp_tx_rx_transaction(const uint8_t *tx_packet, uint8_t tx_length, uint8_t *rx_dst, uint8_t *rx_length, uint8_t pipe) { gzp_tx_rx_trans_result_t retval; uint8_t fetch_packet[GZPAR_CMD_FETCH_RESP_PAYLOAD_LENGTH]; gzll_rx_fifo_flush(); retval = GZP_TX_RX_FAILED_TO_SEND; if(gzp_tx_packet(tx_packet, tx_length, pipe)) { retval = GZP_TX_RX_NO_RESPONSE; gzll_rx_fifo_flush(); fetch_packet[0] = GZP_CMD_FETCH_RESP; gzp_delay_rx_periods(GZP_TX_RX_TRANS_DELAY); gzp_tx_packet(fetch_packet, GZPAR_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe); if(gzll_rx_fifo_read(rx_dst, rx_length, NULL)) { retval = GZP_TX_RX_SUCCESS; } } return retval; }
static bool gzp_key_update(void) { uint8_t tx_packet[GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH], rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH]; // Send "prepare packet" to get session token to be used for key update tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE; // If packet was successfully sent AND a response packet was received if(gzp_tx_rx_transaction(tx_packet, GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS) { if(rx_packet[0] == (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP) { gzp_crypt_set_session_token(&rx_packet[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]); // Build "key update" packet tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE; gzp_add_validation_id(&tx_packet[GZP_CMD_KEY_UPDATE_VALIDATION_ID]); gzp_random_numbers_generate(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY], GZP_DYN_KEY_LENGTH); gzp_crypt_set_dyn_key(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY]); // Encrypt "key update packet" gzp_crypt_select_key(GZP_KEY_EXCHANGE); gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1); // Send "key update" packet if(gzp_tx_packet(tx_packet, GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH, GZP_DATA_PIPE)) { return true; } } } return false; }
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) { gzp_tx_rx_trans_result_t retval; uint8_t fetch_packet[GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH]; bool tx_packet_success; bool fetch_success; uint32_t local_rx_length = GZP_MAX_ACK_PAYLOAD_LENGTH; uint32_t temp_lifetime; nrf_gzp_flush_rx_fifo(pipe); retval = GZP_TX_RX_FAILED_TO_SEND; (void)nrf_gzll_disable(); while(nrf_gzll_is_enabled()) {} temp_lifetime = nrf_gzll_get_sync_lifetime(); (void)nrf_gzll_set_sync_lifetime(GZP_TX_RX_TRANS_DELAY * 3); // 3 = RXPERIOD * 2 + margin (void)nrf_gzll_enable(); tx_packet_success = gzp_tx_packet(tx_packet, tx_length, pipe); if(tx_packet_success) { retval = GZP_TX_RX_NO_RESPONSE; nrf_gzp_flush_rx_fifo(pipe); fetch_packet[0] = (uint8_t)GZP_CMD_FETCH_RESP; gzp_tick_sleep_rx_periods(GZP_TX_RX_TRANS_DELAY); tx_packet_success = gzp_tx_packet(fetch_packet, GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe); if(tx_packet_success) { if(nrf_gzll_get_rx_fifo_packet_count(pipe)) { local_rx_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; fetch_success = nrf_gzll_fetch_packet_from_rx_fifo(pipe, rx_dst, &local_rx_length); } else { fetch_success = false; } if(fetch_success) { retval = GZP_TX_RX_SUCCESS; } else { //print_string("GZP_TX_FETCH_FAILED\r\n"); } } else { //print_string("GZP_TX_FETCH_NO_ACK\r\n"); } } (void)nrf_gzll_disable(); while(nrf_gzll_is_enabled()) {} (void)nrf_gzll_set_sync_lifetime(temp_lifetime); (void)nrf_gzll_enable(); return retval; }
gzp_id_req_res_t gzp_id_req_send() { uint8_t tx_packet[GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH]; uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH]; gzp_tx_rx_trans_result_t trans_result; // If no ID request is pending, send new "ID request" if(!gzp_id_req_pending) { // Build "Host ID request packet" tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_REQ; // Generate new session token gzp_random_numbers_generate(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH); // Send "Host ID request" if(gzp_tx_packet(tx_packet, GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH, GZP_DATA_PIPE)) { // Update session token if "Host ID request" was successfully transmitted gzp_crypt_set_session_token(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]); gzp_id_req_pending = true; return GZP_ID_RESP_PENDING; } } else // If "ID request is pending" send "fetch ID" packet { // Build "host ID fetch" packet tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_FETCH; gzp_add_validation_id(&tx_packet[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]); // Encrypt "host ID fetch" packet gzp_crypt_select_key(GZP_ID_EXCHANGE); gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1); trans_result = gzp_tx_rx_transaction(tx_packet, GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE); // If packet was successfully sent AND a response packet was received if(trans_result == GZP_TX_RX_SUCCESS) { // Validate response packet if(rx_packet[0] == (uint8_t)GZP_CMD_HOST_ID_FETCH_RESP) { gzp_crypt(&rx_packet[1], &rx_packet[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1); if(gzp_validate_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID])) { switch(rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS]) { case GZP_ID_RESP_PENDING: break; case GZP_ID_RESP_REJECTED: gzp_id_req_pending = false; break; case GZP_ID_RESP_GRANTED: gzp_set_host_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]); gzp_random_numbers_generate(dyn_key, GZP_DYN_KEY_LENGTH); gzp_crypt_set_dyn_key(dyn_key); #ifndef GZP_NV_STORAGE_DISABLE (void)gzp_params_store(true); #endif gzp_id_req_pending = false; break; default: break; } return (gzp_id_req_res_t)rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS]; } else { gzp_id_req_pending = false; return GZP_ID_RESP_REJECTED; } } } } gzp_id_req_pending = false; return GZP_ID_RESP_FAILED; }
bool gzp_address_req_send() { //lint -save -e514 Unusual use of a Boolean expression (gzll_update_ok &= ...) uint8_t i; bool retval = false; bool success; uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH]; uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; nrf_gzll_tx_power_t temp_power; uint32_t temp_max_tx_attempts; bool gzll_update_ok = true; // Store parameters that are temporarily changed temp_max_tx_attempts = nrf_gzll_get_max_tx_attempts(); temp_power = nrf_gzll_get_tx_power(); // Modify parameters nrf_gzp_disable_gzll(); gzll_update_ok &= nrf_gzll_set_max_tx_attempts(GZP_REQ_TX_TIMEOUT); gzll_update_ok &= nrf_gzll_set_tx_power(GZP_POWER); // Flush RX FIFO gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE); gzll_update_ok &= nrf_gzll_enable(); // Build "request" packet address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_REQ; // Send a number of packets in order to broadcast that devices not within // close proximity must back off. for(i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++) { success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE); if(success) { nrf_gzp_flush_rx_fifo(GZP_PAIRING_PIPE); } else { break; } } gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT); // Send message for fetching pairing response from host. address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH; success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE); if(success && latest_tx_info.payload_received_in_ack) { // If pairing response received if(nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0) { rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; //dummy placeholder if(nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &rx_payload_length)) { if(rx_payload[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_RESP) { memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH); gzll_update_ok &= gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]); #ifndef GZP_NV_STORAGE_DISABLE (void)gzp_params_store(false); // "False" indicates that only "system address" part of DB element will be stored #endif retval = true; } } } } else { gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT); } gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT); // Clean-up and restore parameters temporarily modified nrf_gzp_disable_gzll(); gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE); gzll_update_ok &= nrf_gzll_flush_tx_fifo(GZP_PAIRING_PIPE); gzll_update_ok &= nrf_gzll_set_max_tx_attempts(temp_max_tx_attempts); gzll_update_ok &= nrf_gzll_set_tx_power(temp_power); gzll_update_ok &= nrf_gzll_enable(); if(!gzll_update_ok) { /* The update of the Gazell parameters failed. Use nrf_gzll_get_error_code() to investigate the cause. */ } return retval; //lint -restore }
bool gzp_address_req_send(uint8_t idx) { uint8_t i; bool retval = false; uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH]; uint8_t rx_payload[GZLL_MAX_PAYLOAD_LENGTH]; uint16_t temp_power, temp_tx_timeout, temp_device_mode; if(gzll_get_state() == GZLL_IDLE) { // Store parameters that are temporarily changed temp_tx_timeout = gzll_get_param(GZLL_PARAM_TX_TIMEOUT); temp_power = gzll_get_param(GZLL_PARAM_OUTPUT_POWER); temp_device_mode = gzll_get_param(GZLL_PARAM_DEVICE_MODE); // Modify parameters gzll_set_param(GZLL_PARAM_TX_TIMEOUT, GZP_REQ_TX_TIMEOUT); gzll_set_param(GZLL_PARAM_OUTPUT_POWER, GZP_POWER); gzll_set_param(GZLL_PARAM_DEVICE_MODE, 0); // Flush RX FIFO gzll_rx_fifo_flush(); // Build "request" packet address_req[0] = GZP_CMD_HOST_ADDRESS_REQ; // Send a number of packets in order to broadcast that devices not within // close proximity must back off. for(i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++) { if(!gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0)) { break; } } gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT); // Send message for fetching pairing response from host. address_req[0] = GZP_CMD_HOST_ADDRESS_FETCH; if(gzp_tx_packet(&address_req[0], GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0)) { // If pairing response received if(gzll_rx_fifo_read(rx_payload, NULL, NULL)) { if(rx_payload[0] == GZP_CMD_HOST_ADDRESS_RESP) { memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH); gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]); pairing_list_addr_write(idx, gzp_system_address); retval = true; } } } else { gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT); } gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT); // Clean-up and restore parameters temporarily modified gzll_rx_fifo_flush(); gzll_tx_fifo_flush(); gzll_set_param(GZLL_PARAM_TX_TIMEOUT, temp_tx_timeout); gzll_set_param(GZLL_PARAM_OUTPUT_POWER, temp_power); gzll_set_param(GZLL_PARAM_DEVICE_MODE, temp_device_mode); } return retval; }