3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2014-2017 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements objects which provide an abstraction layer between
22 * a platform's Bluetooth Low Energy (BLE) implementation and the CHIP
25 * The BleLayer obect accepts BLE data and control input from the
26 * application via a functional interface. It performs the fragmentation
27 * and reassembly required to transmit CHIP message via a BLE GATT
28 * characteristic interface, and drives incoming messages up the CHIP
31 * During initialization, the BleLayer object requires a pointer to the
32 * platform's implementation of the BlePlatformDelegate and
33 * BleApplicationDelegate objects.
35 * The BlePlatformDelegate provides the CHIP stack with an interface
36 * by which to form and cancel GATT subscriptions, read and write
37 * GATT characteristic values, send GATT characteristic notifications,
38 * respond to GATT read requests, and close BLE connections.
40 * The BleApplicationDelegate provides a mechanism for CHIP to inform
41 * the application when it has finished using a given BLE connection,
42 * i.e when the chipConnection object wrapping this connection has
43 * closed. This allows the application to either close the BLE connection
44 * or continue to keep it open for non-CHIP purposes.
46 * To enable CHIP over BLE for a new platform, the application developer
47 * must provide an implementation for both delegates, provides points to
48 * instances of these delegates on startup, and ensure that the
49 * application calls the necessary BleLayer functions when appropriate to
50 * drive BLE data and control input up the stack.
53 #include <ble/BleConfig.h>
55 #if CONFIG_NETWORK_LAYER_BLE
59 #include <ble/BLEEndPoint.h>
60 #include <ble/BleApplicationDelegate.h>
61 #include <ble/BleLayer.h>
62 #include <ble/BlePlatformDelegate.h>
63 #include <ble/BleUUID.h>
65 #include <core/CHIPEncoding.h>
66 #include <support/CodeUtils.h>
67 #include <support/logging/CHIPLogging.h>
69 // Magic values expected in first 2 bytes of valid BLE transport capabilities request or response:
70 #define CAPABILITIES_MSG_CHECK_BYTE_1 'n'
71 #define CAPABILITIES_MSG_CHECK_BYTE_2 'l'
79 int Size() const { return BLE_LAYER_NUM_BLE_ENDPOINTS; }
81 BLEEndPoint * Get(size_t i) const
85 uint8_t Pool[sizeof(BLEEndPoint) * BLE_LAYER_NUM_BLE_ENDPOINTS];
86 BLEEndPoint::AlignT ForceAlignment;
89 if (i < BLE_LAYER_NUM_BLE_ENDPOINTS)
91 return reinterpret_cast<BLEEndPoint *>(sEndPointPool.Pool + (sizeof(BLEEndPoint) * i));
97 BLEEndPoint * Find(BLE_CONNECTION_OBJECT c)
99 if (c == BLE_CONNECTION_UNINITIALIZED)
104 for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
106 BLEEndPoint * elem = Get(i);
107 if (elem->mBle != nullptr && elem->mConnObj == c)
116 BLEEndPoint * GetFree() const
118 for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
120 BLEEndPoint * elem = Get(i);
121 if (elem->mBle == nullptr)
132 static BleEndPointPool sBLEEndPointPool;
134 // UUIDs used internally by BleLayer:
136 const ChipBleUUID BleLayer::CHIP_BLE_CHAR_1_ID = { { // 18EE2EF5-263D-4559-959F-4F9C429F9D11
137 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42,
138 0x9F, 0x9D, 0x11 } };
140 const ChipBleUUID BleLayer::CHIP_BLE_CHAR_2_ID = { { // 18EE2EF5-263D-4559-959F-4F9C429F9D12
141 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42,
142 0x9F, 0x9D, 0x12 } };
144 const ChipBleUUID BleLayer::CHIP_BLE_CHAR_3_ID = { { // 64630238-8772-45F2-B87D-748A83218F04
145 0x64, 0x63, 0x02, 0x38, 0x87, 0x72, 0x45, 0xF2, 0xB8, 0x7D, 0x74, 0x8A, 0x83,
146 0x21, 0x8F, 0x04 } };
148 void BleLayerObject::Release()
150 // Decrement the ref count. When it reaches zero, NULL out the pointer to the chip::System::Layer
151 // object. This effectively declared the object free and ready for re-allocation.
159 // BleTransportCapabilitiesRequestMessage implementation:
161 void BleTransportCapabilitiesRequestMessage::SetSupportedProtocolVersion(uint8_t index, uint8_t version)
165 // If even-index, store version in lower 4 bits; else, higher 4 bits.
173 version = static_cast<uint8_t>(version << 4);
178 uint8_t & slot = mSupportedProtocolVersions[(index / 2)];
179 slot = static_cast<uint8_t>(slot & ~mask); // Clear version at index; leave other version in same byte alone
183 BLE_ERROR BleTransportCapabilitiesRequestMessage::Encode(const PacketBufferHandle & msgBuf) const
185 uint8_t * p = msgBuf->Start();
186 BLE_ERROR err = BLE_NO_ERROR;
188 // Verify we can write the fixed-length request without running into the end of the buffer.
189 VerifyOrExit(msgBuf->MaxDataLength() >= kCapabilitiesRequestLength, err = BLE_ERROR_NO_MEMORY);
191 chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_1);
192 chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_2);
194 for (uint8_t version : mSupportedProtocolVersions)
196 chip::Encoding::Write8(p, version);
199 chip::Encoding::LittleEndian::Write16(p, mMtu);
200 chip::Encoding::Write8(p, mWindowSize);
202 msgBuf->SetDataLength(kCapabilitiesRequestLength);
208 BLE_ERROR BleTransportCapabilitiesRequestMessage::Decode(const PacketBufferHandle & msgBuf,
209 BleTransportCapabilitiesRequestMessage & msg)
211 const uint8_t * p = msgBuf->Start();
212 BLE_ERROR err = BLE_NO_ERROR;
214 // Verify we can read the fixed-length request without running into the end of the buffer.
215 VerifyOrExit(msgBuf->DataLength() >= kCapabilitiesRequestLength, err = BLE_ERROR_MESSAGE_INCOMPLETE);
217 VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_1 == chip::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
218 VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_2 == chip::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
220 for (size_t i = 0; i < kCapabilitiesRequestSupportedVersionsLength; i++)
222 msg.mSupportedProtocolVersions[i] = chip::Encoding::Read8(p);
225 msg.mMtu = chip::Encoding::LittleEndian::Read16(p);
226 msg.mWindowSize = chip::Encoding::Read8(p);
232 // BleTransportCapabilitiesResponseMessage implementation:
234 BLE_ERROR BleTransportCapabilitiesResponseMessage::Encode(const PacketBufferHandle & msgBuf) const
236 uint8_t * p = msgBuf->Start();
237 BLE_ERROR err = BLE_NO_ERROR;
239 // Verify we can write the fixed-length request without running into the end of the buffer.
240 VerifyOrExit(msgBuf->MaxDataLength() >= kCapabilitiesResponseLength, err = BLE_ERROR_NO_MEMORY);
242 chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_1);
243 chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_2);
245 chip::Encoding::Write8(p, mSelectedProtocolVersion);
246 chip::Encoding::LittleEndian::Write16(p, mFragmentSize);
247 chip::Encoding::Write8(p, mWindowSize);
249 msgBuf->SetDataLength(kCapabilitiesResponseLength);
255 BLE_ERROR BleTransportCapabilitiesResponseMessage::Decode(const PacketBufferHandle & msgBuf,
256 BleTransportCapabilitiesResponseMessage & msg)
258 const uint8_t * p = msgBuf->Start();
259 BLE_ERROR err = BLE_NO_ERROR;
261 // Verify we can read the fixed-length response without running into the end of the buffer.
262 VerifyOrExit(msgBuf->DataLength() >= kCapabilitiesResponseLength, err = BLE_ERROR_MESSAGE_INCOMPLETE);
264 VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_1 == chip::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
265 VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_2 == chip::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
267 msg.mSelectedProtocolVersion = chip::Encoding::Read8(p);
268 msg.mFragmentSize = chip::Encoding::LittleEndian::Read16(p);
269 msg.mWindowSize = chip::Encoding::Read8(p);
275 // BleLayer implementation:
279 mState = kState_NotInitialized;
282 BLE_ERROR BleLayer::Init(BlePlatformDelegate * platformDelegate, BleConnectionDelegate * connDelegate,
283 BleApplicationDelegate * appDelegate, chip::System::Layer * systemLayer)
285 BLE_ERROR err = BLE_NO_ERROR;
287 Ble::RegisterLayerErrorFormatter();
289 // It is totally valid to not have a connDelegate. In this case the client application
290 // will take care of the connection steps.
291 VerifyOrExit(platformDelegate != nullptr, err = BLE_ERROR_BAD_ARGS);
292 VerifyOrExit(appDelegate != nullptr, err = BLE_ERROR_BAD_ARGS);
293 VerifyOrExit(systemLayer != nullptr, err = BLE_ERROR_BAD_ARGS);
295 if (mState != kState_NotInitialized)
297 return BLE_ERROR_INCORRECT_STATE;
300 mConnectionDelegate = connDelegate;
301 mPlatformDelegate = platformDelegate;
302 mApplicationDelegate = appDelegate;
303 mSystemLayer = systemLayer;
305 memset(&sBLEEndPointPool, 0, sizeof(sBLEEndPointPool));
307 mState = kState_Initialized;
309 #if CHIP_ENABLE_CHIPOBLE_TEST
310 mTestBleEndPoint = NULL;
317 BLE_ERROR BleLayer::Init(BlePlatformDelegate * platformDelegate, BleApplicationDelegate * appDelegate,
318 chip::System::Layer * systemLayer)
320 return Init(platformDelegate, nullptr, appDelegate, systemLayer);
323 BLE_ERROR BleLayer::Shutdown()
325 mState = kState_NotInitialized;
327 // Close and free all BLE end points.
328 for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
330 BLEEndPoint * elem = sBLEEndPointPool.Get(i);
332 // If end point was initialized, and has not since been freed...
333 if (elem->mBle != nullptr)
335 // If end point hasn't already been closed...
336 if (elem->mState != BLEEndPoint::kState_Closed)
338 // Close end point such that callbacks are suppressed and pending transmissions aborted.
342 // If end point was closed, but is still waiting for GATT unsubscribe to complete, free it anyway.
343 // This cancels the unsubscribe timer (plus all the end point's other timers).
344 if (elem->IsUnsubscribePending())
354 BLE_ERROR BleLayer::NewBleConnection(void * appState, const uint16_t connDiscriminator,
355 BleConnectionDelegate::OnConnectionCompleteFunct onConnectionComplete,
356 BleConnectionDelegate::OnConnectionErrorFunct onConnectionError)
358 BLE_ERROR err = BLE_NO_ERROR;
360 VerifyOrExit(mState == kState_Initialized, err = BLE_ERROR_INCORRECT_STATE);
361 VerifyOrExit(mConnectionDelegate != nullptr, err = BLE_ERROR_INCORRECT_STATE);
363 mConnectionDelegate->OnConnectionComplete = onConnectionComplete;
364 mConnectionDelegate->OnConnectionError = onConnectionError;
365 mConnectionDelegate->NewConnection(this, appState, connDiscriminator);
371 BLE_ERROR BleLayer::CancelBleIncompleteConnection()
373 BLE_ERROR err = BLE_NO_ERROR;
375 VerifyOrExit(mState == kState_Initialized, err = BLE_ERROR_INCORRECT_STATE);
376 VerifyOrExit(mConnectionDelegate != nullptr, err = BLE_ERROR_INCORRECT_STATE);
378 err = mConnectionDelegate->CancelConnection();
379 if (err == BLE_ERROR_NOT_IMPLEMENTED)
381 ChipLogError(Ble, "BleConnectionDelegate::CancelConnection is not implemented.");
388 BLE_ERROR BleLayer::NewBleEndPoint(BLEEndPoint ** retEndPoint, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose)
390 *retEndPoint = nullptr;
392 if (mState != kState_Initialized)
394 return BLE_ERROR_INCORRECT_STATE;
397 if (connObj == BLE_CONNECTION_UNINITIALIZED)
399 return BLE_ERROR_BAD_ARGS;
402 *retEndPoint = sBLEEndPointPool.GetFree();
403 if (*retEndPoint == nullptr)
405 ChipLogError(Ble, "%s endpoint pool FULL", "Ble");
406 return BLE_ERROR_NO_ENDPOINTS;
409 (*retEndPoint)->Init(this, connObj, role, autoClose);
411 #if CHIP_ENABLE_CHIPOBLE_TEST
412 mTestBleEndPoint = *retEndPoint;
418 // Handle remote central's initiation of CHIP over BLE protocol handshake.
419 BLE_ERROR BleLayer::HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, PacketBufferHandle pBuf)
421 BLE_ERROR err = BLE_NO_ERROR;
422 BLEEndPoint * newEndPoint = nullptr;
424 // Only BLE peripherals can receive GATT writes, so specify this role in our creation of the BLEEndPoint.
425 // Set autoClose = false. Peripherals only notify the application when an end point releases a BLE connection.
426 err = NewBleEndPoint(&newEndPoint, connObj, kBleRole_Peripheral, false);
429 newEndPoint->mAppState = mAppState;
431 err = newEndPoint->Receive(std::move(pBuf));
432 SuccessOrExit(err); // If we fail here, end point will have already released connection and freed itself.
435 // If we failed to allocate a new end point, release underlying BLE connection. Central's handshake will time out
436 // if the application decides to keep the BLE connection open.
437 if (newEndPoint == nullptr)
439 mApplicationDelegate->NotifyChipConnectionClosed(connObj);
442 if (err != BLE_NO_ERROR)
444 ChipLogError(Ble, "HandleChipConnectionReceived failed, err = %d", err);
450 bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
451 PacketBufferHandle pBuf)
453 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
455 ChipLogError(Ble, "ble write rcvd on unknown svc id");
459 if (UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId))
463 ChipLogError(Ble, "rcvd null ble write");
467 // Find matching connection end point.
468 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
470 if (endPoint != nullptr)
472 BLE_ERROR status = endPoint->Receive(std::move(pBuf));
473 if (status != BLE_NO_ERROR)
475 ChipLogError(Ble, "BLEEndPoint rcv failed, err = %d", status);
480 BLE_ERROR status = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
481 if (status != BLE_NO_ERROR)
483 ChipLogError(Ble, "failed handle new chip BLE connection, status = %d", status);
489 ChipLogError(Ble, "ble write rcvd on unknown char");
496 bool BleLayer::HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
497 PacketBufferHandle pBuf)
499 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
504 if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId))
508 ChipLogError(Ble, "rcvd null ble indication");
512 // find matching connection end point.
513 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
515 if (endPoint != nullptr)
517 BLE_ERROR status = endPoint->Receive(std::move(pBuf));
518 if (status != BLE_NO_ERROR)
520 ChipLogError(Ble, "BLEEndPoint rcv failed, err = %d", status);
525 ChipLogDetail(Ble, "no endpoint for rcvd indication");
530 ChipLogError(Ble, "ble ind rcvd on unknown char");
537 bool BleLayer::HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
539 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
544 if (UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId))
546 HandleAckReceived(connObj);
550 ChipLogError(Ble, "ble write con rcvd on unknown char");
556 bool BleLayer::HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
558 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
563 if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId))
565 HandleAckReceived(connObj);
569 ChipLogError(Ble, "ble ind con rcvd on unknown char");
575 void BleLayer::HandleAckReceived(BLE_CONNECTION_OBJECT connObj)
577 // find matching connection end point.
578 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
580 if (endPoint != nullptr)
582 BLE_ERROR status = endPoint->HandleGattSendConfirmationReceived();
584 if (status != BLE_NO_ERROR)
586 ChipLogError(Ble, "endpoint conf recvd failed, err = %d", status);
591 ChipLogError(Ble, "no endpoint for BLE sent data ack");
595 bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
597 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
602 if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
604 // Find end point already associated with BLE connection, if any.
605 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
607 if (endPoint != nullptr)
609 endPoint->HandleSubscribeReceived();
613 ChipLogError(Ble, "no endpoint for sub recvd");
620 bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
622 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
627 if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
629 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
631 if (endPoint != nullptr)
633 endPoint->HandleSubscribeComplete();
637 ChipLogError(Ble, "no endpoint for sub complete");
644 bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
646 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
651 if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
653 // Find end point already associated with BLE connection, if any.
654 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
656 if (endPoint != nullptr)
658 endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
662 ChipLogError(Ble, "no endpoint for unsub recvd");
669 bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
671 if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
676 if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
678 // Find end point already associated with BLE connection, if any.
679 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
681 if (endPoint != nullptr)
683 endPoint->HandleUnsubscribeComplete();
687 ChipLogError(Ble, "no endpoint for unsub complete");
694 void BleLayer::HandleConnectionError(BLE_CONNECTION_OBJECT connObj, BLE_ERROR err)
696 // BLE connection has failed somehow, we must find and abort matching connection end point.
697 BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
699 if (endPoint != nullptr)
701 if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
703 // If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
704 // stops unsubscribe timer.
709 endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
714 BleTransportProtocolVersion BleLayer::GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg)
716 BleTransportProtocolVersion retVersion = kBleTransportProtocolVersion_None;
718 uint8_t shift_width = 4;
720 for (int i = 0; i < NUM_SUPPORTED_PROTOCOL_VERSIONS; i++)
724 uint8_t version = reqMsg.mSupportedProtocolVersions[(i / 2)];
725 version = (version >> shift_width) & 0x0F; // Grab just the nibble we want.
727 if ((version >= CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION) &&
728 (version <= CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION) && (version > retVersion))
730 retVersion = static_cast<BleTransportProtocolVersion>(version);
732 else if (version == kBleTransportProtocolVersion_None) // Signifies end of supported versions list
741 } /* namespace Ble */
742 } /* namespace chip */
744 #endif /* CONFIG_NETWORK_LAYER_BLE */