7396d486c882e08711083b854d742e22424ab124
[platform/upstream/connectedhomeip.git] / src / platform / Zephyr / BLEManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 /**
19  *    @file
20  *          Provides an implementation of the BLEManager singleton object
21  *          for Zephyr platforms.
22  */
23
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
25
26 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
27
28 #include <platform/Zephyr/BLEManagerImpl.h>
29
30 #include <ble/CHIPBleServiceData.h>
31 #include <platform/internal/BLEManager.h>
32 #include <support/CodeUtils.h>
33 #include <support/logging/CHIPLogging.h>
34
35 #include <logging/log.h>
36 #include <sys/byteorder.h>
37 #include <sys/util.h>
38
39 LOG_MODULE_DECLARE(chip);
40
41 using namespace ::chip;
42 using namespace ::chip::Ble;
43 using namespace ::chip::System;
44
45 namespace chip {
46 namespace DeviceLayer {
47 namespace Internal {
48
49 namespace {
50
51 const bt_uuid_128 UUID128_CHIPoBLEChar_RX =
52     BT_UUID_INIT_128(0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18);
53 const bt_uuid_128 UUID128_CHIPoBLEChar_TX =
54     BT_UUID_INIT_128(0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18);
55 bt_uuid_16 UUID16_CHIPoBLEService = BT_UUID_INIT_16(0xFEAF);
56
57 const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
58                                                  0x9D, 0x11 } };
59
60 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
61                                                  0x9D, 0x12 } };
62
63 _bt_gatt_ccc CHIPoBLEChar_TX_CCC = BT_GATT_CCC_INITIALIZER(nullptr, BLEManagerImpl::HandleTXCCCWrite, nullptr);
64
65 // clang-format off
66
67 BT_GATT_SERVICE_DEFINE(CHIPoBLE_Service,
68     BT_GATT_PRIMARY_SERVICE(&UUID16_CHIPoBLEService.uuid),
69         BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_RX.uuid,
70                                BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
71                                BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
72                                nullptr, BLEManagerImpl::HandleRXWrite, nullptr),
73         BT_GATT_CHARACTERISTIC(&UUID128_CHIPoBLEChar_TX.uuid,
74                                BT_GATT_CHRC_INDICATE,
75                                BT_GATT_PERM_NONE,
76                                nullptr, nullptr, nullptr),
77         BT_GATT_CCC_MANAGED(&CHIPoBLEChar_TX_CCC, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)
78 );
79
80 // clang-format on
81
82 // Index of the CCC descriptor in the CHIPoBLE_Service array of attributes.
83 // This value should be adjusted accordingly if the service declaration changes.
84 constexpr int kCHIPoBLE_CCC_AttributeIndex = 3;
85
86 } // unnamed namespace
87
88 BLEManagerImpl BLEManagerImpl::sInstance;
89
90 CHIP_ERROR BLEManagerImpl::_Init()
91 {
92     CHIP_ERROR err;
93
94     mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
95     mFlags       = CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? kFlag_AdvertisingEnabled : 0;
96     mGAPConns    = 0;
97
98     memset(mSubscribedConns, 0, sizeof(mSubscribedConns));
99
100     err = bt_enable(NULL);
101     VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
102
103     memset(&mConnCallbacks, 0, sizeof(mConnCallbacks));
104     mConnCallbacks.connected    = HandleConnect;
105     mConnCallbacks.disconnected = HandleDisconnect;
106
107     bt_conn_cb_register(&mConnCallbacks);
108
109     // Initialize the CHIP BleLayer.
110     err = BleLayer::Init(this, this, &SystemLayer);
111     SuccessOrExit(err);
112
113     PlatformMgr().ScheduleWork(DriveBLEState, 0);
114
115 exit:
116     return err;
117 }
118
119 void BLEManagerImpl::DriveBLEState(intptr_t arg)
120 {
121     BLEMgrImpl().DriveBLEState();
122 }
123
124 void BLEManagerImpl::DriveBLEState()
125 {
126     CHIP_ERROR err = CHIP_NO_ERROR;
127
128     ChipLogDetail(DeviceLayer, "In DriveBLEState");
129
130     // Perform any initialization actions that must occur after the CHIP task is running.
131     if (!GetFlag(mFlags, kFlag_AsyncInitCompleted))
132     {
133         SetFlag(mFlags, kFlag_AsyncInitCompleted);
134
135         // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
136         // disable CHIPoBLE advertising if the device is fully provisioned.
137 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
138         if (ConfigurationMgr().IsFullyProvisioned())
139         {
140             ClearFlag(mFlags, kFlag_AdvertisingEnabled);
141             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
142         }
143 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
144     }
145
146     // If the application has enabled CHIPoBLE and BLE advertising...
147     if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
148         GetFlag(mFlags, kFlag_AdvertisingEnabled)
149 #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
150         // and no connections are active...
151         && (NumConnections() == 0)
152 #endif
153     )
154     {
155         // Start/re-start advertising if not already advertising, or if the
156         // advertising state needs to be refreshed.
157         if (!GetFlag(mFlags, kFlag_Advertising) || GetFlag(mFlags, kFlag_AdvertisingRefreshNeeded))
158         {
159             err = StartAdvertising();
160             SuccessOrExit(err);
161         }
162     }
163     // Otherwise, stop advertising if currently active.
164     else
165     {
166         err = StopAdvertising();
167         SuccessOrExit(err);
168     }
169
170 exit:
171     if (err != CHIP_NO_ERROR)
172     {
173         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
174         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
175     }
176 }
177
178 struct BLEManagerImpl::ServiceData
179 {
180     uint8_t uuid[2];
181     ChipBLEDeviceIdentificationInfo deviceIdInfo;
182 } __attribute__((packed));
183
184 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
185 {
186     CHIP_ERROR err;
187
188     const char * deviceName   = bt_get_name();
189     const uint8_t advFlags    = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR;
190     bt_le_adv_param advParams = BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, GetAdvertisingInterval(),
191                                                      CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL, nullptr);
192
193     // Define advertising data
194     ServiceData serviceData;
195     bt_data ad[] = { BT_DATA(BT_DATA_FLAGS, &advFlags, sizeof(advFlags)),
196                      BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)),
197                      BT_DATA(BT_DATA_NAME_COMPLETE, deviceName, static_cast<uint8_t>(strlen(deviceName))) };
198
199     // Initialize service data
200     static_assert(sizeof(serviceData) == 9, "Size of BLE advertisement data changed! Was that intentional?");
201     chip::Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val);
202     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo);
203     SuccessOrExit(err);
204
205     // If necessary, inform the ThreadStackManager that CHIPoBLE advertising is about to start.
206 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
207     if (!GetFlag(mFlags, kFlag_Advertising))
208     {
209         ThreadStackMgr().OnCHIPoBLEAdvertisingStart();
210     }
211 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
212
213     // Restart advertising
214     err = bt_le_adv_stop();
215     VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
216
217     err = bt_le_adv_start(&advParams, ad, ARRAY_SIZE(ad), nullptr, 0u);
218     if (err == -ENOMEM)
219     {
220         // No free connection objects for connectable advertiser. Advertise as non-connectable instead.
221         advParams.options &= ~BT_LE_ADV_OPT_CONNECTABLE;
222         err = bt_le_adv_start(&advParams, ad, ARRAY_SIZE(ad), nullptr, 0u);
223     }
224
225     VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
226
227     // Transition to the Advertising state...
228     if (!GetFlag(mFlags, kFlag_Advertising))
229     {
230         ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
231
232         SetFlag(mFlags, kFlag_Advertising);
233
234         // Post a CHIPoBLEAdvertisingChange(Started) event.
235         {
236             ChipDeviceEvent advChange;
237             advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
238             advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
239             PlatformMgr().PostEvent(&advChange);
240         }
241
242         // Start timer to disable CHIPoBLE advertisement after timeout expiration
243         SystemLayer.StartTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT, HandleBLEAdvertisementTimeout, this);
244     }
245
246 exit:
247     return err;
248 }
249
250 CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
251 {
252     CHIP_ERROR err = CHIP_NO_ERROR;
253
254     err = bt_le_adv_stop();
255     VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
256
257     // Transition to the not Advertising state...
258     if (GetFlag(mFlags, kFlag_Advertising))
259     {
260         ClearFlag(mFlags, kFlag_Advertising);
261
262         ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
263
264 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
265         // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
266         ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
267 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
268
269         // Post a CHIPoBLEAdvertisingChange(Stopped) event.
270         {
271             ChipDeviceEvent advChange;
272             advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
273             advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
274             PlatformMgr().PostEvent(&advChange);
275         }
276
277         // Cancel timer event disabling CHIPoBLE advertisement after timeout expiration
278         SystemLayer.CancelTimer(HandleBLEAdvertisementTimeout, this);
279     }
280
281 exit:
282     return err;
283 }
284
285 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
286 {
287     CHIP_ERROR err = CHIP_NO_ERROR;
288
289     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
290     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
291
292     if (val != mServiceMode)
293     {
294         mServiceMode = val;
295         PlatformMgr().ScheduleWork(DriveBLEState, 0);
296     }
297
298 exit:
299     return err;
300 }
301
302 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
303 {
304     CHIP_ERROR err = CHIP_NO_ERROR;
305
306     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
307
308     if (GetFlag(mFlags, kFlag_AdvertisingEnabled) != val)
309     {
310         ChipLogDetail(DeviceLayer, "SetAdvertisingEnabled(%s)", val ? "true" : "false");
311
312         SetFlag(mFlags, kFlag_AdvertisingEnabled, val);
313         PlatformMgr().ScheduleWork(DriveBLEState, 0);
314     }
315
316 exit:
317     return err;
318 }
319
320 CHIP_ERROR BLEManagerImpl::_SetFastAdvertisingEnabled(bool val)
321 {
322     CHIP_ERROR err = CHIP_NO_ERROR;
323
324     VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
325
326     if (GetFlag(mFlags, kFlag_FastAdvertisingEnabled) != val)
327     {
328         ChipLogDetail(DeviceLayer, "SetFastAdvertisingEnabled(%s)", val ? "true" : "false");
329
330         SetFlag(mFlags, kFlag_FastAdvertisingEnabled, val);
331         PlatformMgr().ScheduleWork(DriveBLEState, 0);
332     }
333
334 exit:
335     return err;
336 }
337
338 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
339 {
340     size_t len = bufSize - 1;
341
342     strncpy(buf, bt_get_name(), len);
343     buf[len] = 0;
344
345     return CHIP_NO_ERROR;
346 }
347
348 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
349 {
350     if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
351     {
352         return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
353     }
354
355     ChipLogDetail(DeviceLayer, "Device name set to: %s", deviceName);
356     return MapErrorZephyr(bt_set_name(deviceName));
357 }
358
359 CHIP_ERROR BLEManagerImpl::HandleGAPConnect(const ChipDeviceEvent * event)
360 {
361     const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
362
363     if (connEvent->HciResult == BT_HCI_ERR_SUCCESS)
364     {
365         ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02" PRIx16 ")", bt_conn_index(connEvent->BtConn));
366         mGAPConns++;
367     }
368     else
369     {
370         ChipLogProgress(DeviceLayer, "BLE connection failed (reason: 0x%02" PRIx16 ")", connEvent->HciResult);
371     }
372
373     ChipLogProgress(DeviceLayer, "Current number of connections: %" PRIu16 "/%" PRIu16, NumConnections(), CONFIG_BT_MAX_CONN);
374
375     SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
376     PlatformMgr().ScheduleWork(DriveBLEState, 0);
377
378     bt_conn_unref(connEvent->BtConn);
379
380     return CHIP_NO_ERROR;
381 }
382
383 CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(const ChipDeviceEvent * event)
384 {
385     const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
386
387     ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02" PRIx16 ")", connEvent->HciResult);
388
389     mGAPConns--;
390
391     // If indications were enabled for this connection, record that they are now disabled and
392     // notify the BLE Layer of a disconnect.
393     if (UnsetSubscribed(connEvent->BtConn))
394     {
395         CHIP_ERROR disconReason;
396         switch (connEvent->HciResult)
397         {
398         case BT_HCI_ERR_REMOTE_USER_TERM_CONN:
399             // Do not treat proper connection termination as an error and exit.
400             VerifyOrExit(!ConfigurationMgr().IsFullyProvisioned(), );
401             disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
402             break;
403         case BT_HCI_ERR_LOCALHOST_TERM_CONN:
404             disconReason = BLE_ERROR_APP_CLOSED_CONNECTION;
405             break;
406         default:
407             disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
408             break;
409         }
410         HandleConnectionError(connEvent->BtConn, disconReason);
411     }
412
413 exit:
414     // Unref bt_conn before scheduling DriveBLEState.
415     bt_conn_unref(connEvent->BtConn);
416
417     ChipLogProgress(DeviceLayer, "Current number of connections: %" PRIu16 "/%" PRIu16, NumConnections(), CONFIG_BT_MAX_CONN);
418
419     // Force a reconfiguration of advertising in case we switched to non-connectable mode when
420     // the BLE connection was established.
421     SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
422     PlatformMgr().ScheduleWork(DriveBLEState, 0);
423
424     return CHIP_NO_ERROR;
425 }
426
427 CHIP_ERROR BLEManagerImpl::HandleTXCharCCCDWrite(const ChipDeviceEvent * event)
428 {
429     const BleCCCWriteEventType * writeEvent = &event->Platform.BleCCCWriteEvent;
430
431     ChipLogDetail(DeviceLayer, "ConnId: 0x%02" PRIx16 ", New CCCD value: 0x%04" PRIx16, bt_conn_index(writeEvent->BtConn),
432                   writeEvent->Value);
433
434     // If the client has requested to enabled indications and if it is not yet subscribed
435     if (writeEvent->Value == BT_GATT_CCC_INDICATE && SetSubscribed(writeEvent->BtConn))
436     {
437         // Alert the BLE layer that CHIPoBLE "subscribe" has been received and increment the bt_conn reference counter.
438         HandleSubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
439
440         ChipLogProgress(DeviceLayer, "CHIPoBLE connection established (ConnId: 0x%02" PRIx16 ", GATT MTU: %" PRIu16 ")",
441                         bt_conn_index(writeEvent->BtConn), GetMTU(writeEvent->BtConn));
442
443         // Post a CHIPoBLEConnectionEstablished event to the DeviceLayer and the application.
444         {
445             ChipDeviceEvent conEstEvent;
446             conEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
447             PlatformMgr().PostEvent(&conEstEvent);
448         }
449     }
450     else
451     {
452         if (UnsetSubscribed(writeEvent->BtConn))
453         {
454             HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
455         }
456     }
457
458     bt_conn_unref(writeEvent->BtConn);
459
460     return CHIP_NO_ERROR;
461 }
462
463 CHIP_ERROR BLEManagerImpl::HandleRXCharWrite(const ChipDeviceEvent * event)
464 {
465     const BleC1WriteEventType * c1WriteEvent = &event->Platform.BleC1WriteEvent;
466
467     ChipLogDetail(DeviceLayer, "Write request received for CHIPoBLE RX characteristic (ConnId 0x%02" PRIx16 ")",
468                   bt_conn_index(c1WriteEvent->BtConn));
469
470     HandleWriteReceived(c1WriteEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
471                         PacketBufferHandle::Adopt(c1WriteEvent->Data));
472     bt_conn_unref(c1WriteEvent->BtConn);
473
474     return CHIP_NO_ERROR;
475 }
476
477 CHIP_ERROR BLEManagerImpl::HandleTXComplete(const ChipDeviceEvent * event)
478 {
479     const BleC2IndDoneEventType * c2IndDoneEvent = &event->Platform.BleC2IndDoneEvent;
480
481     ChipLogDetail(DeviceLayer, "Indication for CHIPoBLE TX characteristic done (ConnId 0x%02" PRIx16 ", result 0x%02" PRIx16 ")",
482                   bt_conn_index(c2IndDoneEvent->BtConn), c2IndDoneEvent->Result);
483
484     // Signal the BLE Layer that the outstanding indication is complete.
485     HandleIndicationConfirmation(c2IndDoneEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
486     bt_conn_unref(c2IndDoneEvent->BtConn);
487
488     return CHIP_NO_ERROR;
489 }
490
491 void BLEManagerImpl::HandleBLEAdvertisementTimeout(System::Layer * layer, void * param, System::Error error)
492 {
493     BLEMgr().SetAdvertisingEnabled(false);
494     ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because of timeout expired");
495 }
496
497 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
498 {
499     CHIP_ERROR err = CHIP_NO_ERROR;
500
501     switch (event->Type)
502     {
503     case DeviceEventType::kPlatformZephyrBleConnected:
504         err = HandleGAPConnect(event);
505         break;
506
507     case DeviceEventType::kPlatformZephyrBleDisconnected:
508         err = HandleGAPDisconnect(event);
509         break;
510
511     case DeviceEventType::kPlatformZephyrBleCCCWrite:
512         err = HandleTXCharCCCDWrite(event);
513         break;
514
515     case DeviceEventType::kPlatformZephyrBleC1WriteEvent:
516         err = HandleRXCharWrite(event);
517         break;
518
519     case DeviceEventType::kPlatformZephyrBleC2IndDoneEvent:
520         err = HandleTXComplete(event);
521         break;
522
523     case DeviceEventType::kFabricMembershipChange:
524     case DeviceEventType::kServiceProvisioningChange:
525     case DeviceEventType::kAccountPairingChange:
526
527         // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
528         // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
529         // is now fully provisioned.
530 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
531         if (ConfigurationMgr().IsFullyProvisioned())
532         {
533             ClearFlag(mFlags, kFlag_AdvertisingEnabled);
534             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
535         }
536 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
537
538         // Force the advertising state to be refreshed to reflect new provisioning state.
539         SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
540
541         DriveBLEState();
542
543         break;
544
545     default:
546         break;
547     }
548
549     if (err != CHIP_NO_ERROR)
550     {
551         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
552         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
553         PlatformMgr().ScheduleWork(DriveBLEState, 0);
554     }
555 }
556
557 uint16_t BLEManagerImpl::_NumConnections(void)
558 {
559     return mGAPConns;
560 }
561
562 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
563 {
564     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (ConnId %02" PRIx16 ")", bt_conn_index(conId));
565     return bt_conn_disconnect(conId, BT_HCI_ERR_REMOTE_USER_TERM_CONN) == CHIP_NO_ERROR;
566 }
567
568 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
569 {
570     return bt_gatt_get_mtu(conId);
571 }
572
573 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
574 {
575     ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
576     return true;
577 }
578
579 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
580 {
581     ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
582     return true;
583 }
584
585 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
586                                     PacketBufferHandle pBuf)
587 {
588     CHIP_ERROR err                   = CHIP_NO_ERROR;
589     uint8_t index                    = bt_conn_index(conId);
590     bt_gatt_indicate_params * params = &mIndicateParams[index];
591
592     VerifyOrExit(IsSubscribed(conId) == true, err = CHIP_ERROR_INVALID_ARGUMENT);
593
594     ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE TX characteristic (ConnId %u, len %u)", index, pBuf->DataLength());
595
596     params->uuid = nullptr;
597     params->attr = &CHIPoBLE_Service.attrs[kCHIPoBLE_CCC_AttributeIndex];
598     params->func = HandleTXIndicated;
599     params->data = pBuf->Start();
600     params->len  = pBuf->DataLength();
601
602     err = bt_gatt_indicate(conId, params);
603     VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
604
605 exit:
606     if (err != CHIP_NO_ERROR)
607     {
608         ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
609     }
610
611     return err == CHIP_NO_ERROR;
612 }
613
614 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
615                                       PacketBufferHandle pBuf)
616 {
617     ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
618     return true;
619 }
620
621 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
622                                      PacketBufferHandle pBuf)
623 {
624     ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
625     return true;
626 }
627
628 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
629                                       const ChipBleUUID * svcId, const ChipBleUUID * charId)
630 {
631     ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
632     return true;
633 }
634
635 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
636 {
637     // Intentionally empty.
638 }
639
640 bool BLEManagerImpl::IsSubscribed(bt_conn * conn)
641 {
642     return mSubscribedConns[bt_conn_index(conn)];
643 }
644
645 bool BLEManagerImpl::SetSubscribed(bt_conn * conn)
646 {
647     uint8_t index           = bt_conn_index(conn);
648     bool isSubscribed       = mSubscribedConns[index];
649     mSubscribedConns[index] = true;
650
651     // If we were not subscribed previously, increment the reference counter of the connection.
652     if (!isSubscribed)
653     {
654         bt_conn_ref(conn);
655     }
656
657     return !isSubscribed;
658 }
659
660 bool BLEManagerImpl::UnsetSubscribed(bt_conn * conn)
661 {
662     uint8_t index           = bt_conn_index(conn);
663     bool isSubscribed       = mSubscribedConns[index];
664     mSubscribedConns[index] = false;
665
666     // If we were subscribed previously, decrement the reference counter of the connection.
667     if (isSubscribed)
668     {
669         bt_conn_unref(conn);
670     }
671
672     return isSubscribed;
673 }
674
675 uint32_t BLEManagerImpl::GetAdvertisingInterval()
676 {
677     return (NumConnections() == 0 && !ConfigurationMgr().IsFullyProvisioned()) || GetFlag(mFlags, kFlag_FastAdvertisingEnabled)
678         ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL
679         : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL;
680 }
681
682 ssize_t BLEManagerImpl::HandleRXWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, const void * buf, uint16_t len,
683                                       uint16_t offset, uint8_t flags)
684 {
685     ChipDeviceEvent event;
686     PacketBufferHandle packetBuf = PacketBufferHandle::NewWithData(buf, len);
687
688     // Unfortunately the Zephyr logging macros end up assigning uint16_t
689     // variables to uint16_t:10 fields, which triggers integer conversion
690     // warnings.  And treating the Zephyr headers as system headers does not
691     // help, apparently.  Just turn off that warning around this log call.
692 #pragma GCC diagnostic push
693 #pragma GCC diagnostic ignored "-Wconversion"
694     LOG_HEXDUMP_DBG(buf, len, "Rx char write");
695 #pragma GCC diagnostic pop
696
697     // If successful...
698     if (!packetBuf.IsNull())
699     {
700         // Arrange to post a CHIPoBLERXWriteEvent event to the CHIP queue.
701         event.Type                            = DeviceEventType::kPlatformZephyrBleC1WriteEvent;
702         event.Platform.BleC1WriteEvent.BtConn = bt_conn_ref(conId);
703         event.Platform.BleC1WriteEvent.Data   = std::move(packetBuf).UnsafeRelease();
704     }
705
706     // If we failed to allocate a buffer, post a kPlatformZephyrBleOutOfBuffersEvent event.
707     else
708     {
709         event.Type = DeviceEventType::kPlatformZephyrBleOutOfBuffersEvent;
710     }
711
712     PlatformMgr().PostEvent(&event);
713
714     return len;
715 }
716
717 ssize_t BLEManagerImpl::HandleTXCCCWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr, uint16_t value)
718 {
719     ChipDeviceEvent event;
720
721     if (value != BT_GATT_CCC_INDICATE && value != 0)
722     {
723         return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
724     }
725
726     event.Type                             = DeviceEventType::kPlatformZephyrBleCCCWrite;
727     event.Platform.BleCCCWriteEvent.BtConn = bt_conn_ref(conId);
728     event.Platform.BleCCCWriteEvent.Value  = value;
729
730     PlatformMgr().PostEvent(&event);
731
732     return sizeof(value);
733 }
734
735 void BLEManagerImpl::HandleTXIndicated(struct bt_conn * conId, IndicationAttrType, uint8_t err)
736 {
737     ChipDeviceEvent event;
738
739     event.Type                              = DeviceEventType::kPlatformZephyrBleC2IndDoneEvent;
740     event.Platform.BleC2IndDoneEvent.BtConn = bt_conn_ref(conId);
741     event.Platform.BleC2IndDoneEvent.Result = err;
742
743     PlatformMgr().PostEvent(&event);
744 }
745
746 void BLEManagerImpl::HandleConnect(struct bt_conn * conId, uint8_t err)
747 {
748     ChipDeviceEvent event;
749
750     event.Type                            = DeviceEventType::kPlatformZephyrBleConnected;
751     event.Platform.BleConnEvent.BtConn    = bt_conn_ref(conId);
752     event.Platform.BleConnEvent.HciResult = err;
753
754     PlatformMgr().PostEvent(&event);
755 }
756
757 void BLEManagerImpl::HandleDisconnect(struct bt_conn * conId, uint8_t reason)
758 {
759     ChipDeviceEvent event;
760
761     event.Type                            = DeviceEventType::kPlatformZephyrBleDisconnected;
762     event.Platform.BleConnEvent.BtConn    = bt_conn_ref(conId);
763     event.Platform.BleConnEvent.HciResult = reason;
764
765     PlatformMgr().PostEvent(&event);
766 }
767
768 } // namespace Internal
769 } // namespace DeviceLayer
770 } // namespace chip
771
772 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE