3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * Provides an implementation of the BLEManager singleton object
21 * for Zephyr platforms.
24 #ifndef GENERIC_BLE_MANAGER_IMPL_ZEPHYR_IPP
25 #define GENERIC_BLE_MANAGER_IMPL_ZEPHYR_IPP
27 #include <platform/Zephyr/GenericBLEManagerImpl_Zephyr.h>
29 #include <ble/CHIPBleServiceData.h>
30 #include <platform/internal/BLEManager.h>
31 #include <support/CodeUtils.h>
32 #include <support/logging/CHIPLogging.h>
34 #include <logging/log.h>
35 #include <sys/byteorder.h>
38 LOG_MODULE_DECLARE(chip);
40 using namespace ::chip;
41 using namespace ::chip::Ble;
42 using namespace ::chip::System;
45 namespace DeviceLayer {
48 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
49 template class GenericBLEManagerImpl_Zephyr<BLEManagerImpl>;
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);
59 const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
62 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
65 _bt_gatt_ccc CHIPoBLEChar_TX_CCC =
66 BT_GATT_CCC_INITIALIZER(nullptr, GenericBLEManagerImpl_Zephyr<BLEManagerImpl>::HandleTXCCCWrite, nullptr);
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,
79 nullptr, nullptr, nullptr),
80 BT_GATT_CCC_MANAGED(&CHIPoBLEChar_TX_CCC, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)
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;
89 } // unnamed namespace
91 template <class ImplClass>
92 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::_Init()
96 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
97 mFlags = CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? kFlag_AdvertisingEnabled : 0;
100 memset(mSubscribedConns, 0, sizeof(mSubscribedConns));
102 err = bt_enable(NULL);
103 VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
105 memset(&mConnCallbacks, 0, sizeof(mConnCallbacks));
106 mConnCallbacks.connected = HandleConnect;
107 mConnCallbacks.disconnected = HandleDisconnect;
109 bt_conn_cb_register(&mConnCallbacks);
111 // Initialize the CHIP BleLayer.
112 err = BleLayer::Init(this, this, &SystemLayer);
115 PlatformMgr().ScheduleWork(DriveBLEState, 0);
121 template <class ImplClass>
122 void GenericBLEManagerImpl_Zephyr<ImplClass>::DriveBLEState(intptr_t arg)
124 BLEMgrImpl().DriveBLEState();
127 template <class ImplClass>
128 void GenericBLEManagerImpl_Zephyr<ImplClass>::DriveBLEState()
130 CHIP_ERROR err = CHIP_NO_ERROR;
132 ChipLogDetail(DeviceLayer, "In DriveBLEState");
134 // Perform any initialization actions that must occur after the CHIP task is running.
135 if (!GetFlag(mFlags, kFlag_AsyncInitCompleted))
137 SetFlag(mFlags, kFlag_AsyncInitCompleted);
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())
144 ClearFlag(mFlags, kFlag_AdvertisingEnabled);
145 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
147 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
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)
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))
163 err = StartAdvertising();
167 // Otherwise, stop advertising if currently active.
170 err = StopAdvertising();
175 if (err != CHIP_NO_ERROR)
177 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
178 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
182 template <class ImplClass>
183 struct GenericBLEManagerImpl_Zephyr<ImplClass>::ServiceData
186 ChipBLEDeviceIdentificationInfo deviceIdInfo;
187 } __attribute__((packed));
189 template <class ImplClass>
190 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::StartAdvertising(void)
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);
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))) };
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);
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))
215 ThreadStackMgr().OnCHIPoBLEAdvertisingStart();
217 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
219 // Restart advertising
220 err = bt_le_adv_stop();
221 VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
223 err = bt_le_adv_start(&advParams, ad, ARRAY_SIZE(ad), nullptr, 0u);
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);
231 VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
233 // Transition to the Advertising state...
234 if (!GetFlag(mFlags, kFlag_Advertising))
236 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
238 SetFlag(mFlags, kFlag_Advertising);
240 // Post a CHIPoBLEAdvertisingChange(Started) event.
242 ChipDeviceEvent advChange;
243 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
244 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
245 PlatformMgr().PostEvent(&advChange);
248 // Start timer to disable CHIPoBLE advertisement after timeout expiration
249 SystemLayer.StartTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT, HandleBLEAdvertisementTimeout, this);
256 template <class ImplClass>
257 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::StopAdvertising(void)
259 CHIP_ERROR err = CHIP_NO_ERROR;
261 err = bt_le_adv_stop();
262 VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
264 // Transition to the not Advertising state...
265 if (GetFlag(mFlags, kFlag_Advertising))
267 ClearFlag(mFlags, kFlag_Advertising);
269 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
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
276 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
278 ChipDeviceEvent advChange;
279 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
280 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
281 PlatformMgr().PostEvent(&advChange);
284 // Cancel timer event disabling CHIPoBLE advertisement after timeout expiration
285 SystemLayer.CancelTimer(HandleBLEAdvertisementTimeout, this);
292 template <class ImplClass>
293 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
295 CHIP_ERROR err = CHIP_NO_ERROR;
297 VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
298 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
300 if (val != mServiceMode)
303 PlatformMgr().ScheduleWork(DriveBLEState, 0);
310 template <class ImplClass>
311 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::_SetAdvertisingEnabled(bool val)
313 CHIP_ERROR err = CHIP_NO_ERROR;
315 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
317 if (GetFlag(mFlags, kFlag_AdvertisingEnabled) != val)
319 ChipLogDetail(DeviceLayer, "SetAdvertisingEnabled(%s)", val ? "true" : "false");
321 SetFlag(mFlags, kFlag_AdvertisingEnabled, val);
322 PlatformMgr().ScheduleWork(DriveBLEState, 0);
329 template <class ImplClass>
330 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::_SetFastAdvertisingEnabled(bool val)
332 CHIP_ERROR err = CHIP_NO_ERROR;
334 VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
336 if (GetFlag(mFlags, kFlag_FastAdvertisingEnabled) != val)
338 ChipLogDetail(DeviceLayer, "SetFastAdvertisingEnabled(%s)", val ? "true" : "false");
340 SetFlag(mFlags, kFlag_FastAdvertisingEnabled, val);
341 PlatformMgr().ScheduleWork(DriveBLEState, 0);
348 template <class ImplClass>
349 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::_GetDeviceName(char * buf, size_t bufSize)
351 size_t len = bufSize - 1;
353 strncpy(buf, bt_get_name(), len);
356 return CHIP_NO_ERROR;
359 template <class ImplClass>
360 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::_SetDeviceName(const char * deviceName)
362 if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
364 return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
367 ChipLogDetail(DeviceLayer, "Device name set to: %s", deviceName);
368 return MapErrorZephyr(bt_set_name(deviceName));
371 template <class ImplClass>
372 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::HandleGAPConnect(const ChipDeviceEvent * event)
374 const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
376 if (connEvent->HciResult == BT_HCI_ERR_SUCCESS)
378 ChipLogProgress(DeviceLayer, "BLE connection established (ConnId: 0x%02" PRIx16 ")", bt_conn_index(connEvent->BtConn));
383 ChipLogProgress(DeviceLayer, "BLE connection failed (reason: 0x%02" PRIx16 ")", connEvent->HciResult);
386 ChipLogProgress(DeviceLayer, "Current number of connections: %" PRIu16 "/%" PRIu16, NumConnections(), CONFIG_BT_MAX_CONN);
388 SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
389 PlatformMgr().ScheduleWork(DriveBLEState, 0);
391 bt_conn_unref(connEvent->BtConn);
393 return CHIP_NO_ERROR;
396 template <class ImplClass>
397 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::HandleGAPDisconnect(const ChipDeviceEvent * event)
399 const BleConnEventType * connEvent = &event->Platform.BleConnEvent;
401 ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (reason 0x%02" PRIx16 ")", connEvent->HciResult);
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))
409 CHIP_ERROR disconReason;
410 switch (connEvent->HciResult)
412 case BT_HCI_ERR_REMOTE_USER_TERM_CONN:
413 disconReason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
415 case BT_HCI_ERR_LOCALHOST_TERM_CONN:
416 disconReason = BLE_ERROR_APP_CLOSED_CONNECTION;
419 disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
422 HandleConnectionError(connEvent->BtConn, disconReason);
425 // Unref bt_conn before scheduling DriveBLEState.
426 bt_conn_unref(connEvent->BtConn);
428 ChipLogProgress(DeviceLayer, "Current number of connections: %" PRIu16 "/%" PRIu16, NumConnections(), CONFIG_BT_MAX_CONN);
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);
435 return CHIP_NO_ERROR;
438 template <class ImplClass>
439 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::HandleTXCharCCCDWrite(const ChipDeviceEvent * event)
441 const BleCCCWriteEventType * writeEvent = &event->Platform.BleCCCWriteEvent;
443 ChipLogDetail(DeviceLayer, "ConnId: 0x%02" PRIx16 ", New CCCD value: 0x%04" PRIx16, bt_conn_index(writeEvent->BtConn),
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))
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);
452 ChipLogProgress(DeviceLayer, "CHIPoBLE connection established (ConnId: 0x%02" PRIx16 ", GATT MTU: %" PRIu16 ")",
453 bt_conn_index(writeEvent->BtConn), GetMTU(writeEvent->BtConn));
455 // Post a CHIPoBLEConnectionEstablished event to the DeviceLayer and the application.
457 ChipDeviceEvent conEstEvent;
458 conEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
459 PlatformMgr().PostEvent(&conEstEvent);
464 if (UnsetSubscribed(writeEvent->BtConn))
466 HandleUnsubscribeReceived(writeEvent->BtConn, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
470 bt_conn_unref(writeEvent->BtConn);
472 return CHIP_NO_ERROR;
475 template <class ImplClass>
476 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::HandleRXCharWrite(const ChipDeviceEvent * event)
478 const BleC1WriteEventType * c1WriteEvent = &event->Platform.BleC1WriteEvent;
480 ChipLogDetail(DeviceLayer, "Write request received for CHIPoBLE RX characteristic (ConnId 0x%02" PRIx16 ")",
481 bt_conn_index(c1WriteEvent->BtConn));
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);
488 return CHIP_NO_ERROR;
491 template <class ImplClass>
492 CHIP_ERROR GenericBLEManagerImpl_Zephyr<ImplClass>::HandleTXComplete(const ChipDeviceEvent * event)
494 const BleC2IndDoneEventType * c2IndDoneEvent = &event->Platform.BleC2IndDoneEvent;
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);
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);
503 return CHIP_NO_ERROR;
506 template <class ImplClass>
507 void GenericBLEManagerImpl_Zephyr<ImplClass>::HandleBLEAdvertisementTimeout(System::Layer * layer, void * param,
510 BLEMgr().SetAdvertisingEnabled(false);
511 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because of timeout expired");
514 template <class ImplClass>
515 void GenericBLEManagerImpl_Zephyr<ImplClass>::_OnPlatformEvent(const ChipDeviceEvent * event)
517 CHIP_ERROR err = CHIP_NO_ERROR;
521 case DeviceEventType::kPlatformZephyrBleConnected:
522 err = HandleGAPConnect(event);
525 case DeviceEventType::kPlatformZephyrBleDisconnected:
526 err = HandleGAPDisconnect(event);
529 case DeviceEventType::kPlatformZephyrBleCCCWrite:
530 err = HandleTXCharCCCDWrite(event);
533 case DeviceEventType::kPlatformZephyrBleC1WriteEvent:
534 err = HandleRXCharWrite(event);
537 case DeviceEventType::kPlatformZephyrBleC2IndDoneEvent:
538 err = HandleTXComplete(event);
541 case DeviceEventType::kFabricMembershipChange:
542 case DeviceEventType::kServiceProvisioningChange:
543 case DeviceEventType::kAccountPairingChange:
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())
551 ClearFlag(mFlags, kFlag_AdvertisingEnabled);
552 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
554 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
556 // Force the advertising state to be refreshed to reflect new provisioning state.
557 SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
567 if (err != CHIP_NO_ERROR)
569 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
570 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
571 PlatformMgr().ScheduleWork(DriveBLEState, 0);
575 template <class ImplClass>
576 uint16_t GenericBLEManagerImpl_Zephyr<ImplClass>::_NumConnections(void)
581 template <class ImplClass>
582 bool GenericBLEManagerImpl_Zephyr<ImplClass>::CloseConnection(BLE_CONNECTION_OBJECT conId)
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;
588 template <class ImplClass>
589 uint16_t GenericBLEManagerImpl_Zephyr<ImplClass>::GetMTU(BLE_CONNECTION_OBJECT conId) const
591 return bt_gatt_get_mtu(conId);
594 template <class ImplClass>
595 bool GenericBLEManagerImpl_Zephyr<ImplClass>::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
596 const ChipBleUUID * charId)
598 ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
602 template <class ImplClass>
603 bool GenericBLEManagerImpl_Zephyr<ImplClass>::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
604 const ChipBleUUID * charId)
606 ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
610 template <class ImplClass>
611 bool GenericBLEManagerImpl_Zephyr<ImplClass>::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
612 const ChipBleUUID * charId, PacketBufferHandle pBuf)
614 CHIP_ERROR err = CHIP_NO_ERROR;
615 uint8_t index = bt_conn_index(conId);
616 bt_gatt_indicate_params * params = &mIndicateParams[index];
618 VerifyOrExit(IsSubscribed(conId) == true, err = CHIP_ERROR_INVALID_ARGUMENT);
620 ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE TX characteristic (ConnId %u, len %u)", index, pBuf->DataLength());
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();
628 err = bt_gatt_indicate(conId, params);
629 VerifyOrExit(err == CHIP_NO_ERROR, err = MapErrorZephyr(err));
632 if (err != CHIP_NO_ERROR)
634 ChipLogError(DeviceLayer, "GenericBLEManagerImpl_Zephyr<ImplClass>::SendIndication() failed: %s", ErrorStr(err));
637 return err == CHIP_NO_ERROR;
640 template <class ImplClass>
641 bool GenericBLEManagerImpl_Zephyr<ImplClass>::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
642 const ChipBleUUID * charId, PacketBufferHandle pBuf)
644 ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
648 template <class ImplClass>
649 bool GenericBLEManagerImpl_Zephyr<ImplClass>::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
650 const ChipBleUUID * charId, PacketBufferHandle pBuf)
652 ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
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)
660 ChipLogError(DeviceLayer, "%s: NOT IMPLEMENTED", __PRETTY_FUNCTION__);
664 template <class ImplClass>
665 void GenericBLEManagerImpl_Zephyr<ImplClass>::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
667 // Intentionally empty.
670 template <class ImplClass>
671 bool GenericBLEManagerImpl_Zephyr<ImplClass>::IsSubscribed(bt_conn * conn)
673 return mSubscribedConns[bt_conn_index(conn)];
676 template <class ImplClass>
677 bool GenericBLEManagerImpl_Zephyr<ImplClass>::SetSubscribed(bt_conn * conn)
679 uint8_t index = bt_conn_index(conn);
680 bool isSubscribed = mSubscribedConns[index];
681 mSubscribedConns[index] = true;
683 // If we were not subscribed previously, increment the reference counter of the connection.
689 return !isSubscribed;
692 template <class ImplClass>
693 bool GenericBLEManagerImpl_Zephyr<ImplClass>::UnsetSubscribed(bt_conn * conn)
695 uint8_t index = bt_conn_index(conn);
696 bool isSubscribed = mSubscribedConns[index];
697 mSubscribedConns[index] = false;
699 // If we were subscribed previously, decrement the reference counter of the connection.
708 template <class ImplClass>
709 uint32_t GenericBLEManagerImpl_Zephyr<ImplClass>::GetAdvertisingInterval()
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;
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)
720 ChipDeviceEvent event;
721 PacketBufferHandle packetBuf = PacketBuffer::NewWithAvailableSize(len);
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
733 if (!packetBuf.IsNull())
735 // Copy the characteristic value into the packet buffer.
736 memcpy(packetBuf->Start(), buf, len);
737 packetBuf->SetDataLength(len);
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();
745 // If we failed to allocate a buffer, post a kPlatformZephyrBleOutOfBuffersEvent event.
748 event.Type = DeviceEventType::kPlatformZephyrBleOutOfBuffersEvent;
751 PlatformMgr().PostEvent(&event);
756 template <class ImplClass>
757 ssize_t GenericBLEManagerImpl_Zephyr<ImplClass>::HandleTXCCCWrite(struct bt_conn * conId, const struct bt_gatt_attr * attr,
760 ChipDeviceEvent event;
762 if (value != BT_GATT_CCC_INDICATE && value != 0)
764 return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
767 event.Type = DeviceEventType::kPlatformZephyrBleCCCWrite;
768 event.Platform.BleCCCWriteEvent.BtConn = bt_conn_ref(conId);
769 event.Platform.BleCCCWriteEvent.Value = value;
771 PlatformMgr().PostEvent(&event);
773 return sizeof(value);
776 template <class ImplClass>
777 void GenericBLEManagerImpl_Zephyr<ImplClass>::HandleTXIndicated(struct bt_conn * conId, const struct bt_gatt_attr * attr,
780 ChipDeviceEvent event;
782 event.Type = DeviceEventType::kPlatformZephyrBleC2IndDoneEvent;
783 event.Platform.BleC2IndDoneEvent.BtConn = bt_conn_ref(conId);
784 event.Platform.BleC2IndDoneEvent.Result = err;
786 PlatformMgr().PostEvent(&event);
789 template <class ImplClass>
790 void GenericBLEManagerImpl_Zephyr<ImplClass>::HandleConnect(struct bt_conn * conId, uint8_t err)
792 ChipDeviceEvent event;
794 event.Type = DeviceEventType::kPlatformZephyrBleConnected;
795 event.Platform.BleConnEvent.BtConn = bt_conn_ref(conId);
796 event.Platform.BleConnEvent.HciResult = err;
798 PlatformMgr().PostEvent(&event);
801 template <class ImplClass>
802 void GenericBLEManagerImpl_Zephyr<ImplClass>::HandleDisconnect(struct bt_conn * conId, uint8_t reason)
804 ChipDeviceEvent event;
806 event.Type = DeviceEventType::kPlatformZephyrBleDisconnected;
807 event.Platform.BleConnEvent.BtConn = bt_conn_ref(conId);
808 event.Platform.BleConnEvent.HciResult = reason;
810 PlatformMgr().PostEvent(&event);
813 } // namespace Internal
814 } // namespace DeviceLayer
817 #endif // GENERIC_BLE_MANAGER_IMPL_ZEPHYR_IPP