Peripheral setup

The Peripheral starts advertising and waits for scan and connection requests from other Central devices.

Advertising

Before starting advertising, the advertising parameters should be configured. Otherwise, the following defaults are used.

**\#define** gGapDefaultAdvertisingParameters_d \
{ \
   /* minInterval */     gGapAdvertisingIntervalDefault_c, \
   /* maxInterval */     gGapAdvertisingIntervalDefault_c, \
   /* advertisingType */ gConnectableUndirectedAdv_c, \
   /* addressType */     gBleAddrTypePublic_c, \
   /* peerAddressType */  gBleAddrTypePublic_c, \
   /* peerAddress */     {0U, 0U, 0U, 0U, 0U, 0U}, \
   /* channelMap */      
                        (gapAdvertisingChannelMapFlags_t)gGapAdvertisingChannelMapDefault_c,  \
   /* filterPolicy */    gProcessAll_c \
}

To set different advertising parameters, a gapAdvertisingParameters_t structure should be allocated and initialized with defaults. Then, the necessary fields may be modified.

After that, the following function should be called:

bleResult_t **Gap\_SetAdvertisingParameters**
(
    const gapAdvertisingParameters_t *     pAdvertisingParameters
);

The application should listen to the gAdvertisingParametersSetupComplete_c generic event.

Next, the advertising data should be configured and, if the advertising type supports active scanning, the scan response data should also be configured. If either of these is not configured, they are defaulted to empty data.

The function used to configure the advertising and/or scan response data is shown here:

bleResult_t **Gap\_SetAdvertisingData**
(
  const gapAdvertisingData_t *     pAdvertisingData,
  const gapScanResponseData_t *    pScanResponseData
);

Either of the two pointers may be NULL, in which case they are ignored (the corresponding data is left as it was previously configured, or empty if it has never been set), but not both at the same time.

The application should listen to the gAdvertisingDataSetupComplete_c generic event.

After all the necessary setup is done, advertising may be started with this function:

bleResult_t **Gap\_StartAdvertising**
(
    gapAdvertisingCallback_t advertisingCallback,
    gapConnectionCallback_t connectionCallback
);

The advertising callback is used to receive advertising events (advertising state changed or advertising command failed), while the connection callback is only used if a connection is established during advertising.

The connection callback is the same as the callback used by the Central when calling the Gap_Connect function.

When using the common application structure, the application can use the following API defined in app_conn.h:

bleResult_t **BluetoothLEHost\_StartAdvertising**
(
    appAdvertisingParams_t   *pAdvParams,
    gapAdvertisingCallback_t pfAdvertisingCallback,
    gapConnectionCallback_t  pfConnectionCallback
);

The API goes through the steps of setting the advertising data and parameters. Events from the Host task are treated in the App_AdvertiserHandler() function, implemented in app_advertiser.c. To set the advertising parameters and data BluetoothLEHost_StartAdvertising requires a parameter of the following type:

typedef struct appAdvertisingParams_tag { gapAdvertisingParameters_t *pGapAdvParams; /*!< Pointer to the GAP advertising parameters */ const gapAdvertisingData_t *pGapAdvData; /*!< Pointer to the GAP advertising data */ const gapScanResponseData_t *pScanResponseData; /*!< Pointer to the scan response data */ } appAdvertisingParams_t;

If a Central initiates a connection to this Peripheral, the gConnEvtConnected_c connection event is triggered.

To stop advertising while the Peripheral has not yet received any connection requests, use this function:

bleResult_t **Gap\_StopAdvertising** (**void**);

This function should not be called after the Peripheral enters a connection, as the advertising automatically stops in this case.

Parent topic:Peripheral setup

Pairing and bonding (peripheral)

After a connection has been established to a Central, the Peripheral’s role regarding security is a passive one. It is the responsibility of the Central device to start the pairing process. In case, the devices have already bonded in the past, the Central encrypts the link using the shared LTK.

The Peripheral sends error responses (at ATT level) with proper error code if the Central attempts to access sensitive data without authenticating. Examples of such error responses are: Insufficient Authentication, Insufficient Encryption, Insufficient Authorization, and so on. Therefore, it indicates to the Central that it needs to perform security procedures.

All security checks are performed internally by the GAP module and the security error responses are sent automatically. All the application developer needs to do is register the security requirements.

First, when building the GATT Database (see Creating GATT database), the sensitive attributes should have the security built into their access permissions (for example, read-only / read with authentication / write with authentication / write with authorization, and so on.).

Second, if the GATT Database requires additional security besides that already specified in attribute permissions (for example, certain services require higher security in certain situations), the following function must be called:

The parameter is a pointer to a structure which contains a “device security setting” and service-specific security settings. All these security requirements are pointers to gapSecurityRequirements_t structures. The pointers that are to be ignored should be set to NULL.

Although the Peripheral does not initiate any kind of security procedure, it can inform the Central about its security requirements. This is usually done immediately after the connection to avoid exchanging useless packets for requests that might be denied because of insufficient security.

The informing is performed through the Peripheral Security Request packet at SMP level. To use it, the following GAP API is provided:

The gapPairingParameters_t structure includes two important fields. The withBonding field indicates to the Central whether this Peripheral can bond and the securityModeAndLevel field informs about the required security mode and level that the Central should pair for. See Pairing and bonding (Central) for an explanation about security modes and levels, as defined by the GAP module.

This request expects no reply, nor any immediate action from the Central. The Central may easily choose to ignore the Peripheral Security Request.

If the two devices have bonded in the past, the Central proceeds directly to encrypting the link. If the bond was not made using LE Secure Connections, the Peripheral expects to receive a gConnEvtLongTermKeyRequest_c connection event. If the bond was made using LE Secure Connections, the Host provides the LTK automatically to the LE Controller.

When the devices have been previously pairing without using LE Secure Connections, along with the Peripheral’s LTK, the EDIV (2 bytes) and RAND (8 bytes) values were also sent (their meaning is defined by the SMP). Therefore, before providing the key to the Controller, the application should check that the two values match with those received in the gConnEvtLongTermKeyRequest_c event. If they do, the application should reply with:

The LTK size cannot exceed the maximum value of 16.

If the EDIV and RAND values do not match, or if the Peripheral does not recognize the bond, it can reject the encryption request with:

If LE SC Pairing was used then the LTK is generated internally by the Bluetooth LE Host Stack and it is not requested from the application during post-bonding link encryption. In this scenario, the application is only notified of the link encryption through the gConnEvtEncryptionChanged_c connection event.

If the devices are not bonded, the Peripheral should expect to receive the gConnEvtPairingRequest_c, indicating that the Central has initiated pairing.

If the application agrees with the pairing parameters (see Pairing and bonding (Central) for detailed explanations), it can reply with:

This time, the Peripheral sends its own pairing parameters, as defined by the SMP.

After sending this response, the application should expect to receive the same pairing events as the Central (see Pairing and bonding (Central)), with one exception: the gConnEvtPasskeyRequest_c event is not called if the application sets the Passkey (PIN) for pairing before the connection by calling the API:

This is done because, usually, the Peripheral has a static secret PIN that it distributes only to trusted devices. If, for any reason, the Peripheral must dynamically change the PIN, it can call the aforementioned function every time it wants to, before the pairing starts (for example, right before sending the pairing response with Gap_AcceptPairingRequest).

If the Peripheral application never calls Gap_SetLocalPasskey, then the gConnEvtPasskeyRequest_c event is sent to the application as usual.

The Peripheral can use the following API to reject the pairing process:

The reason should indicate why the application rejects the pairing. The value gLinkEncryptionFailed_c is reserved for the gConnEvtAuthenticationRejected_c connection event to indicate the link encryption failure rather than pairing failures. Therefore, it is not meant as a pairing reject reason.

The Gap_RejectPairing function may be called not only after the Pairing Request was received, but also during the pairing process. For example, when handling pairing events or asynchronously, if for any reason the Peripheral decides to abort the pairing, this function can be called. This also holds true for the Central. Figure 1 illustrates the Peripheral pairing flow and lists the main APIs and events. Gap_RejectPairing can be called on any pairing event.

For both the Central and the Peripheral, bonding is performed internally and is not the application’s concern. The gConnEvtPairingComplete_c event parameters inform the application if bonding has occurred.

Parent topic:Peripheral setup

Parent topic:Generic Access Profile (GAP) Layer