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