3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2018 Nest Labs, Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 * Provides an implementation of the BLEManager singleton object
23 * for the ESP32 platform.
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
28 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
30 #include "sdkconfig.h"
32 #if CONFIG_BT_BLUEDROID_ENABLED
34 #include <ble/CHIPBleServiceData.h>
35 #include <platform/internal/BLEManager.h>
36 #include <support/CodeUtils.h>
37 #include <support/logging/CHIPLogging.h>
40 #include "esp_bt_main.h"
41 #include "esp_gap_ble_api.h"
42 #include "esp_gatt_common_api.h"
43 #include "esp_gatts_api.h"
46 #define MAX_ADV_DATA_LEN 31
47 #define CHIP_ADV_DATA_TYPE_FLAGS 0x01
48 #define CHIP_ADV_DATA_FLAGS 0x06
49 #define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
51 using namespace ::chip;
52 using namespace ::chip::Ble;
55 namespace DeviceLayer {
60 struct ESP32ChipServiceData
62 uint8_t ServiceUUID[2];
63 ChipBLEDeviceIdentificationInfo DeviceIdInfo;
66 const uint16_t CHIPoBLEAppId = 0x235A;
68 const uint8_t UUID_PrimaryService[] = { 0x00, 0x28 };
69 const uint8_t UUID_CharDecl[] = { 0x03, 0x28 };
70 const uint8_t UUID_ClientCharConfigDesc[] = { 0x02, 0x29 };
71 const uint8_t UUID_CHIPoBLEService[] = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
72 0x00, 0x10, 0x00, 0x00, 0xAF, 0xFE, 0x00, 0x00 };
73 const uint8_t ShortUUID_CHIPoBLEService[] = { 0xAF, 0xFE };
74 const uint8_t UUID_CHIPoBLEChar_RX[] = { 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95,
75 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 };
76 const uint8_t UUID_CHIPoBLEChar_TX[] = { 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95,
77 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 };
78 const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
80 const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
83 const uint8_t CharProps_ReadNotify = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
84 const uint8_t CharProps_Write = ESP_GATT_CHAR_PROP_BIT_WRITE;
86 // Offsets into CHIPoBLEGATTAttrs for specific attributes.
89 kAttrIndex_ServiceDeclaration = 0,
90 kAttrIndex_RXCharValue = 2,
91 kAttrIndex_TXCharValue = 4,
92 kAttrIndex_TXCharCCCDValue = 5,
95 // Table of attribute definitions for Chip over BLE GATT service.
96 const esp_gatts_attr_db_t CHIPoBLEGATTAttrs[] = {
97 // Service Declaration for Chip over BLE Service
98 { { ESP_GATT_AUTO_RSP },
99 { ESP_UUID_LEN_16, (uint8_t *) UUID_PrimaryService, ESP_GATT_PERM_READ, ESP_UUID_LEN_16, ESP_UUID_LEN_16,
100 (uint8_t *) ShortUUID_CHIPoBLEService } },
102 // ----- Chip over BLE RX Characteristic -----
104 // Characteristic declaration
105 { { ESP_GATT_AUTO_RSP },
106 { ESP_UUID_LEN_16, (uint8_t *) UUID_CharDecl, ESP_GATT_PERM_READ, 1, 1, (uint8_t *) &CharProps_Write } },
107 // Characteristic value
108 { { ESP_GATT_RSP_BY_APP }, { ESP_UUID_LEN_128, (uint8_t *) UUID_CHIPoBLEChar_RX, ESP_GATT_PERM_WRITE, 512, 0, NULL } },
110 // ----- Chip over BLE TX Characteristic -----
112 // Characteristic declaration
113 { { ESP_GATT_AUTO_RSP },
114 { ESP_UUID_LEN_16, (uint8_t *) UUID_CharDecl, ESP_GATT_PERM_READ, 1, 1, (uint8_t *) &CharProps_ReadNotify } },
115 // Characteristic value
116 { { ESP_GATT_RSP_BY_APP }, { ESP_UUID_LEN_128, (uint8_t *) UUID_CHIPoBLEChar_TX, ESP_GATT_PERM_READ, 512, 0, NULL } },
117 // Client characteristic configuration description (CCCD) value
118 { { ESP_GATT_RSP_BY_APP },
119 { ESP_UUID_LEN_16, (uint8_t *) UUID_ClientCharConfigDesc, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 2, 0, NULL } },
122 const uint16_t CHIPoBLEGATTAttrCount = sizeof(CHIPoBLEGATTAttrs) / sizeof(CHIPoBLEGATTAttrs[0]);
124 } // unnamed namespace
126 BLEManagerImpl BLEManagerImpl::sInstance;
128 BLEManagerImpl::BLEManagerImpl() {}
130 CHIP_ERROR BLEManagerImpl::_Init()
134 // Initialize the Chip BleLayer.
135 err = BleLayer::Init(this, this, &SystemLayer);
138 memset(mCons, 0, sizeof(mCons));
139 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
140 mAppIf = ESP_GATT_IF_NONE;
141 mServiceAttrHandle = 0;
142 mRXCharAttrHandle = 0;
143 mTXCharAttrHandle = 0;
144 mTXCharCCCDAttrHandle = 0;
145 mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
146 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
147 memset(mDeviceName, 0, sizeof(mDeviceName));
149 PlatformMgr().ScheduleWork(DriveBLEState, 0);
155 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
157 CHIP_ERROR err = CHIP_NO_ERROR;
159 VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
160 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
162 if (val != mServiceMode)
165 PlatformMgr().ScheduleWork(DriveBLEState, 0);
172 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
174 CHIP_ERROR err = CHIP_NO_ERROR;
176 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
178 if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
180 mFlags.Set(Flags::kAdvertisingEnabled, val);
181 PlatformMgr().ScheduleWork(DriveBLEState, 0);
188 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
192 case BLEAdvertisingMode::kFastAdvertising:
193 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
195 case BLEAdvertisingMode::kSlowAdvertising:
196 mFlags.Set(Flags::kFastAdvertisingEnabled, false);
199 return CHIP_ERROR_INVALID_ARGUMENT;
201 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
202 PlatformMgr().ScheduleWork(DriveBLEState, 0);
203 return CHIP_NO_ERROR;
206 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
208 if (strlen(mDeviceName) >= bufSize)
210 return CHIP_ERROR_BUFFER_TOO_SMALL;
212 strcpy(buf, mDeviceName);
213 return CHIP_NO_ERROR;
216 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
218 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
220 return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
222 if (deviceName != NULL && deviceName[0] != 0)
224 if (strlen(deviceName) >= kMaxDeviceNameLength)
226 return CHIP_ERROR_INVALID_ARGUMENT;
228 strcpy(mDeviceName, deviceName);
229 mFlags.Set(Flags::kUseCustomDeviceName);
234 mFlags.Clear(Flags::kUseCustomDeviceName);
236 return CHIP_NO_ERROR;
239 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
243 case DeviceEventType::kCHIPoBLESubscribe:
244 HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
246 ChipDeviceEvent connectionEvent;
247 connectionEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
248 PlatformMgr().PostEvent(&connectionEvent);
252 case DeviceEventType::kCHIPoBLEUnsubscribe:
253 HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
256 case DeviceEventType::kCHIPoBLEWriteReceived:
257 HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
258 PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
261 case DeviceEventType::kCHIPoBLEIndicateConfirm:
262 HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
265 case DeviceEventType::kCHIPoBLEConnectionError:
266 HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
269 case DeviceEventType::kFabricMembershipChange:
270 case DeviceEventType::kServiceProvisioningChange:
271 case DeviceEventType::kAccountPairingChange:
272 case DeviceEventType::kWiFiConnectivityChange:
273 // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
274 // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
275 // is now fully provisioned.
276 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
277 if (ConfigurationMgr().IsFullyProvisioned())
279 mFlags.Clear(Flags::kAdvertisingEnabled);
280 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
282 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
284 // Force the advertising configuration to be refreshed to reflect new provisioning state.
285 ChipLogProgress(DeviceLayer, "Updating advertising data");
286 mFlags.Clear(Flags::kAdvertisingConfigured);
287 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
296 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
298 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
302 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
304 ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
308 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
312 ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
314 // Signal the ESP BLE layer to close the conntion.
315 err = esp_ble_gatts_close(mAppIf, conId);
316 if (err != CHIP_NO_ERROR)
318 ChipLogError(DeviceLayer, "esp_ble_gatts_close() failed: %s", ErrorStr(err));
321 // Release the associated connection state record.
322 ReleaseConnectionState(conId);
324 // Force a refresh of the advertising state.
325 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
326 mFlags.Clear(Flags::kAdvertisingConfigured);
327 PlatformMgr().ScheduleWork(DriveBLEState, 0);
329 return (err == CHIP_NO_ERROR);
332 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
334 CHIPoBLEConState * conState = const_cast<BLEManagerImpl *>(this)->GetConnectionState(conId);
335 return (conState != NULL) ? conState->MTU : 0;
338 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
339 PacketBufferHandle data)
341 CHIP_ERROR err = CHIP_NO_ERROR;
342 CHIPoBLEConState * conState = GetConnectionState(conId);
344 ESP_LOGD(TAG, "Sending indication for CHIPoBLE TX characteristic (con %u, len %u)", conId, data->DataLength());
346 VerifyOrExit(conState != NULL, err = CHIP_ERROR_INVALID_ARGUMENT);
348 VerifyOrExit(conState->PendingIndBuf.IsNull(), err = CHIP_ERROR_INCORRECT_STATE);
350 err = esp_ble_gatts_send_indicate(mAppIf, conId, mTXCharAttrHandle, data->DataLength(), data->Start(), false);
351 if (err != CHIP_NO_ERROR)
353 ChipLogError(DeviceLayer, "esp_ble_gatts_send_indicate() failed: %s", ErrorStr(err));
357 // Save a reference to the buffer until we get a indication from the ESP BLE layer that it
359 conState->PendingIndBuf = std::move(data);
362 if (err != CHIP_NO_ERROR)
364 ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
370 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
371 PacketBufferHandle pBuf)
373 ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
377 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
378 PacketBufferHandle pBuf)
380 ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
384 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
385 const ChipBleUUID * svcId, const ChipBleUUID * charId)
387 ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
391 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) {}
393 void BLEManagerImpl::DriveBLEState(void)
395 CHIP_ERROR err = CHIP_NO_ERROR;
397 // Perform any initialization actions that must occur after the Chip task is running.
398 if (!mFlags.Has(Flags::kAsyncInitCompleted))
400 mFlags.Set(Flags::kAsyncInitCompleted);
402 // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
403 // disable CHIPoBLE advertising if the device is fully provisioned.
404 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
405 if (ConfigurationMgr().IsFullyProvisioned())
407 mFlags.Clear(Flags::kAdvertisingEnabled);
408 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
410 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
413 // If there's already a control operation in progress, wait until it completes.
414 VerifyOrExit(!mFlags.Has(Flags::kControlOpInProgress), /* */);
416 // Initializes the ESP BLE layer if needed.
417 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kESPBLELayerInitialized))
419 err = InitESPBleLayer();
423 // Register the CHIPoBLE application with the ESP BLE layer if needed.
424 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAppRegistered))
426 err = esp_ble_gatts_app_register(CHIPoBLEAppId);
427 if (err != CHIP_NO_ERROR)
429 ChipLogError(DeviceLayer, "esp_ble_gatts_app_register() failed: %s", ErrorStr(err));
433 mFlags.Set(Flags::kControlOpInProgress);
438 // Register the CHIPoBLE GATT attributes with the ESP BLE layer if needed.
439 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kAttrsRegistered))
441 err = esp_ble_gatts_create_attr_tab(CHIPoBLEGATTAttrs, mAppIf, CHIPoBLEGATTAttrCount, 0);
442 if (err != CHIP_NO_ERROR)
444 ChipLogError(DeviceLayer, "esp_ble_gatts_create_attr_tab() failed: %s", ErrorStr(err));
448 mFlags.Set(Flags::kControlOpInProgress);
453 // Start the CHIPoBLE GATT service if needed.
454 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kGATTServiceStarted))
456 err = esp_ble_gatts_start_service(mServiceAttrHandle);
457 if (err != CHIP_NO_ERROR)
459 ChipLogError(DeviceLayer, "esp_ble_gatts_start_service() failed: %s", ErrorStr(err));
463 mFlags.Set(Flags::kControlOpInProgress);
468 // If the application has enabled CHIPoBLE and BLE advertising...
469 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
470 mFlags.Has(Flags::kAdvertisingEnabled)
471 #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
472 // and no connections are active...
473 && (_NumConnections() == 0)
477 // Start/re-start advertising if not already advertising, or if the advertising state of the
478 // ESP BLE layer needs to be refreshed.
479 if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
481 // Configure advertising data if it hasn't been done yet. This is an asynchronous step which
482 // must complete before advertising can be started. When that happens, this method will
483 // be called again, and execution will proceed to the code below.
484 if (!mFlags.Has(Flags::kAdvertisingConfigured))
486 err = ConfigureAdvertisingData();
490 // Start advertising. This is also an asynchronous step.
491 err = StartAdvertising();
496 // Otherwise stop advertising if needed...
499 if (mFlags.Has(Flags::kAdvertising))
501 err = esp_ble_gap_stop_advertising();
502 if (err != CHIP_NO_ERROR)
504 ChipLogError(DeviceLayer, "esp_ble_gap_stop_advertising() failed: %s", ErrorStr(err));
508 mFlags.Set(Flags::kControlOpInProgress);
514 // Stop the CHIPoBLE GATT service if needed.
515 if (mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kGATTServiceStarted))
517 // TODO: what to do about existing connections??
519 err = esp_ble_gatts_stop_service(mServiceAttrHandle);
520 if (err != CHIP_NO_ERROR)
522 ChipLogError(DeviceLayer, "esp_ble_gatts_stop_service() failed: %s", ErrorStr(err));
526 mFlags.Set(Flags::kControlOpInProgress);
532 if (err != CHIP_NO_ERROR)
534 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
535 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
539 CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
541 CHIP_ERROR err = CHIP_NO_ERROR;
543 VerifyOrExit(!mFlags.Has(Flags::kESPBLELayerInitialized), /* */);
545 // If the ESP Bluetooth controller has not been initialized...
546 if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE)
548 // Since Chip only uses BLE, release memory held by ESP classic bluetooth stack.
549 err = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
550 if (err != CHIP_NO_ERROR)
552 ChipLogError(DeviceLayer, "esp_bt_controller_mem_release() failed: %s", ErrorStr(err));
556 // Initialize the ESP Bluetooth controller.
557 esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
558 err = esp_bt_controller_init(&bt_cfg);
559 if (err != CHIP_NO_ERROR)
561 ChipLogError(DeviceLayer, "esp_bt_controller_init() failed: %s", ErrorStr(err));
566 // If the ESP Bluetooth controller has not been enabled, enable it now.
567 if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED)
569 err = esp_bt_controller_enable(ESP_BT_MODE_BLE);
570 if (err != CHIP_NO_ERROR)
572 ChipLogError(DeviceLayer, "esp_bt_controller_enable() failed: %s", ErrorStr(err));
577 // If the ESP Bluedroid stack has not been initialized, initialize it now.
578 if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED)
580 err = esp_bluedroid_init();
581 if (err != CHIP_NO_ERROR)
583 ChipLogError(DeviceLayer, "esp_bluedroid_init() failed: %s", ErrorStr(err));
588 // If the ESP Bluedroid stack has not been enabled, enable it now.
589 if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED)
591 err = esp_bluedroid_enable();
592 if (err != CHIP_NO_ERROR)
594 ChipLogError(DeviceLayer, "esp_bluedroid_enable() failed: %s", ErrorStr(err));
599 // Register a callback to receive GATT events.
600 err = esp_ble_gatts_register_callback(HandleGATTEvent);
601 if (err != CHIP_NO_ERROR)
603 ChipLogError(DeviceLayer, "esp_ble_gatts_register_callback() failed: %s", ErrorStr(err));
607 // Register a callback to receive GAP events.
608 err = esp_ble_gap_register_callback(HandleGAPEvent);
609 if (err != CHIP_NO_ERROR)
611 ChipLogError(DeviceLayer, "esp_ble_gap_register_callback() failed: %s", ErrorStr(err));
615 // Set the maximum supported MTU size.
616 err = esp_ble_gatt_set_local_mtu(ESP_GATT_MAX_MTU_SIZE);
617 if (err != CHIP_NO_ERROR)
619 ChipLogError(DeviceLayer, "esp_ble_gatt_set_local_mtu() failed: %s", ErrorStr(err));
623 mFlags.Set(Flags::kESPBLELayerInitialized);
629 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
632 uint8_t advData[MAX_ADV_DATA_LEN];
635 // If a custom device name has not been specified, generate a CHIP-standard name based on the
636 // discriminator value
637 uint16_t discriminator;
638 SuccessOrExit(err = ConfigurationMgr().GetSetupDiscriminator(discriminator));
640 if (!mFlags.Has(Flags::kUseCustomDeviceName))
642 snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
643 mDeviceName[kMaxDeviceNameLength] = 0;
646 // Configure the BLE device name.
647 err = esp_ble_gap_set_device_name(mDeviceName);
648 if (err != CHIP_NO_ERROR)
650 ChipLogError(DeviceLayer, "esp_ble_gap_set_device_name() failed: %s", ErrorStr(err));
654 memset(advData, 0, sizeof(advData));
655 advData[index++] = 0x02; // length
656 advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
657 advData[index++] = CHIP_ADV_DATA_FLAGS; // AD value
658 advData[index++] = 0x0A; // length
659 advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type: (Service Data - 16-bit UUID)
660 advData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value
661 advData[index++] = ShortUUID_CHIPoBLEService[1]; // AD value
663 chip::Ble::ChipBLEDeviceIdentificationInfo deviceIdInfo;
664 err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
665 if (err != CHIP_NO_ERROR)
667 ChipLogError(DeviceLayer, "GetBLEDeviceIdentificationInfo(): ", ErrorStr(err));
671 VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = BLE_ERROR_OUTBOUND_MESSAGE_TOO_BIG);
672 memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo));
673 index = static_cast<uint8_t>(index + sizeof(deviceIdInfo));
675 // Construct the Chip BLE Service Data to be sent in the scan response packet.
676 err = esp_ble_gap_config_adv_data_raw(advData, sizeof(advData));
677 if (err != CHIP_NO_ERROR)
679 ChipLogError(DeviceLayer, "esp_ble_gap_config_adv_data_raw(<raw_data>) failed: %s", ErrorStr(err));
683 mFlags.Set(Flags::kControlOpInProgress);
689 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
692 esp_ble_adv_params_t advertParams = {
695 ADV_TYPE_IND, // adv_type
696 BLE_ADDR_TYPE_PUBLIC, // own_addr_type
698 BLE_ADDR_TYPE_RANDOM, // peer_addr_type
699 ADV_CHNL_ALL, // channel_map
700 ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // adv_filter_policy
703 // Inform the ThreadStackManager that CHIPoBLE advertising is about to start.
704 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
705 ThreadStackMgr().OnCHIPoBLEAdvertisingStart();
706 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
708 // Advertise connectable if we haven't reached the maximum number of connections.
709 size_t numCons = NumConnections();
710 bool connectable = (numCons < kMaxConnections);
711 advertParams.adv_type = connectable ? ADV_TYPE_IND : ADV_TYPE_NONCONN_IND;
713 // Advertise in fast mode if not fully provisioned and there are no CHIPoBLE connections, or
714 // if the application has expressly requested fast advertising.
715 if ((numCons == 0 && !ConfigurationMgr().IsPairedToAccount()) || mFlags.Has(Flags::kFastAdvertisingEnabled))
717 advertParams.adv_int_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
718 advertParams.adv_int_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
722 advertParams.adv_int_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
723 advertParams.adv_int_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
726 ChipLogProgress(DeviceLayer, "Configuring CHIPoBLE advertising (interval %" PRIu32 " ms, %sconnectable, device name %s)",
727 (((uint32_t) advertParams.adv_int_min) * 10) / 16, (connectable) ? "" : "non-", mDeviceName);
729 err = esp_ble_gap_start_advertising(&advertParams);
730 if (err != CHIP_NO_ERROR)
732 ChipLogError(DeviceLayer, "esp_ble_gap_start_advertising() failed: %s", ErrorStr(err));
736 mFlags.Set(Flags::kControlOpInProgress);
742 void BLEManagerImpl::HandleGATTControlEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param)
744 CHIP_ERROR err = CHIP_NO_ERROR;
745 bool controlOpComplete = false;
747 // Ignore GATT control events that do not pertain to the CHIPoBLE application, except for ESP_GATTS_REG_EVT.
748 if (event != ESP_GATTS_REG_EVT && (!mFlags.Has(Flags::kAppRegistered) || gatts_if != mAppIf))
755 case ESP_GATTS_REG_EVT:
757 if (param->reg.app_id == CHIPoBLEAppId)
759 if (param->reg.status != ESP_GATT_OK)
761 ChipLogError(DeviceLayer, "ESP_GATTS_REG_EVT error: %d", (int) param->reg.status);
762 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
765 // Save the 'interface type' assigned to the CHIPoBLE application by the ESP BLE layer.
768 mFlags.Set(Flags::kAppRegistered);
769 controlOpComplete = true;
774 case ESP_GATTS_CREAT_ATTR_TAB_EVT:
776 if (param->add_attr_tab.status != ESP_GATT_OK)
778 ChipLogError(DeviceLayer, "ESP_GATTS_CREAT_ATTR_TAB_EVT error: %d", (int) param->add_attr_tab.status);
779 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
782 // Save the attribute handles assigned by the ESP BLE layer to the CHIPoBLE attributes.
783 mServiceAttrHandle = param->add_attr_tab.handles[kAttrIndex_ServiceDeclaration];
784 mRXCharAttrHandle = param->add_attr_tab.handles[kAttrIndex_RXCharValue];
785 mTXCharAttrHandle = param->add_attr_tab.handles[kAttrIndex_TXCharValue];
786 mTXCharCCCDAttrHandle = param->add_attr_tab.handles[kAttrIndex_TXCharCCCDValue];
788 mFlags.Set(Flags::kAttrsRegistered);
789 controlOpComplete = true;
793 case ESP_GATTS_START_EVT:
795 if (param->start.status != ESP_GATT_OK)
797 ChipLogError(DeviceLayer, "ESP_GATTS_START_EVT error: %d", (int) param->start.status);
798 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
801 ChipLogProgress(DeviceLayer, "CHIPoBLE GATT service started");
803 mFlags.Set(Flags::kGATTServiceStarted);
804 controlOpComplete = true;
808 case ESP_GATTS_STOP_EVT:
810 if (param->stop.status != ESP_GATT_OK)
812 ChipLogError(DeviceLayer, "ESP_GATTS_STOP_EVT error: %d", (int) param->stop.status);
813 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
816 ChipLogProgress(DeviceLayer, "CHIPoBLE GATT service stopped");
818 mFlags.Clear(Flags::kGATTServiceStarted);
819 controlOpComplete = true;
823 case ESP_GATTS_RESPONSE_EVT:
824 ESP_LOGD(TAG, "ESP_GATTS_RESPONSE_EVT (handle %u, status %d)", param->rsp.handle, (int) param->rsp.status);
828 // Ignore all other event types.
833 if (err != CHIP_NO_ERROR)
835 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
836 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
838 if (controlOpComplete)
840 mFlags.Clear(Flags::kControlOpInProgress);
841 PlatformMgr().ScheduleWork(DriveBLEState, 0);
845 void BLEManagerImpl::HandleGATTCommEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param)
847 // Ignore the event if the CHIPoBLE service hasn't been started, or if the event is for a different
849 if (!sInstance.mFlags.Has(Flags::kGATTServiceStarted) || gatts_if != sInstance.mAppIf)
856 case ESP_GATTS_CONNECT_EVT:
857 ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", param->connect.conn_id);
859 // Allocate a connection state record for the new connection.
860 GetConnectionState(param->mtu.conn_id, true);
862 // Receiving a connection stops the advertising processes. So force a refresh of the advertising
864 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
865 mFlags.Clear(Flags::kAdvertisingConfigured);
866 PlatformMgr().ScheduleWork(DriveBLEState, 0);
870 case ESP_GATTS_DISCONNECT_EVT:
871 HandleDisconnect(param);
874 case ESP_GATTS_READ_EVT:
875 if (param->read.handle == mTXCharAttrHandle)
877 HandleTXCharRead(param);
879 if (param->read.handle == mTXCharCCCDAttrHandle)
881 HandleTXCharCCCDRead(param);
885 case ESP_GATTS_WRITE_EVT:
886 if (param->write.handle == mRXCharAttrHandle)
888 HandleRXCharWrite(param);
890 if (param->write.handle == mTXCharCCCDAttrHandle)
892 HandleTXCharCCCDWrite(param);
896 case ESP_GATTS_CONF_EVT: {
897 CHIPoBLEConState * conState = GetConnectionState(param->conf.conn_id);
898 if (conState != NULL)
900 HandleTXCharConfirm(conState, param);
905 case ESP_GATTS_MTU_EVT: {
906 ESP_LOGD(TAG, "MTU for con %u: %u", param->mtu.conn_id, param->mtu.mtu);
907 CHIPoBLEConState * conState = GetConnectionState(param->mtu.conn_id);
908 if (conState != NULL)
910 // conState->MTU is a 10-bit field inside a uint16_t. We're
911 // assigning to it from a uint16_t, and compilers warn about
912 // possibly not fitting. There's no way to suppress that warning
913 // via explicit cast; we have to disable the warning around the
916 // TODO: https://github.com/project-chip/connectedhomeip/issues/2569
917 // tracks making this safe with a check or explaining why no check
919 #pragma GCC diagnostic push
920 #pragma GCC diagnostic ignored "-Wconversion"
921 conState->MTU = param->mtu.mtu;
922 #pragma GCC diagnostic pop
932 void BLEManagerImpl::HandleRXCharWrite(esp_ble_gatts_cb_param_t * param)
934 CHIP_ERROR err = CHIP_NO_ERROR;
935 bool needResp = param->write.need_rsp;
936 PacketBufferHandle buf;
938 ESP_LOGD(TAG, "Write request received for CHIPoBLE RX characteristic (con %u, len %u)", param->write.conn_id, param->write.len);
940 // Disallow long writes.
941 VerifyOrExit(param->write.is_prep == false, err = CHIP_ERROR_INVALID_ARGUMENT);
943 // Copy the data to a packet buffer.
944 buf = System::PacketBufferHandle::NewWithData(param->write.value, param->write.len, 0, 0);
945 VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
947 // Send a response if requested.
950 esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
954 // Post an event to the Chip queue to deliver the data into the Chip stack.
956 ChipDeviceEvent event;
957 event.Type = DeviceEventType::kCHIPoBLEWriteReceived;
958 event.CHIPoBLEWriteReceived.ConId = param->write.conn_id;
959 event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease();
960 PlatformMgr().PostEvent(&event);
964 if (err != CHIP_NO_ERROR)
966 ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
969 esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_INTERNAL_ERROR, NULL);
971 // TODO: fail connection???
975 void BLEManagerImpl::HandleTXCharRead(esp_ble_gatts_cb_param_t * param)
980 ESP_LOGD(TAG, "Read request received for CHIPoBLE TX characteristic (con %u)", param->read.conn_id);
982 // Send a zero-length response.
983 memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
984 rsp.attr_value.handle = param->read.handle;
985 err = esp_ble_gatts_send_response(mAppIf, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
986 if (err != CHIP_NO_ERROR)
988 ChipLogError(DeviceLayer, "esp_ble_gatts_send_response() failed: %s", ErrorStr(err));
992 void BLEManagerImpl::HandleTXCharCCCDRead(esp_ble_gatts_cb_param_t * param)
995 CHIPoBLEConState * conState;
998 ESP_LOGD(TAG, "Read request received for CHIPoBLE TX characteristic CCCD (con %u)", param->read.conn_id);
1000 // Find the connection state record.
1001 conState = GetConnectionState(param->read.conn_id);
1003 // Send current CCCD value, or an error if we failed to allocate a connection state object.
1004 memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
1005 rsp.attr_value.handle = param->read.handle;
1006 if (conState != NULL)
1008 rsp.attr_value.len = 2;
1009 rsp.attr_value.value[0] = conState->Subscribed ? 1 : 0;
1011 err = esp_ble_gatts_send_response(mAppIf, param->read.conn_id, param->read.trans_id,
1012 (conState != NULL) ? ESP_GATT_OK : ESP_GATT_INTERNAL_ERROR, &rsp);
1013 if (err != CHIP_NO_ERROR)
1015 ChipLogError(DeviceLayer, "esp_ble_gatts_send_response() failed: %s", ErrorStr(err));
1019 void BLEManagerImpl::HandleTXCharCCCDWrite(esp_ble_gatts_cb_param_t * param)
1021 CHIP_ERROR err = CHIP_NO_ERROR;
1022 CHIPoBLEConState * conState;
1023 bool needResp = param->write.need_rsp;
1024 bool indicationsEnabled;
1026 ESP_LOGD(TAG, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", param->write.conn_id,
1029 // Find the connection state record.
1030 conState = GetConnectionState(param->read.conn_id);
1031 VerifyOrExit(conState != NULL, err = CHIP_ERROR_NO_MEMORY);
1033 // Disallow long writes.
1034 VerifyOrExit(param->write.is_prep == false, err = CHIP_ERROR_INVALID_ARGUMENT);
1036 // Determine if the client is enabling or disabling indications.
1037 indicationsEnabled = (param->write.len > 0 && (param->write.value[0] != 0));
1039 // Send a response to the Write if requested.
1042 esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
1046 // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
1047 // whether the client is enabling or disabling indications.
1049 ChipDeviceEvent event;
1050 event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
1051 event.CHIPoBLESubscribe.ConId = param->write.conn_id;
1052 PlatformMgr().PostEvent(&event);
1055 ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
1058 if (err != CHIP_NO_ERROR)
1060 ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
1063 esp_ble_gatts_send_response(mAppIf, param->write.conn_id, param->write.trans_id, ESP_GATT_INTERNAL_ERROR, NULL);
1065 // TODO: fail connection???
1069 void BLEManagerImpl::HandleTXCharConfirm(CHIPoBLEConState * conState, esp_ble_gatts_cb_param_t * param)
1071 ESP_LOGD(TAG, "Confirm received for CHIPoBLE TX characteristic indication (con %u, status %u)", param->conf.conn_id,
1072 param->conf.status);
1074 // If there is a pending indication buffer for the connection, release it now.
1075 conState->PendingIndBuf = nullptr;
1077 // If the confirmation was successful...
1078 if (param->conf.status == ESP_GATT_OK)
1080 // Post an event to the Chip queue to process the indicate confirmation.
1081 ChipDeviceEvent event;
1082 event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm;
1083 event.CHIPoBLEIndicateConfirm.ConId = param->conf.conn_id;
1084 PlatformMgr().PostEvent(&event);
1089 ChipDeviceEvent event;
1090 event.Type = DeviceEventType::kCHIPoBLEConnectionError;
1091 event.CHIPoBLEConnectionError.ConId = param->disconnect.conn_id;
1092 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
1093 PlatformMgr().PostEvent(&event);
1097 void BLEManagerImpl::HandleDisconnect(esp_ble_gatts_cb_param_t * param)
1099 ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", param->disconnect.conn_id,
1100 param->disconnect.reason);
1102 // If this was a CHIPoBLE connection, release the associated connection state record
1103 // and post an event to deliver a connection error to the CHIPoBLE layer.
1104 if (ReleaseConnectionState(param->disconnect.conn_id))
1106 ChipDeviceEvent event;
1107 event.Type = DeviceEventType::kCHIPoBLEConnectionError;
1108 event.CHIPoBLEConnectionError.ConId = param->disconnect.conn_id;
1109 switch (param->disconnect.reason)
1111 case ESP_GATT_CONN_TERMINATE_PEER_USER:
1112 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
1114 case ESP_GATT_CONN_TERMINATE_LOCAL_HOST:
1115 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
1118 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
1121 PlatformMgr().PostEvent(&event);
1123 // Force a refresh of the advertising state.
1124 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
1125 mFlags.Clear(Flags::kAdvertisingConfigured);
1126 PlatformMgr().ScheduleWork(DriveBLEState, 0);
1130 BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint16_t conId, bool allocate)
1132 uint16_t freeIndex = kMaxConnections;
1134 for (uint16_t i = 0; i < kMaxConnections; i++)
1136 if (mCons[i].Allocated == 1)
1138 if (mCons[i].ConId == conId)
1144 else if (i < freeIndex)
1152 if (freeIndex < kMaxConnections)
1154 mCons[freeIndex].Set(conId);
1155 return &mCons[freeIndex];
1158 ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
1164 bool BLEManagerImpl::ReleaseConnectionState(uint16_t conId)
1166 for (uint16_t i = 0; i < kMaxConnections; i++)
1168 if (mCons[i].Allocated && mCons[i].ConId == conId)
1178 uint16_t BLEManagerImpl::_NumConnections(void)
1180 uint16_t numCons = 0;
1181 for (uint16_t i = 0; i < kMaxConnections; i++)
1183 if (mCons[i].Allocated)
1192 void BLEManagerImpl::HandleGATTEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param)
1194 ESP_LOGV(TAG, "GATT Event: %d (if %d)", (int) event, (int) gatts_if);
1196 // This method is invoked on the ESP BLE thread. Therefore we must hold a lock
1197 // on the Chip stack while processing the event.
1198 PlatformMgr().LockChipStack();
1200 sInstance.HandleGATTControlEvent(event, gatts_if, param);
1201 sInstance.HandleGATTCommEvent(event, gatts_if, param);
1203 PlatformMgr().UnlockChipStack();
1206 void BLEManagerImpl::HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param)
1208 CHIP_ERROR err = CHIP_NO_ERROR;
1210 ESP_LOGV(TAG, "GAP Event: %d", (int) event);
1212 // This method is invoked on the ESP BLE thread. Therefore we must hold a lock
1213 // on the Chip stack while processing the event.
1214 PlatformMgr().LockChipStack();
1218 case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
1220 if (param->adv_data_cmpl.status != ESP_BT_STATUS_SUCCESS)
1222 ChipLogError(DeviceLayer, "ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT error: %d", (int) param->adv_data_cmpl.status);
1223 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
1226 sInstance.mFlags.Set(Flags::kAdvertisingConfigured);
1227 sInstance.mFlags.Clear(Flags::kControlOpInProgress);
1231 case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
1233 if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS)
1235 ChipLogError(DeviceLayer, "ESP_GAP_BLE_ADV_START_COMPLETE_EVT error: %d", (int) param->adv_start_cmpl.status);
1236 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
1239 sInstance.mFlags.Clear(Flags::kControlOpInProgress);
1240 sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
1242 // Transition to the Advertising state...
1243 if (!sInstance.mFlags.Has(Flags::kAdvertising))
1245 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
1247 sInstance.mFlags.Set(Flags::kAdvertising);
1249 // Post a CHIPoBLEAdvertisingChange(Started) event.
1251 ChipDeviceEvent advChange;
1252 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
1253 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
1254 PlatformMgr().PostEvent(&advChange);
1260 case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
1262 if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS)
1264 ChipLogError(DeviceLayer, "ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT error: %d", (int) param->adv_stop_cmpl.status);
1265 ExitNow(err = ESP_ERR_INVALID_RESPONSE);
1268 sInstance.mFlags.Clear(Flags::kControlOpInProgress);
1269 sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
1271 // Transition to the not Advertising state...
1272 if (sInstance.mFlags.Has(Flags::kAdvertising))
1274 sInstance.mFlags.Clear(Flags::kAdvertising);
1275 sInstance.mFlags.Set(Flags::kFastAdvertisingEnabled, true);
1277 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
1279 // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
1280 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
1281 ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
1282 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
1284 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
1286 ChipDeviceEvent advChange;
1287 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
1288 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
1289 PlatformMgr().PostEvent(&advChange);
1300 if (err != CHIP_NO_ERROR)
1302 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
1303 sInstance.mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
1305 PlatformMgr().ScheduleWork(DriveBLEState, 0);
1306 PlatformMgr().UnlockChipStack();
1309 void BLEManagerImpl::DriveBLEState(intptr_t arg)
1311 sInstance.DriveBLEState();
1314 } // namespace Internal
1315 } // namespace DeviceLayer
1318 #endif // CONFIG_BT_BLUEDROID_ENABLED
1320 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE