.. _gap:

Generic Access Profile (GAP)
----------------------------

The GAP layer of the Bluetooth Low Energy protocol stack is
responsible for connection functionality. This layer handles the
access modes and procedures of the device including device
discovery, link establishment, link termination, initiation of
security features, and device configuration. See :ref:`gap_state_diagram` for
more details.

.. _gap_state_diagram:
.. figure:: resources/image72.jpeg
    :align: center

    GAP State Diagram.

Based on the role for which the device is configured, :ref:`gap_state_diagram`
shows the states of the device. The following describes these states.

-  **Standby**: The device is in the initial idle state upon reset.

-  **Advertiser**: The device is advertising with specific data letting
   any scanner/initiator devices know its existence. (This
   advertisement contains the device address and can contain some
   additional data such as the device name).

-  **Scanner**: When receiving the advertisement, the scanning device
   can send a scan request to the advertiser. The advertiser responds
   with a scan response. This process is called device discovery.
   The scanning device is aware of the advertising device and can
   initiate a connection with it.

-  **Initiator**: When initiating, the initiator must specify a peer
   device address to which to connect. If an advertisement is
   received matching that address of the peer device, the initiating
   device then sends out a request to establish a connection (link) with the
   advertising device with the connection parameters described in
   :ref:`connection_parameters`.

-  **Peripheral/Central**: When a connection is formed, the device functions
   as a Peripheral if it is the advertiser and a Central if it is the initiator.

Bluetooth devices operate in one or more GAP roles based on the application use
case. The GAP roles utilize one or more of the GAP states.
Based on this configuration, many Bluetooth Low Energy protocol stack events
are handled directly by the main application task and sometimes routed from the
GAP Bond Manager. The application can register with the stack to be notified of
certain events.

.. _gap_roles:

GAP Roles
^^^^^^^^^

Based on the configuration of the device, the GAP layer always operates in one
of four (4) roles as defined by the specification:

-  **Broadcaster** - The device is an advertiser that is non connectable.

-  **Observer** - The device scans for advertisements but cannot initiate
   connections.

-  **Peripheral** - The device is an advertiser that is connectable and operates as
   Peripheral in a single link-layer connection.

-  **Central** - The device scans for advertisements and initiates
   connections and operates as a Central in a single or multiple
   link-layer connections.

The |CORESPEC| allows for certain combinations of multiple roles, which are
supported by the Bluetooth Low Energy protocol stack. 
The following modules will modify and examine the ``basic_ble`` example project 
included in the SDK. For configuration of the Bluetooth Low Energy stack
features, see :ref:`creating_custom_ble_app` and :ref:`stack_features_configuration`.

.. note::
    Bluetooth 5 also introduces new features including Extended Advertising. Bluetooth 5
    supports legacy advertising maintaining backwards compatibility with previous versions.
    The following sections will describe how to operate the device for various GAP roles along with
    how to use the Extended Advertising features.

The following sections will describe how to use the LE Advertising Extension
feature. As its name suggests, the amount of advertising data that can be sent
over the air has been extended from 31 bytes to 1650 bytes. Also multiple
advertising sets can be created using a mix of legacy and extended
advertisements. Extended advertisements introduces use the secondary
advertising channels which uses the data channels to send extensive data in
addition to the primary advertising channels (Ch. 37, 38, and 39) used in
legacy advertisement.

GAP Constraints
^^^^^^^^^^^^^^^

* GAP Scanner can only scan one PHY per scanning cycle.
* The data length of the advertising data and the scan response data for
  Extended Advertising is limited to 1650 bytes. The connectable undirected
  advertising data is limited to 212 bytes. The connectable directed advertising
  data is limited to 206 bytes. For more information, refer to the Host Advertising Data section
  ([Vol 6], Part B, Section 2.3.4.9) of the |CORESPEC|.


.. _gap-advertiser:

GAP Advertiser
^^^^^^^^^^^^^^

The application and profiles can directly call GAP API functions to perform
Bluetooth Low Energy-related functions such as advertising or connecting.
The GAP layer functionality is mostly defined in library code. The
function headers can be found in :ble_api:`gap.h`. The advertising specific
implementation is found in :ble_api:`gap_advertiser.h`. Most of these functions
can be called directly.

.. note::
    Here we will use the BLEAppUtil framework
    as example code which abstracts the direct gap api interaction, therefore,
    you may not see the actual gap APIs from the following code snippets. 

The GAP Advertiser module lets you create advertisement sets. The application
can then enable and disable the sets. This way, the application can quickly
change the advertisement parameters and advertisement data. For example, an
application can create an advertisement set for legacy advertising and one for
long range advertising. If both sets are enabled, the application advertises
both on the primary advertising channels with legacy advertising, and on a LE
Coded PHY with the long range set. With long range advertising, more advertising data can
be sent and connections can be formed from larger distances compared to legacy advertising.

.. note::
  The advertisement data is de-coupled from the advertisement sets, so multiple
  sets can use the same advertisement data.

Multiple active advertising sets can set different advertising intervals. The 
figure below illustrate how two advertising sets with different intervals are 
scheduled. The intervals do not have to be multiples of each other. The
advertising interval can be set in the ``.primIntMin`` and ``.primIntMax``
Advertisement Params (``GapAdv_params_t``) member before the advertisement set
is enabled or during advertising as described in :ref:`gap-changing-adv-param`.

  .. code-block:: c
    :caption: **app\_peripheral.c :: Peripheral\_start()** -  Change advertising interval before advertisment enable
    :linenos:

      advSetInitParamsSet_1.advParam->primIntMin = 160; //100ms
      advSetInitParamsSet_1.advParam->primIntMax = 160; //100ms

      status = BLEAppUtil_initAdvSet(&peripheralAdvHandle_1, &advSetInitParamsSet_1);

Following shows an alternative for changing the advertising interval after 
the advertising set is initialized by using :ble_api:`gap_advertiser.h`.

  .. code-block:: c
    :caption: **app\_peripheral.c :: Peripheral\_start()** -  Change advertising interval after advertisment initialized
    :linenos:
    :emphasize-lines: 5, 6

      status = BLEAppUtil_initAdvSet(&peripheralAdvHandle_1, &advSetInitParamsSet_1);

      uint32_t advInt = 160; //160*0.625ms = 100ms 

      GapAdv_setParam(peripheralAdvHandle_1, GAP_ADV_PARAM_PRIMARY_INTERVAL_MIN, &advInt);
      GapAdv_setParam(peripheralAdvHandle_1, GAP_ADV_PARAM_PRIMARY_INTERVAL_MAX, &advInt);

.. _gap_diff_adv_interval:
.. figure:: resources/multiple_ae_adv_diff_interval.png
    :align: center

    Multiple AE Advertising sets with different interval.

The following list describes how to configure the GAP layer for
advertising. The *basic_ble* example project will be used as an example.

.. note:: 
   The advertisement set creation can be done using SysConfig.

.. _basic_ble_gap_configuration_example:

.. _gap-advertiser-gap-create:

Create Advertisement
********************
#. **Create Advertisement set with** :ble_api:`GapAdv_create`. This function
   expects application to register a callback, pass in advertising parameter and
   allocate a handle for the associated advertising set. 

   The first step is to create a callback function. By using BLEAppUtil framework,
   the advertising callback function is already created.

   .. code-block:: c
      :caption: **bleapputil\_stack\_callback.c :: BLEAppUtil_advCB()** - Create Application Callback
      :linenos:

       void BLEAppUtil_advCB(uint32_t event, GapAdv_data_t *pBuf, uint32_t *arg)
       {
           BLEAppUtil_AdvEventData_t *pData = BLEAppUtil_malloc(sizeof(BLEAppUtil_AdvEventData_t));

           if (pData)
           {
               pData->event = event;
               pData->pBuf = pBuf;
               pData->arg = arg;

               // Enqueue the event
               if (BLEAppUtil_enqueueMsg(BLEAPPUTIL_EVT_ADV_CB_EVENT, pData) != SUCCESS)
               {
                   BLEAppUtil_free(pData);
               }
           }
       }

   Next we need to create advertising parameters with :ble_api:`GapAdv_params_t` struct
   which by default is generated using SysConfig tool.

   .. code-block:: c
      :caption: **ti\_ble\_config.c :: advParams1** - Create Advertising Parameters
      :linenos:

       GapAdv_params_t advParams1 = {
         .eventProps =   GAP_ADV_PROP_CONNECTABLE | GAP_ADV_PROP_LEGACY | GAP_ADV_PROP_SCANNABLE,
         .primIntMin =   160,
         .primIntMax =   160,
         .primChanMap =  GAP_ADV_CHAN_ALL,
         .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
         .peerAddr =     { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
         .filterPolicy = GAP_ADV_AL_POLICY_ANY_REQ,
         .txPower =      GAP_ADV_TX_POWER_NO_PREFERENCE,
         .primPhy =      GAP_ADV_PRIM_PHY_1_MBPS,
         .secPhy =       GAP_ADV_SEC_PHY_1_MBPS,
         .sid =          0
       };

   **The Tx Power of legacy advertisements cannot be individually set.**

   Lastly, we need to create a handle for this advertising set.

   .. code-block:: c
      :caption: **app\_peripheral.c** - Create Advertising Handle 1

      //! Store handle needed for each advertise set
      uint8 peripheralAdvHandle_1;

   Now we have all the pieces ready, let's see how the BLEAppUtil framework
   creates an advertising set.

   .. code-block:: c
      :caption: **app\_peripheral.c :: Peripheral_start** - Application Layer Abstraction

      // Initialize Advertising Set
      status = BLEAppUtil_initAdvSet(&peripheralAdvHandle_1, &advSetInitParamsSet_1);


   .. code-block:: c
      :caption: **bleapputil\_init.c :: BLEAppUtil_initAdvSet** - Dissect The Parameters
      :linenos:

        bStatus_t BLEAppUtil_initAdvSet(uint8 *advHandle, const BLEAppUtil_AdvInit_t *advInitInfo)
        {
            return bleStk_initAdvSet(BLEAppUtil_advCB, advHandle, GAP_ADV_EVT_MASK_ALL,
                                     advInitInfo->advParam, advInitInfo->advDataLen ,
                                     advInitInfo->advData, advInitInfo->scanRespDataLen,
                                     advInitInfo->scanRespData);
        }


   .. code-block:: c
      :caption: **ble\_stack\_api.c :: bleStk_initAdvSet** - Create the Advertising Set
      :linenos:

        bStatus_t bleStk_initAdvSet(pfnBleStkAdvCB_t advCallback, uint8_t *advHandle,
                                           GapAdv_eventMaskFlags_t eventMask,
                                           GapAdv_params_t *advParams,
                                           uint16_t advDataLen ,uint8_t advData[],
                                           uint16_t scanRespDataLen, uint8_t scanRespData[])
        {
          bStatus_t status;

        #ifdef ERPC_SERVER
         // keep the remote eRPC app callback
          remote_bleApp_GapAdvCb = advCallback;

          // Create Advertisement set and assign handle
          status = GapAdv_create((pfnGapCB_t)local_bleApp_GapAdvCb, advParams, advHandle);
        #else
          status = GapAdv_create((pfnGapCB_t)advCallback, advParams, advHandle);
        #endif
          if (status != SUCCESS)
          {
            return status;
          }
          // .....
          // .....
        }

#. **Set Advertiser's virtual address set with** :ble_api:`GapAdv_setVirtualAdvAddr`.
   The handle for the advertisement set, returned from :ble_api:`GapAdv_create`, can 
   also be used to create a custom private address for that advertisement set. This
   allows different advertising sets to have different addresses. 

   .. warning::
       This is only applicable for legacy non-connectable and non-scannable 
       advertising sets and it is optional.

#. **Load Advertisement and Scan Response data**. Advertising and scan response
   data is decoupled from the advertising set. That is, it is possible for multiple
   advertising sets to use the same memory for advertising\/scan response data. An
   advertising set could also use the same memory for its advertising and scan
   response data. (Note that this requires diligence as there are some data types
   that are only allowed once in the advertisement and scan response data. See the
   `Bluetooth Core Specification Supplement (CSSv7) <https://www.bluetooth.com/
   specifications/bluetooth-core-specification>`_ for specifics.)

   If your advertisement set is not scannable, you can of course skip the last step
   (load scan response data). Example advertising and scan response data is shown
   in :numref:`advertdata` and :numref:`scanrspdata`

   .. code-block:: c
     :caption: **ble\_stack\_api.c ::bleStk_initAdvSet** - Load the Advertising and Scan Response Data
     :linenos:

      bStatus_t bleStk_initAdvSet(pfnBleStkAdvCB_t advCallback, uint8_t *advHandle,
                                         GapAdv_eventMaskFlags_t eventMask,
                                         GapAdv_params_t *advParams,
                                         uint16_t advDataLen ,uint8_t advData[],
                                         uint16_t scanRespDataLen, uint8_t scanRespData[])
      {
       bStatus_t status;
       //...
       //...

       // Load advertising data for set that is statically allocated by the app
       status = GapAdv_loadByHandle(*advHandle, GAP_ADV_DATA_TYPE_ADV, advDataLen, advData);

       if (status != SUCCESS)
       {
         return status;
       }

       // Load scan response data for set that is statically allocated by the app
       if (scanRespData != NULL)
       {
         status = GapAdv_loadByHandle(*advHandle, GAP_ADV_DATA_TYPE_SCAN_RSP, scanRespDataLen, scanRespData);
         if (status != SUCCESS)
         {
           return status;
         }
       }
       //....
       //....
      }

   .. code-block:: c
     :name: advertdata
     :caption: ti\_ble\_config.c - Example Advertisement Data

      uint8_t advData1[] =
      {
        0x02,
        GAP_ADTYPE_FLAGS,
        GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED | GAP_ADTYPE_FLAGS_GENERAL,

        0x03,
        GAP_ADTYPE_16BIT_MORE,
        LO_UINT16(0xfff0),
        HI_UINT16(0xfff0),
      };

   .. code-block:: c
     :name: scanrspdata
     :caption: ti\_ble\_config.c - Example Scan Response Data

      uint8_t scanResData1[] =
      {
        0x12,
        GAP_ADTYPE_LOCAL_NAME_COMPLETE,
        'B',
        'a',
        's',
        'i',
        'c',
        ' ',
        'B',
        'L',
        'E',
        ' ',
        'p',
        'r',
        'o',
        'j',
        'e',
        'c',
        't',

        0x02,
        GAP_ADTYPE_POWER_LEVEL,
        0,

        0x05,
        GAP_ADTYPE_PERIPHERAL_CONN_INTERVAL_RANGE,
        LO_UINT16(80),
        HI_UINT16(80),
        LO_UINT16(104),
        HI_UINT16(104),

      };

#. **Set events of interest to send to application.** The events will be sent to the
   callback function given in :ble_api:`GapAdv_create`.

   .. code-block:: c
     :caption: **bleapputil\_init.c ::BLEAppUtil_initAdvSet** - Declare Callback Function and the events to registers
     :linenos:
     :emphasize-lines: 6

      bStatus_t BLEAppUtil_initAdvSet(uint8 *advHandle, const BLEAppUtil_AdvInit_t *advInitInfo)
      {
          // BLEAppUtil_advCB is the callback function
          // The mask is to register all GAP_ADV_EVT_MASK_ALL
          // That means in BLEAppUtil
          return bleStk_initAdvSet(BLEAppUtil_advCB, advHandle, GAP_ADV_EVT_MASK_ALL,
                                   advInitInfo->advParam, advInitInfo->advDataLen ,
                                   advInitInfo->advData, advInitInfo->scanRespDataLen,
                                   advInitInfo->scanRespData);
      }

   As you can see that the registered events for advertising callback is all. However,
   this only applies to the BLEAppUtil layer. In the application layer, you can further
   refine it to what you are interested in knowing. You can also just update the **GAP_ADV_EVT_MASK_ALL**
   to something else.

   If you don't want to modify the BLEAppUtil Framework, then you can use 
   ``BLEAppUtil_registerEventHandler`` to register the advertising events of interest
   on top of the BLEAppUtil framework.
   The aforementioned API expects ``BLEAppUtil_EventHandler_t`` struct.

   .. code-block:: c
     :name: bleapputil_eventhandle_declaration
     :caption: **app\_peripheral.c** - Advertising Event Handler
     :linenos:

      BLEAppUtil_EventHandler_t peripheralAdvHandler =
      {
          .handlerType    = BLEAPPUTIL_GAP_ADV_TYPE,
          .pEventHandler  = Peripheral_AdvEventHandler,
          .eventMask      = BLEAPPUTIL_ADV_START_AFTER_ENABLE |
                            BLEAPPUTIL_ADV_END_AFTER_DISABLE
      };    

   The first parameter is highlighted in :numref:`bleapputil_eventhandletype`.
   Here we are interested in advertising, thus we choose **BLEAPPUTIL_GAP_ADV_TYPE**.
   The second one is declaration of the function name, :numref:`peripheral_adveventhandler`,
   of where/how the events will be processed. Lastly, it takes the event masks
   :numref:`bleapputil_gapadveventmaskflags` which are mapped to the GAP Event masks.

   .. code-block:: c
     :name: bleapputil_eventhandletype
     :caption: **bleapputil\_api.h** - Event Handler Type
     :linenos:
     :emphasize-lines: 6

      // Event Handler Types
      typedef enum BLEAppUtil_eventHandlerType_e
      {
          BLEAPPUTIL_GAP_CONN_TYPE,
          BLEAPPUTIL_CONN_NOTI_TYPE,
          BLEAPPUTIL_GAP_ADV_TYPE,
          BLEAPPUTIL_GAP_SCAN_TYPE,
          BLEAPPUTIL_GAP_PERIODIC_TYPE,
          BLEAPPUTIL_GATT_TYPE,
          BLEAPPUTIL_PASSCODE_TYPE,
          BLEAPPUTIL_PAIR_STATE_TYPE,
          BLEAPPUTIL_L2CAP_DATA_TYPE,
          BLEAPPUTIL_L2CAP_SIGNAL_TYPE,
          BLEAPPUTIL_HCI_DATA_TYPE,
          BLEAPPUTIL_HCI_GAP_TYPE,
          BLEAPPUTIL_HCI_SMP_TYPE,
          BLEAPPUTIL_HCI_SMP_META_TYPE,
          BLEAPPUTIL_HCI_CTRL_TO_HOST_TYPE
      } BLEAppUtil_eventHandlerType_e;

   .. code-block:: c
     :name: peripheral_adveventhandler
     :caption: **app\_peripheral.c** - Function to process the event
     :linenos:

     void Peripheral_AdvEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
     {
         switch(event)
         {
             case BLEAPPUTIL_ADV_START_AFTER_ENABLE:
             {
                 MenuModule_printf(APP_MENU_ADV_EVENT, 0, "Adv status: Started - handle: "
                                   MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                                   ((BLEAppUtil_AdvEventData_t *)pMsgData)->pBuf->advHandle);
                 break;
             }

             case BLEAPPUTIL_ADV_END_AFTER_DISABLE:
             {
                 MenuModule_printf(APP_MENU_ADV_EVENT, 0, "Adv status: Ended - handle: "
                                   MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                                   ((BLEAppUtil_AdvEventData_t *)pMsgData)->pBuf->advHandle);
                 break;
             }

             default:
             {
                 break;
             }
          }
      }


   .. code-block:: c
     :name: bleapputil_gapadveventmaskflags
     :caption: **bleapputil\_api.h** - GAP Adv Event Mask
     :linenos:
     :emphasize-lines: 4, 6

     typedef enum BLEAppUtil_GAPAdvEventMaskFlags_e
     {
         // Gets advertising handle using pBuf
         BLEAPPUTIL_ADV_START_AFTER_ENABLE    = GAP_EVT_ADV_START_AFTER_ENABLE,
         // Gets advertising handle using pBuf
         BLEAPPUTIL_ADV_END_AFTER_DISABLE     = GAP_EVT_ADV_END_AFTER_DISABLE,
         // Gets advertising handle using pBuf
         BLEAPPUTIL_ADV_START                 = GAP_EVT_ADV_START,
         // Gets advertising handle using pBuf
         BLEAPPUTIL_ADV_END                   = GAP_EVT_ADV_END,
         // Gets @ref GapAdv_setTerm_t using pBuf
         BLEAPPUTIL_ADV_SET_TERMINATED        = GAP_EVT_ADV_SET_TERMINATED,
         // Gets @ref GapAdv_scanReqReceived_t using pBuf
         BLEAPPUTIL_SCAN_REQ_RECEIVED         = GAP_EVT_SCAN_REQ_RECEIVED,
         // Gets @ref GapAdv_truncData_t using pBuf
         BLEAPPUTIL_ADV_DATA_TRUNCATED        = GAP_EVT_ADV_DATA_TRUNCATED,
         BLEAPPUTIL_ADV_INSUFFICIENT_MEMORY   = GAP_EVT_INSUFFICIENT_MEMORY
     } BLEAppUtil_GAPAdvEventMaskFlags_e;

#. **Enable advertising.** Calling :ble_api:`GapAdv_enable` to start
   advertising. Note that ``BLEAppUtil_advStart`` is a wrapper for 
   ``GapAdv_enable``

   .. code-block:: c
     :caption: **app\_peripheral.c** :: Peripheral\_start() - Start advertising.
     :linenos:

        // Enable advertising
        status = BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);

   .. code-block:: c
     :caption: **bleapputil\_init.c** :: BLEAppUtil_advStart - Start advertising.
     :linenos:

      bStatus_t BLEAppUtil_advStart(uint8 handle, const BLEAppUtil_AdvStart_t *advStartInfo)
      {
          return GapAdv_enable(handle, advStartInfo->enableOptions ,
                               advStartInfo->durationOrMaxEvents);
      }


The above steps can be repeated to create multiple advertising sets. There is an
upper limit of 20 advertising sets (defined in the controller). The heap may
also restrict the number of advertising sets you can create in one application.



.. _gap-changing-adv-param:

Changing advertising parameters
*******************************
In order to change an individual parameter after advertising has been enabled,
advertising must first be disabled. Re-enable advertising after the parameter is modified.
Here we will illustrate the sequence using BLEAppUtil framework.

.. code-block:: c
  :caption: Changing advertising parameter during advertising.
  :linenos:

     // Stop advertising
     BLEAppUtil_advStop(peripheralAdvHandle_1);

     // Set a parameter
     uint32_t newAdvInt = 200;
     GapAdv_setParam(peripheralAdvHandle_1, GAP_ADV_PARAM_PRIMARY_INTERVAL_MIN, &newAdvInt);
     GapAdv_setParam(peripheralAdvHandle_1, GAP_ADV_PARAM_PRIMARY_INTERVAL_MAX, &newAdvInt);

     // Re-enable advertising
     status = BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);

.. _gap-advertiser-gap-destroy:

Ending Advertisement
********************
An advertising set can be disabled with :ble_api:`GapAdv_disable` and deleted
(such that all memory related to the set is freed) with :ble_api:`GapAdv_destroy`.

.. code-block:: c
  :caption: Stop advertising and free memory.
  :linenos:

    // Stop advertising
    BLEAppUtil_advStop(peripheralAdvHandle_1);

    // Free all parameter settings related to advertising set 
    // Keep the advertising / scan response data
    // Note that this can be called while advertising is still enabled
    GapAdv_destroy(peripheralAdvHandle_1, GAP_ADV_FREE_OPTION_DONT_FREE);

.. warning::
    In the out of box example, the advertising and scan response data are
    declared as global array using sysconfig tool, thus the |STACK| has not
    allocated memory to the advertising and scan response data. If attempt
    to free the data using **GAP_ADV_FREE_OPTION_ADV_DATA** or 
    **GAP_ADV_FREE_OPTION_SCAN_RESP_DATA**, it will cause hardfault.

Updating Advertisement/Scan Response Data
*****************************************
Again, since the advertising and scan response data is decoupled from the
advertising set, it is possible for multiple advertising sets to use the same
memory for advertising\/scan response data. An advertising set could also use
the same memory for its advertising and scan response data. The memory used for
advertising\/scan response data is referred to as a "buffer" throughout this
section.

The preferred and safest method to update a buffer is to use the prepare\/load
latching mechanism. This will ensure the following:

- No buffer is freed if it is used by another advertising set.
- Advertising is always disabled before the buffer is modified, thus ensuring
  that no corrupted advertisement packets are transmitted.
- Prevent double-copying.

The following offers several ways to update the advertising and scan response
data.

Update the Advertising\/Scan Response Data of a Single Handle
#############################################################

If the application wants to modify a few bytes of advertising\/scan response data
that is used by a single advertisement set, use :ble_api:`GapAdv_prepareLoadByHandle`
and :ble_api:`GapAdv_loadByHandle`.

.. code-block:: c
  :caption: Update the advertising buffer of a single handle.
  :linenos:

    bStatus_t status;

    // Don't free anything since we're going to use the same buffer to re-load
    status = GapAdv_prepareLoadByHandle(peripheralAdvHandle_1, GAP_ADV_FREE_OPTION_DONT_FREE);

    // Only update the data when return is successful
    if (status == SUCCESS)
    {
      // Sample buffer modification
      advData1[3] = 0xAA;

      // Reload buffer to handle
      // Here the advDataLen = sizeof(advData1) and it is setup in the app\_peripheral.c
      // under advSetInitParamsSet_1
      GapAdv_loadByHandle(peripheralAdvHandle_1, GAP_ADV_DATA_TYPE_ADV, advSetInitParamsSet_1->advDataLen, advData1);
    }

The GapAdv_prepareLoadByHandle() will perform the following here:

- Check that this buffer isn't used by other handles. If
  :ble_api:`GapAdv_prepareLoadByHandle` returns success, the application will
  know that it can now safely modify this buffer.
- Automatically disable advertising and mark it for re-enabling

:ble_api:`GapAdv_loadByHandle` will automatically re-enable advertising with the
updated buffer. This method can also be used to use a subset of the original
advertising data. In this case, simply update the data length parameter of
:ble_api:`GapAdv_loadByHandle`.

.. warning:: 
    The above methods of changing advertising or scan response data have one
    limitation. A special procedure is required when the data length is 
    currently set to zero and application wants to change that to a non-zero
    length. In this case the application needs to 

    #. Destroy the advertisement set, please see :ref:`gap-advertiser-gap-destroy`
    #. Re-create it with the desired data, please see :ref:`gap-advertiser-gap-create`

Load a New Buffer to a Single Advertising Handle
################################################

If the application wants to load a new buffer to a single advertising handle
without double-copying, use :ble_api:`GapAdv_prepareLoadByHandle` and
:ble_api:`GapAdv_loadByHandle`. This way, the advertising data exists in only one
place in memory that is used by the GAP Advertiser. In this case we will free the buffer and
allocate a new one.

.. code-block:: c
  :caption: Load a new advertising buffer for a single handle.
  :linenos:

    // Free the buffer (to avoid double copying) since we're loading a new buffer
    // However, only free the buffer if it's allocated in the application.
    // Using out of box example, the buffer is a global array and can not be freed
    GapAdv_prepareLoadByHandle(advHandleLegacy, GAP_ADV_FREE_OPTION_ADV_DATA);

    // Allocate new buffer (and then fill it as desired)
    uint8_t *advertData2= ICall_malloc(ADV_DATA2_LEN);

    // Load the new buffer to the advertisement set handle
    GapAdv_loadByHandle(peripheralAdvHandle_1, GAP_ADV_DATA_TYPE_ADV, ADV_DATA2_LEN, advertData2);

:ble_api:`GapAdv_prepareLoadByHandle` will perform the following here:

- Check that the buffer isn't used by any other advertisement handles. If
  :ble_api:`GapAdv_prepareLoadByHandle` returns success, the application will
  know that it can now safely modify this buffer.
- Automatically disable advertising and mark it for re-enabling
- Free the original buffer

The :ble_api:`GapAdv_loadByHandle` will automatically re-enable advertising on
the handle with the new buffer.

Update Advertising\/Scan Response Data that is Used for Multiple Advertising Handles
####################################################################################

This is the case where the application wants to modify a few bytes of
advertising or scan response data that is shared among advertisement sets.

.. code-block:: c
  :caption: Update an advertising buffer used by multiple handles.
  :linenos:

    // Don't free anything since we're going to use the same buffer to reload
    GapAdv_prepareLoadByBuffer(advertData, FALSE);

    // Sample buffer modification
    advertData[3] = 0xAA;

    // Reload the buffer to be used by the advertisement set handles
    GapAdv_loadByBuffer(ADV_DATA_LEN, advertData);

:ble_api:`GapAdv_prepareLoadByBuffer` will automatically disable advertising for
all advertising handles that use this buffer. :ble_api:`GapAdv_loadByBuffer`
will automatically re-enable advertising for all handles that use this buffer.

Load a New Buffer To Multiple Advertising Handles
#################################################

This is the case where the applications wants to load a new buffer to all
advertisement set handles that are using this buffer.

.. code-block:: c
  :caption: Load new advertising buffer for multiple handles.
  :linenos:

    // Free buffer (to avoid double copying) since we're loading a new buffer
    // However, only free the buffer if it's allocated in the application.
    // Using out of box example, the buffer is a global array and can not be freed
    GapAdv_prepareLoadByBuffer(advertData, TRUE);

    // Allocate new buffer (and then fill as desired)
    uint8_t *advertData2= ICall_malloc(ADV_DATA2_LEN);

    // Reload the buffer to be used by all the handles
    GapAdv_loadByBuffer(ADV_DATA2_LEN, advertData2);

:ble_api:`GapAdv_loadByBuffer` will perform the following here:

- Automatically disable advertising and mark it for re-enabling on all handles
  that use this buffer
- Free the original buffer

:ble_api:`GapAdv_loadByBuffer` will automatically re-enable advertising on all
handles that used the original buffer.

Directly Manipulating a Buffer While Advertising is Enabled
***********************************************************

Since the application owns the advertising and scan response buffers and thus has access to
the memory where the buffers are stored, there is nothing preventing it from directly
modifying this memory. While discouraged, there are scenarios where this can
be useful, such as updating the data after each advertisement in the most power-efficient
manner. The main drawback to this is that there is no way to guarantee that this update
won't occur while an advertising packet is being transmitted that is using this buffer,
potentially resulting in a corrupted advertising packet. This is especially true if
multiple advertising sets are using the same buffer. If the application accepts the risk
of potentially corrupting an advertising packet, there is a recommended way to do this with
minimized risk.

The buffer should be updated directly in the advertising callback (in the stack context)
when the ``GAP_EVT_ADV_END`` or ``BLEAPPUTIL_ADV_END`` is received. Generally,
it is recommended to minimize processing in these callbacks and, instead, to 
post an event to process in the application context. It should be noted that 
any processing in the stack context has the potential to break the timing of
the controller. This should not be a problem if the only processing is to 
update the buffer. Also, for both this reason and because it will lead to
a semaphore that never gets posted due to calling an ICall API from the stack
context, it should be noted that no stack API calls can be made from the stack
context. To reiterate for clarity, no BLE-Stack APIs can be called from the callback (stack) context.

.. code-block:: c
  :caption: Directly update advertising data in advertising event handle.
  :linenos:

   void Peripheral_AdvEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
   {
     switch(event)
     {
       // Advertisement just ended so it should be safe to update buffer here
       // without corrupting an advertisement.
       case BLEAPPUTIL_ADV_END:
       {
          advertData[3] = 0xAA;
       }
     }
   }

Note that this can not be guaranteed to work all the time without corrupting an
advertisement. Also, if the buffer is used by multiple advertisement handles, the
application would need to track the ``GAP_EVT_ADV_END`` or ``BLEAPPUTIL_ADV_END``
across all of these handles to find an ideal time to update the buffer. 
If this processing is added to the callback in the stack context, this 
increases the risk of breaking the timing of the controller.
Also, remember to include ``GAP_EVT_ADV_END`` or ``BLEAPPUTIL_ADV_END`` in the event mask,
please refer to :numref:`bleapputil_eventhandle_declaration`.

.. _gap_read_RSSI_scanrequest:

Get RSSI from Scan Request
**************************

In order to fetch useful information from a Scan Request, it is possible to read the
``GapAdv_scanReqReceived_t`` struct that contains valid information when ``GAP_EVT_SCAN_REQ_RECEIVED``
is received at the application layer. One relevant information that can be retreived is the RSSI value of
the scan request. If we are using an out-of-the-box example such as ``basic_ble``, then 
to get to the scan request struct we need to address ``BLEAppUtil_AdvEventData_t``
struct first, then ``GapAdv_data_t`` (pBuf) and finally ``GapAdv_scanReqReceived_t`` (pScanReqRcv) 
where we can find the rssi value. Please see the code snippet below for reference on how to implement:

.. code-block:: c
  :caption: Get RSSI from Scan Request.
  :linenos:

   int8 rsb_adv_rssi = 0;

   BLEAppUtil_EventHandler_t peripheralAdvHandler =
   {
    .handlerType    = BLEAPPUTIL_GAP_ADV_TYPE,
    .pEventHandler  = Peripheral_AdvEventHandler,
    .eventMask      = BLEAPPUTIL_ADV_START_AFTER_ENABLE |
                      BLEAPPUTIL_ADV_END_AFTER_DISABLE  |
                      BLEAPPUTIL_ADV_END |
                      BLEAPPUTIL_SCAN_REQ_RECEIVED
   };

   void Peripheral_AdvEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
   {
     switch(event)
     //...
     {
       case BLEAPPUTIL_SCAN_REQ_RECEIVED:
       {
        BLEAppUtil_AdvEventData_t* lpts_scanReqReceived = (BLEAppUtil_AdvEventData_t*)pMsgData;
        rsb_adv_rssi = lpts_scanReqReceived->pBuf->pScanReqRcv.rssi;
        break;
       }
       //...
     }
   }


.. _gap_limited_advertising:

Limited Advertising
*******************
The above code can set the advertising for limited or general
advertising modes. By default, the peripheral advertises in general
discoverable mode. To use limited discoverable mode, the
corresponding fields inside the :numref:`advertdata` should be
corresponding fields inside the :numref:`advertdata` should be
changed by changing ``GAP_ADTYPE_FLAGS_GENERAL`` to
``GAP_ADTYPE_FLAGS_LIMITED``. This can be achieved by using :ref:`sysconfig-ble5`.

.. note::

  When using Limited Advertising, special care must be taken to ensure the proper
  advertising parameters are used with :ble_api:`GapAdv_enable`. If improper
  parameters are used, then the function will return ``bleInvalidRange``.

  When setting ``enableOptions`` to  ``GAP_ADV_ENABLE_OPTIONS_USE_DURATION``,
  the duration must be set to no longer than 180 seconds. If the duration is set for
  longer than 180 seconds, then the function will return ``bleInvalidRange``.

  When setting ``enableOptions`` to  ``GAP_ADV_ENABLE_OPTIONS_USE_MAX_EVENTS``,
  the number of advertisements to be sent must take less than 180 seconds to send.
  The time to send all of the advertisements will depend on the advertising interval
  used and the value assigned to ``durationOrMaxEvents``. The time to send all
  advertisements is (10ms + advertisingInterval) * ``durationOrMaxEvents``. If
  this time exceeds 180 seconds, then the function will return ``bleInvalidRange``.

.. _gap_periodic_advertising:

Periodic Advertising
********************

.. warning::
    The symbol ``USE_PERIODIC_ADV`` must be pre-defined if you
    wish to send periodic advertisements (for more details, please see 
    :ref:`stackconfigurablefeatures`).
  
Periodic advertising is part of the Advertising Extension and it allows device to 
send data synchronously at a fixed interval. Periodic advertising is not scannable, 
not connectable and the advertiser's address should not be hidden.
  
In order for scanner to receive periodic advertisement, the extended advertisement 
needs to be enabled and contain at least one PDU type ``AUX_ADV_IND`` packet. The reason for that
is the ``SyncInfo`` to the periodic advertisement packets can only be found 
under ``AUX_ADV_IND`` packet. 
  
The detailed process for enabling periodic advertisement is as follows:
  
- Advertiser sends out ``ADV_EXT_IND`` PDU type. Scanner will find the channel  index, timing and PHY that a coming 
  auxiliary packet(``AUX_ADV_IND``) will be sent at under AuxPtr field. 
- Advertiser then sends out ``AUX_ADV_IND`` PDU type package. If there is periodic  advertisement coming
  up, scanner will find ``SyncInfo`` field under extended header. The SyncInfo field
  contains the needed information for a scanner to follow periodic advertisement  packets. 
  For more detail, please refer to the picture below and Vol 6, Part B, Section 2.3   of |CORESPEC|.


  .. ditaa::
    :--no-separation:
    :--no-shadows:


    +-------------------------------------------------------------------------------------------------------+
    |                                   Advertising  PDU   c900                                             | 
    +-------------------------------------------------+-----------------------------------------------------+
    |                    Header         c156          | Payload (Common Extended   Advertising Payload) c156|
    +----------+-----+-------+-------+-------+--------+---------------------+----------+------------+-------+
    | PDU Type | RFU | ChSel | TxAdd | RxAdd | Length |  Extended Header    |  AdvMode |  Extended  | Data  |
    |  c189    | c189| c189  | c189  | c189  | c189   |       Length c189   |  c189    |   Header   | c189  |
    |  0b111   |     |       |       |       |        |                     |          |    c189    |       | 
    +----------+-----+-------+-------+-------+--------+---------------------+----------+------------+-------+
                                                                                       |            |
                                                                                       |            |
          /----------------------------------------------------------------------------/            |
          |                                                                                         |
          |                                                                                         |
          v                                                                                         v
          +-----------------------------------------------------------------------------------------+
          |                                   Extended Header   c156                                |
          +------------+-------+---------+---------+---------+--------+----------+----------+-------+
          |   Extended | AdvA  | TargetA | CTEInfo | AdvData | AuxPtr | SyncInfo |  TxPower | ACAD  |
          | Header Flag|       |         |         |  Info   |        |          |          |       |
          |   c189     | c189  | c189    | c189    | c189    | c189   | c189     |  c189    | c189  |
          +------------+-------+---------+---------+---------+--------+----------+----------+-------+
                                                                      |          | 
          /-----------------------------------------------------------/          \----------------\
          |                                                                                       |
          v                                                                                       v
          +---------------------------------------------------------------------------------------+
          |                                       SyncInfo  c189                                  |  
          +-------------+--------+--------+-----+----------+-----+-----+----+-----------+---------+
          | Sync Packet | Offset | Offset | RFU | Interval | ChM | SCA | AA | CRCInit   | Event   |
          |   Offset    | Units  | Adjust |     |          |     |     |    |           | Counter |
          |  cAAA       | cAAA   | cAAA   | cAAA| cAAA     | cAAA|cAAA |cAAA| cAAA      | cAAA    |
          +-------------+--------+--------+-----+----------+-----+-----+----+-----------+---------+
          <------------------------------->     <---------->     <-------------------------------->
                    packet timing               advertising         has same meaning as when in 
                                                  interval                  connection

The picture below depicts the overall flow of how periodic advertisement works.

.. ditaa::
    :--no-separation:
    :--no-shadows:


                        +-----------+    +-----------+    +-----------+  
      Primary Channels  |ADV_EXT_IND|    |ADV_EXT_IND|    |ADV_EXT_IND|--\
                        | cGRE      |    | cGRE      |    | cGRE      |  | 
                        +-----------+    +-----------+    +-----------+  |
                                                                         |
      -------------------------------------------------------------------|----------------------------------
                                                                         |
                                                                         v 
      Data Channels                                          +-------------+
                                                             | AUX_ADV_IND |--\
                                                             | c189        |  |
                                                             +-------------+  |
                                                                              |
                                                                              |
                                                                              v
                                                                       +------------+          +------------+         
                                                                       |AUX_SYNC_IND|          |AUX_SYNC_IND|
                                                                       | cAAA       |          |   cAAA     |
                                                                       +------------+          +------------+ 

                                                                       <----------------------->
                                                                         Fixed  Interval



The following list describes how to configure the GAP layer for periodic  advertising.

.. warning:: The periodic advertisement set creation is not supported in SysConfig.

Enable Non-Connectable Non-Scannable Extended Advertisement
###########################################################

  #. Setup parameters for **non-connectable and non-scannable** extended  advertisement.  
     To achieve this, you can set eventProps = 0 and sid != 0 

     .. code-block:: c
       :caption: Setting up advertising parameters for non-connectable and  non-scannable extended advertisement set
       :emphasize-lines: 3, 13
       :linenos:

        /// Non-Connectable & Non-Scannable advertising set
        #define GAPADV_PARAMS_AE_NC_NS {                                           \
          .eventProps = 0,                                                         \
          .primIntMin = 160,                                                       \
          .primIntMax = 160,                                                       \
          .primChanMap = GAP_ADV_CHAN_ALL,                                         \
          .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,                       \
          .peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },                      \
          .filterPolicy = GAP_ADV_AL_POLICY_ANY_REQ,                               \
          .txPower = GAP_ADV_TX_POWER_NO_PREFERENCE,                               \
          .primPhy = GAP_ADV_PRIM_PHY_1_MBPS,                                      \
          .secPhy = GAP_ADV_SEC_PHY_1_MBPS,                                        \
          .sid = 1                                                                 \
        }

        // Create non connectable & non scannable advertising
        GapAdv_params_t advParamNonConn = GAPADV_PARAMS_AE_NC_NS;

  #. Creating **non-connectable and non-scannable** extended advertisement.

     .. code-block:: c
       :caption: Creating and enable extended advertisement
       :linenos:

          static uint8 advHandleNCNS;      // Non-Connactable & Non-Scannable

          // Create Advertisement set #3 and assign handle
          status = GapAdv_create(&advCallback, &advParamNonConn,
                                               &advHandleNCNS);

          // Load advertising data for set #3 that is statically allocated by the app
          status = GapAdv_loadByHandle(advHandleNCNS, GAP_ADV_DATA_TYPE_ADV,
                                       sizeof(advertData), advertData);

          // Set event mask for set #3
          status = GapAdv_setEventMask(advHandleNCNS,
                                       GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
                                       GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
                                       GAP_ADV_EVT_MASK_SET_TERMINATED);

          // Enable non connectable & non scannable advertising for set #3
          // This is a must in order to enable periodic advertisement
          status = GapAdv_enable(advHandleNCNS, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);

  #. Setup parameters for periodic advertisement.
     The |STACK| will then return ``GAP_ADV_SET_PERIODIC_ADV_PARAMS_EVENT`` to the  application layer whether 
     or not the parameters are set successfully.

     .. code-block:: c
       :caption: Setting up advertising parameters for non-connectable and  non-scannable extended advertisement set
       :linenos:

        /// Non-Connectable & Non-Scannable advertising set
        #define GAPADV_PARAMS_PERIODIC_ADV {                                     \
          .periodicAdvIntervalMin = 160,                                         \
          .periodicAdvIntervalMax = 160,                                         \
          .periodicAdvProp = GAPADV_PERIODIC_ADV_ENABLE_TX_POWER                 \
        }

        // Set Periodic Advertising parameters
        GapAdv_periodicAdvParams_t advParamsPerAdv = GAPADV_PARAMS_PERIODIC_ADV;

        status = GapAdv_SetPeriodicAdvParams(advHandleNCNS, &advParamsPerAdv);

.. warning:: Only bit 6 in periodicAdvProp field can be set, otherwise the |STACK| will return bleInvalidRange. 
.. Keep Commented until periodic is tested

  .. _gap_periodic_advertising_advdata_set:

  Configure Advertising Data For Periodic Advertisement
  #####################################################
  Advertising data for periodic advertisement is optional. It's not needed to have  periodic advertisment running.

  #. Setup advertising data for periodic advertisement.
     The |STACK| will then return ``GAP_ADV_SET_PERIODIC_ADV_DATA_EVENT`` to the  application layer whether 
     or not the adverting data are set successfully.

     .. code-block:: c
       :caption: Setting up advertising data for periodic advertising
       :linenos:

        // Periodic Advertising Data
        static uint8_t periodicData[] =
        {
          'P',
          'e',
          'r',
          'i',
          'o',
          'd',
          'i',
          'c',
          'A',
          'd',
          'v'
        };

        #define GAPADV_DATA_PERIODIC_ADV {                          \
          .operation = GAPADV_PERIODIC_ADV_DATA_COMPLETE,           \
          .dataLength = sizeof(periodicData),                       \
          .pData = periodicData                                     \
        }

        GapAdv_periodicAdvData_t periodicDataParams = GAPADV_DATA_PERIODIC_ADV;
        status = GapAdv_SetPeriodicAdvData(advHandleNCNS, &periodicDataParams);

     .. note:: You can find a list of define made for periodic advertisement under  gap_advertiser.h.


     .. warning:: The maximum data length that is supported here is 252 bytes.  Therefore, if you have a advertising
        data for more than 252 bytes, you will have to fragment the payload in the  application layer before calling
        :ble_api:`GapAdv_SetPeriodicAdvData`.

        For example, if you have 1000 bytes advertising data you want to send using   periodic advertisement, you will
        have to call :ble_api:`GapAdv_SetPeriodicAdvData` four times. 
        The operation field for first 252 bytes needs to be set to `` GAPADV_PERIODIC_ADV_DATA_FIRST_FRAG(0x01)``. 
        The operation field for 253 ~ 504 and 505 ~ 756 bytes needs to be set to 
        ``GAPADV_PERIODIC_ADV_DATA_INTERMIDIATE_FRAG (0x00)``, and the operation  field for the last part of 
        the data needs to be set to ``GAPADV_PERIODIC_ADV_DATA_LAST_FRAG (0x02)``.

        The |STACK| will chain the data based on the order of :ble_api:`  GapAdv_SetPeriodicAdvData` calls.

  .. _gap_periodic_advertising_enable:

  Enable Periodic Advertisement
  #############################

  #. Enable periodic advertisement.
     The |STACK| will then return ``GAP_ADV_SET_PERIODIC_ADV_ENABLE_EVENT`` to the  application layer whether 
     or not the periodic advertising starts successfully.

     .. code-block:: c
       :caption: Enable periodic advertising
       :linenos:

        status = GapAdv_SetPeriodicAdvEnable(1, advHandleNCNS);

     .. attention:: Even when :ble_api:`GapAdv_SetPeriodicAdvEnable` was called, if   the non-connectable non-scannable 
        extended advertisement is not enabled, the periodic advertisement will not  start.

  .. _gap_periodic_advertising_disable:

  Disable Periodic Advertisement
  ##############################

  #. Disable periodic advertisement.
     The |STACK| will then return ``GAP_ADV_SET_PERIODIC_ADV_ENABLE_EVENT`` to the  application layer whether 
     or not the periodic advertising stops successfully.

     .. code-block:: c
       :caption: Enable periodic advertising
       :linenos:

        status = GapAdv_SetPeriodicAdvEnable(0, advHandleNCNS);


  Change Advertising Data For Periodic Advertisement
  ##################################################
  There are two methods to change the advertising data for periodic advertisement.

  #. If the new data is less than or equal to 252 bytes, which means operation mode = 
     ``GAPADV_PERIODIC_ADV_DATA_COMPLETE (0x3)``. Then you can just follow 
     :ref:`gap_periodic_advertising_advdata_set` to populate the new data.

  #. If the new data is more than 252 bytes, then you will have to disable the  periodic advertisement 
     first, please refer to :ref:`gap_periodic_advertising_disable` and then 
     follow :ref:`gap_periodic_advertising_advdata_set` to populate the new data.

.. _creating-a-custom-ble-app_directed_advertisements:

Directed Advertisements as GATT Server
######################################
In |STACKVER|, Privacy is always enabled. Most of the privacy
features are handled by the GAP bond manager in the stack. To conserve
flash memory, by default, the GAP bond manager does not enable GATT
client features. The implication of these disabled GATT client features
is that the GAP bond manager will not query the Central Address
Resolution characteristic of the remote device.

In order to perform a directed advertisement when the initiator's
address is set to Private Resolvable Address, the peripheral device
must read the Central Address Resolution characteristic of its remote
device to make sure address resolution is supported. Failure to do so
before sending directed advertisements violates the |CORESPEC|.

By default, sample applications such as basic\_ble does not define
``GATT_NO_CLIENT`` but initializes the GATT Client as shown below:

  .. code-block:: c
    :caption: **ble\_stack\_api.c** :: bleStack_initGatt - Initialize GATT Client for peripheral & central
    :linenos:

     if (role & (GAP_PROFILE_PERIPHERAL | GAP_PROFILE_CENTRAL))
     {
         // Initialize GATT Client
         GATT_InitClient();
     }

.. note:: 
    ``GATT_NO_CLIENT`` can be set using :ref:`sysconfig-ble5`.

.. _gaprole_peripheral_role:

GAP Peripheral
^^^^^^^^^^^^^^

The Peripheral role demonstrates the use of the advertising and
connection states. The steps to use this role will be demonstrated by
examining the ``basic_ble`` example project and related GAP APIs.

.. note:: 
    Many of the GAP default values may configured using ``syscfg``. The examples
    below show how to make these modifications when ``syscfg`` is not desired.


#. Initialize the GAP parameters. This initialization typically occurs in the
   application initialization function by calling ``GAP_SetParamValue()``. 
   In the ``basic_ble`` example project included in the SDK, this initialization 
   occurs in ``bleStack_initGap()`` as shown below.

   .. _gaprole_init:

   .. code-block:: c
     :caption: **ble_stack_api.c :: bleStack_initGap()** - Setup of the GAP Peripheral Role
     :linenos:
     :emphasize-lines: 4

     {
       bStatus_t status = SUCCESS;
       // Pass all parameter update requests to the app for it to decide
       GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision);

       //...
       return status;
     }

   Additional calls to ``GAP_SetParamValue()`` may be made in 
   ``bleStack_initGap()`` to override default GAP parameters when using
   ``basic_ble``. A list of configurable parameters may be located in the 
   :ref:`ble_api_reference` GAP section.

#. Modifing GAP initialization parameters in ``basic_ble``. By default, 
   ``basic_ble`` will send all GAP parameter updates to the application. 
   To change this behavior, modify the ``appMainPeriCentParams`` structure 
   located in ``app_main.c``. 

   .. code-block:: c
     :caption: **app_main.c :: appMainPeriCentParams** - Modifying GAP Parameters 
     :linenos:
     :emphasize-lines: 3

     BLEAppUtil_PeriCentParams_t appMainPeriCentParams =
     {
      .connParamUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION,
      .gapBondParams = &gapBondParams
     };

#. Initialize the application task using ``GAP_DeviceInit`` for the Peripheral 
   Role and register to receive GAP events. To modify the default GAP device 
   initialization parameters in ``basic_ble``, modify the ``appMainParams`` 
   structure located in ``app_main.c``.

   .. code-block:: c
     :caption: **app_main.c :: appMainParams** - GAP Application Parameters.
     :linenos:

     // Parameters that should be given as input to the BLEAppUtil_init function
     BLEAppUtil_GeneralParams_t appMainParams =
     {
         .taskPriority = 1,
         .taskStackSize = 1024,
         .profileRole = (BLEAppUtil_Profile_Roles_e)(HOST_CONFIG),
         .addressMode = DEFAULT_ADDRESS_MODE,
         .deviceNameAtt = attDeviceName,
     };

   .. code-block:: c
     :caption: **bleapputil_init.c :: BLEAppUtil_stackInit()** - Initialize the GAP layer and register for GAP events.
     :linenos:
     :emphasize-lines: 3

     //...

     status = GAP_DeviceInit(BLEAppUtilLocal_GeneralParams->profileRole,
                             BLEAppUtilSelfEntity,
                             BLEAppUtilLocal_GeneralParams->addressMode,
                             BLEAppUtilLocal_GeneralParams->pDeviceRandomAddress);

     //...



#. Now you can send commands from the application. The following is an example
   of the application initiating PHY change using :ble_api:`HCI_LE_SetPhyCmd`.

   .. code-block:: c
     :caption: **bleapputil_init.c :: BLEAppUtil_setConnPhy()** - Changing the PHY
     :linenos:
     :emphasize-lines: 6

      bStatus_t BLEAppUtil_setConnPhy(BLEAppUtil_ConnPhyParams_t *phyParams)
      {
          // Set Phy Preference on the current connection. Apply the same value
          // for RX and TX. For more information, see the LE 2M PHY section in the User's Guide:
          // http://software-dl.ti.com/lprf/ble5stack-latest/
          return HCI_LE_SetPhyCmd(phyParams->connHandle, phyParams->allPhys, phyParams->txPhy, phyParams->rxPhy, phyParams->phyOpts);
      }

   The following shows the software flow when the user chooses to set the PHY preference
   from the terminal in the ``basic_ble`` example:

   .. uml::
       :caption: Context Diagram of Application Updating PHY.
       :align: center

       @startuml
       participant Application
       participant "BLE Stack"

       group Connected to a device

       group User presses button to initiate PHY change
         Application -> Application: Button ISR
       end

         rnote over Application
          Button handler calls
          application callback
         end note

         Application -> Application : Menu_connPhyChangeCB()
         Application -> Application : BLEAppUtil_setConnPhy()
         Application -> "BLE Stack" : HCI_LE_SetPhyCmd()

         "BLE Stack" -> Application : return(status)

         group Receive HCI Event
           "BLE Stack" -> Application : Connection_HciGAPEventHandler 

           rnote over "Application"
            BLEAPPUTIL_HCI_GAP_TYPE -> BLEAPPUTIL_HCI_LE_EVENT_CODE -> HCI_BLE_PHY_UPDATE_COMPLETE_EVENT
           end note

           rnote over "Application"
            Display changed PHY
           end note
         end
       end

       @enduml

   As shown in the diagram above, the actual PHY change is returned asynchronously and is
   passed to the application with event code HCI_BLE_PHY_UPDATE_COMPLETE_EVENT.

#. The application task processes most of the GAP-related events passed to it
   from the Bluetooth Low Energy protocol stack. For example, when a link is
   terminated, the application removes the connection information and displays 
   the terminated device's peer address and connection handle number.
   The following code snippet can be found in ``app_connection.c``:

   .. code-block:: c
     :caption: **app_connection.c :: Connection_ConnEventHandler()** - Removing connection info
     :linenos:
     :emphasize-lines: 11

     void Connection_ConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
     {
         switch(event)
         {
             // ...
             case BLEAPPUTIL_LINK_TERMINATED_EVENT:
             {
                 gapTerminateLinkEvent_t *gapTermMsg = (gapTerminateLinkEvent_t *)pMsgData;

                 // Remove the connection from the conneted device list
                 Connection_removeConnInfo(gapTermMsg->connectionHandle);

                 /*! Print the peer address and connection handle number */
                 MenuModule_printf(APP_MENU_CONN_EVENT, 0, "Conn status: Terminated - "
                                   "connectionHandle = " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET
                                   "reason = " MENU_MODULE_COLOR_YELLOW "%d" MENU_MODULE_COLOR_RESET,
                                   gapTermMsg->connectionHandle, gapTermMsg->reason);

                 /*! Print the number of current connections */
                 MenuModule_printf(APP_MENU_NUM_CONNS, 0, "Connections number: "
                                   MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                                   linkDB_NumActive());

                 break;
             }
             // ... 


.. _gapscanner:

GAP Scanner
^^^^^^^^^^^

The GAP Scanner performs Extended Scanning, Legacy Scanning and 
Synchronization with periodic advertisements operations as
defined by the |CORESPEC|. It controls the Scanner GAP state (see
:ref:`gap_state_diagram`). The Central and Observer role uses the scanning
state implemented by the GAP Scanner. The GAP Scanner is demonstrated in the
``app_central.c`` and ``app_observer.c`` source files in the ``basic_ble`` 
example project. See the
:ref:`ble_api_reference` for the full GAP Scanner API including commands,
configurable parameters, events, and callbacks. The steps to use this module are
listed in the following, along with example code from ``basic_ble``.

1. **Start a Central or Observer GAP role.** In this case we will use the GAP
   Central role. For configuration of the Bluetooth Low Energy stack features, 
   and changing the role in ``basic_ble``, see :ref:`creating_custom_ble_app` 
   and :ref:`stack_features_configuration`.

2. **Register an event callback handler for scanner events.**
   In the ``basic_ble`` project, an event handler is registered using 
   ``BLEAppUtil_registerEventHandler``. The ``centralScanHandler`` structure 
   contains the event mask and callback function to handle GAP scan events. 

   .. code-block:: c
     :caption: **app_central.c :: centralScanHandler** - Scan event handler structure. 

     // Events handlers struct, contains the handlers and event masks
     // of the application central role module
     BLEAppUtil_EventHandler_t centralScanHandler =
     {
         .handlerType    = BLEAPPUTIL_GAP_SCAN_TYPE, // Event handler type
         .pEventHandler  = Central_ScanEventHandler, // Callback to event handler
         .eventMask      = BLEAPPUTIL_SCAN_ENABLED | // Event mask
                           BLEAPPUTIL_SCAN_DISABLED
     };

  This structure determines what events will be passed to the callback handler, 
  ``Central_ScanEventHandler()``. For a full list of GAP scan events, please see 
  ``BLEAppUtil_GAPScanEventMaskFlags_e`` enum located in ``bleapputil_api.h``.
  Before taking a look at the event handler, it must be registered so that the 
  application recieves GAP scan events.

   .. code-block:: c
     :caption: **app_central.c :: Central_start() :: BLEAppUtil_registerEventHandler()** - Register the event handler.

       // Register callback to process Scanner events
       bStatus_t Central_start()
       {
           bStatus_t status = SUCCESS;

           status = BLEAppUtil_registerEventHandler(&centralScanHandler);
           if(status != SUCCESS)
           {
               // Return status value
               return(status);
           }
           // ...
       }

3. **Handling events in the event handler.** The code block below shows the 
   general callback structure to handle events.

   .. code-block:: c
     :caption: **app_central.c :: Central_ScanEventHandler()** - Central scan event handler.

       void Central_ScanEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
       {
           BLEAppUtil_ScanEventData_t *scanMsg = (BLEAppUtil_ScanEventData_t *)pMsgData;

           switch (event)
           {
               case BLEAPPUTIL_SCAN_ENABLED:
               {
                   //...code...
                   break;
               }

               case BLEAPPUTIL_SCAN_DISABLED:
               {
                   //...code...
                   break;
               }

               default:
               {
                   //...more code...
                   break;
               }

           }
       }


4. **Set scan parameters.** It's worth noting that the parameters are split into
   PHY-related parameters (set with :ble_api:`GapScan_setPhyParams`) and
   non-PHY-related parameters (set with :ble_api:`GapScan_setParam`). The 
   ``basic_ble`` example project abstracts these calls through 
   ``BLEAppUtil_scanInit()`` and ``BLEAppUtil_setConnParams()`` with their 
   definitions located in ``bleapputil_init.c``. The ``basic_ble`` example 
   project provides structures to modify the initial scan and PHY parameters.

.. note::
    Make sure the scanning window is at least twice the length of the expected advertising interval to ensure at least 1 advertising event 
    is captured in each scanning window. Otherwise, the scanning device may not find the advertising device.

.. code-block:: c
 :caption: **app_central.c :: centralScanInitParams :: centralConnInitParams** - Set PHY-related GAP scanner parameters.
 :emphasize-lines: 1, 40

   const BLEAppUtil_ScanInit_t centralScanInitParams =
   {
       /*! Opt SCAN_PRIM_PHY_1M | SCAN_PRIM_PHY_CODED */
       .primPhy                    = DEFAULT_SCAN_PHY,

       /*! Opt SCAN_TYPE_ACTIVE | SCAN_TYPE_PASSIVE */
       .scanType                   = DEFAULT_SCAN_TYPE,

       /*! Scan interval shall be greater than or equal to scan window */
       .scanInterval               = DEFAULT_SCAN_INTERVAL, /* Units of 625 us */

       /*! Scan window shall be less than or equal to scan interval */
       .scanWindow                 = DEFAULT_SCAN_WINDOW, /* Units of 625 us */

       /*! Select which fields of an advertising report will be stored */
       /*! in the AdvRptList, For mor field see @ref Gap_scanner.h     */
       .advReportFields            = ADV_RPT_FIELDS,

       /*! Opt SCAN_PRIM_PHY_1M | SCAN_PRIM_PHY_CODED */
       .scanPhys                   = DEFAULT_SCAN_PHY,

       /*! Opt SCAN_FLT_POLICY_ALL | SCAN_FLT_POLICY_AL |   */
       /*! SCAN_FLT_POLICY_ALL_RPA | SCAN_FLT_POLICY_AL_RPA */
       .fltPolicy                  = SCANNER_FILTER_POLICY,

       /*! For more filter PDU @ref Gap_scanner.h */
       .fltPduType                 = SCANNER_FILTER_PDU_TYPE,

       /*! Opt SCAN_FLT_RSSI_ALL | SCAN_FLT_RSSI_NONE */
       .fltMinRssi                 = SCANNER_FILTER_MIN_RSSI,

       /*! Opt SCAN_FLT_DISC_NONE | SCAN_FLT_DISC_GENERAL | SCAN_FLT_DISC_LIMITED
        *  | SCAN_FLT_DISC_ALL | SCAN_FLT_DISC_DISABLE */
       .fltDiscMode                = SCANNER_FILTER_DISC_MODE,

       /*! Opt SCAN_FLT_DUP_ENABLE | SCAN_FLT_DUP_DISABLE | SCAN_FLT_DUP_RESET */
       .fltDup                     = SCANNER_DUPLICATE_FILTER
   };

   const BLEAppUtil_ConnParams_t centralConnInitParams =
   {
        /*! Opt INIT_PHY_ALL | INIT_PHY_1M | INIT_PHY_2M | INIT_PHY_CODED */
       .initPhys              = DEFAULT_INIT_PHY,

       .scanInterval          = INIT_PHYPARAM_SCAN_INT,      /* Units of 0.625ms */
       .scanWindow            = INIT_PHYPARAM_SCAN_WIN,      /* Units of 0.625ms */
       .minConnInterval       = INIT_PHYPARAM_MIN_CONN_INT,  /* Units of 1.25ms  */
       .maxConnInterval       = INIT_PHYPARAM_MAX_CONN_INT,  /* Units of 1.25ms  */
       .connLatency           = INIT_PHYPARAM_CONN_LAT,
       .supTimeout            = INIT_PHYPARAM_SUP_TO         /* Units of 10ms */
   };


These structures are then passed to ``BLEAppUtil_scanInit()`` and 
``BLEAppUtil_setConnParams()`` respectively. These initialization functions may 
be found in ``Central_start()``.

5. **Start Scanning**. ``Menu_scanStartCB()`` callback triggers when selected
   in the ``basic_ble`` menu. This callback calls ``BLEAppUtil_scanStart()``, 
   which starts scanning for advertisement reports and scan responses. 
   ``Menu_scanStartCB()`` contains parameters for the scan period, duration, 
   and the maximum number of advertisement reports.

   .. code-block:: c
    :caption: **app_menu.c :: Menu_scanStartCB()** - Set scan period, duration, and maximum number of reports.
    :emphasize-lines: 4, 7, 11, 15, 18, 19

     void Menu_scanStartCB(uint8 index)
     {
         bStatus_t status;
         const BLEAppUtil_ScanStart_t centralScanStartParams =
         {
             /*! Zero for continuously scanning */
             .scanPeriod     = DEFAULT_SCAN_PERIOD, /* Units of 1.28sec */

             /*! Scan Duration shall be greater than to scan interval,*/
             /*! Zero continuously scanning. */
             .scanDuration   = DEFAULT_SCAN_DURATION, /* Units of 10ms */

             /*! If non-zero, the list of advertising reports will be */
             /*! generated and come with @ref GAP_EVT_SCAN_DISABLED.  */
             .maxNumReport   = APP_MAX_NUM_OF_ADV_REPORTS
         };

         // Will start scanning by calling GapScan_enable.
         status = BLEAppUtil_scanStart(&centralScanStartParams);

         // Print the status of the scan
         MenuModule_printf(APP_MENU_GENERAL_STATUS_LINE, 0, "Call Status: ScanStart = "
                           MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_RED "%d" MENU_MODULE_COLOR_RESET,
                           status);
     }

   ``BLEAppUtil_scanStart()`` calls ``GapScan_enable()`` with the parameters of 
   the ``centralScanStartParams`` structure. 

   .. code-block:: c
    :caption: **bleapputil_init.c :: BLEAppUtil_scanStart()** - Abstraction to :ble_api:`GapScan_Enable`.
    :emphasize-lines: 3 

       bStatus_t BLEAppUtil_scanStart(const BLEAppUtil_ScanStart_t *scanStartInfo)
       {
           return GapScan_enable(scanStartInfo->scanPeriod, scanStartInfo->scanDuration, scanStartInfo->maxNumReport);
       }



   The return status from the protocol stack call of :ble_api:`GapScan_enable`
   indicates only whether or not the attempt to perform device discovery was
   successful. The actual device discovered is returned asynchronously as a
   ``BLEAPPUTIL_ADV_REPORT`` forwarded through the GAP Scanner callbacks
   registered by the application (here: ``Central_ScanEventHandler()``). This is
   described below.

6. The GAP Scanner performs some processing on the GAP events it
   receives from the protocol stack. The task also forwards some events
   to the application. :numref:`cd_gap_dev_disc` shows this and how the
   ``BLEAPPUTIL_ADV_REPORT`` is processed from the protocol stack to the
   application.

   .. _cd_gap_dev_disc:
   .. uml::
       :caption: Context Diagram of Application using GapScan_enable()
       :align: center

       @startuml
       participant Application
       participant "BLE Stack"

       group !scanning && (central or observer)

         Application -> Application : Menu_scanStartCB()
         Application -> Application : BLEAppUtil_scanStart()
         Application -> "BLE Stack" : GapScan_enable()

         rnote over "BLE Stack"
          BLE stack attempts to
          start device discovery
         end note

         "BLE Stack" -> Application : return(status)


       group status==SUCCESS
       rnote over "Application"
       BLEAPPUTIL_SCAN_ENABLED
       indicates scanning has started
       end note
       Application -> Application: Central_ScanEventHandler()
       ...
       ... BLE Stack does device discovery ...
       ...
       "BLE Stack" -> Application: Advertisement or Scan Report

         rnote over "Application"
         BLEAPPUTIL_ADV_REPORT
         end note
         Application -> Application: Central_ScanEventHandler()
         ...
         rnote over "Application"
         BLEAPPUTIL_SCAN_DISABLED
         indicates scanning has ended
         end note
       end

       end

       @enduml

Note that during scanning, individual advertisements and scan responses are
returned as ``BLEAPPUTIL_ADV_REPORT``. This is defined by the |CORESPEC|. By
default, duplicate reports are filtered such that only one event is returned to
the application per peer device BDA. This can be configured via the
:ble_api:`SCAN_PARAM_FLT_DUP` GAP Scanner parameter (You can change scanning 
parameters with :ble_api:`GapScan_setParam` or by modifying the 
``centralScanInitParams`` structure within ``app_central.c``). 

``BLEAPPUTIL_SCAN_ENABLED`` indicates the start of scanning. After the scan
has completed, a summary of discovered reports will be returned to the
application with ``BLEAPPUTIL_SCAN_DISABLED``. You can see the implementation
of this in ``Central_ScanEventHandler()``.

.. code-block:: c
  :emphasize-lines: 7, 15, 27, 29

    void Central_ScanEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
        BLEAppUtil_ScanEventData_t *scanMsg = (BLEAppUtil_ScanEventData_t *)pMsgData;

        switch (event)
        {
            case BLEAPPUTIL_SCAN_ENABLED:
            {
                centralScanIndex = 0;
                MenuModule_printf(APP_MENU_SCAN_EVENT, 0, "Scan status: Scan started...");

                break;
            }

            case BLEAPPUTIL_SCAN_DISABLED:
            {
                uint8 i;

                for(int i = 0; i < APP_MAX_NUM_OF_ADV_REPORTS; i++)
                {
                    memset(&centralScanRes[i], 0, sizeof(App_scanResults));
                }

                // Go over the advertise reports that was saved in the host level and save it
                for (i = 0; i < scanMsg->pBuf->pScanDis.numReport; i++)
                {
                  GapScan_Evt_AdvRpt_t advReport;
                  // Get the address from the report
                  GapScan_getAdvReport(i, &advReport);
                  // Add the report to the scan list
                  Central_addScanRes(&advReport);
                }

                MenuModule_printf(APP_MENU_SCAN_EVENT, 0, "Scan status: Scan disabled - "
                                  "Reason: " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET
                                  "Num results: " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                                  scanMsg->pBuf->pScanDis.reason,
                                  scanMsg->pBuf->pScanDis.numReport);
                break;
            }

            default:
            {
                break;
            }

        }
    }


The maximum amount of scan responses that can be discovered during one scan can
be set with the ``DEFAULT_MAX_SCAN_RES`` parameter that is passed into the 
``maxNumReport`` parameter of :ble_api:`GapScan_enable`.

In an environment saturated with advertisements and scan responses, this can have
a drastic impact on heap usage to the point of potentially breaking the stack.
Therefore, it is essential to profile your application for the worst-case
scenario where the maximum amount of scan responses are discovered during a scan.

Note that some scanning parameters will not be updated before scanning has been 
disabled and re-enabled. This is true for the following parameters:

  - :ble_api:`SCAN_PARAM_FLT_PDU_TYPE` - Filter by PDU Type
  - :ble_api:`SCAN_PARAM_FLT_MIN_RSSI` - Filter by Minimum RSSI
  - :ble_api:`SCAN_PARAM_FLT_DISC_MODE` - Filter by Discoverable Mode
  - :ble_api:`SCAN_PARAM_RPT_FIELDS` - Advertising Report Fields

Advertising Report Recording
****************************
The Advertising Report Recording feature allows a developer to specify what 
information is received and recorded in an Advertisement Report. This is useful 
in the use case where the application does not require the payload of the 
Advertising Report, but requires specific information such as address type, 
address, RSSI, etc. while eleminating the ``BLEAPPUTIL_ADV_REPORT`` event from 
GAP Scanner. 

To prepare recording, GAP Scanner allocates necessary amount of memory when 
calling ``GapScan_enable()``. Whenever a new packet arrives, GAP 
Scanner puts the specified fields of the information in the Advertising Report
List in packed form. The list resides in RAM after the scanning ends until the 
application calls ``GapScan_discardAdvReportList()`` or a new scanning session 
starts. While the list is available, the application may retrieve the
information by using ``GapScan_getAdvReport()``. When the list fills, 
GAP Scanner issues ``BLEAPPUTIL_ADV_REPORT_FULL`` notifying the application 
that no more Advertising Reports will be recorded. The application may specify 
which fields of the Advertising Report information by using ``GapScan_setParam()`` 
with the parameter ID ``SCAN_PARAM_RPT_FIELDS`` and the associated bitmap.

The number of an Advertising Report's information recorded may be found in the 
``numReport`` field of the data buffer of type ``GapScan_Evt_End_t``, coming 
with ``BLEAPPUTIL_SCAN_DISABLED`` event. Alternatively, if the application 
didn't mask ``BLEAPPUTIL_SCAN_DISABLED``, ``GapScan_getParam()`` with 
parameter ID SCAN_PARAM_NUM_ADV_RPT may be used.


.. _gap_scanner_filtering:

.. _gap_advertising_channel:

Obtain Advertising Channel from Advertising Report
**************************************************

The application can extract the advertising channel from the advertising report with the following modifications:

#. Enable the advertising channel in the advertising report:

   * With SysConfig: Enable the setting ``Add Advertisement Channel Number`` inside ``Observer Configuration``, see :ref:`fig-observer-configurations`
   * Without SysConfig: Add ``-DADV_RPT_INC_CHANNEL=1`` in the file ``ti_ble_app_config.opt``

#. Use the following example code in ``SimpleCentral_processAppMsg()`` to access the channel information

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processAppMsg() :: SC_EVT_ADV_REPORT** - Extract the advertising channel
     :emphasize-lines: 4

        case SC_EVT_ADV_REPORT:
        {
          GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pMsg->pData);
          volatile uint8_t advChannel = pAdvRpt->secPhy >> 2;

          //...

Filtering
*********

The GAP Scanner module provides 5 different types of filter to reduce the amount of advertising
report notifications to the application and eventually save memory and power consumption.
The result of the filtering affects both advertising reports and advertising report recording.
The packets filtered out by the filter configurations are discarded and will
neither be reported nor recorded. The filters are set by using the API
:ble_api:`GapScan_setParam` with the following parameter IDs:

- :ref:`cd_gap_filter_policy`: :ble_api:`SCAN_PARAM_FLT_POLICY`
- :ref:`cd_gap_filter_type`: :ble_api:`SCAN_PARAM_FLT_PDU_TYPE`
- :ref:`cd_gap_filter_rssi`: :ble_api:`SCAN_PARAM_FLT_MIN_RSSI`
- :ref:`cd_gap_filter_discoverable`: :ble_api:`SCAN_PARAM_FLT_DISC_MODE`
- :ref:`cd_gap_filter_duplicates`: :ble_api:`SCAN_PARAM_FLT_DUP`.

All parameter IDs are described in the following sections. The GAP Scanner
allows the application to apply any combination of the individual filters at the
same time to narrow the scope of packets to receive.

.. _cd_gap_filter_policy:

Filter by LL Filter Policy
##########################

This filter is a link layer-level filter. The associated parameter ID used in
:ble_api:`GapScan_setParam` is :ble_api:`SCAN_PARAM_FLT_POLICY`. The parameter
accompanying :ble_api:`SCAN_PARAM_FLT_POLICY` is passed to the link layer when
:ble_api:`GapScan_enable` is called before actually enabling scanning. Since the filtering
is done by the link layer, the application only receives advertising report events
that have passed the filter. The parameter value can be one of the following:

+-------------------------------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Name                          | Value   | Description                                                                                                                                                                    |
+===============================+=========+================================================================================================================================================================================+
| SCAN\_FLT\_POLICY\_ALL        | 0       | Accept all Advs except directed Adv not addressed to this device.                                                                                                              |
+-------------------------------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SCAN\_FLT\_POLICY\_WL         | 1       | Accept only Advs from devices where the advertiser’s address is in the FIlter Accept List.                                                                                     |
+-------------------------------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SCAN\_FLT\_POLICY\_ALL\_RPA   | 2       | Accept all Advs except directed Adv not addressed to this device and any packet addressed to this device or addressed to a private resolvable address.                         |
+-------------------------------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SCAN\_FLT\_POLICY\_WL\_RPA    | 3       | Accept only Advs from devices where the advertiser’s address is in the FIlter Accept List and any packet addressed to this device or addressed to a private resolvable address.|
+-------------------------------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

.. _cd_gap_filter_type:

Filter by PDU Type
##################

This filter is based on the ``Event_Type`` parameter coming with the LE Extended
Advertising Report Event. The associated parameter ID is
``SCAN_PARAM_FLT_PDY_TYPE``. The parameter value specifies packets
classified in six categories:

- Connectable/Non-Connectable
- Scannable/Non-Scannable
- Directed/Undirected
- ScanRsp/Adv
- Legacy/Extended
- Complete/Incomplete.

Every incoming packet has exactly one attribute in each category. For example,
:ble_api:`SCAN_FLT_PDU_NONSCANNABLE_ONLY` and
:ble_api:`SCAN_FLT_PDU_SCANNABLE_ONLY` cannot be chosen together since they
represent scannable and non-scannable packets. Only either one can be used. If
neither type is selected in a set, the filter will not care about that category.
For example, if neither :ble_api:`SCAN_FLT_PDU_NONCONNECTABLE_ONLY` nor
:ble_api:`SCAN_FLT_PDU_CONNECTABLE_ONLY` is set in the parameter value, the GAP
Scanner will notify the application of both connectable packets and
non-connectable packets. It will also record both connectable packets and
non-connectable packets. The ``SCAN_PARAM_FLT_PDY_TYPE`` parameter value
can be any combination of the following individual values (except individual
values that are mutually exclusive):

+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| Name                                   | Value    | Description                                                                               |
+========================================+==========+===========================================================================================+
| SCAN\_FLT\_PDU\_NONCONNECTABLE\_ONLY   | 0x0001   | Non-connectable packets only. Mutually exclusive with SCAN\_FLT\_PDU\_CONNECTABLE\_ONLY   |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_CONNECTABLE\_ONLY      | 0x0002   | Connectable packets only. Mutually exclusive with SCAN\_FLT\_PDU\_NONCONNECTABLE\_ONLY    |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_NONSCANNABLE\_ONLY     | 0x0004   | Non-scannable packets only. Mutually exclusive with SCAN\_FLT\_PDU\_SCANNABLE\_ONLY       |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_SCANNABLE\_ONLY        | 0x0008   | Scannable packets only. Mutually exclusive with SCAN\_FLT\_PDU\_NONSCANNABLE\_ONLY        |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_UNDIRECTED\_ONLY       | 0x0010   | Undirected packets only. Mutually exclusive with SCAN\_FLT\_PDU\_DIRECTIED\_ONLY          |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_DIRECTED\_ONLY         | 0x0020   | Directed packets only. Mutually exclusive with SCAN\_FLT\_PDU\_UNDIRECTED\_ONLY           |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_ADV\_ONLY              | 0x0040   | Advertisement packets only. Mutually exclusive with SCAN\_FLT\_PDU\_SCANRSP\_ONLY         |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_SCANRSP\_ONLY          | 0x0080   | Scan Response packets only. Mutually exclusive with SCAN\_FLT\_PDU\_ADV\_ONLY             |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_EXTENDED\_ONLY         | 0x0100   | Extended packets only. Mutually exclusive with SCAN\_FLT\_PDU\_LEGACY\_ONLY               |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_LEGACY\_ONLY           | 0x0200   | Legacy packets only. Mutually exclusive with SCAN\_FLT\_PDU\_EXTENDED\_ONLY               |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_TRUNCATED\_ONLY        | 0x0400   | Truncated packets only. Mutually exclusive with SCAN\_FLT\_PDU\_COMPLETE\_ONLY            |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+
| SCAN\_FLT\_PDU\_COMPLETE\_ONLY         | 0x0800   | Complete packets only. Mutually exclusive with SCAN\_FLT\_PDU\_TRUNCATED\_ONLY            |
+----------------------------------------+----------+-------------------------------------------------------------------------------------------+

.. _cd_gap_filter_rssi:

Filter by Minimum RSSI
######################

This filter is based on the RSSI parameter coming with the LE Extended
Advertising Report Event. The associated parameter ID used in
:ble_api:`GapScan_setParam` is :ble_api:`SCAN_PARAM_FLT_MIN_RSSI`. The GAP
Scanner will discard LE Extended Advertising Report Event whose RSSI parameter
value is smaller than the minimum RSSI value given by the application. The
available range is -128 dBm to 127 dBm.

.. _cd_gap_filter_discoverable:

Filter by Discoverable Mode
###########################

This filter is based on the ``Flags AD`` type value in the payload (in
the ``Data`` parameter) of the LE Extended Advertising Report Event. The
associated parameter ID used in :ble_api:`GapScan_setParam` is
:ble_api:`SCAN_PARAM_FLT_DISC_MODE`. This filter is applied after the GAP
Scanner reassembles all the fragmented payloads delivered by multiple LE
Extended Advertising Report Events. The GAP Scanner will discard the
defragmented packet if the found Flags AD type value doesn't match the parameter
value given by the application. The parameter value can be one of the following:

+----------------------------+---------+---------------------------------------------------------------------------+
| Name                       | Value   | Description                                                               |
+============================+=========+===========================================================================+
| SCAN\_FLT\_DISC\_NONE      | 0       | Accept only Non-Discoverable mode                                         |
+----------------------------+---------+---------------------------------------------------------------------------+
| SCAN\_FLT\_DISC\_GENERAL   | 1       | Accept only General Discoverable mode                                     |
+----------------------------+---------+---------------------------------------------------------------------------+
| SCAN\_FLT\_DISC\_LIMITED   | 2       | Accept only Limited Discoverable mode                                     |
+----------------------------+---------+---------------------------------------------------------------------------+
| SCAN\_FLT\_DISC\_ALL       | 3       | Accept both General and Limited Discoverable mode                         |
+----------------------------+---------+---------------------------------------------------------------------------+
| SCAN\_FLT\_DISC\_DISABLE   | 4       | Discoverable Mode Filter Off (Don’t care about the Flags AD type value)   |
+----------------------------+---------+---------------------------------------------------------------------------+

.. _cd_gap_filter_duplicates:

Filter by Duplicates
####################

Like the Link Layer Scanner Filter Policy, this filter is a link layer-level filter.
The associated parameter ID used in :ble_api:`GapScan_setParam` is
:ble_api:`SCAN_PARAM_FLT_DUP`. The parameter accompanying the
:ble_api:`SCAN_PARAM_FLT_DUP` parameter ID is passed to the link layer when
:ble_api:`GapScan_enable` internally calls ``LE_SetExtScanEnable`` to
enable scanning. Since the filtering is done by the link layer, GAP Scanner
receives only the LE Extended Advertising Report Events that have passed the
filter. The parameter value can be one of the following:

+---------------------------+---------+-----------------------------------------------------------+
| Name                      | Value   | Description                                               |
+===========================+=========+===========================================================+
| SCAN\_FLT\_DUP\_DISABLE   | 0       | Disable duplicate filtering.                              |
+---------------------------+---------+-----------------------------------------------------------+
| SCAN\_FLT\_DUP\_ENABLE    | 1       | Enable duplicate filtering.                               |
+---------------------------+---------+-----------------------------------------------------------+
| SCAN\_FLT\_DUP\_RESET     | 2       | Enable duplicate filtering. Reset for each scan period.   |
+---------------------------+---------+-----------------------------------------------------------+

.. warning:: When the duplicate filtering is enabled, the maximum amount of devices that can
   be found is 16. If more than 16 devices need to be discovered, the duplicate filtering needs to
   be disabled.

Synchronize with a Periodic Advertising Train
*********************************************

.. warning::
    This functionality is not yet implemented in the stack.

.. Keep this commented until we have support in the CC23xx stack
  .. important::
      The symbol ``USE_PERIODIC_SCAN`` must be pre-defined if you
      wish to use the functions related to scanning and synchronization with
      periodic advertising (for more details, please see 
      :ref:`stackconfigurablefeatures`).

  Additional information about periodic advertisements is provided within the section
  :ref:`gap_periodic_advertising`.

  From a high level point of view, in order to synchronize with a periodic advertiser,
  the scanner has to:

  #. Start a Central or Observer GAP role
  #. Set up a callback function for scanner events and register to
  #. Set which events to pass to application.
  #. Set scan parameters
  #. Start scanning
  #. Identify periodic advertisers
  #. Synchronize with a periodic advertising train
  #. Enable the reception of the periodic advertisements
  #. Handle the periodic advertisements reports
  #. Disable the reception of the periodic advertisements and terminate the   synchronization

  The first steps are detailed at the beginning of the :ref:`gapscanner` section.

  Identify periodic advertisers
  #############################

  The advertising reports for
  periodic advertisements have the exact same structure and the exact same way
  of reception like other advertisement types. 
  The actual device discovered is returned asynchronously as a
  ``SC_EVT_ADV_REPORT`` forwarded through the GAP Scanner callbacks
  registered by the application (here: ``SimpleCentral_scanCb()``).

  Periodic advertisements are non-connectable, non-scannable. By default, the
  ``simple_central`` project example filters out non-connectable
  advertisements. Make sure to change this PDU filtering policy.

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processGapMsg() ::   GAP_DEVICE_INIT_DONE_EVENT** - Disable filtering out of non-connectable   advertisements / keep only non-connectable advertisements

        uint16_t temp16;

        // ...

        //temp16 = SCAN_FLT_PDU_CONNECTABLE_ONLY | SCAN_FLT_PDU_COMPLETE_ONLY;
        temp16 = SCAN_FLT_PDU_NONCONNECTABLE_ONLY;

        GapScan_setParam(SCAN_PARAM_FLT_PDU_TYPE, &temp16);

  The parameter ``periodicAdvInt`` from the structure :ble_api:`GapScan_Evt_AdvRpt_t`
  will help to assess it is possible to synchronize with the advertiser.
  It means this field of the advertise report has to be activated.
  The same apply to the field ``advSid`` (Advertise Set Id).

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processAppMsg() ::   SC_EVT_ADV_REPORT** - Assess if the advertisement is a periodic advertisement

        GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pMsg->pData);

        if(0 != pAdvRpt->periodicAdvInt)
        {
            // this is a periodic advertisement
        }
        else
        {
            // this is NOT a periodic advertisement
        }

  Synchronize with a periodic advertising train
  #############################################

  When a periodic advertisement is identified, the synchronization can be started.

  .. note::
      The |CORESPEC| (Vol 6, Part B, §4.3.5) define two ways for the scanner's Link
      Layer to process advertising PDUs when attempting to synchronize to a
      periodic advertising train.
      The first policy which requires specifying the device to synchronize with.
      The second policy allows to synchronize with all the devices in the
      Periodic Advertiser List with only one scan. This is then a way to save
      time and energy.

  - **Policy 1: Ignore the Periodic Advertiser List and process advertising PDUs from   a specific single device**

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processAppMsg() ::   SC_EVT_ADV_REPORT** - Create synchronization with a periodic advertsiement train

        GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pMsg->pData);

        if(0 != pAdvRpt->periodicAdvInt)
        {
            // this is a periodic advertisement
            GapScan_PeriodicAdvCreateSyncParams_t pSyncParams;

            pSyncParams.options = SCAN_PERIODIC_DO_NOT_USE_PERIODIC_ADV_LIST |
                                  SCAN_PERIODIC_REPORTING_INITIALLY_DISABLED;
            pSyncParams.advAddrType = (uint8)pAdvRpt->addrType; // only   ADDRTYPE_PUBLIC and ADDRTYPE_RANDOM are allowed
            osal_memcpy(pSyncParams.advAddress, pAdvRpt->addr, B_ADDR_LEN);
            pSyncParams.skip = 0; // should be between 0 and SCAN_PERIODIC_SKIP_MAX 
            pSyncParams.syncTimeout = 1000; // synchronization timeout for the  periodic advertising train is 1000*10ms = 10s
                                            // should be between  SCAN_PERIODIC_TIMEOUT_MIN and  SCAN_PERIODIC_TIMEOUT_MAX
            pSyncParams.syncCteType = SCAN_PERIODIC_CTE_TYPE_ALL;

            uint8_t status = GapScan_PeriodicAdvCreateSync(pAdvRpt->advSid,   &pSyncParams);
            if(SUCCESS != status){
              // handle error
            }

            GapScan_disable("");

            break;
        }
        else
        {
            // this is NOT a periodic advertisement
        }

  - **Policy 2: process advertising PDUs from all devices in the Periodic Advertiser  List.**

    This policy first requires to add one or several device(s) to the
    Periodic Advertiser List. This can be done using the function
    :ble_api:`GapScan_AddDeviceToPeriodicAdvList`

     .. code-block:: c
       :caption: **simple_central.c :: SimpleCentral_processAppMsg() ::   SC_EVT_ADV_REPORT** - Create synchronization with a periodic advertsiement  train using the Periodic Advertiser List

        GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pMsg->pData);

        if(0 != pAdvRpt->periodicAdvInt)
        {
            // this is a periodic advertisement

            // add the device to the Periodic Advertiser List
            GapScan_AddDeviceToPeriodicAdvList((uint8)pAdvRpt->addrType,
                                               pAdvRpt->addr,
                                               pAdvRpt->advSid);

            // connect the devices on the Periodic Advertiser List.
            GapScan_PeriodicAdvCreateSyncParams_t pSyncParams;

            pSyncParams.options = SCAN_PERIODIC_USE_PERIODIC_ADV_LIST |
                                  SCAN_PERIODIC_REPORTING_INITIALLY_DISABLED;
            pSyncParams.skip = 0; // should be between 0 and SCAN_PERIODIC_SKIP_MAX 
            pSyncParams.syncTimeout = 1000; // synchronization timeout for the  periodic advertising train is 1000*10ms = 10s
                                            // should be between  SCAN_PERIODIC_TIMEOUT_MIN and  SCAN_PERIODIC_TIMEOUT_MAX
            pSyncParams.syncCteType = SCAN_PERIODIC_CTE_TYPE_ALL;

            uint8_t status = GapScan_PeriodicAdvCreateSync(0, &pSyncParams);
            if(SUCCESS != status){
              // handle error
            }

            GapScan_disable("");

            break;
        }

    The functions :ble_api:`GapScan_RemoveDeviceFromPeriodicAdvList`
    and :ble_api:`GapScan_ClearPeriodicAdvList` can be used to remove
    device(s) from the Periodic Advertiser List.

  Once the synchronization is created, a :ble_api:`GAP_SCAN_CREATE_SYNC_EVENT`
  event with status ``SUCCESS`` is issued. After this, scanning has to be
  enabled in order to let the device find the periodic advertisement train
  that has been specified before.

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processGapMsg() ::   GAP_SCAN_CREATE_SYNC_EVENT** - Re-enable scanning after receiving   GAP_SCAN_CREATE_SYNC_EVENT event to establish the synchronization 

        {
          GapScan_PeriodicAdvEvt_t *pPkt = (GapScan_PeriodicAdvEvt_t *)pMsg;
          uint8_t status;

          if(pPkt->status == SUCCESS)
          {
            status = GapScan_enable(0, DEFAULT_SCAN_DURATION, 0);
            if(SUCCESS != status){
              // handle error
            }
          }

          break;
        }

  Enable the reception of the periodic advertisements
  ###################################################

    After the synchronization is established, the event ``GAP_SCAN_PERIODIC_ADV_SYNC_EST_EVENT``
    is issued. If not already done, the reception of the periodic advertisements  reports
    has to be turned on.

     .. code-block:: c
       :caption: **simple_central.c :: SimpleCentral_processGapMsg() ::   GAP_SCAN_CREATE_SYNC_EVENT** - Re-enable scanning after receiving   GAP_SCAN_CREATE_SYNC_EVENT event to establish the synchronization 

          {
            GapScan_Evt_PeriodicAdvSyncEst_t *pPkt = (  GapScan_Evt_PeriodicAdvSyncEst_t *)pMsg;
            uint8_t status;

            if(pPkt->status == SUCCESS)
            {
              status = GapScan_SetPeriodicAdvReceiveEnable(pPkt->syncHandle, 0x01);
              if(SUCCESS != status){
                // handle error
              }
            }

            break;
          }

  Handle the periodic advertisements reports
  ##########################################

  After enabling the reception of the periodic advertisements,
  the reception of a periodic advertisement leads to the generation of a
  ``GAP_SCAN_PERIODIC_ADV_REPORT_EVENT`` event.

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processGapMsg() ::   GAP_SCAN_PERIODIC_ADV_REPORT_EVENT** - Reception of the periodic advertisement  reports

        {
          GapScan_Evt_PeriodicAdvRpt_t *pPkt = (GapScan_Evt_PeriodicAdvRpt_t *)pMsg;

          // Handle periodic advertisement report
          // ...

          // Free report payload data
          if (pPkt->pData != NULL)
          {
            ICall_free(pPkt->pData);
          }

          break;
        }

  Disable the reception of the periodic advertisements and terminate the  synchronization
  #######################################################################################

  The periodic advertisement reports can be disabled using the function 
  :ble_api:`GapScan_SetPeriodicAdvReceiveEnable`.

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processGapMsg() ::   GAP_SCAN_PERIODIC_ADV_REPORT_EVENT** - Disable the reception of periodic  advertisement reports

        {
          GapScan_Evt_PeriodicAdvRpt_t *pPkt = (GapScan_Evt_PeriodicAdvRpt_t *)pMsg;
          uint8_t status;

          status = GapScan_SetPeriodicAdvReceiveEnable(pPkt->syncHandle, 0x00);
          if(SUCCESS != status){
              // handle error
          }

          break;
        }

  Disabling the periodic advertisement reports does NOT interrupt the synchronization.
  In other words, the device will still wake-up and scan at each periodic   advertisement.
  The function :ble_api:`GapScan_PeriodicAdvTerminateSync` is used to terminate
  the synchronization.

   .. code-block:: c
     :caption: **simple_central.c :: SimpleCentral_processGapMsg() ::   GAP_SCAN_PERIODIC_ADV_REPORT_EVENT** - Disable the reception of periodic  advertisement reports

        {
          GapScan_Evt_PeriodicAdvRpt_t *pPkt = (GapScan_Evt_PeriodicAdvRpt_t *)pMsg;
          uint8_t status;

          status = GapScan_PeriodicAdvTerminateSync(pPkt->syncHandle);
          if(SUCCESS != status){
            // handle error
          }

          break;
        }

  The event :ble_api:`GAP_SCAN_TERMINATE_SYNC_EVENT` will be received once the
  synchronization is terminated.

.. _gapinitiator:

GAP Initiator
^^^^^^^^^^^^^

The initiator module is used to initiate the connection to a peripheral device.
An initiator generally scans for advertisements then connects to a specific
device. The initiator is a short lived state that transitions to the Central
Role after a connection is established. Unlike the GAP Advertiser and GAP
Scanner modules, GAP Initiator doesn't have any callback function to call or to
be called. Only a device initiated with the GAP Central Role can become an
initiator.

In the ``basic_ble`` example, developers choose the device role in
``Sysconfig``. This is covered in :ref:`creating_custom_ble_app`. Like all other
BLE roles, after the stack is initialized, handlers are registered in the role's
respective start function.

.. code-block:: c
    :caption: **app_central.c :: Central_Start()** Setup of Central Role
    :linenos:

    bStatus_t Central_start()
    {
        bStatus_t status = SUCCESS;
    
        status = BLEAppUtil_registerEventHandler(&centralScanHandler);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_scanInit(&centralScanInitParams);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_setConnParams(&centralConnInitParams);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        // Return status value
        return(status);
    }


Initiiating connections is handled through the application menu, located in
``app_menu.c``. 

.. code-block:: c
    :caption: **app_menu.c :: Menu_connectToDeviceCB** - Initiating connection in Central Role
    :linenos:
    :emphasize-lines: 19, 10, 11, 12, 13, 14, 15

    void Menu_connectToDeviceCB(uint8 index)
    {
        bStatus_t status;
    
        // Get the scan results list
        App_scanResults *menuScanRes;
        uint8 size = Scan_getScanResList(&menuScanRes);
    
        // Set the connection parameters
        BLEAppUtil_ConnectParams_t connParams =
        {
         .peerAddrType = menuScanRes[index].addressType,
         .phys = INIT_PHY_1M,
         .timeout = 1000
        };
    
        // Copy the selected address
        memcpy(connParams.pPeerAddress, menuScanRes[index].address, B_ADDR_LEN);
        status = BLEAppUtil_connect(&connParams);
    
        // Print the status of the connect call
        MenuModule_printf(APP_MENU_GENERAL_STATUS_LINE, 0, "Call Status: Connect = "
                          MENU_MODULE_COLOR_BOLD MENU_MODULE_COLOR_RED "%d" MENU_MODULE_COLOR_RESET,
                          status);
    
        // Go back to the last menu
        MenuModule_goBack();
    }

Note that the call to ``BLEAppUtil_connect()`` serves as a wrapper to the GAP
API that connects to the address and parameters specified in the
``BLEAppUtil_ConnectParams_t`` structure. Taking a closer look at the
``BLEAppUtil_connect()`` function will reveal the GAP API ``GapInit_connect()``.

.. code-block:: c
    :caption: **bleapputil_init.c :: BLEAppUtil_connect()** - Initiating connection in Central Role
    :linenos:
    :emphasize-lines: 3 

     bStatus_t BLEAppUtil_connect(BLEAppUtil_ConnectParams_t *connParams)
     {
         return GapInit_connect(connParams->peerAddrType, connParams->pPeerAddress,
                                connParams->phys, connParams->timeout);
     }


If the on-going connection attempt is intended to be canceled by either timeout
or a user request (the application calling :ble_api:`GapInit_cancelConnect` or
``BLEAppUtil_cancelConnect()``), the stack notifies the application of the
cancellation completion with a :ble_api:`BLEAPPUTIL_CONNECTING_CANCELLED_EVENT`.

.. attention::
   When initiating timeout is set to 0 (wait indefinitely), the |DEVICE| will
   stay in initiator role until a connection is successfully established.
   If the peripheral device disappeared from the network before the connection
   is established, the only method for initiator to exit this state is 
   to call :ble_api:`GapInit_cancelConnect` or ``BLEAppUtil_cancelConnect()``.

GAP Central
^^^^^^^^^^^

The GAP Central role is demonstrated in ``app_central.c``. The Central
role demonstrates the use of the scanning and initiating states and supports
connections to peripheral devices. The steps to use this module are as follows.

For configuration of the Bluetooth Low Energy stack
features, see :ref:`creating_custom_ble_app` and
:ref:`stack_features_configuration`.

#. After the stack is initialized, the ``Central_start()`` function initializes
all the handlers necessary to implement the Central role.

   .. code-block:: c

    bStatus_t Central_start()
    {
        bStatus_t status = SUCCESS;
    
        status = BLEAppUtil_registerEventHandler(&centralScanHandler);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_scanInit(&centralScanInitParams);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        status = BLEAppUtil_setConnParams(&centralConnInitParams);
        if(status != SUCCESS)
        {
            // Return status value
            return(status);
        }
    
        // Return status value
        return(status);
    }

.. _connection_parameters:

GAP Connection State
^^^^^^^^^^^^^^^^^^^^

A BLE device can be either in the Central or Peripheral role in
the Connection State. After devices enter connection state,
the devices exchange data under specific time within a specific time slot. 
This slot where the data is exchanged is called a **Connection Event**.

The beginning of the Connection Event is called an **Anchor Point**. 
During the connection event, the central and peripheral device will meet at 
the anchor point and the central will transmit the first packet, while the 
peripheral will have woken up to listen for the central devices transmitted packet.

.. ditaa::
   :--no-separation:
   :--no-shadows:

             Anchor Point     
                   |
                   |
                   v  
                   +-----+ +-----+                        +-----+ +-----+             
                   | TX  | | RX  |       IDLE             | TX  | | RX  |            
      Central      | cGRE| | cAAA|                        | cGRE| | cAAA| 
                   +-----+-+-----+------------------------+-----+-+-----+
                   <------------->
                     Connection
                       Event
                   <-------------------------------------->
                            Connection Interval

                   +-----+ +-----+                        +-----+ +-----+                   
                   | RX  | | TX  |       IDLE             | RX  | | TX  |
      Peripheral   | cAAA| | cGRE|                        | cAAA| | cGRE|
                   +-----+-+-----+------------------------+-----+-+-----+       

.. note:: 
    There is no limitation on the number of packet transactions per connection
    event other than MAX_NUM_PDU define in TI's |STACK|. It can either be one packet 
    per direction or multiple packets per direction.

.. _connection_event_callback:

Connection Event Callback
*************************

Knowing what happened during the connection event can be beneficial for
the system design. For example, by knowing which channels has higher CRC error,
the application layer can decide to do a channelmap update to avoid those channels
to ensure better communication. 

In addition to CRC error, the connection report
also contains RSSI value per channel, which can be useful for Real Time Localization System
(RTLS) to distinguish which channel has higher interference.

TI's |STACK| provides the ability for application to obtain a detailed report of the
connection event. The report will be sent at the end of the connection event and 
it contains status and statistics of the most recent connection event.

The report contains the following parameters:

- **status** - Status of the last connection event.

    +-----------------------------+--------------------------------------------------------------------+
    |     **status**              |     **Description**                                                |
    +=============================+====================================================================+
    | GAP_CONN_EVT_STAT_SUCCESS   | Both central and peripheral show up for the conenction event and   |
    |                             | exchange packets.                                                  |
    +-----------------------------+--------------------------------------------------------------------+
    | GAP_CONN_EVT_STAT_CRC_ERROR | Packets were exchanged but the failed at the CRC checkout.         |
    +-----------------------------+--------------------------------------------------------------------+
    | GAP_CONN_EVT_STAT_MISSED    | The peer device did not show up for the connection event.          |
    +-----------------------------+--------------------------------------------------------------------+

- **handle** - Connection event handle which is used to identify the most recent connection 
  event when there are multilple connections per device.
- **channel** - The RF channel which the most recent connection event used.   
- **phy** - The PHY which the most recent connection event used.
- **lastRssi** - The RSSI value measured on the last packet of the most recent connection event.
- **packets** - Number of packets received during the most recent connection event.
- **errors** - Accumulated number of packets with CRC error for this connection handle.  
- **nextTaskType** - The next task the link layer is going to run.
- **nextTaskTime** - The time to next task.
- **eventCounter** - The event counter of the most recent connection event.
- **timeStamp** - The anchor point of the most recent connection event.
- **eventType** - There are 3 types of events returning from |STACK|.

    +-------------------------+--------------------------------------------------------------------+
    |     **eventType**       |     **Description**                                                |
    +=========================+====================================================================+
    | GAP_CB_CONN_ESTABLISHED | This event is returned when connection is established. When this   |
    |                         | returns, the eventCount will be 0.                                 |
    +-------------------------+--------------------------------------------------------------------+
    |   GAP_CB_PHY_UPDATE     | This event is returned when last connection event received         |
    |                         | LL_PHY_UPDATE_IND packet.                                          |
    +-------------------------+--------------------------------------------------------------------+
    |  GAP_CB_CONN_EVENT_ALL  | This event covers the above and rest of the scenarios.             |
    +-------------------------+--------------------------------------------------------------------+

To enable the application layer to receive connection report, you can use
``BLEAppUtil_registerConnNotifHandler()`` located in ``bleapputil_init.c``.

The following code is an example of how to register connection event report 
for all types of event within certain connection. 

.. code-block:: c
    :caption: Register for connection event report
    :linenos:

    // Assuming connHandle was assigned when the connection established.
    uint16_t connHandle;

    BLEAppUtil_registerConnNotifHandler(connHandle);

``BLEAppUtil_registerConnNotifHandler()`` serves as a wrapper for
``Gap_registerConnEventCb()`` and defaults to all events. For finer control, 
a developer can call ``Gap_registerConnEventCb()`` directly with the bit mask
desired or modify the function call directly within
``BLEAppUtil_registerConnNotifHandler()``.

The available bit masks may be found in ``gap.h``.

.. code-block:: c
    :caption: Available Connection Event bit masks 
    :linenos:

    /**
     * Connection Event type to register
     */
    typedef enum
    {
      GAP_CB_EVENT_INVALID                   = 0x00,   //!< Invalid event type
      GAP_CB_CONN_ESTABLISHED                = 0x01,   //!< Connection established, procedure 0
      GAP_CB_PHY_UPDATE                      = 0x02,   //!< PHY was updated, procedure 1
      GAP_CB_CONN_EVENT_ALL                  = 0xFF    //!< All connection Events
    } GAP_CB_Event_e;

.. code-block:: c
    :caption: Register for connection event report directly 
    :linenos:

    bStatus_t BLEAppUtil_registerConnNotifHandler(uint16_t connHandle)
    {
        return Gap_RegisterConnEventCb(BLEAppUtil_connEventCB, GAP_CB_REGISTER, GAP_CB_CONN_EVENT_ALL, connHandle);
    }

Whenever a connection event is received, ``BLEAPPUTIL_EVT_CONN_EVENT_CB`` will
queued to the application.

Connection Parameters
*********************

This section describes the connection parameters which are sent by
the initiating device with the connection request and can be
modified by either device when the connection is established. These
parameters are as follows:

-  **Connection Interval** - In Bluetooth Low Energy connections, a
   frequency-hopping scheme is used. The two devices each send and
   receive data from one another only on a specific channel at a
   specific time. These devices meet a specific amount of time later
   at a new channel (the link layer of the Bluetooth Low Energy
   protocol stack handles the channel switching). This meeting
   where the two devices send and receive data is known as a
   ``connection event``. If there is no application data to be sent or
   received, the two devices exchange link layer data with empty 
   application payload to maintain the connection. 
   The connection interval is the amount of time
   between two connection events in units of 1.25 ms. The connection
   interval can range from a minimum value of 6 (7.5 ms) to a
   maximum of 3200 (4.0 s). See :ref:`gap_connection_event` for more details.

.. _gap_connection_event:
.. figure:: resources/image73.jpeg
    :align: center

    Connection Event and Interval

Different applications may require different connection intervals.
As described in :ref:`connection_parameter_considerations`, these requirements
affect the power consumption of the device. For more detailed information on
power consumption, see the `Measuring Bluetooth Smart Power Consumption Application Report (SWRA478) <http://www.ti.com/lit/pdf/swra478>`_.

-  **Peripheral Latency** - Formerly known as 'Slave Latency'.
   This parameter gives the Peripheral 
   device the option of skipping a number of connection events. This
   ability gives the peripheral device some flexibility. If the
   peripheral does not have any data to send, it can skip connection
   events, stay asleep, and save power. The peripheral device
   selects whether to wake or not on a per connection event basis.
   The peripheral can skip connection events but must not skip more
   than allowed by the Peripheral latency parameter or the connection
   fails. See picture below for more details.

.. ditaa::
   :--no-separation:
   :--no-shadows:

     Peripheral Latency 0

       +----+ +----+          +----+ +----+          +----+ +----+          +----+ +----+          +----+ +----+            
       | C  | | P  |          | C  | | P  |          | C  | | P  |          | C  | | P  |          | C  | | P  |            
       |cGRE| |cAAA|          |cGRE| |cAAA|          |cGRE| |cAAA|          |cGRE| |cAAA|          |cGRE| |cAAA|
       +----+-+----+----------+----+-+----+----------+----+-+----+----------+----+-+----+----------+----+-+----+
       <---------------------->                                                                       
         Connection Interval             

     Peripheral Latency 3

       +----+ +----+          +----+                 +----+                 +----+                 +----+ +----+
       | C  | | P  |          | C  |                 | C  |                 | C  |                 | C  | | P  |
       |cGRE| |cAAA|          |cGRE|                 |cGRE|                 |cGRE|                 |cGRE| |cAAA|
       +----+-+----+----------+----+-----------------+----+-----------------+----+-----------------+----+-+----+
       <---------------------->
         Connection Interval                                                                       

-  **Supervision Time-out** - This time-out is the maximum amount of
   time between two successful connection events. If this time
   passes without a successful connection event, the device
   terminates the connection and returns to an unconnected state.
   This parameter value is represented in units of 10 ms. The
   supervision time-out value can range from a minimum of 10 (100
   ms) to 3200 (32.0 s). The time-out must be larger than the
   effective connection interval (see :ref:`effective_connection_interval` for
   more details).

.. _effective_connection_interval:

Effective Connection Interval
*****************************

The effective connection interval is equal to the amount of time
between two connection events, assuming that the Peripheral skips the
maximum number of possible events if Peripheral latency is allowed (the
effective connection interval is equal to the actual connection
interval if Peripheral latency is set to 0).

The Peripheral Latency value represents the maximum number of events that
can be skipped. This number can range from a minimum value of 0
(meaning that no connection events can be skipped) to a maximum of
499. The maximum value must not make the effective connection
interval (see the following formula) greater than 16 s. The interval
can be calculated using the following formula:

 ``Effective Connection Interval = (Connection Interval) * (1 + [Peripheral Latency])``

Consider the following example:

-  Connection Interval: 80 (100 ms)

-  Peripheral Latency: 4

-  Effective Connection Interval: (100 ms) * (1 + 4) = 500 ms

When no data is being sent from the Peripheral to the Central, the Peripheral
transmits during a connection event once every 500 ms.

.. _connection_parameter_considerations:

Connection Parameter Considerations
***********************************

In many applications, the Peripheral skips the maximum number of
connection events. Consider the effective connection interval when
selecting or requesting connection parameters. Selecting the correct
group of connection parameters plays an important role in power
optimization of the Bluetooth Low Energy device. The following list
gives a general summary of the trade-offs in connection parameter
settings.

Reducing the connection interval does as follows:

-  Increases the power consumption for both devices
-  Increases the throughput in both directions
-  Reduces the time for sending data in either direction

Increasing the connection interval does as follows:

-  Reduces the power consumption for both devices
-  Reduces the throughput in both directions
-  Increases the time for sending data in either direction

Reducing the Peripheral latency (or setting it to zero) does as follows:

-  Increases the power consumption for the peripheral device
-  Reduces the time for the peripheral device to receive the data sent
   from a central device

Increasing the Peripheral latency does as follows:

-  Reduces power consumption for the peripheral during periods when the
   peripheral has no data to send to the central device
-  Increases the time for the peripheral device to receive the data sent
   from the central device

Connection Parameter Update
***************************

In some cases, the central device requests a connection with a
peripheral device containing connection parameters that are
unfavorable to the peripheral device. In other cases, a peripheral
device might have the desire to change connection parameters in the middle of a
connection, based on the peripheral application. The peripheral
device can request the central device to change the connection
parameters by sending a ``Connection Parameter Update Request``.
For Bluetooth 4.1, 4.2, 5.0 and 5.1-capable devices, this request is handled directly by
the Link Layer. For Bluetooth 4.0 devices, the L2CAP layer of the
protocol stack handles the request. The Bluetooth Low Energy stack
automatically selects the update method.

The ``Connection Parameter Update Request`` contains four parameters:

- Minimum connection interval
- Maximum connection interval
- Peripheral latency
- Supervision time-out

These values represent the parameters that the peripheral device wants for
the connection. The connection interval is given as a range. When
the central device receives the ``Connection Parameter Update Request`` request,
it can accept or reject the new parameters.

Sending a ``Connection Parameter Update Request`` is optional and it is not
required for the central device to accept or apply the requested
parameters. Some applications try to establish a connection at a
faster connection interval to allow for a faster service discovery
and initial setup. These applications later request a longer
(slower) connection interval for optimal power usage.

Regardless of the roles (peripheral or central), connection parameter updates can
be sent asynchronously with the :ble_api:`GAP_UpdateLinkParamReq` command. The
simple\_peripheral application can be configured to automatically send a
parameter update a certain amount of time after establishing a connection. For
example, the simple\_peripheral application uses the following symbols, defined
in ``simple_peripheral.c``:

.. code-block:: c

    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     80
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     800
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    #define DEFAULT_DESIRED_CONN_TIMEOUT          1000
    #define SP_SEND_PARAM_UPDATE_DELAY            6000

In simple\_peripheral, six seconds after a connection is established the application
automatically sends a GAP Update Link Parameter Request:

.. code-block:: c
  :caption: **simple_peripheral.c :: SimplePeripheral_processParamUpdate()** - Initiating parameter update request
  :linenos:

    static void SimplePeripheral_processParamUpdate(uint16_t connHandle)
    {
      gapUpdateLinkParamReq_t req;
      req.connectionHandle = connHandle;
      req.connLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
      req.connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
      req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
      req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;

      // Send parameter update
      bStatus_t status = GAP_UpdateLinkParamReq(&req);

When the peer device receives this update request, the GAP parameter
:ble_api:`GAP_PARAM_LINK_UPDATE_DECISION` determines how it responds. See
:ref:`gaprole_peripheral_role` for an explanation of how this parameter is
configured.

Connection Termination
**********************

Either the Central or the Peripheral can terminate a connection for any
reason. One side initiates termination and the other side must
respond before both devices exit the connected state. Use the
:ble_api:`GAP_TerminateLinkReq` command to terminate an existing connection.
