Connection Handover

This chapter serves as a guide to the Texas Instruments Connection Handover feature including application implementation, drivers, and middle layers of the stack. Connection handover is a feature which transfers BLE connections among devices sharing the same LTK and ID Address.

The guide will cover the main principles of the Connection Handover process, the process of adding Connection Handover to a project, and an out of the box example project available within the SimpleLink Low Power F3 SDK.

The CC23xx or CC27xx LaunchPad allows for quick and easy development of BLE applications, such as Connection Handover. To run the Connection Handover example, you will need three BLE supported devices, two of which will be CC23xx or CC27xx LaunchPads.

Connection Handover Overview

Three BLE supported devices are needed for Connection Handover. The devices are referred to as:

  • Serving Node (SN)

  • Candidate Node (CN)

  • Peer Node (PN)

The SN is the BLE device which which will transfer its existing connection with the PN. The CN is the BLE device which will take over the existing connection with the PN from the SN. Handover is defined in handover.h. ble_api_reference (Connection Handover) describes the full API including commands, parameters, events, and callbacks. The PN can be any device which supports BLE. Additionally, the peer device can be configured as either peripheral or central GAP roles. The connection handover is the same for either GAP role, but has one variation with the CN parameters, which is documented below.

Connection Handover is enabled within SysConfig in all BLE projects, with the exception of host_test. The following steps on how to enable Connection Handover are provided as a reference.

Connection Handover Limitations

The limitations to connection handover are as follows:

  • All devices must support the same feature set.

    • For example, Maximum TX Power, Maximum RX and TX Length, and MTU size are not transferred between SN and CN.

  • The application must authenticate and encrypt the data transferred over the external medium.

  • All devices must allow the same set of GATT services with the same characteristics.

    • GATT handles must match between devices

    • See GATT_SetNextHandle (ble_api_reference) within the GATT APIs to automatically setup new services at the same stopping point.

How to Enable Connection Handover

  1. Enable Connection Handover within SysConfig.

../_images/CH_SysConfigEnabled.png

Connection Handover Enabled in SysConfig.

2. Register the SN and CN callbacks. To register callbacks for the SN and the CN, use the functions shown below:

handover.h - Register SN Callback
1  // Register Serving Node Callbacks
2
3  status = Handover_RegisterSNCBs();
handover.h - Register CN Callback
1  // Register Candidate Node Callbacks
2
3  status = Handover_RegisterCNCBs();

The functions will register the SN and CN callbacks. The SN Callback will trigger with a success when the connection handle, and connection pointer are populated and a failure otherwise. The CN callback will trigger with a success if the CN is able to follow the connection and a failure if not.

  1. Configure and initialize SN and CN parameters:

    handover.h - Initialize SN Parameters
    1  // Initialize Serving Node Parameters
    2  handoverSNParams_t gSnParams;
    3
    4  status = Handover_InitSNParams(&gSnParams);
    
    handover.h - Initialize CN Parameters
    1  // Initialize Candidate Node Parameters
    2  handoverCNParams_t gCnParams;
    3
    4  status = Handover_InitCNParams(&gCnParams);
    

The parameters for SN and CN are available within the ble_api_reference (Connection Handover) section and are defined in handover.h. The parameters are also seen below:

handover.h - SN Parameters
 1   /**
 2   * @brief Host Handover Serving Node Configuration parameters
 3   */
 4   typedef struct
 5   {
 6   uint16_t connHandle;          //!< Connection handle
 7   uint32_t handoverDataSize;    //!< The stack handover data size
 8   uint8_t *pHandoverData;       //!< Pointer to the buffer the application allocated
 9   uint32_t rfu;                 //!< Reserved for future use
10   uint8_t  handoverSnMode;      //!< 0 - Terminate the connection immediately on the serving node side, 1 - wait for the candidate response
11   uint16_t minGattHandle;       //!< Minimum GATT handle
12   uint16_t maxGattHandle;       //!< Maximum GATT handle
13   } handoverSNParams_t;

HandoverDataSize` is used to indicate the sum of the controller and host data size. The data size can be received from the Handover_GetSNDataSize function for dynamic allocation. Additionally, the size can be statically allocated. The HandoverGetSNDataSize should be used to verify if the statically allocated size is large enough. The *pHandoverData, is the pointer to the buffer the application has allocated. The transfer data will be located here. The handoverSnMode indicates whether the SN should terminate the connection between it and the PN immediately after the start of connection handover (mode 0), or after the CN has assumed the connection (mode 1).

handover.h - CN Parameters
 1   /**
 2   * @brief Host Handover Candidate Node Configuration parameters
 3   */
 4   typedef struct
 5   {
 6   uint8_t *pHandoverData;       //!< The handover data given by the serving node
 7   uint8_t  appTaskId;           //!< Application task ID
 8   uint32_t timeDeltaInUs;       //!< The time in us it took for the data to be transferred from the serving node to the candidate node
 9   uint32_t timeDeltaMaxErrInUs; //!< The maximum deviation time in us
10   uint16_t rfu;                 //!< Reserved for future use
11   uint32_t maxFailedConnEvents; //!< Number of connection events the candidate node will try to follow the central
12                                 //!< When this value is 0, it will try to follow the central device until it reaches supervision timeout
13   uint8_t  txBurstRatio;        //!< Precentage of the connection event the TxBurst will be active. when this value is 0,
14                                 //!<TxBurst will not be activated.
15   } handoverCNParams_t;

The *pHandoverData points to where the connection handover data will be placed by the SN. The timeDeltaInUs parameter is the amount of time taken from transferring the data until the execution of Handover_StartCN. The maxFailedConnEvents is used to indicate the amount of events the CN will follow the connection for before building the connection. The default is six connection events. Lastly, the txBurstRatio is only used in the situation where the PN is in a central GAP role. The txBurstRatio is the percentage of the connection event that the TxBurst will be active. This is used to identify the anchor point of the connection events.

4. Get the SN data size. The function below is used by the SN to request the stack transfer data size. The data size is the sum of the controller and hosts data sizes. The size is then populated into the SN parameters structure:

handover.h - Initialize CN Parameters
1  gSnParams.handoverDataSize = Handover_GetSNDataSize(&gSnParams)
  1. Start SN.

    handover.h - Start SN
    1  status = Handover_StartSN(&gSnParams);
    2
    3  if(status != SUCCESS)[
    4      // Free allocated data
    5      ICall_free(gSnParams.pHandoverData);
    6      gSnParams.pHandoverData = NULL;
    7  ]
    

For this example, the SN will be in mode 1, thus the connection will terminate on the SN side when a successful connection handover response is received from the CN. After connection handover is initiated from the SN side, a few checks are made. These include whether there is an active connection, if connection handover is already started, if the SN callback function is NULL, and if the allocated buffer is large enough for the data. If there is no active connection, handover is not started, the SN callback function is NULL, or the buffer is not large enough for the connection handover data, an error will be returned.

When data transfer is triggered, the host will block the TX queue, and the RX queue. From here, any RX control or data packets sent from the PN will receive a negative acknowledgment (NACK) from the SN. Along with blocking the TX and RX queue, other checks are initiated when the data transfer is initiated. These include whether the connection handle provided in the SN parameters matches the active connection handle, if connection handover has already been started, and the buffer size compared to the data size. If the connection handle does not match, connection handover is not already started, the buffer size is smaller than the data size, or the if the TX and RX queue have not been blocked, then an error will be returned.

Successful data transfer between the SN and CN will trigger the start SN callback. The data transferred between the SN and the CN is available within the handoverDataFull_t structure. See the structure below.

  1. Start CN.

    handover.h - Start CN
    1status = Handover_StartCN(&gCnParams)
    

When the CN is started, the software will check if the pointer to the transfer data is NULL, if the maximum number of connections has been reached, and if connection handover is already in process. If the pointer is NULL, the maximum number of connections has been reached, or connection handover is already in progress from the CN perspective, then an error will be returned.

7. The CN will then begin the handover process. The process involved receiving the data from the SN and building the connection with the data. An Connection Complete Event will be raised from the CN side. The event occurs when the CN has successfully taken the data from the SN and built the connection. The SN needs to receive the status from the CN. The CN node will return the success status, if the CN was able to follow the specified number of connection events, and a connection established event was triggered If the connection handover process is not successful, closing the SN will be unsuccessful, and the SN will maintain the connection. If the CN successfully creates the connection, the SN will terminate the connection. See the function below to close the SN:

handover.h - Close SN
1 status = Handover_CloseSN(&gSnParams, closeSn.handoverStatus);

To summarize the flow of connection monitor, please reference the flow diagram below. The diagram goes through the connection handover process from the perspective of the application of the SN and CN.

@startuml
participant "SN Application"
participant "SN Stack"
participant "CN Application"
participant "CN Stack"

group Connection Handover

  "SN Application" -> "SN Stack" : Handover_InitSNParams()
  "SN Application" -> "SN Stack" : Handover_RegisterSNCBs()
  "SN Application" -> "SN Stack" : Handover_GetSNDataSize()
  "SN Application" -> "SN Application" : Allocate handover data buffer
  "SN Application" -> "SN Stack" : Handover_StartSN()
  "SN Stack" -> "SN Application" : SN Callback - Data ready
  "SN Application" -> "CN Application": Transfer data
  "CN Application" -> "CN Stack" : Handover_InitCNParams()
  "CN Application" -> "CN Stack" : Handover_RegisterCNCBs()
  "CN Application" -> "CN Stack" : Handover_StartCN()
  "CN Stack" -> "CN Application" : Connection Established Event
  "CN Stack" -> "CN Application" : CN Callback - Connection Status
  "CN Application" -> "SN Application" : Transfer CN connection status
  "SN Application" -> "CN Application" : Handover_CloseSN()

    rnote over "CN Application"
     Assumes connection
    end note
  end


@enduml

Context Diagram of Connection Handover on SN and CN.