85d44f32a1e858365272b2a217c86233e4b60983
[platform/upstream/connectedhomeip.git] / src / platform / EFR32 / BLEManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2019 Nest Labs, Inc.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *          Provides an implementation of the BLEManager singleton object
22  *          for the Silicon Labs EFR32 platforms.
23  */
24
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
27 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
28
29 #include <platform/internal/BLEManager.h>
30
31 #include "sl_bt_api.h"
32 #include "sl_bt_stack_config.h"
33 #include "sl_bt_stack_init.h"
34 #include <ble/CHIPBleServiceData.h>
35 #include <platform/EFR32/freertos_bluetooth.h>
36 #include <support/CodeUtils.h>
37 #include <support/logging/CHIPLogging.h>
38
39 using namespace ::chip;
40 using namespace ::chip::Ble;
41
42 namespace chip {
43 namespace DeviceLayer {
44 namespace Internal {
45
46 namespace {
47
48 #define CHIP_ADV_DATA_TYPE_FLAGS 0x01
49 #define CHIP_ADV_DATA_TYPE_UUID 0x03
50 #define CHIP_ADV_DATA_TYPE_NAME 0x09
51 #define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
52
53 #define CHIP_ADV_DATA_FLAGS 0x06
54
55 #define CHIP_ADV_DATA 0
56 #define CHIP_ADV_SCAN_RESPONSE_DATA 1
57 #define CHIP_ADV_SHORT_UUID_LEN 2
58
59 #define MAX_RESPONSE_DATA_LEN 31
60 #define MAX_ADV_DATA_LEN 31
61
62 // Timer Frequency used.
63 #define TIMER_CLK_FREQ ((uint32_t) 32768)
64 // Convert msec to timer ticks.
65 #define TIMER_MS_2_TIMERTICK(ms) ((TIMER_CLK_FREQ * ms) / 1000)
66 #define TIMER_S_2_TIMERTICK(s) (TIMER_CLK_FREQ * s)
67
68 #define BLE_MAX_BUFFER_SIZE (3150)
69 #define BLE_MAX_ADVERTISERS (1)
70 #define BLE_CONFIG_MAX_PERIODIC_ADVERTISING_SYNC (0)
71 #define BLE_CONFIG_MAX_SOFTWARE_TIMERS (4)
72 #define BLE_CONFIG_MIN_TX_POWER (-30)
73 #define BLE_CONFIG_MAX_TX_POWER (80)
74 #define BLE_CONFIG_RF_PATH_GAIN_TX (0)
75 #define BLE_CONFIG_RF_PATH_GAIN_RX (0)
76
77 /* Bluetooth stack configuration parameters (see "UG136: Silicon Labs Bluetooth C Application Developer's Guide" for
78  * details on each parameter) */
79 static sl_bt_configuration_t config;
80
81 const uint8_t UUID_CHIPoBLEService[]       = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
82                                          0x00, 0x10, 0x00, 0x00, 0xAF, 0xFE, 0x00, 0x00 };
83 const uint8_t ShortUUID_CHIPoBLEService[]  = { 0xAF, 0xFE };
84 const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
85                                                  0x9D, 0x11 } };
86 const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
87                                                  0x9D, 0x12 } };
88
89 } // namespace
90
91 BLEManagerImpl BLEManagerImpl::sInstance;
92
93 /***************************************************************************/
94 /**
95  * Setup the bluetooth init function.
96  *
97  * @return none
98  *
99  * All bluetooth specific initialization
100  * code should be here like sl_bt_init_stack(),
101  * sl_bt_init_multiprotocol() and so on.
102  ******************************************************************************/
103 extern "C" sl_status_t initialize_bluetooth()
104 {
105     sl_status_t ret = sl_bt_init_stack(&config);
106     sl_bt_class_system_init();
107     sl_bt_class_advertiser_init();
108     sl_bt_class_gap_init();
109     sl_bt_class_scanner_init();
110     sl_bt_class_connection_init();
111     sl_bt_class_gatt_init();
112     sl_bt_class_gatt_server_init();
113     sl_bt_class_nvm_init();
114     sl_bt_class_sm_init();
115     sl_bt_init_multiprotocol();
116     return ret;
117 }
118
119 static void initBleConfig(void)
120 {
121     memset(&config, 0, sizeof(sl_bt_configuration_t));
122     config.config_flags                = SL_BT_CONFIG_FLAG_RTOS;      /* Check flag options from UG136 */
123     config.bluetooth.max_connections   = BLE_LAYER_NUM_BLE_ENDPOINTS; /* Maximum number of simultaneous connections */
124     config.bluetooth.max_advertisers   = BLE_MAX_ADVERTISERS;
125     config.bluetooth.max_periodic_sync = BLE_CONFIG_MAX_PERIODIC_ADVERTISING_SYNC;
126     config.bluetooth.max_buffer_memory = BLE_MAX_BUFFER_SIZE;
127     config.gattdb                      = &bg_gattdb_data; /* Pointer to GATT database */
128     config.scheduler_callback          = BluetoothLLCallback;
129     config.stack_schedule_callback     = BluetoothUpdate;
130     config.max_timers                  = BLE_CONFIG_MAX_SOFTWARE_TIMERS;
131     config.rf.tx_gain                  = BLE_CONFIG_RF_PATH_GAIN_TX;
132     config.rf.rx_gain                  = BLE_CONFIG_RF_PATH_GAIN_RX;
133     config.rf.tx_min_power             = BLE_CONFIG_MIN_TX_POWER;
134     config.rf.tx_max_power             = BLE_CONFIG_MAX_TX_POWER;
135 #if (HAL_PA_ENABLE)
136     config.pa.config_enable = 1; /* Set this to be a valid PA config */
137 #if defined(FEATURE_PA_INPUT_FROM_VBAT)
138     config.pa.input = SL_BT_RADIO_PA_INPUT_VBAT; /* Configure PA input to VBAT */
139 #else
140     config.pa.input = SL_BT_RADIO_PA_INPUT_DCDC; /* Configure PA input to DCDC */
141 #endif // defined(FEATURE_PA_INPUT_FROM_VBAT)
142 #endif // (HAL_PA_ENABLE)
143 }
144
145 CHIP_ERROR BLEManagerImpl::_Init()
146 {
147     CHIP_ERROR err;
148     sl_status_t ret;
149
150     // Initialize the CHIP BleLayer.
151     err = BleLayer::Init(this, this, &SystemLayer);
152     SuccessOrExit(err);
153
154     memset(mBleConnections, 0, sizeof(mBleConnections));
155     memset(mIndConfId, kUnusedIndex, sizeof(mIndConfId));
156     mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
157
158     initBleConfig();
159
160     // Start Bluetooth Link Layer and stack tasks
161     ret =
162         bluetooth_start(CHIP_DEVICE_CONFIG_BLE_LL_TASK_PRIORITY, CHIP_DEVICE_CONFIG_BLE_STACK_TASK_PRIORITY, initialize_bluetooth);
163
164     VerifyOrExit(ret == bg_err_success, err = MapBLEError(ret));
165
166     // Create the Bluetooth Application task
167     xTaskCreate(bluetoothStackEventHandler,                                       /* Function that implements the task. */
168                 CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME,                             /* Text name for the task. */
169                 CHIP_DEVICE_CONFIG_BLE_APP_TASK_STACK_SIZE / sizeof(StackType_t), /* Number of indexes in the xStack array. */
170                 this,                                                             /* Parameter passed into the task. */
171                 CHIP_DEVICE_CONFIG_BLE_APP_TASK_PRIORITY,                         /* Priority at which the task is created. */
172                 NULL);                                                            /* Variable to hold the task's data structure. */
173
174     mFlags = CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? kFlag_AdvertisingEnabled : 0;
175     PlatformMgr().ScheduleWork(DriveBLEState, 0);
176
177 exit:
178     return err;
179 }
180
181 uint16_t BLEManagerImpl::_NumConnections(void)
182 {
183     uint16_t numCons = 0;
184     for (uint16_t i = 0; i < kMaxConnections; i++)
185     {
186         if (mBleConnections[i].allocated)
187         {
188             numCons++;
189         }
190     }
191
192     return numCons;
193 }
194
195 void BLEManagerImpl::bluetoothStackEventHandler(void * p_arg)
196 {
197     EventBits_t flags = 0;
198
199     while (1)
200     {
201         // wait for Bluetooth stack events, do not consume set flag
202         flags = xEventGroupWaitBits(bluetooth_event_flags,            /* The event group being tested. */
203                                     BLUETOOTH_EVENT_FLAG_EVT_WAITING, /* The bits within the event group to wait for. */
204                                     pdFALSE,                          /* Dont clear flags before returning */
205                                     pdFALSE,                          /* Any flag will do, dont wait for all flags to be set */
206                                     portMAX_DELAY);                   /* Wait for maximum duration for bit to be set */
207
208         if (flags & BLUETOOTH_EVENT_FLAG_EVT_WAITING)
209         {
210             flags &= ~BLUETOOTH_EVENT_FLAG_EVT_WAITING;
211             xEventGroupClearBits(bluetooth_event_flags, BLUETOOTH_EVENT_FLAG_EVT_WAITING);
212
213             // As this is running in a separate thread, we need to block CHIP from operating,
214             // until the events are handled.
215             PlatformMgr().LockChipStack();
216
217             // handle bluetooth events
218             switch (SL_BT_MSG_ID(bluetooth_evt->header))
219             {
220             case sl_bt_evt_system_boot_id: {
221                 ChipLogProgress(DeviceLayer, "Bluetooth stack booted: v%d.%d.%d-b%d\n", bluetooth_evt->data.evt_system_boot.major,
222                                 bluetooth_evt->data.evt_system_boot.minor, bluetooth_evt->data.evt_system_boot.patch,
223                                 bluetooth_evt->data.evt_system_boot.build);
224                 sInstance.HandleBootEvent();
225             }
226             break;
227
228             case sl_bt_evt_connection_opened_id: {
229                 sInstance.HandleConnectEvent(bluetooth_evt);
230             }
231             break;
232             case sl_bt_evt_connection_parameters_id: {
233                 // ChipLogProgress(DeviceLayer, "Connection parameter ID received. Nothing to do");
234             }
235             break;
236             case sl_bt_evt_connection_phy_status_id: {
237                 // ChipLogProgress(DeviceLayer, "PHY update procedure is completed");
238             }
239             break;
240             case sl_bt_evt_connection_closed_id: {
241                 sInstance.HandleConnectionCloseEvent(bluetooth_evt);
242             }
243             break;
244
245             /* This event indicates that a remote GATT client is attempting to write a value of an
246              * attribute in to the local GATT database, where the attribute was defined in the GATT
247              * XML firmware configuration file to have type="user".  */
248             case sl_bt_evt_gatt_server_attribute_value_id: {
249                 sInstance.HandleWriteEvent(bluetooth_evt);
250             }
251             break;
252
253             case sl_bt_evt_gatt_mtu_exchanged_id: {
254                 sInstance.UpdateMtu(bluetooth_evt);
255             }
256             break;
257
258             // confirmation of indication received from remote GATT client
259             case sl_bt_evt_gatt_server_characteristic_status_id: {
260                 sl_bt_gatt_server_characteristic_status_flag_t StatusFlags;
261
262                 StatusFlags = (sl_bt_gatt_server_characteristic_status_flag_t)
263                                   bluetooth_evt->data.evt_gatt_server_characteristic_status.status_flags;
264
265                 if (sl_bt_gatt_server_confirmation == StatusFlags)
266                 {
267                     sInstance.HandleTxConfirmationEvent(bluetooth_evt);
268                 }
269                 else if ((bluetooth_evt->data.evt_gatt_server_characteristic_status.characteristic == gattdb_CHIPoBLEChar_Tx) &&
270                          (bluetooth_evt->data.evt_gatt_server_characteristic_status.status_flags == gatt_server_client_config))
271                 {
272                     sInstance.HandleTXCharCCCDWrite(bluetooth_evt);
273                 }
274             }
275             break;
276
277             /* Software Timer event */
278             case sl_bt_evt_system_soft_timer_id: {
279                 sInstance.HandleSoftTimerEvent(bluetooth_evt);
280             }
281             break;
282
283             default:
284                 ChipLogProgress(DeviceLayer, "evt_UNKNOWN id = %08x", SL_BT_MSG_ID(bluetooth_evt->header));
285                 break;
286             }
287         }
288
289         PlatformMgr().UnlockChipStack();
290
291         vRaiseEventFlagBasedOnContext(bluetooth_event_flags, BLUETOOTH_EVENT_FLAG_EVT_HANDLED);
292     }
293 }
294
295 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
296 {
297     CHIP_ERROR err = CHIP_NO_ERROR;
298
299     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
300     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
301
302     if (val != mServiceMode)
303     {
304         mServiceMode = val;
305         PlatformMgr().ScheduleWork(DriveBLEState, 0);
306     }
307
308 exit:
309     return err;
310 }
311
312 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
313 {
314     CHIP_ERROR err = CHIP_NO_ERROR;
315
316     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
317
318     if (GetFlag(mFlags, kFlag_AdvertisingEnabled) != val)
319     {
320         SetFlag(mFlags, kFlag_AdvertisingEnabled, val);
321         PlatformMgr().ScheduleWork(DriveBLEState, 0);
322     }
323
324 exit:
325     return err;
326 }
327
328 CHIP_ERROR BLEManagerImpl::_SetFastAdvertisingEnabled(bool val)
329 {
330     CHIP_ERROR err = CHIP_NO_ERROR;
331
332     VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
333
334     if (GetFlag(mFlags, kFlag_FastAdvertisingEnabled) != val)
335     {
336         SetFlag(mFlags, kFlag_FastAdvertisingEnabled, val);
337         PlatformMgr().ScheduleWork(DriveBLEState, 0);
338     }
339
340 exit:
341     return err;
342 }
343
344 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
345 {
346     if (strlen(mDeviceName) >= bufSize)
347     {
348         return CHIP_ERROR_BUFFER_TOO_SMALL;
349     }
350     strcpy(buf, mDeviceName);
351     return CHIP_NO_ERROR;
352 }
353
354 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
355 {
356     sl_status_t ret;
357     CHIP_ERROR err = CHIP_NO_ERROR;
358     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
359     {
360         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
361     }
362     if (deviceName != NULL && deviceName[0] != 0)
363     {
364         if (strlen(deviceName) >= kMaxDeviceNameLength)
365         {
366             return CHIP_ERROR_INVALID_ARGUMENT;
367         }
368         strcpy(mDeviceName, deviceName);
369         SetFlag(mFlags, kFlag_DeviceNameSet, true);
370         ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", deviceName);
371         static_assert(kMaxDeviceNameLength <= UINT16_MAX, "deviceName length might not fit in a uint8_t");
372         ret = sl_bt_gatt_server_write_attribute_value(gattdb_device_name, 0, strlen(deviceName), (uint8_t *) deviceName);
373         if (ret != SL_STATUS_OK)
374         {
375             err = MapBLEError(ret);
376             ChipLogError(DeviceLayer, "sl_bt_gatt_server_write_attribute_value() failed: %s", ErrorStr(err));
377             return err;
378         }
379     }
380     else
381     {
382         mDeviceName[0] = 0;
383     }
384     return CHIP_NO_ERROR;
385 }
386
387 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
388 {
389     switch (event->Type)
390     {
391     case DeviceEventType::kCHIPoBLESubscribe: {
392         ChipDeviceEvent connEstEvent;
393
394         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLESubscribe");
395         HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
396         connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
397         PlatformMgr().PostEvent(&connEstEvent);
398     }
399     break;
400
401     case DeviceEventType::kCHIPoBLEUnsubscribe: {
402         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
403         HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
404     }
405     break;
406
407     case DeviceEventType::kCHIPoBLEWriteReceived: {
408         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived");
409         HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
410                             PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
411     }
412     break;
413
414     case DeviceEventType::kCHIPoBLEConnectionError: {
415         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
416         HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
417     }
418     break;
419
420     case DeviceEventType::kCHIPoBLEIndicateConfirm: {
421         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
422         HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
423     }
424     break;
425
426     default:
427         ChipLogProgress(DeviceLayer, "_OnPlatformEvent default:  event->Type = %d", event->Type);
428         break;
429     }
430 }
431
432 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
433 {
434     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
435     return false;
436 }
437
438 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
439 {
440     ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
441     return false;
442 }
443
444 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
445 {
446     CHIP_ERROR err = CHIP_NO_ERROR;
447     sl_status_t ret;
448
449     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
450
451     ret = sl_bt_connection_close(conId);
452     err = MapBLEError(ret);
453
454     if (err != CHIP_NO_ERROR)
455     {
456         ChipLogError(DeviceLayer, "sl_bt_connection_close() failed: %s", ErrorStr(err));
457     }
458
459     return (err == CHIP_NO_ERROR);
460 }
461
462 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
463 {
464     CHIPoBLEConState * conState = const_cast<BLEManagerImpl *>(this)->GetConnectionState(conId);
465     return (conState != NULL) ? conState->mtu : 0;
466 }
467
468 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
469                                     PacketBufferHandle data)
470 {
471     CHIP_ERROR err              = CHIP_NO_ERROR;
472     CHIPoBLEConState * conState = GetConnectionState(conId);
473     sl_status_t ret;
474     uint16_t cId        = (UUIDsMatch(&ChipUUID_CHIPoBLEChar_RX, charId) ? gattdb_CHIPoBLEChar_Rx : gattdb_CHIPoBLEChar_Tx);
475     uint8_t timerHandle = GetTimerHandle(conId, true);
476
477     VerifyOrExit(((conState != NULL) && (conState->subscribed != 0)), err = CHIP_ERROR_INVALID_ARGUMENT);
478     VerifyOrExit(timerHandle != kMaxConnections, err = CHIP_ERROR_NO_MEMORY);
479
480     // start timer for light indication confirmation. Long delay for spake2 indication
481     sl_bt_system_set_soft_timer(TIMER_S_2_TIMERTICK(6), timerHandle, true);
482
483     ret = sl_bt_gatt_server_send_indication(conId, cId, (data->DataLength()), data->Start());
484
485     err = MapBLEError(ret);
486
487 exit:
488     if (err != CHIP_NO_ERROR)
489     {
490         ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
491         return false;
492     }
493     return true;
494 }
495
496 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
497                                       PacketBufferHandle pBuf)
498 {
499     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
500     return false;
501 }
502
503 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
504                                      PacketBufferHandle pBuf)
505 {
506     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
507     return false;
508 }
509
510 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
511                                       const ChipBleUUID * svcId, const ChipBleUUID * charId)
512 {
513     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
514     return false;
515 }
516
517 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
518 {
519     // Nothing to do
520 }
521
522 CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr)
523 {
524     switch (bleErr)
525     {
526     case SL_STATUS_OK:
527         return CHIP_NO_ERROR;
528     case SL_STATUS_BT_ATT_INVALID_ATT_LENGTH:
529         return CHIP_ERROR_INVALID_STRING_LENGTH;
530     case SL_STATUS_INVALID_PARAMETER:
531         return CHIP_ERROR_INVALID_ARGUMENT;
532     default:
533         return (CHIP_ERROR) bleErr + CHIP_DEVICE_CONFIG_EFR32_BLE_ERROR_MIN;
534     }
535 }
536
537 void BLEManagerImpl::DriveBLEState(void)
538 {
539     CHIP_ERROR err = CHIP_NO_ERROR;
540
541     // Check if BLE stack is initialized
542     VerifyOrExit(GetFlag(mFlags, kFlag_EFRBLEStackInitialized), /* */);
543
544     // Start advertising if needed...
545     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && GetFlag(mFlags, kFlag_AdvertisingEnabled))
546     {
547         // Start/re-start advertising if not already started, or if there is a pending change
548         // to the advertising configuration.
549         if (!GetFlag(mFlags, kFlag_Advertising) || GetFlag(mFlags, kFlag_RestartAdvertising))
550         {
551             err = StartAdvertising();
552             SuccessOrExit(err);
553         }
554     }
555
556     // Otherwise, stop advertising if it is enabled.
557     else if (GetFlag(mFlags, kFlag_Advertising))
558     {
559         err = StopAdvertising();
560         SuccessOrExit(err);
561     }
562
563 exit:
564     if (err != CHIP_NO_ERROR)
565     {
566         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
567         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
568     }
569 }
570
571 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
572 {
573     sl_status_t ret;
574     ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
575     CHIP_ERROR err;
576     uint8_t responseData[MAX_RESPONSE_DATA_LEN];
577     uint8_t advData[MAX_ADV_DATA_LEN];
578     uint32_t index              = 0;
579     uint32_t mDeviceNameLength  = 0;
580     uint8_t mDeviceIdInfoLength = 0;
581
582     VerifyOrExit((kMaxDeviceNameLength + 1) < UINT8_MAX, err = CHIP_ERROR_INVALID_ARGUMENT);
583
584     memset(responseData, 0, MAX_RESPONSE_DATA_LEN);
585     memset(advData, 0, MAX_ADV_DATA_LEN);
586
587     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
588     SuccessOrExit(err);
589
590     if (!GetFlag(mFlags, kFlag_DeviceNameSet))
591     {
592         snprintf(mDeviceName, sizeof(mDeviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0);
593
594         mDeviceName[kMaxDeviceNameLength] = 0;
595         mDeviceNameLength                 = strlen(mDeviceName);
596
597         VerifyOrExit(mDeviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
598
599         ret = sl_bt_gatt_server_write_attribute_value(gattdb_device_name, 0, mDeviceNameLength, (uint8_t *) mDeviceName);
600         if (ret != SL_STATUS_OK)
601         {
602             err = MapBLEError(ret);
603             ChipLogError(DeviceLayer, "sl_bt_gatt_server_write_attribute_value() failed: %s", ErrorStr(err));
604             return err;
605         }
606     }
607
608     mDeviceNameLength = strlen(mDeviceName); // Device Name length + length field
609     VerifyOrExit(mDeviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
610
611     mDeviceIdInfoLength = sizeof(mDeviceIdInfo); // Servicedatalen + length+ UUID (Short)
612     static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t");
613     static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= MAX_ADV_DATA_LEN, "Our buffer is not big enough");
614
615     index            = 0;
616     advData[index++] = 0x02;                                                                    // length
617     advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS;                                                // AD type : flags
618     advData[index++] = CHIP_ADV_DATA_FLAGS;                                                     // AD value
619     advData[index++] = static_cast<uint8_t>(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length
620     advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA;                                         // AD type : Service Data
621     advData[index++] = ShortUUID_CHIPoBLEService[0];                                            // AD value
622     advData[index++] = ShortUUID_CHIPoBLEService[1];
623     memcpy(&advData[index], (void *) &mDeviceIdInfo, mDeviceIdInfoLength); // AD value
624     index += mDeviceIdInfoLength;
625
626     advData[index++] = static_cast<uint8_t>(mDeviceNameLength + 1); // length
627     advData[index++] = CHIP_ADV_DATA_TYPE_NAME;                     // AD type : name
628     memcpy(&advData[index], mDeviceName, mDeviceNameLength);        // AD value
629     index += mDeviceNameLength;
630
631     if (0xff != advertising_set_handle)
632     {
633         sl_bt_advertiser_delete_set(advertising_set_handle);
634         advertising_set_handle = 0xff;
635     }
636
637     ret = sl_bt_advertiser_create_set(&advertising_set_handle);
638     if (ret != SL_STATUS_OK)
639     {
640         err = MapBLEError(ret);
641         ChipLogError(DeviceLayer, "sl_bt_advertiser_create_set() failed: %s", ErrorStr(err));
642         ExitNow();
643     }
644     ret = sl_bt_advertiser_set_data(advertising_set_handle, CHIP_ADV_DATA, index, (uint8_t *) advData);
645
646     if (ret != SL_STATUS_OK)
647     {
648         err = MapBLEError(ret);
649         ChipLogError(DeviceLayer, "sl_bt_advertiser_set_data() failed: %s", ErrorStr(err));
650         ExitNow();
651     }
652
653     index = 0;
654
655     responseData[index++] = CHIP_ADV_SHORT_UUID_LEN + 1;  // AD length
656     responseData[index++] = CHIP_ADV_DATA_TYPE_UUID;      // AD type : uuid
657     responseData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value
658     responseData[index++] = ShortUUID_CHIPoBLEService[1];
659
660     ret = sl_bt_advertiser_set_data(advertising_set_handle, CHIP_ADV_SCAN_RESPONSE_DATA, index, (uint8_t *) responseData);
661
662     if (ret != SL_STATUS_OK)
663     {
664         err = MapBLEError(ret);
665         ChipLogError(DeviceLayer, "sl_bt_advertiser_set_data() failed: %s", ErrorStr(err));
666         ExitNow();
667     }
668
669     err = MapBLEError(ret);
670
671 exit:
672     return err;
673 }
674
675 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
676 {
677     CHIP_ERROR err;
678     sl_status_t ret;
679     uint32_t interval_min;
680     uint32_t interval_max;
681     uint16_t numConnectionss = NumConnections();
682     uint8_t connectableAdv =
683         (numConnectionss < kMaxConnections) ? sl_bt_advertiser_connectable_scannable : sl_bt_advertiser_scannable_non_connectable;
684
685     err = ConfigureAdvertisingData();
686     SuccessOrExit(err);
687
688     ClearFlag(mFlags, kFlag_RestartAdvertising);
689
690     interval_min = interval_max =
691         ((numConnectionss == 0 && !ConfigurationMgr().IsPairedToAccount()) || GetFlag(mFlags, kFlag_FastAdvertisingEnabled))
692         ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL
693         : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL;
694
695     ret = sl_bt_advertiser_set_timing(advertising_set_handle, interval_min, interval_max, 0, 0);
696     err = MapBLEError(ret);
697     SuccessOrExit(err);
698
699     ret = sl_bt_advertiser_start(advertising_set_handle, sl_bt_advertiser_user_data, connectableAdv);
700
701     if (SL_STATUS_OK == ret)
702     {
703         SetFlag(mFlags, kFlag_Advertising, true);
704     }
705
706     err = MapBLEError(ret);
707
708 exit:
709     return err;
710 }
711
712 CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
713 {
714     CHIP_ERROR err = CHIP_NO_ERROR;
715     sl_status_t ret;
716
717     if (GetFlag(mFlags, kFlag_Advertising))
718     {
719         ClearFlag(mFlags, kFlag_Advertising);
720         ClearFlag(mFlags, kFlag_RestartAdvertising);
721
722         ret = sl_bt_advertiser_stop(advertising_set_handle);
723         sl_bt_advertiser_delete_set(advertising_set_handle);
724         advertising_set_handle = 0xff;
725         err                    = MapBLEError(ret);
726         SuccessOrExit(err);
727     }
728
729 exit:
730     return err;
731 }
732
733 void BLEManagerImpl::UpdateMtu(volatile sl_bt_msg_t * evt)
734 {
735     CHIPoBLEConState * bleConnState = GetConnectionState(evt->data.evt_gatt_mtu_exchanged.connection);
736     if (bleConnState != NULL)
737     {
738         // bleConnState->MTU is a 10-bit field inside a uint16_t.  We're
739         // assigning to it from a uint16_t, and compilers warn about
740         // possibly not fitting.  There's no way to suppress that warning
741         // via explicit cast; we have to disable the warning around the
742         // assignment.
743         //
744         // TODO: https://github.com/project-chip/connectedhomeip/issues/2569
745         // tracks making this safe with a check or explaining why no check
746         // is needed.
747 #pragma GCC diagnostic push
748 #pragma GCC diagnostic ignored "-Wconversion"
749         bleConnState->mtu = evt->data.evt_gatt_mtu_exchanged.mtu;
750 #pragma GCC diagnostic pop
751         ;
752     }
753 }
754
755 void BLEManagerImpl::HandleBootEvent(void)
756 {
757     SetFlag(mFlags, kFlag_EFRBLEStackInitialized, true);
758     PlatformMgr().ScheduleWork(DriveBLEState, 0);
759 }
760
761 void BLEManagerImpl::HandleConnectEvent(volatile sl_bt_msg_t * evt)
762 {
763     sl_bt_evt_connection_opened_t * conn_evt = (sl_bt_evt_connection_opened_t *) &(evt->data);
764     uint8_t connHandle                       = conn_evt->connection;
765     uint8_t bondingHandle                    = conn_evt->bonding;
766
767     ChipLogProgress(DeviceLayer, "Connect Event for handle : %d", connHandle);
768
769     AddConnection(connHandle, bondingHandle);
770
771     // SetFlag(mFlags, kFlag_RestartAdvertising, true);
772     PlatformMgr().ScheduleWork(DriveBLEState, 0);
773 }
774
775 void BLEManagerImpl::HandleConnectionCloseEvent(volatile sl_bt_msg_t * evt)
776 {
777     sl_bt_evt_connection_closed_t * conn_evt = (sl_bt_evt_connection_closed_t *) &(evt->data);
778     uint8_t connHandle                       = conn_evt->connection;
779
780     ChipLogProgress(DeviceLayer, "Disconnect Event for handle : %d", connHandle);
781
782     if (RemoveConnection(connHandle))
783     {
784         ChipDeviceEvent event;
785         event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
786         event.CHIPoBLEConnectionError.ConId = connHandle;
787
788         switch (conn_evt->reason)
789         {
790         case bg_err_bt_remote_user_terminated:
791         case bg_err_bt_remote_device_terminated_connection_due_to_low_resources:
792         case bg_err_bt_remote_powering_off:
793             event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
794             break;
795
796         case bg_err_bt_connection_terminated_by_local_host:
797             event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
798             break;
799
800         default:
801             event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
802             break;
803         }
804
805         ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", connHandle, conn_evt->reason);
806
807         PlatformMgr().PostEvent(&event);
808
809         // Arrange to re-enable connectable advertising in case it was disabled due to the
810         // maximum connection limit being reached.
811         SetFlag(mFlags, kFlag_RestartAdvertising, true);
812         PlatformMgr().ScheduleWork(DriveBLEState, 0);
813     }
814 }
815
816 void BLEManagerImpl::HandleWriteEvent(volatile sl_bt_msg_t * evt)
817 {
818     uint16_t attribute = evt->data.evt_gatt_server_user_write_request.characteristic;
819
820     ChipLogProgress(DeviceLayer, "Char Write Req, char : %d", attribute);
821
822     if (gattdb_CHIPoBLEChar_Rx == attribute)
823     {
824         HandleRXCharWrite(evt);
825     }
826 }
827
828 void BLEManagerImpl::HandleTXCharCCCDWrite(volatile sl_bt_msg_t * evt)
829 {
830     CHIP_ERROR err = CHIP_NO_ERROR;
831     CHIPoBLEConState * bleConnState;
832     bool indicationsEnabled;
833     ChipDeviceEvent event;
834
835     bleConnState = GetConnectionState(evt->data.evt_gatt_server_user_write_request.connection);
836
837     VerifyOrExit(bleConnState != NULL, err = CHIP_ERROR_NO_MEMORY);
838
839     // Determine if the client is enabling or disabling indications.
840     indicationsEnabled = (evt->data.evt_gatt_server_characteristic_status.client_config_flags == gatt_indication);
841
842     ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
843
844     if (indicationsEnabled)
845     {
846         // If indications are not already enabled for the connection...
847         if (!bleConnState->subscribed)
848         {
849             bleConnState->subscribed = 1;
850             // Post an event to the CHIP queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
851             // whether the client is enabling or disabling indications.
852             {
853                 event.Type                    = DeviceEventType::kCHIPoBLESubscribe;
854                 event.CHIPoBLESubscribe.ConId = evt->data.evt_gatt_server_user_write_request.connection;
855                 PlatformMgr().PostEvent(&event);
856             }
857         }
858     }
859     else
860     {
861         bleConnState->subscribed      = 0;
862         event.Type                    = DeviceEventType::kCHIPoBLEUnsubscribe;
863         event.CHIPoBLESubscribe.ConId = evt->data.evt_gatt_server_user_write_request.connection;
864         PlatformMgr().PostEvent(&event);
865     }
866
867 exit:
868     if (err != CHIP_NO_ERROR)
869     {
870         ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
871     }
872 }
873
874 void BLEManagerImpl::HandleRXCharWrite(volatile sl_bt_msg_t * evt)
875 {
876     CHIP_ERROR err = CHIP_NO_ERROR;
877     System::PacketBufferHandle buf;
878     uint16_t writeLen = evt->data.evt_gatt_server_user_write_request.value.len;
879     uint8_t * data    = (uint8_t *) evt->data.evt_gatt_server_user_write_request.value.data;
880
881     // Copy the data to a packet buffer.
882     buf = System::PacketBufferHandle::NewWithData(data, writeLen, 0, 0);
883     VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
884
885     ChipLogDetail(DeviceLayer, "Write request/command received for CHIPoBLE RX characteristic (con %" PRIu16 ", len %" PRIu16 ")",
886                   evt->data.evt_gatt_server_user_write_request.connection, buf->DataLength());
887
888     // Post an event to the CHIP queue to deliver the data into the CHIP stack.
889     {
890         ChipDeviceEvent event;
891         event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
892         event.CHIPoBLEWriteReceived.ConId = evt->data.evt_gatt_server_user_write_request.connection;
893         event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
894         PlatformMgr().PostEvent(&event);
895     }
896
897 exit:
898     if (err != CHIP_NO_ERROR)
899     {
900         ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
901     }
902 }
903
904 void BLEManagerImpl::HandleTxConfirmationEvent(volatile sl_bt_msg_t * evt)
905 {
906     ChipDeviceEvent event;
907     uint8_t timerHandle = sInstance.GetTimerHandle(evt->data.evt_gatt_server_characteristic_status.connection);
908
909     ChipLogProgress(DeviceLayer, "Tx Confirmation received");
910
911     // stop indication confirmation timer
912     if (timerHandle < kMaxConnections)
913     {
914         ChipLogProgress(DeviceLayer, " stop soft timer");
915         sl_bt_system_set_soft_timer(0, timerHandle, false);
916     }
917
918     event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
919     event.CHIPoBLEIndicateConfirm.ConId = evt->data.evt_gatt_server_characteristic_status.connection;
920     PlatformMgr().PostEvent(&event);
921 }
922
923 void BLEManagerImpl::HandleSoftTimerEvent(volatile sl_bt_msg_t * evt)
924 {
925     // BLE Manager starts soft timers with timer handles less than kMaxConnections
926     // If we receive a callback for unknown timer handle ignore this.
927     if (evt->data.evt_system_soft_timer.handle < kMaxConnections)
928     {
929         ChipLogProgress(DeviceLayer, "BLEManagerImpl::HandleSoftTimerEvent CHIPOBLE_PROTOCOL_ABORT");
930         ChipDeviceEvent event;
931         event.Type                                                   = DeviceEventType::kCHIPoBLEConnectionError;
932         event.CHIPoBLEConnectionError.ConId                          = mIndConfId[evt->data.evt_system_soft_timer.handle];
933         sInstance.mIndConfId[evt->data.evt_system_soft_timer.handle] = kUnusedIndex;
934         event.CHIPoBLEConnectionError.Reason                         = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
935         PlatformMgr().PostEvent(&event);
936     }
937 }
938
939 bool BLEManagerImpl::RemoveConnection(uint8_t connectionHandle)
940 {
941     CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true);
942     bool status                     = false;
943
944     if (bleConnState != NULL)
945     {
946         memset(bleConnState, 0, sizeof(CHIPoBLEConState));
947         status = true;
948     }
949
950     return status;
951 }
952
953 void BLEManagerImpl::AddConnection(uint8_t connectionHandle, uint8_t bondingHandle)
954 {
955     CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true);
956
957     if (bleConnState != NULL)
958     {
959         memset(bleConnState, 0, sizeof(CHIPoBLEConState));
960         bleConnState->allocated        = 1;
961         bleConnState->connectionHandle = connectionHandle;
962         bleConnState->bondingHandle    = bondingHandle;
963     }
964 }
965
966 BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint8_t connectionHandle, bool allocate)
967 {
968     uint8_t freeIndex = kMaxConnections;
969
970     for (uint8_t i = 0; i < kMaxConnections; i++)
971     {
972         if (mBleConnections[i].allocated == 1)
973         {
974             if (mBleConnections[i].connectionHandle == connectionHandle)
975             {
976                 return &mBleConnections[i];
977             }
978         }
979
980         else if (i < freeIndex)
981         {
982             freeIndex = i;
983         }
984     }
985
986     if (allocate)
987     {
988         if (freeIndex < kMaxConnections)
989         {
990             return &mBleConnections[freeIndex];
991         }
992
993         ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
994     }
995
996     return NULL;
997 }
998
999 uint8_t BLEManagerImpl::GetTimerHandle(uint8_t connectionHandle, bool allocate)
1000 {
1001     uint8_t freeIndex = kMaxConnections;
1002
1003     for (uint8_t i = 0; i < kMaxConnections; i++)
1004     {
1005         if (mIndConfId[i] == connectionHandle)
1006         {
1007             return i;
1008         }
1009         else if (allocate)
1010         {
1011             if (i < freeIndex)
1012             {
1013                 freeIndex = i;
1014             }
1015         }
1016     }
1017
1018     if (freeIndex < kMaxConnections)
1019     {
1020         mIndConfId[freeIndex] = connectionHandle;
1021     }
1022     else
1023     {
1024         ChipLogError(DeviceLayer, "Failed to Save Conn Handle for indication");
1025     }
1026
1027     return freeIndex;
1028 }
1029
1030 void BLEManagerImpl::DriveBLEState(intptr_t arg)
1031 {
1032     sInstance.DriveBLEState();
1033 }
1034
1035 } // namespace Internal
1036 } // namespace DeviceLayer
1037 } // namespace chip
1038 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE