예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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
}
예제 #6
0
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;
}