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.
28 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
30 #include "sdkconfig.h"
32 #if CONFIG_BT_BLUEDROID_ENABLED
34 #include "core/CHIPCallback.h"
36 #include "esp_gap_ble_api.h"
37 #include "esp_gatts_api.h"
38 #elif CONFIG_BT_NIMBLE_ENABLED
40 /* min max macros in NimBLE can cause build issues with generic min max
41 * functions defined in CHIP.*/
44 #include "host/ble_hs.h"
49 struct ble_gatt_char_context
53 struct ble_gatt_access_ctxt * ctxt;
60 namespace DeviceLayer {
64 * Concrete implementation of the BLEManager singleton object for the ESP32 platform.
66 class BLEManagerImpl final : public BLEManager,
67 private Ble::BleLayer,
68 private Ble::BlePlatformDelegate,
69 private Ble::BleApplicationDelegate
75 // Allow the BLEManager interface class to delegate method calls to
76 // the implementation methods provided by this class.
79 // ===== Members that implement the BLEManager internal interface.
81 CHIP_ERROR _Init(void);
82 CHIPoBLEServiceMode _GetCHIPoBLEServiceMode(void);
83 CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val);
84 bool _IsAdvertisingEnabled(void);
85 CHIP_ERROR _SetAdvertisingEnabled(bool val);
86 bool _IsAdvertising(void);
87 CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode);
88 CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize);
89 CHIP_ERROR _SetDeviceName(const char * deviceName);
90 uint16_t _NumConnections(void);
91 void _OnPlatformEvent(const ChipDeviceEvent * event);
92 ::chip::Ble::BleLayer * _GetBleLayer(void);
94 // ===== Members that implement virtual methods on BlePlatformDelegate.
96 bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
97 const Ble::ChipBleUUID * charId) override;
98 bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
99 const Ble::ChipBleUUID * charId) override;
100 bool CloseConnection(BLE_CONNECTION_OBJECT conId) override;
101 uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override;
102 bool SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
103 System::PacketBufferHandle pBuf) override;
104 bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
105 System::PacketBufferHandle pBuf) override;
106 bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
107 System::PacketBufferHandle pBuf) override;
108 bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const Ble::ChipBleUUID * svcId,
109 const Ble::ChipBleUUID * charId) override;
111 // ===== Members that implement virtual methods on BleApplicationDelegate.
113 void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override;
115 // ===== Members for internal use by the following friends.
117 friend BLEManager & BLEMgr(void);
118 friend BLEManagerImpl & BLEMgrImpl(void);
120 static BLEManagerImpl sInstance;
122 // ===== Private members reserved for use by this class only.
124 enum class Flags : uint16_t
126 kAsyncInitCompleted = 0x0001, /**< One-time asynchronous initialization actions have been performed. */
127 kESPBLELayerInitialized = 0x0002, /**< The ESP BLE layer has been initialized. */
128 kAppRegistered = 0x0004, /**< The CHIPoBLE application has been registered with the ESP BLE layer. */
129 kAttrsRegistered = 0x0008, /**< The CHIPoBLE GATT attributes have been registered with the ESP BLE layer. */
130 kGATTServiceStarted = 0x0010, /**< The CHIPoBLE GATT service has been started. */
131 kAdvertisingConfigured = 0x0020, /**< CHIPoBLE advertising has been configured in the ESP BLE layer. */
132 kAdvertising = 0x0040, /**< The system is currently CHIPoBLE advertising. */
133 kControlOpInProgress = 0x0080, /**< An async control operation has been issued to the ESP BLE layer. */
134 kAdvertisingEnabled = 0x0100, /**< The application has enabled CHIPoBLE advertising. */
135 kFastAdvertisingEnabled = 0x0200, /**< The application has enabled fast advertising. */
136 kUseCustomDeviceName = 0x0400, /**< The application has configured a custom BLE device name. */
137 kAdvertisingRefreshNeeded = 0x0800, /**< The advertising configuration/state in ESP BLE layer needs to be updated. */
142 kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS,
143 kMaxDeviceNameLength = 16
146 #if CONFIG_BT_NIMBLE_ENABLED
147 uint16_t mSubscribedConIds[kMaxConnections];
150 struct CHIPoBLEConState
152 System::PacketBufferHandle PendingIndBuf;
155 uint16_t Allocated : 1;
156 uint16_t Subscribed : 1;
159 void Set(uint16_t conId)
161 PendingIndBuf = nullptr;
170 PendingIndBuf = nullptr;
171 ConId = BLE_CONNECTION_UNINITIALIZED;
179 CHIPoBLEConState mCons[kMaxConnections];
180 CHIPoBLEServiceMode mServiceMode;
181 #if CONFIG_BT_BLUEDROID_ENABLED
182 esp_gatt_if_t mAppIf;
183 #elif CONFIG_BT_NIMBLE_ENABLED
184 uint16_t mNumGAPCons;
186 uint16_t mServiceAttrHandle;
187 uint16_t mRXCharAttrHandle;
188 uint16_t mTXCharAttrHandle;
189 uint16_t mTXCharCCCDAttrHandle;
190 BitFlags<Flags> mFlags;
191 char mDeviceName[kMaxDeviceNameLength + 1];
193 void DriveBLEState(void);
194 CHIP_ERROR InitESPBleLayer(void);
195 CHIP_ERROR ConfigureAdvertisingData(void);
196 CHIP_ERROR StartAdvertising(void);
198 #if CONFIG_BT_BLUEDROID_ENABLED
199 void HandleGATTControlEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
200 void HandleGATTCommEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
201 void HandleRXCharWrite(esp_ble_gatts_cb_param_t * param);
202 void HandleTXCharRead(esp_ble_gatts_cb_param_t * param);
203 void HandleTXCharCCCDRead(esp_ble_gatts_cb_param_t * param);
204 void HandleTXCharCCCDWrite(esp_ble_gatts_cb_param_t * param);
205 void HandleTXCharConfirm(CHIPoBLEConState * conState, esp_ble_gatts_cb_param_t * param);
206 void HandleDisconnect(esp_ble_gatts_cb_param_t * param);
207 CHIPoBLEConState * GetConnectionState(uint16_t conId, bool allocate = false);
208 bool ReleaseConnectionState(uint16_t conId);
210 static void HandleGATTEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
211 static void HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
213 #elif CONFIG_BT_NIMBLE_ENABLED
214 static constexpr uint32_t kAdvertiseTimeout = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT;
215 static constexpr uint32_t kFastAdvertiseTimeout = CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME;
216 uint64_t mAdvertiseStartTime;
217 chip::Callback::Callback<> mAdvertiseTimerCallback;
218 chip::Callback::Callback<> mFastAdvertiseTimerCallback;
220 static void HandleFastAdvertisementTimer(void * context);
221 void HandleFastAdvertisementTimer();
222 static void HandleAdvertisementTimer(void * context);
223 void HandleAdvertisementTimer();
225 void HandleRXCharRead(struct ble_gatt_char_context * param);
226 void HandleRXCharWrite(struct ble_gatt_char_context * param);
227 void HandleTXCharWrite(struct ble_gatt_char_context * param);
228 void HandleTXCharRead(struct ble_gatt_char_context * param);
229 void HandleTXCharCCCDRead(void * param);
230 void HandleTXCharCCCDWrite(struct ble_gap_event * gapEvent);
231 CHIP_ERROR HandleTXComplete(struct ble_gap_event * gapEvent);
232 CHIP_ERROR HandleGAPConnect(struct ble_gap_event * gapEvent);
233 CHIP_ERROR HandleGAPDisconnect(struct ble_gap_event * gapEvent);
234 CHIP_ERROR SetSubscribed(uint16_t conId);
235 bool UnsetSubscribed(uint16_t conId);
236 bool IsSubscribed(uint16_t conId);
238 static void bleprph_host_task(void * param);
239 static void bleprph_on_sync(void);
240 static void bleprph_on_reset(int);
241 static const struct ble_gatt_svc_def CHIPoBLEGATTAttrs[];
242 static int ble_svr_gap_event(struct ble_gap_event * event, void * arg);
244 static int gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg);
247 static void DriveBLEState(intptr_t arg);
251 * Returns a reference to the public interface of the BLEManager singleton object.
253 * Internal components should use this to access features of the BLEManager object
254 * that are common to all platforms.
256 inline BLEManager & BLEMgr(void)
258 return BLEManagerImpl::sInstance;
262 * Returns the platform-specific implementation of the BLEManager singleton object.
264 * Internal components can use this to gain access to features of the BLEManager
265 * that are specific to the ESP32 platform.
267 inline BLEManagerImpl & BLEMgrImpl(void)
269 return BLEManagerImpl::sInstance;
272 inline ::chip::Ble::BleLayer * BLEManagerImpl::_GetBleLayer()
277 inline BLEManager::CHIPoBLEServiceMode BLEManagerImpl::_GetCHIPoBLEServiceMode(void)
282 inline bool BLEManagerImpl::_IsAdvertisingEnabled(void)
284 return mFlags.Has(Flags::kAdvertisingEnabled);
287 inline bool BLEManagerImpl::_IsAdvertising(void)
289 return mFlags.Has(Flags::kAdvertising);
292 } // namespace Internal
293 } // namespace DeviceLayer
296 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE