
#include "SS1BTPS.h"             /* Main SS1 Bluetooth Stack Header.          */
#include "BTPSKRNL.h"            /* BTPS Kernel Header.                       */
#include "cardicell_board.h"
#include "cardicell_app.h"
#include "spp.h"
#include "EHCILL.h"              /* eHCILL Implementation Header.             */
#include "utils.h"
#include "gap.h"


#define REQUEST_LINK_KEY_TABLE          1
#define SEND_LINK_KEY                   2

extern unsigned int BluetoothStackID;
static st_gap_context gap_context ;
static char debug_buffer[256];
static BD_ADDR_t gap_null_bd_addr;

typedef enum
{
  enGAP_INIT = 0,
  enGAP_TEMPO,
  enGAP_SENDPINCODE
}enState;

static unsigned int _gap_tempo;
static enState _gap_state;

// The following string table is used to map the API I/O Capabilities values to
// an easily displayable string.
static BTPSCONST char *IOCapabilitiesStrings[] =
{
   "Display Only",
   "Display Yes/No",
   "Keyboard Only",
   "No Input/Output"
} ;


void _gap_request_linkkey( unsigned char src_port,  unsigned char dest_port ,unsigned int size )
{
  unsigned int checksum = 0;
  unsigned char msg_type = REQUEST_LINK_KEY_TABLE;
  
  checksum += (size + sizeof(msg_type));
  checksum += src_port;
  checksum += dest_port;
  checksum += msg_type;
  

  msg_send_header( src_port, dest_port, size );

  drv_main_interface_transmit_buffer( (const char*)msg_type, sizeof(char) );  
  drv_main_interface_transmit_buffer( (const char*)&checksum, sizeof(unsigned int) );
}


void _gap_send_linkkey( char * ptr,  unsigned char src_port,  unsigned char dest_port ,unsigned int size )
{
  unsigned int checksum ;
  unsigned char msg_type = SEND_LINK_KEY;
  
  checksum = (size + sizeof(msg_type));
  checksum += src_port;
  checksum += dest_port;
  checksum += msg_type;
  
  checksum += calculate_checksum( ptr, size );
  
  msg_send_header( src_port, dest_port, size );

  drv_main_interface_transmit_buffer( (const char*)msg_type, sizeof(char) );  
  drv_main_interface_transmit_buffer( (const char*)ptr, sizeof(LinkKeyInfo_t) );
  drv_main_interface_transmit_buffer( (const char*)&checksum, sizeof(unsigned int) );
}


static void _set_tempo(  unsigned int delay )
{
  _gap_tempo = delay;
  _gap_state = enGAP_TEMPO;
}

// The following function is responsible for issuing a GAP
// Authentication Response with a PIN Code value specified via the
// input parameter.  This function returns zero on successful
// execution and a negative value on all errors.
static int _pin_code_response( unsigned int bt_stack_id )
{
  int                                  result;
  int                                  ret_val;
  PIN_Code_t                           pin_code;
  GAP_Authentication_Information_t     GAP_Authentication_Information;
  
  // First, check that valid Bluetooth Stack ID exists.
  if( !bt_stack_id )
    return INVALID_STACK_ID_ERROR;
  
  // First, check to see if there is an on-going Pairing operation active.
  if(!COMPARE_BD_ADDR(gap_context.currentRemoteAddr, gap_null_bd_addr))
  {
    if( BTPS_StringLength( BT_PIN_CODE ) <= sizeof(PIN_Code_t) )
    {
      // Initialize the PIN code.
      ASSIGN_PIN_CODE(pin_code, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
      
      BTPS_MemCopy(&pin_code, BT_PIN_CODE, BTPS_StringLength(BT_PIN_CODE));
      
      // Populate the response structure.
      GAP_Authentication_Information.GAP_Authentication_Type      = atPINCode;
      GAP_Authentication_Information.Authentication_Data_Length   = BTPS_StringLength(BT_PIN_CODE);
      GAP_Authentication_Information.Authentication_Data.PIN_Code = pin_code;
      
      // Submit the Authentication Response.
      result = GAP_Authentication_Response(bt_stack_id, gap_context.currentRemoteAddr, &GAP_Authentication_Information);
      
      // Check the return value for the submitted command for success.
      if(!result)
      {
        // Operation was successful, inform the user.
        drv_debug_log("GAP_Authentication_Response(), Pin Code Response Success.\r\n");
        
        // Flag success to the caller.
        ret_val = 0;
      }
      else
      {
        // Inform the user that the Authentication Response was
        // not successful.
        drv_debug_log("GAP_Authentication_Response() Failed\n\r");
        
        ret_val = FUNCTION_ERROR;
      }
      
      // Flag that there is no longer a current Authentication
      // procedure in progress.
      ASSIGN_BD_ADDR(gap_context.currentRemoteAddr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
    }
    else
    {
      // One or more of the necessary parameters is/are invalid.
      drv_debug_log("PINCodeResponse [PIN Code]");
      
      ret_val = INVALID_PARAMETERS_ERROR;
    }
  }
  else
  {
    // There is not currently an on-going authentication operation, inform 
    // the user of this error condition.
    drv_debug_log("PIN Code Authentication Response: Authentication not in progress.\r\n");
    
    ret_val = FUNCTION_ERROR;
  }
  
  return ret_val;
}


static void _process_remote_name_request_event( GAP_Event_Data_t * GAP_Event_Data )
{
  GAP_Remote_Name_Event_Data_t     *GAP_Remote_Name_Event_Data;
  
  // Bluetooth Stack has responded to a previously issued Remote Name Request that was issued.
  GAP_Remote_Name_Event_Data = GAP_Event_Data->Event_Data.GAP_Remote_Name_Event_Data;
  
  if(GAP_Remote_Name_Event_Data)
  {
    if(GAP_Remote_Name_Event_Data->Remote_Name)
    {
      //TODO: Notify main interface
      strncpy( gap_context.remoteDeviceNameBuffer, GAP_Remote_Name_Event_Data->Remote_Name, MAX_NAME_LENGTH );
      gap_context.remoteDeviceNameBuffer[MAX_NAME_LENGTH-1]=0;
      
      SprintF(gap_context.unsolicited_buffer,"remote device: %s\n\r", gap_context.remoteDeviceNameBuffer);
      //cmd_line_put_unsolicited_response((const char *)gap_context.unsolicited_buffer);
      drv_debug_log((const char *)gap_context.unsolicited_buffer);
    }
  }
}

static void _process_authentication_event( GAP_Event_Data_t * GAP_Event_Data )
{
  int i, result;
  GAP_Authentication_Information_t  GAP_Authentication_Information;
  GAP_IO_Capability_t               remote_io_capability;

  Boolean_t                         oob_data;
  Boolean_t                         mitm;

  switch(GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->GAP_Authentication_Event_Type)
  {
  case atLinkKeyRequest:
    drv_debug_log("\r\natLinkKeyRequest\r\n");

    // Setup the authentication information response structure.
    GAP_Authentication_Information.GAP_Authentication_Type    = atLinkKey;
    GAP_Authentication_Information.Authentication_Data_Length = 0;
    
    // See if we have stored a Link Key for the specified device.
    for(i=0;i< MAX_SUPPORTED_LINK_KEYS;i++)
    {
      if(COMPARE_BD_ADDR(gap_context.LinkKeyInfo[i].BD_ADDR, 
                         GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device))
      {
        /* Link Key information stored, go ahead and    */
        /* respond with the stored Link Key.            */
        GAP_Authentication_Information.Authentication_Data_Length   = sizeof(Link_Key_t);
        GAP_Authentication_Information.Authentication_Data.Link_Key = gap_context.LinkKeyInfo[i].LinkKey;
        break;
      }
    }
    
    // Submit the authentication response.
    if(!GAP_Authentication_Response(BluetoothStackID, 
                                         GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device, 
                                         &GAP_Authentication_Information))
    {
      drv_debug_log("GAP_Authentication_Response succedded\n\r");
    }
    else
    {
      drv_debug_log("GAP_Authentication_Response error\n\r");
    }

    break;
    
  case atPINCodeRequest:
    // A pin code request event occurred, first display the BD_ADD of the 
    // remote device requesting the pin.
    drv_debug_log("\r\natPINCodeRequest\r\n");
   
   // Note the current Remote BD_ADDR that is requesting the PIN Code.
   gap_context.currentRemoteAddr = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device;
   
#if 0
    //Send a PIN Code Response.
    _pin_code_response( BluetoothStackID );
#else
    _set_tempo( 3000 );
#endif
    break;
    
  case atAuthenticationStatus:
    // An authentication status event occurred, display all relevant information.
    SprintF(debug_buffer,"\r\natAuthenticationStatus: %d.\r\n",
            GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.Authentication_Status);
    drv_debug_log(debug_buffer);
    
    // Flag that there is no longer a current Authentication procedure in progress.
    ASSIGN_BD_ADDR(gap_context.currentRemoteAddr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
    break;
  case atLinkKeyCreation:
      // A link key creation event occurred, first display the remote device that caused this event
      drv_debug_log("atLinkKeyCreation\r\n");
      
      for(i=0; i< MAX_SUPPORTED_LINK_KEYS ;i++)
      {
        if(COMPARE_BD_ADDR(gap_context.LinkKeyInfo[i].BD_ADDR, 
                           GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device))
        {
          drv_debug_log("Already in the memory\r\n");
          gap_context.current_linkkey_index = i;
          return;
        }
      }
      
      if(gap_context.nb_key_in_table < MAX_SUPPORTED_LINK_KEYS)
      {
        gap_context.LinkKeyInfo[gap_context.nb_key_in_table].BD_ADDR = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device;
        gap_context.LinkKeyInfo[gap_context.nb_key_in_table].LinkKey = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.Link_Key_Info.Link_Key;
        gap_context.current_linkkey_index = gap_context.nb_key_in_table;
        drv_debug_log("The link key table is full, remove last element to store last linkkey.\n\r");
        
        // Send to upper board the link key.
        _gap_send_linkkey((char *)&gap_context.LinkKeyInfo[gap_context.nb_key_in_table], 2, 14 , sizeof(LinkKeyInfo_t));
        
        gap_context.nb_key_in_table++;
      }
      else
      {
        gap_context.LinkKeyInfo[MAX_SUPPORTED_LINK_KEYS-1].BD_ADDR = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device;
        gap_context.LinkKeyInfo[MAX_SUPPORTED_LINK_KEYS-1].LinkKey = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.Link_Key_Info.Link_Key;
        gap_context.current_linkkey_index = gap_context.nb_key_in_table;
        drv_debug_log("The link key table is full, remove last element to store last linkkey.\n\r");
        
        // Send to upper board the link key.
        _gap_send_linkkey((char *)&gap_context.LinkKeyInfo[MAX_SUPPORTED_LINK_KEYS-1], 2, 14 , sizeof(LinkKeyInfo_t));
      }
      
      drv_debug_log("Link Key sent.\r\n");
      
    break;
    
  case atIOCapabilityRequest:
    drv_debug_log("\n\ratIOCapabilityRequest\r\n");
    
    // Setup the Authentication Information Response structure.
    GAP_Authentication_Information.GAP_Authentication_Type                                      = atIOCapabilities;
    GAP_Authentication_Information.Authentication_Data_Length                                   = sizeof(GAP_IO_Capabilities_t);
    GAP_Authentication_Information.Authentication_Data.IO_Capabilities.IO_Capability            = (GAP_IO_Capability_t)gap_context.io_capability;
    GAP_Authentication_Information.Authentication_Data.IO_Capabilities.MITM_Protection_Required = gap_context.mitm_protection;
    GAP_Authentication_Information.Authentication_Data.IO_Capabilities.OOB_Data_Present         = gap_context.oob_support;
    
    // Submit the Authentication Response.
    result = GAP_Authentication_Response(BluetoothStackID, 
                                         GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device, 
                                         &GAP_Authentication_Information);
    
    // Check the result of the submitted command.
    if(!result)
      drv_debug_log("Auth success");
    else
      drv_debug_log("Auth error");
    break;
    
  case atIOCapabilityResponse:
    drv_debug_log("\n\ratIOCapabilityResponse.\r\n");
    
    remote_io_capability = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.IO_Capabilities.IO_Capability;
    mitm               = (Boolean_t)GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.IO_Capabilities.MITM_Protection_Required;
    oob_data           = (Boolean_t)GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.IO_Capabilities.OOB_Data_Present;
    
    SprintF(debug_buffer,"Capabilities: %s%s%s\r\n", IOCapabilitiesStrings[remote_io_capability], ((mitm)?", MITM":""), ((oob_data)?", OOB Data":""));
    drv_debug_log(debug_buffer);
    break;
    
  case atUserConfirmationRequest:
    drv_debug_log("atUserConfirmationRequest !!! I don't know what I need to responds\n\r");
    break;
    
  case atPasskeyRequest:
    drv_debug_log("atPasskeyRequest\r\n");
    
    // Note the current Remote BD_ADDR that is requesting the Passkey.
    gap_context.currentRemoteAddr = GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device;
    
    // Inform the user that they will need to respond with a Passkey Response.
    drv_debug_log("Respond with: PassKeyResponse\r\n");
    break;
    
  case atRemoteOutOfBandDataRequest:
    drv_debug_log("atRemoteOutOfBandDataRequest\r\n");
    
    // This application does not support OOB data so respond with a data length 
    // of Zero to force a negative reply.
    GAP_Authentication_Information.GAP_Authentication_Type    = atOutOfBandData;
    GAP_Authentication_Information.Authentication_Data_Length = 0;
    
    result = GAP_Authentication_Response(BluetoothStackID, GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Remote_Device, &GAP_Authentication_Information);
    
    if(!result)
      drv_debug_log("GAP_Authentication_Response succedded");
    else
      drv_debug_log("GAP_Authentication_Response failed\n\r");
    break;
    
  case atPasskeyNotification:
    drv_debug_log("atPasskeyNotification\r\n");
    SprintF(debug_buffer,"Passkey Value: %lu\r\n", GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.Numeric_Value);
    drv_debug_log(debug_buffer);
    break;
    
  case atKeypressNotification:
    drv_debug_log("atKeypressNotification\r\n");
    SprintF(debug_buffer,"Keypress: %d\r\n", (int)GAP_Event_Data->Event_Data.GAP_Authentication_Event_Data->Authentication_Event_Data.Keypress_Type);
    drv_debug_log(debug_buffer);
    break;
    
  default:
    drv_debug_log("Un-handled Auth. Event.\r\n");
    break;
  }
}
   /*********************************************************************/
   /*                         Event Callbacks                           */
   /*********************************************************************/

   /* The following function is for the GAP Event Receive Data Callback.*/
   /* This function will be called whenever a Callback has been         */
   /* registered for the specified GAP Action that is associated with   */
   /* the Bluetooth Stack.  This function passes to the caller the GAP  */
   /* Event Data of the specified Event and the GAP Event Callback      */
   /* Parameter that was specified when this Callback was installed.    */
   /* The caller is free to use the contents of the GAP Event Data ONLY */
   /* in the context of this callback.  If the caller requires the Data */
   /* for a longer period of time, then the callback function MUST copy */
   /* the data into another Data Buffer.  This function is guaranteed   */
   /* NOT to be invoked more than once simultaneously for the specified */
   /* installed callback (i.e.  this function DOES NOT have be          */
   /* reentrant).  It Needs to be noted however, that if the same       */
   /* Callback is installed more than once, then the callbacks will be  */
   /* called serially.  Because of this, the processing in this function*/
   /* should be as efficient as possible.  It should also be noted that */
   /* this function is called in the Thread Context of a Thread that the*/
   /* User does NOT own.  Therefore, processing in this function should */
   /* be as efficient as possible (this argument holds anyway because   */
   /* other GAP Events will not be processed while this function call is*/
   /* outstanding).                                                     */
   /* * NOTE * This function MUST NOT Block and wait for events that    */
   /*          can only be satisfied by Receiving other GAP Events.  A  */
   /*          Deadlock WILL occur because NO GAP Event Callbacks will  */
   /*          be issued while this function is currently outstanding.  */
void BTPSAPI gap_event_callback(unsigned int BluetoothStackID, GAP_Event_Data_t *GAP_Event_Data, unsigned long CallbackParameter)
{
   // First, check to see if the required parameters appear to be semi-valid.
   if((BluetoothStackID) && (GAP_Event_Data))
   {
      switch(GAP_Event_Data->Event_Data_Type)
      {
      case etInquiry_Result:
        // No Inquiry should be done in our application.
        drv_debug_log("\n\retInquiry_Result\n\r");
        break;
      case etInquiry_Entry_Result:
        drv_debug_log("\n\retInquiry_Entry_Result\n\r");
        break;
      case etAuthentication:
        // An authentication event occurred, determine which type of authentication event occurred.
        _process_authentication_event( GAP_Event_Data );
        break;
      case etRemote_Name_Result:
        _process_remote_name_request_event( GAP_Event_Data );
        break;
      case etEncryption_Change_Result:
        drv_debug_log("\n\retEncryption_Change_Result\n\r");
#if 0
        BD_ADDRToStr(GAP_Event_Data->Event_Data.GAP_Encryption_Mode_Event_Data->Remote_Device, Callback_BoardStr);
        Display(("\r\netEncryption_Change_Result for %s, Status: 0x%02X, Mode: %s.\r\n", Callback_BoardStr,
                     GAP_Event_Data->Event_Data.GAP_Encryption_Mode_Event_Data->Encryption_Change_Status,
                     ((GAP_Event_Data->Event_Data.GAP_Encryption_Mode_Event_Data->Encryption_Mode == emDisabled)?"Disabled": "Enabled")));
#endif
        break;
      default:
        //An unknown/unexpected GAP event was received.
        SprintF(debug_buffer,"\r\nUnknown Event: %d.\r\n", GAP_Event_Data->Event_Data_Type);
        drv_debug_log(debug_buffer);
        break;
      }
   }
}

// The following function is responsible for placing the Local
// Bluetooth Device into Connectable Mode.  Once in this mode the
// Device will respond to Page Scans from other Bluetooth Devices.
// This function requires that a valid Bluetooth Stack ID exists
// before running.  This function returns zero on success and a
// negative value if an error occurred.
static int _set_connectable( unsigned int bt_stack_id )
{
  // First, check that a valid Bluetooth Stack ID exists.
  if( !bt_stack_id )
    return INVALID_STACK_ID_ERROR;
  
  // Attempt to set the attached Device to be Connectable.
  if( GAP_Set_Connectability_Mode( bt_stack_id , cmConnectableMode) )
    return -1;
  else
    return 0;
}

// The following function is responsible for placing the Local
// Bluetooth Device into General Discoverablity Mode.  Once in this
// mode the Device will respond to Inquiry Scans from other Bluetooth
// Devices.  This function requires that a valid Bluetooth Stack ID
// exists before running.  This function returns zero on successful
// execution and a negative value if an error occurred.
static int _set_discoverable( unsigned int bt_stack_id )
{
  // First, check that a valid Bluetooth Stack ID exists.
  if( !bt_stack_id )
    return INVALID_STACK_ID_ERROR;
  
  if( GAP_Set_Discoverability_Mode(bt_stack_id, dmGeneralDiscoverableMode, 0) )
    return -1;
  else
    return 0;
}

// The following function is responsible for placing the local
// Bluetooth device into Pairable mode.  Once in this mode the device
// will response to pairing requests from other Bluetooth devices.
// This function returns zero on successful execution and a negative
// value on all errors.
static int _set_pairable( unsigned int bt_stack_id )
{
  // First, check that a valid Bluetooth Stack ID exists.
  if( !bt_stack_id )
    return INVALID_STACK_ID_ERROR;

  // Attempt to set the attached device to be pairable.
  if(GAP_Set_Pairability_Mode( bt_stack_id , pmPairableMode ))
    return -1;
  
  // The device has been set to pairable mode, now register an Authentication 
  // Callback to handle the Authentication events
  if(GAP_Register_Remote_Authentication(bt_stack_id, gap_event_callback, (unsigned long)0))
    return -1;
  
  return 0;
}



static void _init_gap_value( void )
{
  ASSIGN_BD_ADDR( gap_null_bd_addr , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  
  // Initialize the default Secure Simple Pairing parameters.
  gap_context.io_capability     =       DEFAULT_IO_CAPABILITY;
  gap_context.oob_support       =       FALSE;
  gap_context.mitm_protection   =       DEFAULT_MITM_PROTECTION;
  
  _gap_request_linkkey(GAP_SRC_PORT,GAP_DEST_PORT,0);

  gap_context.nb_key_in_table = 0;
  gap_context.current_linkkey_index = 0;
    
  _gap_tempo = 0;
  _gap_state = enGAP_INIT;

}


int gap_init( unsigned int bt_stack_id )
{

  if( !bt_stack_id )
    return INVALID_STACK_ID_ERROR;

  _init_gap_value( );
  
  if(_set_connectable( BluetoothStackID ) < 0)
    return -1;
  
  if( _set_discoverable( BluetoothStackID ) < 0)
    return -1;
  
  if( _set_pairable( BluetoothStackID ) < 0)
    return -1;

  return 0;
}

// The following function is responsible for setting the name of the
// local Bluetooth Device to a specified name.  This function returns
// zero on successful execution and a negative value on all errors.
int gap_set_local_name( unsigned int bt_stack_id, char * arg )
{
   if( !bt_stack_id )
     return INVALID_STACK_ID_ERROR;

   if( !arg )
     return INVALID_PARAMETERS_ERROR;
   
   if(strlen( arg ) > MAX_NAME_LENGTH )
     arg[MAX_NAME_LENGTH-1] = 0;
   
   if(GAP_Set_Local_Device_Name( bt_stack_id , arg ))
     return FUNCTION_ERROR;

   return 0;
}

// The following function is responsible for querying the Bluetooth
// Device Name of the specified remote Bluetooth Device.  This
// function returns zero on successful execution and a negative value
// on all errors.

int gap_get_remote_name( unsigned int bt_stack_id , BD_ADDR_t BD_ADDR )
{
  // First, check that a valid Bluetooth Stack ID exists.
  if( !bt_stack_id )
    return INVALID_STACK_ID_ERROR;  
  
  // Attempt to submit the command.
  if(GAP_Query_Remote_Device_Name(bt_stack_id, BD_ADDR , gap_event_callback, (unsigned long)0))
    return -1;
  
  return 0;
}

void gap_base_time_1ms( void )
{
  if(_gap_tempo)
    _gap_tempo--;
}

void gap_task_handler( void * param )
{
  switch( _gap_state )
  {
  
  case enGAP_INIT:
    //nothing to do...
      break;
  
  case enGAP_TEMPO:
    if(_gap_tempo == 0)
      _gap_state = enGAP_SENDPINCODE;
      break;
  
  case enGAP_SENDPINCODE:
        //Send a PIN Code Response.
    _pin_code_response( BluetoothStackID );
    _gap_state = enGAP_INIT;
      break;
      
  }
}

void gap_push_bt_link_key( char * ptr )
{
  if(gap_context.nb_key_in_table >= MAX_SUPPORTED_LINK_KEYS)
    return;
  
  BTPS_MemCopy(&gap_context.LinkKeyInfo[gap_context.nb_key_in_table],ptr,sizeof(LinkKeyInfo_t));    
  
  gap_context.nb_key_in_table++;
}

