GAP — Usage Scenarios#

WiSeConnect Bluetooth Low Energy (BLE) example projects under examples/snippets/ble/<example_folder>/ show GAP flows. Each scenario below states when to use it and gives a compact implementation example: #include lines as in the SDK, a one-line // caption (same style as other SiWx917 usage-scenario guides), then the API sequence. Non-essential branches are folded to // .... Full sources live under wiseconnect/examples/snippets/ble/ relative to the WiSeConnect SDK content root; the same tree is published in the Silicon Labs wiseconnect GitHub repository (WiseConnect SDK).

Related: BLE usage scenarios hub, GAP overview, BLE initialization and configuration, Debugging and error handling.


Register GAP Callbacks#

When to Use#

  • After wireless/BLE stack initialization, register GAP event handlers before starting advertising, scanning, or connection procedures.

  • Pass NULL only for slots your application does not use (for example advertising report on a peripheral-only device).

Implementation Example#

rsi_ble_gap_register_callbacks() takes ten parameters (WiSeConnect rsi_ble_apis.h). Unused parameters are NULL. A non-NULL argument must be a function pointer type-compatible with that position’s rsi_ble_on_*_t typedef (parameter and return types only; the function identifier is not specified by the API). Snippet identifiers follow SDK examples and are illustrative. End-of-line comments pair role or feature with NULL when peripheral-only, unused, or optional.

#include "rsi_ble_apis.h"

  rsi_ble_gap_register_callbacks(
    rsi_ble_on_adv_report_event,              // adv report — NULL if peripheral_only or unused
    rsi_ble_on_connect_event,                 // connect — NULL if unused
    rsi_ble_on_disconnect_event,              // disconnect — NULL if unused
    rsi_ble_on_le_ping_payload_timeout,       // LE ping timeout — NULL if unused
    rsi_ble_on_phy_update_complete,           // PHY update — NULL if unused
    rsi_ble_on_data_length_update,            // data length update — NULL if unused
    rsi_ble_on_enhance_connect,               // enhanced connection status — NULL if unused
    rsi_ble_on_directed_adv_report_event,     // directed adv report — NULL if peripheral_only or unused
    rsi_ble_on_conn_update_complete,          // connection update complete — NULL if unused
    rsi_ble_on_remote_conn_params_request);   // remote conn params request — NULL if unused

Dual-role or compile-time role samples (for example ble_power_save) pick one set of pointers per BLE_ROLE. SDK example projects use longer internal names (for example rsi_ble_simple_central_on_adv_report_event in ble_central) but the same slot order.

Note: Parameter order matches the WiSeConnect API. See Register Callbacks and Callbacks Declarations. Pairing flows often add rsi_ble_smp_register_callbacks() in the same initialization sequence.


Typical Use Case 1: Peripheral — Advertise and Accept a Connection#

When to Use#

  • The device must be discoverable and connectable using legacy advertising.

  • After a central connects, the application handles connection status and may start SMP (same example project).

Implementation Example#

Step 1: Start Connectable Advertising#

#include "rsi_ble_apis.h"
#include "ble_config.h"

// Legacy ADV + name: ble_secureconnection/app.c (rsi_bt_set_local_name earlier in same init path)
  uint8_t adv[31] = {2, 1, 6};
  adv[3] = strlen(RSI_BLE_DEVICE_NAME) + 1;
  adv[4] = 9; // Complete Local Name (0x09)
  strcpy((char *)&adv[5], RSI_BLE_DEVICE_NAME);
  rsi_ble_set_advertise_data(adv, strlen(RSI_BLE_DEVICE_NAME) + 5);
  status = rsi_ble_start_advertising();
  if (status != RSI_SUCCESS) {
    return;
  }

Note: rsi_ble_start_advertising() has no parameters that carry advertising type or interval. That example project’s ble_config.h defines RSI_BLE_ADV_TYPE, the WiSeConnect GAP sources include ble_config.h and copy those values into the internal advertise request adv_type before it issues RSI_BLE_REQ_ADV. To set advertise fields explicitly at call time, use rsi_ble_start_advertising_with_values().

Step 2: Connection Acceptance and Handling (Peripheral)#

With rsi_ble_on_connect_event registered under Register GAP callbacks, the main task runs on RSI_BLE_CONN_EVENT and can request pairing.

#include "rsi_ble_apis.h"

// GAP callback — connection complete (ble_secureconnection/app.c)
static void rsi_ble_on_connect_event(rsi_ble_event_conn_status_t *resp_conn)
{
  memcpy(remote_dev_address, resp_conn->dev_addr, 6);
  rsi_6byte_dev_address_to_ascii(str_remote_address, resp_conn->dev_addr);
  rsi_ble_app_set_event(RSI_BLE_CONN_EVENT);
}

// Main-task handler — case RSI_BLE_CONN_EVENT (ble_secureconnection/app.c)
  rsi_ble_app_clear_event(RSI_BLE_CONN_EVENT);
  if (!pairing_info_available) {
    status = rsi_ble_smp_pair_request(remote_dev_address, RSI_BLE_SMP_IO_CAPABILITY, MITM_REQ);
  }

Note: Disconnect raises RSI_BLE_DISCONN_EVENT in the same file. Full flow: project readme.md.

SDK Example Project#

Goal

Example folder

Pairing + encryption

ble_secureconnection

Extended advertising

ble_ae_peripheral

Power save

ble_power_save

See also: Peripheral role, GATT server.


Typical Use Case 2: Central — Scan and Connect#

When to Use#

  • Discover peripherals by scanning, then initiate a connection to a selected device.

  • After the link is up, handle connection status in the application task (same example project).

Implementation Example#

Step 1: Start Scanning#

#include "rsi_ble_apis.h"
#include "ble_config.h"

// ble_central/app.c — default scan parameters
  status = rsi_ble_start_scanning();
  if (status != RSI_SUCCESS) {
    return;
  }

Step 2: Advertising Report — Stop Scan, Connect#

rsi_ble_simple_central_on_adv_report_event() is registered in Register GAP callbacks. It fills remote_addr_type and remote_dev_bd_addr when the advertised name or address matches the example’s compile-time defines, then raises RSI_APP_EVENT_ADV_REPORT.

// Main task — case RSI_APP_EVENT_ADV_REPORT (ble_central/app.c)
  status = rsi_ble_stop_scanning();
  if (status != RSI_SUCCESS) {
    return;
  }
  status = rsi_ble_connect(remote_addr_type, (int8_t *)remote_dev_bd_addr);
  if (status != RSI_SUCCESS) {
    return;
  }

Step 3: Connection Established (Central)#

rsi_ble_gap_register_callbacks() registers rsi_ble_simple_central_on_conn_status_event() (or the enhanced variant). The task handles RSI_APP_EVENT_CONNECTED.

#include "rsi_ble_apis.h"

// Connection complete callback — ble_central/app.c
void rsi_ble_simple_central_on_conn_status_event(rsi_ble_event_conn_status_t *resp_conn)
{
  memcpy(&rsi_app_connected_device, resp_conn, sizeof(rsi_ble_event_conn_status_t));
  if (ble_peripheral_conn_sem) {
    osSemaphoreRelease(ble_peripheral_conn_sem);
  }
  rsi_ble_app_set_event(RSI_APP_EVENT_CONNECTED);
}

// Main task — case RSI_APP_EVENT_CONNECTED
  rsi_ble_app_clear_event(RSI_APP_EVENT_CONNECTED);
  rsi_6byte_dev_address_to_ascii(str_remote_address, rsi_app_connected_device.dev_addr);

Recommendation: On RSI_APP_EVENT_DISCONNECTED, the example clears device_found, restarts rsi_ble_start_scanning(), and can rediscover.

SDK Example Project#

Goal

Example folder

Central

ble_central

Extended scan

ble_ae_central

Accept list

ble_accept_list

Multi-link

ble_multiconnection_gatt_test

See also: Central role, GATT client.


Typical Use Case 3: Broadcaster — Beacon-Style Payload#

When to Use#

  • Fixed iBeacon-style (or similar) payload plus optional scan response.

Implementation Example#

#include "rsi_ble_apis.h"
#include "ble_config.h"

// iBeacon payload filled earlier in adv[]; scan response = local name (ble_ibeacon/app.c)
  rsi_ble_set_advertise_data(adv, 30);
  scan_data[3] = strlen(RSI_BLE_LOCAL_NAME) + 1;
  scan_data[4] = 9;
  strcpy((char *)&scan_data[5], RSI_BLE_LOCAL_NAME);
  rsi_ble_set_scan_response_data(scan_data, 31);
  status = rsi_ble_start_advertising();
  if (status != RSI_SUCCESS) {
    // ...
    return;
  }

Note: Assign and check status from each API in production builds.

Note: Broadcaster-style samples use the same rsi_ble_set_advertise_data() / rsi_ble_start_advertising() pattern as connectable peripheral demos; connectable vs non-connectable is determined by RSI_BLE_ADV_TYPE in that example project’s ble_config.h (for example UNDIR_NON_CONN for iBeacon-style advertising), not by extra arguments on rsi_ble_start_advertising(). See the note under Typical Use Case 1 for how those macros reach the stack.

SDK Example Project#

Goal

Example folder

iBeacon

ble_ibeacon

See also: Broadcaster role.


Typical Use Case 4: Observer — Extended Scan#

When to Use#

  • Legacy scan: Use Case 2. Extended scan: configure AE parameters, then enable.

  • Periodic advertising sync (receive a periodic train) uses extended scan plus additional APIs; see Typical Use Case 6.

Implementation Example#

#include "rsi_ble_apis.h"
#include "ble_config.h"

// Extended scan — ble_ae_central/app.c (1M + Coded PHY, interval/window from macros)
  rsi_ble_ae_set_scan_params_t ae_set_scan_params = { 0 };
  ae_set_scan_params.own_addr_type          = LE_PUBLIC_ADDRESS;
  ae_set_scan_params.scanning_filter_policy = RSI_BLE_SCAN_FILTER_TYPE;
  ae_set_scan_params.scanning_phys          = (PHY_1M | PHY_LE_CODED);
  ae_set_scan_params.ScanParams[AE_SCAN_SET1].ScanInterval = LE_SCAN_INTERVAL;
  ae_set_scan_params.ScanParams[AE_SCAN_SET1].ScanWindow   = LE_SCAN_WINDOW;
  // ... optional AE_SCAN_SET2 when SET2_ENABLE
  status = rsi_ble_ae_set_scan_params(&ae_set_scan_params);

  rsi_ble_ae_set_scan_enable_t ae_set_scan_enable = { 0 };
  ae_set_scan_enable.enable            = RSI_BLE_START_SCAN;
  ae_set_scan_enable.filter_duplicates = BLE_SCAN_ENABLE_FILTER_DUP;
  ae_set_scan_enable.duration          = BLE_SCAN_DUR;
  ae_set_scan_enable.period            = BLE_SCAN_PERIOD;
  status = rsi_ble_ae_set_scan_enable(&ae_set_scan_enable);
  if (status != RSI_SUCCESS) {
    // ...
    return;
  }

SDK Example Project#

Goal

Example folder

AE central

ble_ae_central

See also: Observer role, Extended advertising.


Typical Use Case 5: Extended Advertising — Peripheral Enable#

When to Use#

  • After rsi_ble_set_ae_params() / rsi_ble_set_ae_data(), turn the AE set on.

Implementation Example#

#include "rsi_ble_apis.h"
#include "ble_config.h"

// Start extended advertising — ble_ae_peripheral/app.c
  rsi_ble_ae_adv_enable_t ble_ae_adv = { 0 };
  ble_ae_adv.enable        = RSI_BLE_START_ADV;
  ble_ae_adv.no_of_sets    = 1;
  ble_ae_adv.adv_handle    = BLE_ADV_HNDL1;
  ble_ae_adv.duration      = 0;
  ble_ae_adv.max_ae_events = BLE_MAX_AE_EVNTS;
  status = rsi_ble_start_ae_advertising(&ble_ae_adv);
  if (status != RSI_SUCCESS) {
    // ...
    return;
  }

SDK Example Project#

Goal

Example folder

AE peripheral

ble_ae_peripheral

Coex sample

ble_unified_ae_coex_app

See also: Extended advertising.


Typical Use Case 6: Periodic Advertising and Periodic Advertising Sync#

When to Use#

Periodic advertising sends connectionless application data on a fixed schedule (one-to-many). Receivers use periodic sync to align with that schedule and receive at those times instead of scanning continuously—useful for telemetry or beacons and when a GATT connection to every device is not required.

  • Peripheral (advertiser): After extended advertising parameters and data are set for an advertising set, configure periodic advertising parameters and data, start extended advertising, then enable periodic advertising on that set (example: ble_ae_peripheral/app.c with PERIODIC_ADV_EN set to 1).

  • Observer (receiver): With extended scanning enabled (see Typical Use Case 4), register extended advertising callbacks for periodic events, optionally manage the periodic advertiser list, then create periodic sync to a specified advertiser address and SID. Handle sync established, periodic reports, and sync lost in the application task (ble_ae_central/app.c).

Implementation Example#

Peripheral — Periodic Advertising Enable#

Abbreviated from ble_ae_peripheral/app.c (paths under #if PERIODIC_ADV_EN). Set PERIODIC_ADV_EN to 1 in the example to compile this path. Order: rsi_ble_set_ae_params() → rsi_ble_app_set_periodic_ae_params() → rsi_ble_set_ae_data() with BLE_AE_PERIODIC_ADV_DATA_TYPE → rsi_ble_start_ae_advertising() → rsi_ble_app_set_periodic_ae_enable().

#include "rsi_ble_apis.h"
#include "ble_config.h"

// After rsi_ble_set_ae_params() for the set — ble_ae_peripheral/app.c
#if PERIODIC_ADV_EN
  rsi_ble_ae_periodic_adv_params_t ae_periodic_param = { 0 };
  ae_periodic_param.max_interval = 0x190;
  ae_periodic_param.min_interval = 0x90;
  ae_periodic_param.properties   = 0x40;
  ae_periodic_param.adv_handle   = BLE_ADV_HNDL1;
  status = rsi_ble_app_set_periodic_ae_params(&ae_periodic_param);
  if (status != RSI_SUCCESS) {
    return;
  }
#endif

// Periodic advertising data, then extended data as in the example; then:
  status = rsi_ble_start_ae_advertising(&ble_ae_adv);
  // ...

#if PERIODIC_ADV_EN
  status = rsi_ble_app_set_periodic_ae_enable(1, 0);
#endif

Observer — Register Callbacks and Create Periodic Sync#

From ble_ae_central/app.c: call ble_extended_adv_callbacks_register() (or equivalent) so periodic sync established / periodic report / sync lost events are delivered; then after AE scan is enabled:

#include "rsi_ble_apis.h"
#include "ble_config.h"

// Optional: add advertiser to periodic list when BLE_AE_PERIODIC_LIST_USED
// rsi_ble_ae_dev_to_periodic_list(&ae_add_dev);

// Create periodic sync — ble_ae_central/app.c
  rsi_ble_ae_set_periodic_adv_create_sync_t ae_per_sync_create = { 0 };
  rsi_ascii_dev_address_to_6bytes_rev((uint8_t *)ae_per_sync_create.adv_addr, (int8_t *)REM_ADDR);
  ae_per_sync_create.adv_addr_type = LE_PUBLIC_ADDRESS;
  ae_per_sync_create.adv_sid       = BLE_AE_ADV_SID;
  ae_per_sync_create.options       = BLE_AE_OPTIONS;
  ae_per_sync_create.skip          = BLE_AE_ADV_SKIP;
  ae_per_sync_create.sync_timeout  = BLE_AE_SYNC_TIMOUT;
  status = rsi_ble_ae_set_periodic_sync(BLE_AE_PER_SYNC_CREATE, &ae_per_sync_create);
  if (status != RSI_SUCCESS) {
    return;
  }

Main-task branches handle RSI_APP_EVENT_AE_PER_SYNC_ESTBL, periodic report events, and RSI_APP_EVENT_AE_PER_ADV_SYNC_LOST as in the full example. Optional BLE_AE_PER_SYNC_CANCEL and BLE_AE_PER_SYNC_TERMINATE paths use the same rsi_ble_ae_set_periodic_sync() API with different command values.

SDK Example Project#

Goal

Example folder

Periodic advertising (peripheral)

ble_ae_peripheral (enable PERIODIC_ADV_EN)

Periodic sync + reports (observer)

ble_ae_central

See also: Extended advertising, Observer role, Broadcaster role.


Typical Use Case 7: LE Privacy#

When to Use#

  • Add bonded peers to the resolving list, then enable address resolution.

Implementation Example#

#include "rsi_ble_apis.h"

// Add to resolving list — ble_privacy/app.c (helper add_device_to_resolvlist)
  status = rsi_ble_resolvlist(RSI_BLE_ADD_TO_RESOLVE_LIST,
                              resolve_key_p->Identity_addr_type,
                              temp_le_sec_keys.Identity_addr,
                              resolve_key_p->peer_irk,
                              resolve_key_p->local_irk);
  if (status != RSI_SUCCESS) {
    return status;
  }

// Enable resolution + RPA timeout — same file (after list size query)
  status = rsi_ble_set_addr_resolution_enable(RSI_BLE_DEV_ADDR_RESOLUTION_ENABLE,
                                              RSI_BLE_SET_RESOLVABLE_PRIV_ADDR_TOUT);
  if (status != RSI_SUCCESS) {
    // ...
    return;
  }

Caution: Do not call rsi_ble_set_addr_resolution_enable() while scanning, advertising, or connection setup is active. See LE Privacy.

SDK Example Project#

Goal

Example folder

Privacy

ble_privacy

See also: LE Privacy, Pairing and bonding.


Typical Use Case 8: Data Length Extension (DLE)#

When to Use#

  • After connect/MTU handling, read max LL length and set data length.

Implementation Example#

#include "rsi_ble_apis.h"

// DLE request — ble_datalength/app.c (RSI_BLE_MTU_EVENT path); TX_LEN / TX_TIME from project headers
  status = rsi_ble_read_max_data_len(&blereadmaxdatalen);
  if (status != RSI_SUCCESS) {
    return;
  }
  status = rsi_ble_set_data_len(rsi_app_connected_device.dev_addr, TX_LEN, TX_TIME);
  // Retries until success (goto loop in source)

SDK Example Project#

Goal

Example folder

DLE

ble_datalength

PHY

ble_longrange_2mbps

See also: Data length extension.


Typical Use Case 9: Connection Parameter Update#

When to Use#

  • After a connection is established, the host requests updated LL connection interval, peripheral latency, and supervision timeout for that peer (throughput / latency / energy tradeoff on the link). Macro values typically come from ble_config.h (for example CONN_INTERVAL_MIN, CONN_INTERVAL_MAX, CONN_LATENCY, SUPERVISION_TIMEOUT in ble_throughput_app).

Implementation Example#

#include "rsi_ble_apis.h"
#include "ble_config.h"

// ble_throughput_app/app.c — connection parameters (names vary by example project ble_config.h)
  status = rsi_ble_conn_params_update(remote_dev_address,
                                      CONN_INTERVAL_MIN,
                                      CONN_INTERVAL_MAX,
                                      CONN_LATENCY,
                                      SUPERVISION_TIMEOUT);
  if (status != RSI_SUCCESS) {
    // ...
  }

Note: This is GAP / LL connection timing on an active link, not Network Processor (NWP) sleep or MCU power management. NWP power save (PSP, Wi‑Fi performance profile, idle sleep in the app task) is described on the BLE usage scenarios hub using ble_power_save.

SDK Example Project#

Goal

Example folder

Conn param update + throughput demo

ble_throughput_app

See also: Data length extension, Peripheral role.


Summary#

Scenario

Primary example app.c

GAP callback registration

ble_central, ble_secureconnection

Peripheral advertise

ble_secureconnection

Central scan/connect

ble_central

iBeacon

ble_ibeacon

Extended scan

ble_ae_central

Extended adv enable

ble_ae_peripheral

Periodic advertising / periodic sync

ble_ae_peripheral (PERIODIC_ADV_EN), ble_ae_central

Privacy

ble_privacy

DLE

ble_datalength

Connection parameter update

ble_throughput_app


APIs Used in This Section#

Topic

APIs / symbols

Reference

GAP — registration

rsi_ble_gap_register_callbacks()

Register Callbacks

GAP — legacy advertising, scan, connect

rsi_ble_set_advertise_data(), rsi_ble_set_scan_response_data(), rsi_ble_start_advertising(), rsi_ble_start_scanning(), rsi_ble_stop_scanning(), rsi_ble_connect()

GAP

GAP — extended scanning

rsi_ble_ae_set_scan_params(), rsi_ble_ae_set_scan_enable()

GAP

GAP — extended advertising (sets, data, enable)

rsi_ble_set_ae_params(), rsi_ble_set_ae_data(), rsi_ble_start_ae_advertising(), rsi_ble_get_max_adv_data_len(), rsi_ble_get_max_no_of_supp_adv_sets()

GAP

GAP — periodic advertising and periodic sync

rsi_ble_app_set_periodic_ae_params(), rsi_ble_app_set_periodic_ae_enable(), rsi_ble_ae_set_periodic_sync(), rsi_ble_ae_dev_to_periodic_list(), rsi_ble_ae_read_periodic_adv_list_size(), rsi_ble_adv_ext_events_register_callbacks()

GAP

SMP — pairing (examples)

rsi_ble_smp_register_callbacks(), rsi_ble_smp_pair_request()

GAP

LE Privacy

rsi_ble_resolvlist(), rsi_ble_set_addr_resolution_enable()

GAP

Data length extension

rsi_ble_read_max_data_len(), rsi_ble_set_data_len()

GAP

LL connection parameters

rsi_ble_conn_params_update()

GAP

GAP event types (callbacks)

rsi_ble_event_adv_report_t, rsi_ble_event_conn_status_t, rsi_ble_event_disconnect_t, rsi_ble_event_enhance_conn_status_t (and related typedefs used in handlers)

Callbacks Declarations

Integration: BLE API reference; Developing with WiSeConnect SDK.