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