.. _sec-connection-handover:

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 |SDK|. 

    - Connection Handover overview (see :ref:`sec-connection-handover-overview`)
    - Connection Handover Limitations and Constraints (see :ref:`sec-connection-handover-limitations`)
    - Connection Handover APIs (see :ref:`ble_api_reference`)
    - Add Connection Handover to an existing project (see :ref:`sec-enable-connection-handover`)

The |DEVICE| 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 |DEVICE| LaunchPads. 

.. _sec-connection-handover-overview: 

Connection Handover Overview
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

    - Serving Node (:term:`SN`)
    - Candidate Node (:term:`CN`)
    - Peer Node (:term:`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``. 
:ref:`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. 

.. _sec-connection-handover-limitations:

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` (:ref:`ble_api_reference`) within the GATT APIs to automatically setup new services at the same stopping point. 

.. _sec-enable-connection-handover: 

How to Enable Connection Handover 
*********************************

1. Enable Connection Handover within SysConfig. 

.. _CH-SysConfig-Enabled:
.. figure:: resources/CH_SysConfigEnabled.png
    :align: center

    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: 

   .. code-block:: c
      :caption: **handover.h** - Register SN Callback
      :linenos:

        // Register Serving Node Callbacks 

        status = Handover_RegisterSNCBs(); 

   .. code-block:: c
      :caption: **handover.h** - Register CN Callback
      :linenos:

        // Register Candidate Node Callbacks 

        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.

3. Configure and initialize SN and CN parameters: 

   .. code-block:: c
      :caption: **handover.h** - Initialize SN Parameters
      :linenos:

        // Initialize Serving Node Parameters
        handoverSNParams_t gSnParams; 

        status = Handover_InitSNParams(&gSnParams);

   .. code-block:: c
      :caption: **handover.h** - Initialize CN Parameters
      :linenos:

        // Initialize Candidate Node Parameters
        handoverCNParams_t gCnParams; 

        status = Handover_InitCNParams(&gCnParams);

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

   .. code-block:: c
      :caption: **handover.h** - SN Parameters
      :linenos:

         /**
         * @brief Host Handover Serving Node Configuration parameters
         */
         typedef struct
         {
         uint16_t connHandle;          //!< Connection handle
         uint32_t handoverDataSize;    //!< The stack handover data size
         uint8_t *pHandoverData;       //!< Pointer to the buffer the application allocated
         uint32_t rfu;                 //!< Reserved for future use
         uint8_t  handoverSnMode;      //!< 0 - Terminate the connection immediately on the serving node side, 1 - wait for the candidate response
         uint16_t minGattHandle;       //!< Minimum GATT handle
         uint16_t maxGattHandle;       //!< Maximum GATT handle
         } 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). 

   .. code-block:: c
      :caption: **handover.h** - CN Parameters
      :linenos:

         /**
         * @brief Host Handover Candidate Node Configuration parameters
         */
         typedef struct
         {
         uint8_t *pHandoverData;       //!< The handover data given by the serving node
         uint8_t  appTaskId;           //!< Application task ID
         uint32_t timeDeltaInUs;       //!< The time in us it took for the data to be transferred from the serving node to the candidate node
         uint32_t timeDeltaMaxErrInUs; //!< The maximum deviation time in us
         uint16_t rfu;                 //!< Reserved for future use
         uint32_t maxFailedConnEvents; //!< Number of connection events the candidate node will try to follow the central
                                       //!< When this value is 0, it will try to follow the central device until it reaches supervision timeout
         uint8_t  txBurstRatio;        //!< Precentage of the connection event the TxBurst will be active. when this value is 0,
                                       //!<TxBurst will not be activated.
         } 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: 

   .. code-block:: c
      :caption: **handover.h** - Initialize CN Parameters
      :linenos:

        gSnParams.handoverDataSize = Handover_GetSNDataSize(&gSnParams)

5. Start SN.

   .. code-block:: c
      :caption: **handover.h** - Start SN
      :linenos:

        status = Handover_StartSN(&gSnParams);

        if(status != SUCCESS)[
            // Free allocated data 
            ICall_free(gSnParams.pHandoverData);
            gSnParams.pHandoverData = NULL;
        ]

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.

6. Start CN. 
   
   .. code-block:: c
      :caption: **handover.h** - Start CN
      :linenos:

      status = 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: 

   .. code-block:: c
      :caption: **handover.h** - Close SN 
      :linenos:

       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. 

   .. uml::
       :caption: Context Diagram of Connection Handover on SN and CN. 
       :align: center

       @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