Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2014-2017 Nest Labs, Inc.
5 : *
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
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
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.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file implements objects which provide an abstraction layer between
22 : * a platform's Bluetooth Low Energy (BLE) implementation and the CHIP
23 : * stack.
24 : *
25 : * The BleLayer object 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
29 : * stack.
30 : *
31 : * During initialization, the BleLayer object requires a pointer to the
32 : * platform's implementation of the BlePlatformDelegate and
33 : * BleApplicationDelegate objects.
34 : *
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.
39 : *
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.
45 : *
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.
51 : */
52 :
53 : #define _CHIP_BLE_BLE_H
54 : #include "BleLayer.h"
55 :
56 : #include <cstddef>
57 : #include <cstring>
58 : #include <utility>
59 :
60 : #include <lib/core/CHIPEncoding.h>
61 : #include <lib/support/CodeUtils.h>
62 : #include <lib/support/SetupDiscriminator.h>
63 : #include <lib/support/logging/CHIPLogging.h>
64 : #include <system/SystemLayer.h>
65 : #include <system/SystemPacketBuffer.h>
66 :
67 : #include "BLEEndPoint.h"
68 : #include "BleApplicationDelegate.h"
69 : #include "BleConfig.h"
70 : #include "BleConnectionDelegate.h"
71 : #include "BleError.h"
72 : #include "BleLayerDelegate.h"
73 : #include "BlePlatformDelegate.h"
74 : #include "BleRole.h"
75 : #include "BleUUID.h"
76 :
77 : // Magic values expected in first 2 bytes of valid BLE transport capabilities request or response:
78 : #define CAPABILITIES_MSG_CHECK_BYTE_1 0b01100101
79 : #define CAPABILITIES_MSG_CHECK_BYTE_2 0b01101100
80 :
81 : namespace chip {
82 : namespace Ble {
83 :
84 : class BleEndPointPool
85 : {
86 : public:
87 : int Size() const { return BLE_LAYER_NUM_BLE_ENDPOINTS; }
88 :
89 146 : BLEEndPoint * Get(size_t i) const
90 : {
91 : alignas(BLEEndPoint) static std::byte sStorage[sizeof(BLEEndPoint) * BLE_LAYER_NUM_BLE_ENDPOINTS];
92 146 : VerifyOrReturnValue(i < BLE_LAYER_NUM_BLE_ENDPOINTS, nullptr);
93 146 : return reinterpret_cast<BLEEndPoint *>(sStorage) + i;
94 : }
95 :
96 33 : BLEEndPoint * Find(BLE_CONNECTION_OBJECT c) const
97 : {
98 33 : if (c == BLE_CONNECTION_UNINITIALIZED)
99 : {
100 1 : return nullptr;
101 : }
102 :
103 46 : for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
104 : {
105 32 : BLEEndPoint * elem = Get(i);
106 32 : if (elem->mBle != nullptr && elem->mConnObj == c)
107 : {
108 18 : return elem;
109 : }
110 : }
111 :
112 14 : return nullptr;
113 : }
114 :
115 21 : BLEEndPoint * GetFree() const
116 : {
117 23 : for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
118 : {
119 21 : BLEEndPoint * elem = Get(i);
120 21 : if (elem->mBle == nullptr)
121 : {
122 19 : return elem;
123 : }
124 : }
125 2 : return nullptr;
126 : }
127 : };
128 :
129 : // EndPoint Pools
130 : //
131 : static BleEndPointPool sBLEEndPointPool;
132 :
133 : // BleTransportCapabilitiesRequestMessage implementation:
134 :
135 6 : void BleTransportCapabilitiesRequestMessage::SetSupportedProtocolVersion(uint8_t index, uint8_t version)
136 : {
137 : uint8_t mask;
138 :
139 : // If even-index, store version in lower 4 bits; else, higher 4 bits.
140 6 : if (index % 2 == 0)
141 : {
142 5 : mask = 0x0F;
143 : }
144 : else
145 : {
146 1 : mask = 0xF0;
147 1 : version = static_cast<uint8_t>(version << 4);
148 : }
149 :
150 6 : version &= mask;
151 :
152 6 : uint8_t & slot = mSupportedProtocolVersions[(index / 2)];
153 6 : slot = static_cast<uint8_t>(slot & ~mask); // Clear version at index; leave other version in same byte alone
154 6 : slot |= version;
155 6 : }
156 :
157 5 : CHIP_ERROR BleTransportCapabilitiesRequestMessage::Encode(const PacketBufferHandle & msgBuf) const
158 : {
159 5 : uint8_t * p = msgBuf->Start();
160 :
161 : // Verify we can write the fixed-length request without running into the end of the buffer.
162 5 : VerifyOrReturnError(msgBuf->MaxDataLength() >= kCapabilitiesRequestLength, CHIP_ERROR_NO_MEMORY);
163 :
164 5 : chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_1);
165 5 : chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_2);
166 :
167 25 : for (uint8_t version : mSupportedProtocolVersions)
168 : {
169 20 : chip::Encoding::Write8(p, version);
170 : }
171 :
172 5 : chip::Encoding::LittleEndian::Write16(p, mMtu);
173 5 : chip::Encoding::Write8(p, mWindowSize);
174 :
175 5 : msgBuf->SetDataLength(kCapabilitiesRequestLength);
176 :
177 5 : return CHIP_NO_ERROR;
178 : }
179 :
180 15 : CHIP_ERROR BleTransportCapabilitiesRequestMessage::Decode(const PacketBufferHandle & msgBuf,
181 : BleTransportCapabilitiesRequestMessage & msg)
182 : {
183 15 : const uint8_t * p = msgBuf->Start();
184 :
185 : // Verify we can read the fixed-length request without running into the end of the buffer.
186 15 : VerifyOrReturnError(msgBuf->DataLength() >= kCapabilitiesRequestLength, CHIP_ERROR_MESSAGE_INCOMPLETE);
187 :
188 15 : VerifyOrReturnError(CAPABILITIES_MSG_CHECK_BYTE_1 == chip::Encoding::Read8(p), BLE_ERROR_INVALID_MESSAGE);
189 15 : VerifyOrReturnError(CAPABILITIES_MSG_CHECK_BYTE_2 == chip::Encoding::Read8(p), BLE_ERROR_INVALID_MESSAGE);
190 :
191 : static_assert(kCapabilitiesRequestSupportedVersionsLength == sizeof(msg.mSupportedProtocolVersions),
192 : "Expected capability sizes and storage must match");
193 75 : for (unsigned char & version : msg.mSupportedProtocolVersions)
194 : {
195 60 : version = chip::Encoding::Read8(p);
196 : }
197 :
198 15 : msg.mMtu = chip::Encoding::LittleEndian::Read16(p);
199 15 : msg.mWindowSize = chip::Encoding::Read8(p);
200 :
201 15 : return CHIP_NO_ERROR;
202 : }
203 :
204 : // BleTransportCapabilitiesResponseMessage implementation:
205 :
206 16 : CHIP_ERROR BleTransportCapabilitiesResponseMessage::Encode(const PacketBufferHandle & msgBuf) const
207 : {
208 16 : uint8_t * p = msgBuf->Start();
209 :
210 : // Verify we can write the fixed-length request without running into the end of the buffer.
211 16 : VerifyOrReturnError(msgBuf->MaxDataLength() >= kCapabilitiesResponseLength, CHIP_ERROR_NO_MEMORY);
212 :
213 16 : chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_1);
214 16 : chip::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_2);
215 :
216 16 : chip::Encoding::Write8(p, mSelectedProtocolVersion);
217 16 : chip::Encoding::LittleEndian::Write16(p, mFragmentSize);
218 16 : chip::Encoding::Write8(p, mWindowSize);
219 :
220 16 : msgBuf->SetDataLength(kCapabilitiesResponseLength);
221 :
222 16 : return CHIP_NO_ERROR;
223 : }
224 :
225 3 : CHIP_ERROR BleTransportCapabilitiesResponseMessage::Decode(const PacketBufferHandle & msgBuf,
226 : BleTransportCapabilitiesResponseMessage & msg)
227 : {
228 3 : const uint8_t * p = msgBuf->Start();
229 :
230 : // Verify we can read the fixed-length response without running into the end of the buffer.
231 3 : VerifyOrReturnError(msgBuf->DataLength() >= kCapabilitiesResponseLength, CHIP_ERROR_MESSAGE_INCOMPLETE);
232 :
233 3 : VerifyOrReturnError(CAPABILITIES_MSG_CHECK_BYTE_1 == chip::Encoding::Read8(p), BLE_ERROR_INVALID_MESSAGE);
234 3 : VerifyOrReturnError(CAPABILITIES_MSG_CHECK_BYTE_2 == chip::Encoding::Read8(p), BLE_ERROR_INVALID_MESSAGE);
235 :
236 3 : msg.mSelectedProtocolVersion = chip::Encoding::Read8(p);
237 3 : msg.mFragmentSize = chip::Encoding::LittleEndian::Read16(p);
238 3 : msg.mWindowSize = chip::Encoding::Read8(p);
239 :
240 3 : return CHIP_NO_ERROR;
241 : }
242 :
243 : // BleLayer implementation:
244 :
245 196 : BleLayer::BleLayer()
246 : {
247 196 : mState = kState_NotInitialized;
248 196 : }
249 :
250 86 : CHIP_ERROR BleLayer::Init(BlePlatformDelegate * platformDelegate, BleConnectionDelegate * connDelegate,
251 : BleApplicationDelegate * appDelegate, chip::System::Layer * systemLayer)
252 : {
253 86 : Ble::RegisterLayerErrorFormatter();
254 :
255 : // It is totally valid to not have a connDelegate. In this case the client application
256 : // will take care of the connection steps.
257 86 : VerifyOrReturnError(platformDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
258 86 : VerifyOrReturnError(appDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
259 86 : VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
260 :
261 86 : if (mState != kState_NotInitialized)
262 : {
263 0 : return CHIP_ERROR_INCORRECT_STATE;
264 : }
265 :
266 86 : mConnectionDelegate = connDelegate;
267 86 : mPlatformDelegate = platformDelegate;
268 86 : mApplicationDelegate = appDelegate;
269 86 : mSystemLayer = systemLayer;
270 :
271 86 : memset(&sBLEEndPointPool, 0, sizeof(sBLEEndPointPool));
272 :
273 86 : mState = kState_Initialized;
274 :
275 86 : return CHIP_NO_ERROR;
276 : }
277 :
278 3 : CHIP_ERROR BleLayer::Init(BlePlatformDelegate * platformDelegate, BleApplicationDelegate * appDelegate,
279 : chip::System::Layer * systemLayer)
280 : {
281 3 : return Init(platformDelegate, nullptr, appDelegate, systemLayer);
282 : }
283 :
284 0 : void BleLayer::IndicateBleClosing()
285 : {
286 0 : mState = kState_Disconnecting;
287 0 : }
288 :
289 87 : void BleLayer::Shutdown()
290 : {
291 87 : mState = kState_NotInitialized;
292 87 : CloseAllBleConnections();
293 87 : }
294 :
295 91 : void BleLayer::CloseAllBleConnections()
296 : {
297 : // Close and free all BLE end points.
298 182 : for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
299 : {
300 91 : BLEEndPoint * elem = sBLEEndPointPool.Get(i);
301 :
302 : // If end point was initialized, and has not since been freed...
303 91 : if (elem->mBle != nullptr)
304 : {
305 : // If end point hasn't already been closed...
306 13 : if (elem->mState != BLEEndPoint::kState_Closed)
307 : {
308 : // Close end point such that callbacks are suppressed and pending transmissions aborted.
309 11 : elem->Abort();
310 : }
311 :
312 : // If end point was closed, but is still waiting for GATT unsubscribe to complete, free it anyway.
313 : // This cancels the unsubscribe timer (plus all the end point's other timers).
314 13 : if (elem->IsUnsubscribePending())
315 : {
316 2 : elem->Free();
317 : }
318 : }
319 : }
320 91 : }
321 :
322 2 : void BleLayer::CloseBleConnection(BLE_CONNECTION_OBJECT connObj)
323 : {
324 : // Close and free all BLE endpoints.
325 4 : for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
326 : {
327 2 : BLEEndPoint * elem = sBLEEndPointPool.Get(i);
328 :
329 : // If end point was initialized, and has not since been freed...
330 2 : if (elem->mBle != nullptr && elem->ConnectionObjectIs(connObj))
331 : {
332 : // If end point hasn't already been closed...
333 1 : if (elem->mState != BLEEndPoint::kState_Closed)
334 : {
335 : // Close end point such that callbacks are suppressed and pending transmissions aborted.
336 1 : elem->Abort();
337 : }
338 :
339 : // If end point was closed, but is still waiting for GATT unsubscribe to complete, free it anyway.
340 : // This cancels the unsubscribe timer (plus all the end point's other timers).
341 1 : if (elem->IsUnsubscribePending())
342 : {
343 0 : elem->Free();
344 : }
345 : }
346 : }
347 2 : }
348 :
349 2 : CHIP_ERROR BleLayer::CancelBleIncompleteConnection()
350 : {
351 2 : VerifyOrReturnError(mState == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
352 1 : VerifyOrReturnError(mConnectionDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
353 :
354 1 : CHIP_ERROR err = mConnectionDelegate->CancelConnection();
355 1 : if (err == CHIP_ERROR_NOT_IMPLEMENTED)
356 : {
357 0 : ChipLogError(Ble, "BleConnectionDelegate::CancelConnection is not implemented.");
358 : }
359 1 : return err;
360 : }
361 :
362 1 : CHIP_ERROR BleLayer::NewBleConnectionByDiscriminator(const SetupDiscriminator & connDiscriminator, void * appState,
363 : BleConnectionDelegate::OnConnectionCompleteFunct onSuccess,
364 : BleConnectionDelegate::OnConnectionErrorFunct onError)
365 : {
366 1 : VerifyOrReturnError(mState == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
367 1 : VerifyOrReturnError(mConnectionDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
368 1 : VerifyOrReturnError(mBleTransport != nullptr, CHIP_ERROR_INCORRECT_STATE);
369 :
370 1 : mConnectionDelegate->OnConnectionComplete = onSuccess;
371 1 : mConnectionDelegate->OnConnectionError = onError;
372 :
373 1 : mConnectionDelegate->NewConnection(this, appState == nullptr ? this : appState, connDiscriminator);
374 :
375 1 : return CHIP_NO_ERROR;
376 : }
377 :
378 1 : CHIP_ERROR BleLayer::NewBleConnectionByObject(BLE_CONNECTION_OBJECT connObj, void * appState,
379 : BleConnectionDelegate::OnConnectionCompleteFunct onSuccess,
380 : BleConnectionDelegate::OnConnectionErrorFunct onError)
381 : {
382 1 : VerifyOrReturnError(mState == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
383 1 : VerifyOrReturnError(mConnectionDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
384 1 : VerifyOrReturnError(mBleTransport != nullptr, CHIP_ERROR_INCORRECT_STATE);
385 :
386 1 : mConnectionDelegate->OnConnectionComplete = onSuccess;
387 1 : mConnectionDelegate->OnConnectionError = onError;
388 :
389 1 : mConnectionDelegate->NewConnection(this, appState == nullptr ? this : appState, connObj);
390 :
391 1 : return CHIP_NO_ERROR;
392 : }
393 :
394 2 : CHIP_ERROR BleLayer::NewBleConnectionByObject(BLE_CONNECTION_OBJECT connObj)
395 : {
396 2 : VerifyOrReturnError(mState == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
397 2 : VerifyOrReturnError(mBleTransport != nullptr, CHIP_ERROR_INCORRECT_STATE);
398 :
399 2 : OnConnectionComplete(this, connObj);
400 :
401 2 : return CHIP_NO_ERROR;
402 : }
403 :
404 6 : CHIP_ERROR BleLayer::NewBleConnectionByDiscriminators(const Span<const SetupDiscriminator> & discriminators, void * appState,
405 : BleConnectionDelegate::OnConnectionByDiscriminatorsCompleteFunct onSuccess,
406 : BleConnectionDelegate::OnConnectionErrorFunct onError)
407 : {
408 6 : VerifyOrReturnError(mState == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
409 5 : VerifyOrReturnError(mConnectionDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
410 4 : VerifyOrReturnError(mBleTransport != nullptr, CHIP_ERROR_INCORRECT_STATE);
411 :
412 3 : return mConnectionDelegate->NewConnection(this, appState, discriminators, onSuccess, onError);
413 : }
414 :
415 22 : CHIP_ERROR BleLayer::NewBleEndPoint(BLEEndPoint ** retEndPoint, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose)
416 : {
417 22 : if (mState != kState_Initialized)
418 : {
419 0 : return CHIP_ERROR_INCORRECT_STATE;
420 : }
421 :
422 22 : if (connObj == BLE_CONNECTION_UNINITIALIZED)
423 : {
424 1 : return CHIP_ERROR_INVALID_ARGUMENT;
425 : }
426 :
427 21 : auto endPoint = sBLEEndPointPool.GetFree();
428 21 : if (endPoint == nullptr)
429 : {
430 2 : ChipLogError(Ble, "%s endpoint pool FULL", "Ble");
431 2 : return CHIP_ERROR_ENDPOINT_POOL_FULL;
432 : }
433 :
434 19 : endPoint->Init(this, connObj, role, autoClose);
435 19 : endPoint->mBleTransport = mBleTransport;
436 :
437 19 : *retEndPoint = endPoint;
438 19 : return CHIP_NO_ERROR;
439 : }
440 :
441 : // Handle remote central's initiation of CHIP over BLE protocol handshake.
442 15 : CHIP_ERROR BleLayer::HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, PacketBufferHandle && pBuf)
443 : {
444 15 : CHIP_ERROR err = CHIP_NO_ERROR;
445 15 : BLEEndPoint * newEndPoint = nullptr;
446 :
447 : // Only BLE peripherals can receive GATT writes, so specify this role in our creation of the BLEEndPoint.
448 : // Set autoClose = false. Peripherals only notify the application when an end point releases a BLE connection.
449 15 : err = NewBleEndPoint(&newEndPoint, connObj, kBleRole_Peripheral, false);
450 15 : SuccessOrExit(err);
451 :
452 13 : newEndPoint->mBleTransport = mBleTransport;
453 :
454 13 : err = newEndPoint->Receive(std::move(pBuf));
455 13 : SuccessOrExit(err); // If we fail here, end point will have already released connection and freed itself.
456 :
457 15 : exit:
458 : // If we failed to allocate a new end point, release underlying BLE connection. Central's handshake will time out
459 : // if the application decides to keep the BLE connection open.
460 15 : if (newEndPoint == nullptr)
461 : {
462 2 : mApplicationDelegate->NotifyChipConnectionClosed(connObj);
463 : }
464 :
465 15 : if (err != CHIP_NO_ERROR)
466 : {
467 2 : ChipLogError(Ble, "HandleChipConnectionReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format());
468 : }
469 :
470 15 : return err;
471 : }
472 :
473 18 : bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
474 : PacketBufferHandle && pBuf)
475 : {
476 18 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write received on unknown svc"));
477 17 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_UUID, charId), false, ChipLogError(Ble, "Write received on unknown char"));
478 16 : VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Write received null buffer"));
479 :
480 : // Find matching connection end point.
481 16 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
482 :
483 16 : if (endPoint != nullptr)
484 : {
485 1 : CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
486 1 : VerifyOrReturnError(err == CHIP_NO_ERROR, false,
487 : ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
488 : }
489 : else
490 : {
491 15 : CHIP_ERROR err = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
492 15 : VerifyOrReturnError(err == CHIP_NO_ERROR, false,
493 : ChipLogError(Ble, "Handle new BLE connection failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
494 : }
495 :
496 14 : return true;
497 : }
498 :
499 3 : bool BleLayer::HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
500 : PacketBufferHandle && pBuf)
501 : {
502 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication received on unknown svc"));
503 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId), false, ChipLogError(Ble, "Indication received on unknown char"));
504 1 : VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Indication received null buffer"));
505 :
506 : // Find matching connection end point.
507 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
508 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received indication"));
509 :
510 1 : CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
511 1 : VerifyOrReturnError(err == CHIP_NO_ERROR, false, ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
512 :
513 1 : return true;
514 : }
515 :
516 5 : bool BleLayer::HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
517 : {
518 5 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write confirmation on unknown svc"));
519 4 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_UUID, charId), false, ChipLogError(Ble, "Write confirmation on unknown char"));
520 :
521 3 : HandleAckReceived(connObj);
522 3 : return true;
523 : }
524 :
525 3 : bool BleLayer::HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
526 : {
527 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication confirmation on unknown svc"));
528 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId), false,
529 : ChipLogError(Ble, "Indication confirmation on unknown char"));
530 :
531 1 : HandleAckReceived(connObj);
532 1 : return true;
533 : }
534 :
535 4 : void BleLayer::HandleAckReceived(BLE_CONNECTION_OBJECT connObj)
536 : {
537 : // Find matching connection end point.
538 4 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
539 4 : VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for received ack"));
540 :
541 4 : CHIP_ERROR err = endPoint->HandleGattSendConfirmationReceived();
542 4 : VerifyOrReturn(err == CHIP_NO_ERROR,
543 : ChipLogError(Ble, "Send ack confirmation failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
544 : }
545 :
546 8 : bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
547 : {
548 8 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe received on unknown svc"));
549 7 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
550 : ChipLogError(Ble, "Subscribe received on unknown char"));
551 :
552 : // Find end point already associated with BLE connection, if any.
553 6 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
554 6 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received subscribe"));
555 :
556 6 : endPoint->HandleSubscribeReceived();
557 6 : return true;
558 : }
559 :
560 5 : bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
561 : {
562 5 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe complete on unknown svc"));
563 4 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
564 : ChipLogError(Ble, "Subscribe complete on unknown char"));
565 :
566 3 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
567 3 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for subscribe complete"));
568 :
569 3 : endPoint->HandleSubscribeComplete();
570 3 : return true;
571 : }
572 :
573 3 : bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
574 : {
575 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe received on unknown svc"));
576 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
577 : ChipLogError(Ble, "Unsubscribe received on unknown char"));
578 :
579 : // Find end point already associated with BLE connection, if any.
580 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
581 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe received"));
582 :
583 1 : endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
584 1 : return true;
585 : }
586 :
587 3 : bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
588 : {
589 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe complete on unknown svc"));
590 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
591 : ChipLogError(Ble, "Unsubscribe complete on unknown char"));
592 :
593 : // Find end point already associated with BLE connection, if any.
594 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
595 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe complete"));
596 :
597 1 : endPoint->HandleUnsubscribeComplete();
598 1 : return true;
599 : }
600 :
601 1 : void BleLayer::HandleConnectionError(BLE_CONNECTION_OBJECT connObj, CHIP_ERROR err)
602 : {
603 : // BLE connection has failed somehow, we must find and abort matching connection end point.
604 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
605 1 : VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for connection error"));
606 :
607 1 : if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
608 : {
609 : // If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
610 : // stops unsubscribe timer.
611 0 : endPoint->Free();
612 : }
613 : else
614 : {
615 1 : endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
616 : }
617 : }
618 :
619 13 : BleTransportProtocolVersion BleLayer::GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg)
620 : {
621 13 : BleTransportProtocolVersion retVersion = kBleTransportProtocolVersion_None;
622 :
623 13 : uint8_t shift_width = 4;
624 :
625 39 : for (int i = 0; i < NUM_SUPPORTED_PROTOCOL_VERSIONS; i++)
626 : {
627 39 : shift_width ^= 4;
628 :
629 39 : uint8_t version = reqMsg.mSupportedProtocolVersions[(i / 2)];
630 39 : version = static_cast<uint8_t>((version >> shift_width) & 0x0F); // Grab just the nibble we want.
631 :
632 39 : if ((version >= CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION) &&
633 13 : (version <= CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION) && (version > retVersion))
634 : {
635 13 : retVersion = static_cast<BleTransportProtocolVersion>(version);
636 : }
637 26 : else if (version == kBleTransportProtocolVersion_None) // Signifies end of supported versions list
638 : {
639 13 : break;
640 : }
641 : }
642 :
643 13 : return retVersion;
644 : }
645 :
646 3 : void BleLayer::OnConnectionComplete(void * appState, BLE_CONNECTION_OBJECT connObj)
647 : {
648 3 : BleLayer * layer = reinterpret_cast<BleLayer *>(appState);
649 3 : BLEEndPoint * endPoint = nullptr;
650 3 : CHIP_ERROR err = CHIP_NO_ERROR;
651 :
652 3 : SuccessOrExit(err = layer->NewBleEndPoint(&endPoint, connObj, kBleRole_Central, true));
653 2 : layer->mBleTransport->OnBleConnectionComplete(endPoint);
654 :
655 3 : exit:
656 3 : if (err != CHIP_NO_ERROR)
657 : {
658 1 : OnConnectionError(layer, err);
659 : }
660 3 : }
661 :
662 3 : void BleLayer::OnConnectionError(void * appState, CHIP_ERROR err)
663 : {
664 3 : BleLayer * layer = reinterpret_cast<BleLayer *>(appState);
665 3 : layer->mBleTransport->OnBleConnectionError(err);
666 3 : }
667 :
668 : } /* namespace Ble */
669 : } /* namespace chip */
|