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