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
35 #include "esp_gap_ble_api.h"
36 #include "esp_gatts_api.h"
37 #elif CONFIG_BT_NIMBLE_ENABLED
39 /* min max macros in NimBLE can cause build issues with generic min max
40 * functions defined in CHIP.*/
43 #include "host/ble_hs.h"
48 struct ble_gatt_char_context
52 struct ble_gatt_access_ctxt * ctxt;
59 namespace DeviceLayer {
63 * Concrete implementation of the NetworkProvisioningServer singleton object for the ESP32 platform.
65 class BLEManagerImpl final : public BLEManager,
66 private Ble::BleLayer,
67 private Ble::BlePlatformDelegate,
68 private Ble::BleApplicationDelegate
70 // Allow the BLEManager interface class to delegate method calls to
71 // the implementation methods provided by this class.
74 // ===== Members that implement the BLEManager internal interface.
76 CHIP_ERROR _Init(void);
77 CHIPoBLEServiceMode _GetCHIPoBLEServiceMode(void);
78 CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val);
79 bool _IsAdvertisingEnabled(void);
80 CHIP_ERROR _SetAdvertisingEnabled(bool val);
81 bool _IsFastAdvertisingEnabled(void);
82 CHIP_ERROR _SetFastAdvertisingEnabled(bool val);
83 bool _IsAdvertising(void);
84 CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize);
85 CHIP_ERROR _SetDeviceName(const char * deviceName);
86 uint16_t _NumConnections(void);
87 void _OnPlatformEvent(const ChipDeviceEvent * event);
88 ::chip::Ble::BleLayer * _GetBleLayer(void);
90 // ===== Members that implement virtual methods on BlePlatformDelegate.
92 bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
93 const Ble::ChipBleUUID * charId) override;
94 bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
95 const Ble::ChipBleUUID * charId) override;
96 bool CloseConnection(BLE_CONNECTION_OBJECT conId) override;
97 uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override;
98 bool SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
99 System::PacketBufferHandle pBuf) override;
100 bool SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
101 System::PacketBufferHandle pBuf) override;
102 bool SendReadRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
103 System::PacketBufferHandle pBuf) override;
104 bool SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext, const Ble::ChipBleUUID * svcId,
105 const Ble::ChipBleUUID * charId) override;
107 // ===== Members that implement virtual methods on BleApplicationDelegate.
109 void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override;
111 // ===== Members for internal use by the following friends.
113 friend BLEManager & BLEMgr(void);
114 friend BLEManagerImpl & BLEMgrImpl(void);
116 static BLEManagerImpl sInstance;
118 // ===== Private members reserved for use by this class only.
120 enum class Flags : uint16_t
122 kAsyncInitCompleted = 0x0001, /**< One-time asynchronous initialization actions have been performed. */
123 kESPBLELayerInitialized = 0x0002, /**< The ESP BLE layer has been initialized. */
124 kAppRegistered = 0x0004, /**< The CHIPoBLE application has been registered with the ESP BLE layer. */
125 kAttrsRegistered = 0x0008, /**< The CHIPoBLE GATT attributes have been registered with the ESP BLE layer. */
126 kGATTServiceStarted = 0x0010, /**< The CHIPoBLE GATT service has been started. */
127 kAdvertisingConfigured = 0x0020, /**< CHIPoBLE advertising has been configured in the ESP BLE layer. */
128 kAdvertising = 0x0040, /**< The system is currently CHIPoBLE advertising. */
129 kControlOpInProgress = 0x0080, /**< An async control operation has been issued to the ESP BLE layer. */
130 kAdvertisingEnabled = 0x0100, /**< The application has enabled CHIPoBLE advertising. */
131 kFastAdvertisingEnabled = 0x0200, /**< The application has enabled fast advertising. */
132 kUseCustomDeviceName = 0x0400, /**< The application has configured a custom BLE device name. */
133 kAdvertisingRefreshNeeded = 0x0800, /**< The advertising configuration/state in ESP BLE layer needs to be updated. */
138 kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS,
139 kMaxDeviceNameLength = 16
142 #if CONFIG_BT_NIMBLE_ENABLED
143 uint16_t mSubscribedConIds[kMaxConnections];
146 struct CHIPoBLEConState
148 System::PacketBufferHandle PendingIndBuf;
151 uint16_t Allocated : 1;
152 uint16_t Subscribed : 1;
155 void Set(uint16_t conId)
157 PendingIndBuf = nullptr;
166 PendingIndBuf = nullptr;
167 ConId = BLE_CONNECTION_UNINITIALIZED;
175 CHIPoBLEConState mCons[kMaxConnections];
176 CHIPoBLEServiceMode mServiceMode;
177 #if CONFIG_BT_BLUEDROID_ENABLED
178 esp_gatt_if_t mAppIf;
179 #elif CONFIG_BT_NIMBLE_ENABLED
180 uint16_t mNumGAPCons;
182 uint16_t mServiceAttrHandle;
183 uint16_t mRXCharAttrHandle;
184 uint16_t mTXCharAttrHandle;
185 uint16_t mTXCharCCCDAttrHandle;
186 BitFlags<Flags> mFlags;
187 char mDeviceName[kMaxDeviceNameLength + 1];
189 void DriveBLEState(void);
190 CHIP_ERROR InitESPBleLayer(void);
191 CHIP_ERROR ConfigureAdvertisingData(void);
192 CHIP_ERROR StartAdvertising(void);
194 #if CONFIG_BT_BLUEDROID_ENABLED
195 void HandleGATTControlEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
196 void HandleGATTCommEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
197 void HandleRXCharWrite(esp_ble_gatts_cb_param_t * param);
198 void HandleTXCharRead(esp_ble_gatts_cb_param_t * param);
199 void HandleTXCharCCCDRead(esp_ble_gatts_cb_param_t * param);
200 void HandleTXCharCCCDWrite(esp_ble_gatts_cb_param_t * param);
201 void HandleTXCharConfirm(CHIPoBLEConState * conState, esp_ble_gatts_cb_param_t * param);
202 void HandleDisconnect(esp_ble_gatts_cb_param_t * param);
203 CHIPoBLEConState * GetConnectionState(uint16_t conId, bool allocate = false);
204 bool ReleaseConnectionState(uint16_t conId);
206 static void HandleGATTEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
207 static void HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
209 #elif CONFIG_BT_NIMBLE_ENABLED
210 void HandleRXCharRead(struct ble_gatt_char_context * param);
211 void HandleRXCharWrite(struct ble_gatt_char_context * param);
212 void HandleTXCharWrite(struct ble_gatt_char_context * param);
213 void HandleTXCharRead(struct ble_gatt_char_context * param);
214 void HandleTXCharCCCDRead(void * param);
215 void HandleTXCharCCCDWrite(struct ble_gap_event * gapEvent);
216 CHIP_ERROR HandleTXComplete(struct ble_gap_event * gapEvent);
217 CHIP_ERROR HandleGAPConnect(struct ble_gap_event * gapEvent);
218 CHIP_ERROR HandleGAPDisconnect(struct ble_gap_event * gapEvent);
219 CHIP_ERROR SetSubscribed(uint16_t conId);
220 bool UnsetSubscribed(uint16_t conId);
221 bool IsSubscribed(uint16_t conId);
223 static void bleprph_host_task(void * param);
224 static void bleprph_on_sync(void);
225 static void bleprph_on_reset(int);
226 static const struct ble_gatt_svc_def CHIPoBLEGATTAttrs[];
227 static int ble_svr_gap_event(struct ble_gap_event * event, void * arg);
229 static int gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg);
232 static void DriveBLEState(intptr_t arg);
236 * Returns a reference to the public interface of the BLEManager singleton object.
238 * Internal components should use this to access features of the BLEManager object
239 * that are common to all platforms.
241 inline BLEManager & BLEMgr(void)
243 return BLEManagerImpl::sInstance;
247 * Returns the platform-specific implementation of the BLEManager singleton object.
249 * Internal components can use this to gain access to features of the BLEManager
250 * that are specific to the ESP32 platform.
252 inline BLEManagerImpl & BLEMgrImpl(void)
254 return BLEManagerImpl::sInstance;
257 inline ::chip::Ble::BleLayer * BLEManagerImpl::_GetBleLayer()
262 inline BLEManager::CHIPoBLEServiceMode BLEManagerImpl::_GetCHIPoBLEServiceMode(void)
267 inline bool BLEManagerImpl::_IsAdvertisingEnabled(void)
269 return mFlags.Has(Flags::kAdvertisingEnabled);
272 inline bool BLEManagerImpl::_IsFastAdvertisingEnabled(void)
274 return mFlags.Has(Flags::kFastAdvertisingEnabled);
277 inline bool BLEManagerImpl::_IsAdvertising(void)
279 return mFlags.Has(Flags::kAdvertising);
282 } // namespace Internal
283 } // namespace DeviceLayer
286 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE