• Main Page
  • Modules
  • Index
  • File List
  • Globals

gazell/common/gzp_device.c

Go to the documentation of this file.
00001 /* Copyright (c) 2009 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is confidential property of Nordic
00004  * Semiconductor ASA.Terms and conditions of usage are described in detail
00005  * in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *
00011  * $LastChangedRevision: 2500 $
00012  */
00013 
00019 #include <stdint.h>
00020 #include <stdbool.h>
00021 #include <string.h>
00022 
00023 #include "gzll.h"
00024 #include "gzp.h"
00025 #include "hal_aes.h"
00026 #include "hal_delay.h"
00027 #include "hal_flash.h"
00028 #include "memdefs.h"
00029 
00030 //-----------------------------------------------------------------------------
00031 // Misc. defines
00032 //-----------------------------------------------------------------------------
00033 #define GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS 0
00034 #define GZP_PARAMS_DB_ELEMENT_HOST_ID (GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS + GZP_SYSTEM_ADDRESS_WIDTH)
00035 #define GZP_PARAMS_DB_ELEMENT_SIZE (GZP_SYSTEM_ADDRESS_WIDTH + GZP_HOST_ID_LENGTH)
00036 #define GZP_PARAMS_DB_MAX_ENTRIES 14            // [#elements]. Max 14.
00037 
00038 //-----------------------------------------------------------------------------
00039 // Derived parameters
00040 //-----------------------------------------------------------------------------
00041 //lint -esym(40, GZP_PARAMS_STORAGE_ADR) "Undeclare identifier"
00042 #define GZP_PARAMS_DB_ADR GZP_PARAMS_STORAGE_ADR
00043 #define GZP_PARAMS_DB_SIZE (GZP_PARAMS_DB_MAX_ENTRIES * GZP_PARAMS_DB_ELEMENT_SIZE)
00044 
00045 #define GZP_INDEX_DB_ADR (GZP_PARAMS_STORAGE_ADR + GZP_PARAMS_DB_SIZE)
00046 #define GZP_INDEX_DB_SIZE (GZP_DEVICE_PARAMS_STORAGE_SIZE - GZP_PARAMS_DB_SIZE)
00047 
00048 #if(GZP_DEVICE_PARAMS_STORAGE_SIZE < GZP_PARAMS_DB_SIZE)
00049   #error GZP_DEVICE_PARAMS_STORAGE_SIZE must be greater or equal to GZP_PAIRING_PARAMS_DB_SIZE
00050 #elif(GZP_DEVICE_PARAMS_STORAGE_SIZE == GZP_PARAMS_DB_SIZE )
00051   #warning GZP_DEVICE_PARAMS_STORAGE_SIZE to low to be able store any pairing parameters NV memory
00052 #endif
00053 
00054 //-----------------------------------------------------------------------------
00055 // Typedefs
00056 //-----------------------------------------------------------------------------
00057 
00061 typedef enum
00062 {
00063   GZP_TX_RX_SUCCESS,
00064   GZP_TX_RX_FAILED_TO_SEND,
00065   GZP_TX_RX_NO_RESPONSE
00066 } gzp_tx_rx_trans_result_t;
00067 
00068 //-----------------------------------------------------------------------------
00069 // External variables
00070 //-----------------------------------------------------------------------------
00071 
00072 static xdata uint8_t gzp_system_address[GZP_SYSTEM_ADDRESS_WIDTH];
00073 static xdata uint8_t gzp_host_id[GZP_HOST_ID_LENGTH];
00074 
00075 //-----------------------------------------------------------------------------
00076 // Global variables
00077 //-----------------------------------------------------------------------------
00078 
00082 static xdata bool gzp_id_req_pending;
00083 
00084 //-----------------------------------------------------------------------------
00085 // Internal (static) function prototypes
00086 //-----------------------------------------------------------------------------
00087 
00101 static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe);
00102 
00113 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);
00114 
00126 static bool gzp_crypt_tx_transaction(const uint8_t *tx_packet, uint8_t length);
00127 
00134 static bool gzp_key_update();
00135 
00147 static void gzp_params_db_add(const uint8_t *src_element, uint8_t index);
00148 
00157 static void gzp_params_db_read(uint8_t* dst_element, uint8_t index);
00158 
00164 static void gzp_index_db_add(uint8_t index);
00165 
00169 static uint8_t gzp_index_db_read();
00170 
00174 static bool gzp_index_db_full();
00175 
00179 static bool gzp_index_db_empty();
00180 
00187 static bool gzp_array_is_set(const uint8_t* src, uint8_t length);
00188 
00197 static bool gzp_params_store(bool store_all);
00198 
00202 static bool gzp_params_restore(void);
00203 
00207 void gzp_delay_rx_periods(uint16_t rx_periods);
00208 
00209 //-----------------------------------------------------------------------------
00210 // Implementation: Application programming interface (API) functions
00211 //-----------------------------------------------------------------------------
00212 void gzp_init()
00213 {
00214   gzp_id_req_pending = false;
00215 
00216   #ifndef GZP_NV_STORAGE_DISABLE
00217   gzp_params_restore();
00218   #endif
00219 
00220   // Update radio parameters from gzp_system_address
00221   gzp_update_radio_params(gzp_system_address);
00222 }
00223 
00224 bool gzp_address_req_send()
00225 {
00226   uint8_t i;
00227   bool retval = false;
00228   uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH];
00229   uint8_t rx_payload[GZLL_MAX_PAYLOAD_LENGTH];
00230   uint16_t temp_power, temp_tx_timeout, temp_device_mode;
00231 
00232   if(gzll_get_state() == GZLL_IDLE)
00233   {
00234     // Store parameters that are temporarily changed
00235     temp_tx_timeout = gzll_get_param(GZLL_PARAM_TX_TIMEOUT);
00236     temp_power = gzll_get_param(GZLL_PARAM_OUTPUT_POWER);
00237     temp_device_mode = gzll_get_param(GZLL_PARAM_DEVICE_MODE);
00238 
00239     // Modify parameters
00240     gzll_set_param(GZLL_PARAM_TX_TIMEOUT, GZP_REQ_TX_TIMEOUT);
00241     gzll_set_param(GZLL_PARAM_OUTPUT_POWER, GZP_POWER);
00242     gzll_set_param(GZLL_PARAM_DEVICE_MODE, 0);
00243 
00244     // Flush RX FIFO
00245     gzll_rx_fifo_flush();
00246 
00247     // Build "request" packet
00248     address_req[0] = GZP_CMD_HOST_ADDRESS_REQ;
00249 
00250     // Send a number of packets in order to broadcast that devices not within
00251     // close proximity must back off.
00252     for(i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++)
00253     {
00254       if(!gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0))
00255       {
00256         break;
00257       }
00258     }
00259 
00260     gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT);
00261 
00262     // Send message for fetching pairing response from host.
00263     address_req[0] = GZP_CMD_HOST_ADDRESS_FETCH;
00264 
00265     if(gzp_tx_packet(&address_req[0], GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0))
00266     {
00267       // If pairing response received
00268       if(gzll_rx_fifo_read(rx_payload, NULL, NULL))
00269       {
00270         if(rx_payload[0] == GZP_CMD_HOST_ADDRESS_RESP)
00271         {
00272           memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
00273           gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]);
00274 
00275           #ifndef GZP_NV_STORAGE_DISABLE
00276           gzp_params_store(false); // "False" indicates that only "system address" part of DB element will be stored
00277           #endif
00278           retval = true;
00279         }
00280       }
00281     }
00282     else
00283     {
00284       gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT);
00285     }
00286 
00287     gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT);
00288 
00289     // Clean-up and restore parameters temporarily  modified
00290     gzll_rx_fifo_flush();
00291     gzll_tx_fifo_flush();
00292     gzll_set_param(GZLL_PARAM_TX_TIMEOUT, temp_tx_timeout);
00293     gzll_set_param(GZLL_PARAM_OUTPUT_POWER, temp_power);
00294     gzll_set_param(GZLL_PARAM_DEVICE_MODE, temp_device_mode);
00295   }
00296 
00297   return retval;
00298 }
00299 
00300 #ifndef GZP_CRYPT_DISABLE
00301 
00302 gzp_id_req_res_t gzp_id_req_send()
00303 {
00304   uint8_t tx_packet[GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH];
00305   uint8_t rx_packet[GZLL_MAX_ACK_PAYLOAD_LENGTH];
00306 
00307   // If no ID request is pendning, send new "ID request"
00308   if(!gzp_id_req_pending)
00309   {
00310     // Build "Host ID request packet"
00311     tx_packet[0] = GZP_CMD_HOST_ID_REQ;
00312 
00313     // Generate new session token
00314     gzp_random_numbers_generate(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
00315 
00316     // Send "Host ID request"
00317     if(gzp_tx_packet(tx_packet, GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH, GZP_DATA_PIPE))
00318     {
00319       // Update session token if "Host ID request" was successfully transmitted
00320       gzp_crypt_set_session_token(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
00321       gzp_id_req_pending = true;
00322 
00323       return GZP_ID_RESP_PENDING;
00324     }
00325   }
00326   else // If "ID request is pending" send "fetch ID" packet
00327   {
00328     // Build "host ID fetch" packet
00329     tx_packet[0] = GZP_CMD_HOST_ID_FETCH;
00330     gzp_add_validation_id(&tx_packet[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]);
00331 
00332     // Encrypt "host ID fetch" packet
00333     gzp_crypt_select_key(GZP_ID_EXCHANGE);
00334     gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
00335 
00336     // If packet was successfully sent AND a response packet was received
00337     if(gzp_tx_rx_transaction(tx_packet, GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
00338     {
00339       // Validate response packet
00340       if(rx_packet[0] == GZP_CMD_HOST_ID_FETCH_RESP)
00341       {
00342         gzp_crypt(&rx_packet[1], &rx_packet[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
00343         if(gzp_validate_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]))
00344         {
00345           switch(rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS])
00346           {
00347             case GZP_ID_RESP_PENDING:
00348               break;
00349             case GZP_ID_RESP_REJECTED:
00350               gzp_id_req_pending = false;
00351               break;
00352             case GZP_ID_RESP_GRANTED:
00353               gzp_set_host_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
00354               #ifndef GZP_NV_STORAGE_DISABLE
00355               gzp_params_store(true);
00356               #endif
00357               gzp_id_req_pending = false;
00358               break;
00359             default:
00360               break;
00361           }
00362 
00363           return (gzp_id_req_res_t)rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS];
00364         }
00365         else
00366         {
00367           gzp_id_req_pending = false;
00368           return GZP_ID_RESP_REJECTED;
00369         }
00370       }
00371     }
00372   }
00373 
00374   gzp_id_req_pending = false;
00375   return GZP_ID_RESP_FAILED;
00376 }
00377 
00378 void gzp_id_req_cancel()
00379 {
00380   gzp_id_req_pending = false;
00381 }
00382 
00383 bool gzp_crypt_data_send(const uint8_t *src, uint8_t length)
00384 {
00385   if(length <= GZP_ENCRYPTED_USER_DATA_MAX_LENGTH)
00386   {
00387     if(gzp_crypt_tx_transaction(src, length))
00388     {
00389       return true;
00390     }
00391     else
00392     {
00393       // Attempt key update if user data transmission failed
00394       // during normal operation (!gzp_id_req_pending)
00395       if(!gzp_id_req_pending)
00396       {
00397         gzp_key_update();
00398         return gzp_crypt_tx_transaction(src, length);
00399       }
00400       return false;
00401     }
00402   }
00403   else
00404   {
00405     return false;
00406   }
00407 }
00408 
00409 #endif
00410 
00411 //-----------------------------------------------------------------------------
00412 // Implementation: Internal (static) functions
00413 //-----------------------------------------------------------------------------
00414 
00415 static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe)
00416 {
00417   if(gzll_tx_data(tx_packet, length, pipe))
00418   {
00419     while(gzll_get_state() != GZLL_IDLE)
00420     ;
00421     return gzll_tx_success();
00422   }
00423   return false;
00424 }
00425 
00426 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)
00427 {
00428   gzp_tx_rx_trans_result_t retval;
00429   uint8_t fetch_packet[GZPAR_CMD_FETCH_RESP_PAYLOAD_LENGTH];
00430 
00431   gzll_rx_fifo_flush();
00432 
00433   retval = GZP_TX_RX_FAILED_TO_SEND;
00434 
00435   if(gzp_tx_packet(tx_packet, tx_length, pipe))
00436   {
00437     retval = GZP_TX_RX_NO_RESPONSE;
00438 
00439     gzll_rx_fifo_flush();
00440     fetch_packet[0] = GZP_CMD_FETCH_RESP;
00441 
00442     gzp_delay_rx_periods(GZP_TX_RX_TRANS_DELAY);
00443     gzp_tx_packet(fetch_packet, GZPAR_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe);
00444 
00445     if(gzll_rx_fifo_read(rx_dst, rx_length, NULL))
00446     {
00447       retval = GZP_TX_RX_SUCCESS;
00448     }
00449   }
00450   return retval;
00451 }
00452 
00453 #ifndef GZP_CRYPT_DISABLE
00454 
00455 static bool gzp_crypt_tx_transaction(const uint8_t *src, uint8_t length)
00456 {
00457   uint8_t tx_packet[GZLL_MAX_FW_PAYLOAD_LENGTH];
00458   uint8_t rx_packet[GZLL_MAX_ACK_PAYLOAD_LENGTH];
00459   uint8_t tx_packet_length;
00460 
00461   tx_packet_length = length + GZP_USER_DATA_PACKET_OVERHEAD;
00462 
00463   // Assemble tx packet
00464   tx_packet[0] = GZP_CMD_ENCRYPTED_USER_DATA;
00465   gzp_add_validation_id(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]);
00466   memcpy(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], (uint8_t*)src, length);
00467 
00468   // Encrypt tx packet
00469   if(gzp_id_req_pending)
00470   {
00471     gzp_crypt_select_key(GZP_ID_EXCHANGE);
00472   }
00473   else
00474   {
00475     gzp_crypt_select_key(GZP_DATA_EXCHANGE);
00476   }
00477   gzp_crypt(&tx_packet[1], &tx_packet[1], tx_packet_length - 1);
00478 
00479   // If packet was successfully sent AND a response packet was received
00480   if(gzp_tx_rx_transaction(tx_packet, tx_packet_length, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
00481   {
00482 
00483     if(rx_packet[0] == GZP_CMD_ENCRYPTED_USER_DATA_RESP)
00484     {
00485       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);
00486 
00487       // Validate response in order to know whether packet was correctly decrypted by host
00488       if(gzp_validate_id(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]))
00489       {
00490         // Update session token if normal operation (!gzp_id_req_pending)
00491         if(!gzp_id_req_pending)
00492         {
00493           gzp_crypt_set_session_token(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
00494         }
00495         return true;
00496       }
00497       else
00498       {
00499         return false;
00500       }
00501     }
00502   }
00503 
00504   return false;
00505 }
00506 
00507 static bool gzp_key_update(void)
00508 {
00509   uint8_t tx_packet[GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH], rx_packet[GZLL_MAX_ACK_PAYLOAD_LENGTH];
00510 
00511   // Send "prepare packet" to get session token to be used for key update
00512   tx_packet[0] = GZP_CMD_KEY_UPDATE_PREPARE;
00513 
00514   // If packet was successfully sent AND a response packet was received
00515   if(gzp_tx_rx_transaction(tx_packet, GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
00516   {
00517     if(rx_packet[0] == GZP_CMD_KEY_UPDATE_PREPARE_RESP)
00518     {
00519       gzp_crypt_set_session_token(&rx_packet[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
00520 
00521       // Build "key update" packet
00522       tx_packet[0] = GZP_CMD_KEY_UPDATE;
00523       gzp_add_validation_id(&tx_packet[GZP_CMD_KEY_UPDATE_VALIDATION_ID]);
00524       gzp_random_numbers_generate(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY], GZP_DYN_KEY_LENGTH);
00525       gzp_crypt_set_dyn_key(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY]);
00526 
00527       // Encrypt "key update packet"
00528       gzp_crypt_select_key(GZP_KEY_EXCHANGE);
00529       gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
00530 
00531       // Send "key update" packet
00532       if(gzp_tx_packet(tx_packet, GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH, GZP_DATA_PIPE))
00533       {
00534         return true;
00535       }
00536     }
00537   }
00538 
00539   return false;
00540 }
00541 
00542 #endif
00543 
00544 bool gzp_set_host_id(const uint8_t * id)
00545 {
00546   memcpy(gzp_host_id, id, GZP_HOST_ID_LENGTH);
00547   return true;
00548 }
00549 
00550 bool gzp_get_host_id(uint8_t * dst_id)
00551 {
00552   memcpy(dst_id, gzp_host_id, GZP_HOST_ID_LENGTH);
00553   return true;
00554 }
00555 
00556 static void gzp_params_db_add(const uint8_t* src_element, uint8_t index)
00557 {
00558   hal_flash_bytes_write(GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE), src_element, GZP_PARAMS_DB_ELEMENT_SIZE);
00559 }
00560 
00561 static void gzp_params_db_read(uint8_t* dst_element, uint8_t index)
00562 {
00563   hal_flash_bytes_read(GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE), dst_element, GZP_PARAMS_DB_ELEMENT_SIZE);
00564 }
00565 
00566 static void gzp_index_db_add(uint8_t val)
00567 {
00568   int16_t i;
00569   uint8_t temp_val;
00570 
00571   // Search for unwritten loacation in index DB
00572   for(i = 0; i < GZP_INDEX_DB_SIZE; i++)
00573   {
00574     temp_val = hal_flash_byte_read(GZP_INDEX_DB_ADR + i);
00575 
00576     // Lower nibble
00577     if(i != (GZP_INDEX_DB_SIZE - 1))
00578     {
00579       if((temp_val & 0x0f) == 0x0f)
00580       {
00581         temp_val = (temp_val & 0xf0) | val;
00582         break;
00583       }
00584       // Upper nibble
00585       else if((temp_val & 0xf0) == 0xf0)
00586       {
00587         temp_val = (temp_val & 0x0f) | (val << 4);
00588         break;
00589       }
00590     }
00591     else
00592     {
00593       temp_val = (GZP_PARAMS_DB_MAX_ENTRIES << 4) | val;
00594       break;
00595     }
00596   }
00597 
00598   // Write index DB
00599   hal_flash_byte_write(GZP_INDEX_DB_ADR + i, temp_val);
00600 }
00601 
00602 static uint8_t gzp_index_db_read()
00603 {
00604   uint8_t retval;
00605   int16_t i;
00606 
00607   // Search for previously written location
00608   for(i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
00609   {
00610     retval = hal_flash_byte_read(GZP_INDEX_DB_ADR + i);
00611 
00612     if(retval != 0xff)
00613     {
00614       break;
00615     }
00616   }
00617 
00618   if(retval == 0xff)
00619   {
00620     retval = GZP_PARAMS_DB_MAX_ENTRIES;  // index db empty
00621   }
00622   else if((retval & 0xf0) != 0xf0)
00623   {
00624     retval >>= 4;
00625   }
00626   else
00627   {
00628     retval &= 0x0f;
00629   }
00630 
00631   return retval;
00632 }
00633 
00634 static bool gzp_index_db_full()
00635 {
00636   return ((GZP_INDEX_DB_SIZE == 0) || ((hal_flash_byte_read(GZP_INDEX_DB_ADR + (GZP_INDEX_DB_SIZE - 1)) != 0xff)));
00637 }
00638 
00639 static bool gzp_index_db_empty()
00640 {
00641   return ((GZP_INDEX_DB_SIZE == 0) || hal_flash_byte_read(GZP_INDEX_DB_ADR) == 0xff);
00642 }
00643 
00644 static bool gzp_array_is_set(const uint8_t* src, uint8_t length)
00645 {
00646   uint8_t i;
00647 
00648   for(i = 0; i < length; i++)
00649   {
00650     if(*(src++) != 0xff)
00651     {
00652       return false;
00653     }
00654   }
00655   return true;
00656 }
00657 
00658 static bool gzp_params_store(bool store_all)
00659 {
00660   uint8_t i;
00661   bool write_index_db = false;
00662   bool write_param_db = false;
00663   uint8_t new_db_index;
00664   uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
00665 
00666   // Search param DB to see if current setup exists
00667   if(store_all)
00668   {
00669     // Search for: Current system address and host ID exists
00670     for(i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
00671     {
00672       gzp_params_db_read(temp_element, i);
00673 
00674       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))
00675       {
00676         write_index_db = true;
00677         new_db_index = i;
00678         break; // System address + host_id allready exists in database
00679       }
00680     }
00681 
00682     // Search for: Current system address and cleared host ID
00683         if(!write_index_db)
00684     {
00685       for(i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
00686       {
00687             gzp_params_db_read(temp_element, i);
00688 
00689         if(((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0) && \
00690            (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], GZP_HOST_ID_LENGTH)))
00691         {
00692                 memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
00693               new_db_index = i;
00694           write_index_db = true;
00695                 write_param_db = true;
00696                 break;
00697             }
00698       }
00699         }
00700 
00701     // Search for: Cleared system address and cleared host ID
00702         if(!write_index_db)
00703     {
00704       for(i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
00705       {
00706             gzp_params_db_read(temp_element, i);
00707 
00708         if(gzp_array_is_set(temp_element, GZP_PARAMS_DB_ELEMENT_SIZE))
00709         {
00710                 memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
00711                 memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
00712               new_db_index = i;
00713           write_index_db = true;
00714                 write_param_db = true;
00715           break;
00716             }
00717       }
00718     }
00719   }
00720     else
00721     {
00722     // Search for: System address + any host ID
00723     for(i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
00724     {
00725       gzp_params_db_read(temp_element, i);
00726 
00727       if((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0)
00728       {
00729         //memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
00730         write_index_db = true;
00731         new_db_index = i;
00732         break;
00733       }
00734     }
00735 
00736     // Search for: System address cleared
00737     if(!write_index_db)
00738     {
00739       for(i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
00740       {
00741         gzp_params_db_read(temp_element, i);
00742 
00743         if(gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH))
00744         {
00745           memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
00746           write_index_db = true;
00747           write_param_db = true;
00748           new_db_index = i;
00749           break;
00750         }
00751       }
00752     }
00753   }
00754 
00755     if(write_param_db)
00756     {
00757       gzp_params_db_add(temp_element, new_db_index);
00758     }
00759 
00760     if(write_index_db)
00761     {
00762       if(!gzp_index_db_full() && (new_db_index != gzp_index_db_read()) && (new_db_index != GZP_PARAMS_DB_MAX_ENTRIES))
00763       {
00764         gzp_index_db_add(new_db_index);
00765 
00766         return true;
00767       }
00768     }
00769 
00770   return false;
00771 }
00772 
00773 static bool gzp_params_restore(void)
00774 {
00775   uint8_t i;
00776   uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
00777 
00778   if(!gzp_index_db_full() && !gzp_index_db_empty())
00779   {
00780     i = gzp_index_db_read();
00781 
00782     if(i < GZP_PARAMS_DB_MAX_ENTRIES)
00783     {
00784       gzp_params_db_read(temp_element, i);
00785       memcpy(gzp_system_address, &temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
00786       gzp_set_host_id(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID]);
00787       return true;
00788     }
00789   }
00790 
00791   return false;
00792 }
00793 
00794 void gzp_delay_rx_periods(uint16_t rx_periods)
00795 {
00796   uint16_t i;
00797   
00798   for(i=0; i < rx_periods; i++)
00799   {
00800     delay_us(GZLL_DEFAULT_PARAM_RX_PERIOD);
00801   }
00802 }
00803 

Generated on Fri Apr 20 2012 14:11:44 for nRFGo SDK by  doxygen 1.7.2