Application Programming Interface (API) for the Gazell pairing library
[Gazell Pairing Library (gzp)]

Common Device and Host functions

void gzp_init (void)
void gzp_id_req_cancel (void)

Device functions

_Bool gzp_address_req_send (void)
gzp_id_req_res_t gzp_id_req_send (void)
_Bool gzp_crypt_data_send (const uint8_t *src, uint8_t length)

Host functions

void gzp_pairing_enable (_Bool enable)
void gzp_host_execute (void)
_Bool gzp_address_exchanged (void)
_Bool gzp_id_req_received (void)
void gzp_id_req_reject (void)
void gzp_id_req_grant (void)
_Bool gzp_crypt_user_data_received (void)
_Bool gzp_crypt_user_data_read (uint8_t *dst, uint8_t *length)

Function Documentation

void gzp_init ( void   )

Initialization function. This function initializes the Gazell Pairing Library.

This function must be called before any of the other Gazell Pairing Library functions are used and must be called after gzll_init() is called.

Definition at line 212 of file gzp_device.c.

{
  gzp_id_req_pending = false;

  #ifndef GZP_NV_STORAGE_DISABLE
  gzp_params_restore();
  #endif

  // Update radio parameters from gzp_system_address
  gzp_update_radio_params(gzp_system_address);
}
void gzp_id_req_cancel ( void   )

Function for cancelling an ongoing (pending) "Host ID request".

After calling this function the "Host ID request" status will go to "ID request Idle".

Definition at line 378 of file gzp_device.c.

{
  gzp_id_req_pending = false;
}
_Bool gzp_address_req_send ( void   )

Function for sending a "system address" request to a Host.

When calling this function the Device will attempt acquiring the "system address" from any Host within close proximity.

If a host is located within close proximity and pairing is enabled in the Host, a "system address" will be sent in return to the Device.

The new "system address" will apply immediately in the Device, and the new "system address" will be stored in non volatile (NV) memory.

Note. Using OTP devices limits the number of times a new "system address" can be stored in NV memory.

Returns:
Return values:
trueif new "system address" was received from a Host.
falseif no "system address" was received from a Host.

Definition at line 224 of file gzp_device.c.

{
  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]);

          #ifndef GZP_NV_STORAGE_DISABLE
          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
    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;
}
gzp_id_req_res_t gzp_id_req_send ( void   )

Function for sending a "Host ID request" to a Host.

The "Host ID" is needed to be able to send encrypted data using gzp_crypt_data_send().

The request will be sent using the "system address" previously received using gzp_address_req_send().

It is not required that the Host is within close proximity in order to acquire the "Host ID".

The new "Host ID" will apply immediately for the Device, and the new "Host ID" will be stored in non volatile (NV) memory.

Note. Using OTP devices limits the number of times a new "Host ID" can be stored in NV memory.

Returns:
Return values:
GZP_ID_RESP_PENDINGif a "Host ID request" has been sent to the Host, but the Host application has not yet decided whether to Grant or Reject the "ID request".
GZP_ID_RESP_GRANTEDif the "Host ID" has been received from the Host. The received "Host ID" will be stored in non volatile memory.
GZP_ID_RESP_REJECTEDif the Host application has rejected the "Host ID request".
GZP_ID_RESP_FAILEDif failing to send a request or receive a response from the Host.

Definition at line 302 of file gzp_device.c.

{
  uint8_t tx_packet[GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH];
  uint8_t rx_packet[GZLL_MAX_ACK_PAYLOAD_LENGTH];

  // If no ID request is pendning, send new "ID request"
  if(!gzp_id_req_pending)
  {
    // Build "Host ID request packet"
    tx_packet[0] = 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] = 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);

    // If packet was successfully sent AND a response packet was received
    if(gzp_tx_rx_transaction(tx_packet, GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
    {
      // Validate response packet
      if(rx_packet[0] == 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]);
              #ifndef GZP_NV_STORAGE_DISABLE
              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_crypt_data_send ( const uint8_t *  src,
uint8_t  length 
)

Function for sending encrypted user data to the Host.

Before any data can be sent the Device must acquire both the Host's "system address" by using gzp_address_req_send() and the "Host ID" by using gzp_id_req_send().

Parameters:
*srcis a pointer to the data packet to be sent.
lengthis the length of the data packet to be sent.
Returns:
Return values:
trueif the data was successfully transmitted and decrypted by the Host.
falseif data transmission failed or Host failed to decryption data correctly.

Definition at line 383 of file gzp_device.c.

{
  if(length <= GZP_ENCRYPTED_USER_DATA_MAX_LENGTH)
  {
    if(gzp_crypt_tx_transaction(src, length))
    {
      return true;
    }
    else
    {
      // Attempt key update if user data transmission failed
      // during normal operation (!gzp_id_req_pending)
      if(!gzp_id_req_pending)
      {
        gzp_key_update();
        return gzp_crypt_tx_transaction(src, length);
      }
      return false;
    }
  }
  else
  {
    return false;
  }
}
void gzp_pairing_enable ( _Bool  enable )

Function for enabling/disabling pairing in a host. When pairing is enabled the host will be monitoring for "system address" and "Host ID" requests from Devices.

A "system address request" received from a Device will always be granted. When a "host ID request" has been received, the Host application have to grant, reject or cancel this by using one of the following functions:

Parameters:
enable
  • true enables pairing.
  • false disables pairing.

Definition at line 130 of file gzp_host.c.

{
  gzll_states_t temp_gzll_state;

  temp_gzll_state = gzll_get_state();

  if(gzp_pairing_enabled_f != enable)
  {
    gzll_goto_idle();

    if(enable)
    {
      gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE));
    }
    else
    {
      gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) & ~(1 << GZP_PAIRING_PIPE));
      gzp_id_req_stat = GZP_ID_REQ_IDLE;
    }

    gzp_pairing_enabled_f = enable;

    if(temp_gzll_state == GZLL_HOST_ACTIVE)
    {
      gzll_rx_start();
    }
  }
}
void gzp_host_execute ( void   )

Function for executing Gazell Pairing Library host operation.

This function must be called regularly by the Host application.

Definition at line 159 of file gzp_host.c.

{
  uint8_t rx_pipe;
  uint8_t payload_length;
  uint8_t rx_payload[GZLL_MAX_FW_PAYLOAD_LENGTH];

  gzp_address_exchanged_f = false;

  rx_pipe = gzll_get_rx_data_ready_pipe_number();

  if((rx_pipe == GZP_PAIRING_PIPE) || ((rx_pipe == GZP_DATA_PIPE) && (gzp_encrypted_user_data_length == 0)))
  {
    gzll_rx_fifo_read(rx_payload, &payload_length, NULL);

    switch(rx_payload[0])
    {
      case GZP_CMD_HOST_ADDRESS_REQ:
        gzp_process_address_req(rx_payload);
        break;

      #ifndef GZP_CRYPT_DISABLE

      case GZP_CMD_HOST_ID_REQ:
        gzp_process_id_req(rx_payload);
        break;
      case GZP_CMD_HOST_ID_FETCH:
        gzp_process_id_fetch(rx_payload);
        break;
      case GZP_CMD_KEY_UPDATE_PREPARE:
        gzp_process_key_update_prepare();
        break;
      case GZP_CMD_KEY_UPDATE:
        gzp_process_key_update(rx_payload);
        break;
      case GZP_CMD_ENCRYPTED_USER_DATA:
        gzp_process_encrypted_user_data(rx_payload, payload_length);
        break;

      #endif

      case GZP_CMD_FETCH_RESP:
      default:
        break;
    }
  }

  // Restart reception if "not proximity backoff" period has elapsed
  if(gzll_get_state() == GZLL_IDLE)
  {
    gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
    if(gzp_pairing_enabled_f)
    {
      gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE));
    }
    gzll_rx_start();
  }

  #ifndef GZP_CRYPT_DISABLE
  gzp_session_counter_inc();
  #endif
}
_Bool gzp_address_exchanged ( void   )

Function returning true if a "system address" was delivered to a requesting Device during the previous call to gzp_host_execute();

Definition at line 294 of file gzp_host.c.

{
  return gzp_address_exchanged_f;
}
_Bool gzp_id_req_received ( void   )

Function for checking if a "Host ID request" has been received from a Device.

If a request has been received, the Pairing library will enter "ID request pending" state.

The application is responsible for responding to this request by calling one of the following functions:

Returns:
Return values:
trueif a "Host ID request" has been received (internal state is "ID request pending")
falseif no "Host ID request" has been received (internal state is "ID request idle")

Definition at line 326 of file gzp_host.c.

{
  return (gzp_id_req_stat != GZP_ID_REQ_IDLE);
}
void gzp_id_req_reject ( void   )

Function for rejecting the previously received "Host ID request". This function should be called only when a "Host ID request" has been received (internal state is "ID request pending").

The internal state of the Pairing library will remain "ID request pending" until the a "reject" message has been successfully transmitted to the requesting Device. After this the internal state will change to "ID request idle".

Definition at line 331 of file gzp_host.c.

{
  if(gzp_id_req_received())
  {
    gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_REJECTED;
  }
}
void gzp_id_req_grant ( void   )

Function for granting the previously received "Host ID request". This function should be called only when a "Host ID request" has been received (internal state is "ID request pending").

The internal state of the Pairing library will remain "ID request pending" until the "Host ID" has been successfully transmitted to the requesting Device. After this the internal state will change to "ID request idle".

Definition at line 339 of file gzp_host.c.

{
  if(gzp_id_req_received())
  {
    gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_GRANTED;
  }
}
_Bool gzp_crypt_user_data_received ( void   )

Function returning true if encrypted user data has been received.

Definition at line 301 of file gzp_host.c.

{
  return (gzp_encrypted_user_data_length > 0);
}
_Bool gzp_crypt_user_data_read ( uint8_t *  dst,
uint8_t *  length 
)

Function for reading encrypted user data.

Note that the read user data will be automatically decrypted. Only data that was decrypted correctly will be presented.

Parameters:
dst*is a pointer to where the received data will be written.
length*is a pointer for returning the number of bytes received. Only 1 byte will be writtem to length*.
Returns:
Return values:
trueif data has been received and is written to dst*
falseif no data has been received.

Definition at line 306 of file gzp_host.c.

{
  if(gzp_encrypted_user_data_length > 0)
  {
    memcpy(dst, (void*)gzp_encrypted_user_data, gzp_encrypted_user_data_length);

    if(length != NULL)
    {
      *length = gzp_encrypted_user_data_length;
    }
    gzp_encrypted_user_data_length = 0;

    return true;
  }
  else
  {
    return false;
  }
}