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 113 : 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 113 : if (i < BLE_LAYER_NUM_BLE_ENDPOINTS)
97 : {
98 113 : 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 131 : BleLayer::BleLayer()
254 : {
255 131 : mState = kState_NotInitialized;
256 131 : }
257 :
258 67 : CHIP_ERROR BleLayer::Init(BlePlatformDelegate * platformDelegate, BleConnectionDelegate * connDelegate,
259 : BleApplicationDelegate * appDelegate, chip::System::Layer * systemLayer)
260 : {
261 67 : 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 67 : VerifyOrReturnError(platformDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
266 67 : VerifyOrReturnError(appDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
267 67 : VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
268 :
269 67 : if (mState != kState_NotInitialized)
270 : {
271 0 : return CHIP_ERROR_INCORRECT_STATE;
272 : }
273 :
274 67 : mConnectionDelegate = connDelegate;
275 67 : mPlatformDelegate = platformDelegate;
276 67 : mApplicationDelegate = appDelegate;
277 67 : mSystemLayer = systemLayer;
278 :
279 67 : memset(&sBLEEndPointPool, 0, sizeof(sBLEEndPointPool));
280 :
281 67 : mState = kState_Initialized;
282 :
283 67 : 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 67 : void BleLayer::Shutdown()
298 : {
299 67 : mState = kState_NotInitialized;
300 67 : CloseAllBleConnections();
301 67 : }
302 :
303 71 : void BleLayer::CloseAllBleConnections()
304 : {
305 : // Close and free all BLE end points.
306 142 : for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
307 : {
308 71 : BLEEndPoint * elem = sBLEEndPointPool.Get(i);
309 :
310 : // If end point was initialized, and has not since been freed...
311 71 : 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 71 : }
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 14 : CHIP_ERROR BleLayer::NewBleEndPoint(BLEEndPoint ** retEndPoint, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose)
413 : {
414 14 : *retEndPoint = nullptr;
415 :
416 14 : if (mState != kState_Initialized)
417 : {
418 0 : return CHIP_ERROR_INCORRECT_STATE;
419 : }
420 :
421 14 : if (connObj == BLE_CONNECTION_UNINITIALIZED)
422 : {
423 1 : return CHIP_ERROR_INVALID_ARGUMENT;
424 : }
425 :
426 13 : *retEndPoint = sBLEEndPointPool.GetFree();
427 13 : if (*retEndPoint == nullptr)
428 : {
429 1 : ChipLogError(Ble, "%s endpoint pool FULL", "Ble");
430 1 : return CHIP_ERROR_ENDPOINT_POOL_FULL;
431 : }
432 :
433 12 : (*retEndPoint)->Init(this, connObj, role, autoClose);
434 12 : (*retEndPoint)->mBleTransport = mBleTransport;
435 :
436 12 : return CHIP_NO_ERROR;
437 : }
438 :
439 : // Handle remote central's initiation of CHIP over BLE protocol handshake.
440 14 : CHIP_ERROR BleLayer::HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, PacketBufferHandle && pBuf)
441 : {
442 14 : CHIP_ERROR err = CHIP_NO_ERROR;
443 14 : BLEEndPoint * newEndPoint = nullptr;
444 :
445 : // Only BLE peripherals can receive GATT writes, so specify this role in our creation of the BLEEndPoint.
446 : // Set autoClose = false. Peripherals only notify the application when an end point releases a BLE connection.
447 14 : err = NewBleEndPoint(&newEndPoint, connObj, kBleRole_Peripheral, false);
448 14 : SuccessOrExit(err);
449 :
450 12 : newEndPoint->mBleTransport = mBleTransport;
451 :
452 12 : err = newEndPoint->Receive(std::move(pBuf));
453 12 : SuccessOrExit(err); // If we fail here, end point will have already released connection and freed itself.
454 :
455 14 : exit:
456 : // If we failed to allocate a new end point, release underlying BLE connection. Central's handshake will time out
457 : // if the application decides to keep the BLE connection open.
458 14 : if (newEndPoint == nullptr)
459 : {
460 2 : mApplicationDelegate->NotifyChipConnectionClosed(connObj);
461 : }
462 :
463 14 : if (err != CHIP_NO_ERROR)
464 : {
465 2 : ChipLogError(Ble, "HandleChipConnectionReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format());
466 : }
467 :
468 14 : return err;
469 : }
470 :
471 17 : bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
472 : PacketBufferHandle && pBuf)
473 : {
474 17 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write received on unknown svc"));
475 16 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_UUID, charId), false, ChipLogError(Ble, "Write received on unknown char"));
476 15 : VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Write received null buffer"));
477 :
478 : // Find matching connection end point.
479 15 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
480 :
481 15 : if (endPoint != nullptr)
482 : {
483 1 : CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
484 1 : VerifyOrReturnError(err == CHIP_NO_ERROR, false,
485 : ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
486 : }
487 : else
488 : {
489 14 : CHIP_ERROR err = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
490 14 : VerifyOrReturnError(err == CHIP_NO_ERROR, false,
491 : ChipLogError(Ble, "Handle new BLE connection failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
492 : }
493 :
494 13 : return true;
495 : }
496 :
497 3 : bool BleLayer::HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
498 : PacketBufferHandle && pBuf)
499 : {
500 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication received on unknown svc"));
501 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId), false, ChipLogError(Ble, "Indication received on unknown char"));
502 1 : VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Indication received null buffer"));
503 :
504 : // Find matching connection end point.
505 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
506 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received indication"));
507 :
508 1 : CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
509 1 : VerifyOrReturnError(err == CHIP_NO_ERROR, false, ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
510 :
511 1 : return true;
512 : }
513 :
514 3 : bool BleLayer::HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
515 : {
516 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write confirmation on unknown svc"));
517 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_UUID, charId), false, ChipLogError(Ble, "Write confirmation on unknown char"));
518 :
519 1 : HandleAckReceived(connObj);
520 1 : return true;
521 : }
522 :
523 3 : bool BleLayer::HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
524 : {
525 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication confirmation on unknown svc"));
526 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId), false,
527 : ChipLogError(Ble, "Indication confirmation on unknown char"));
528 :
529 1 : HandleAckReceived(connObj);
530 1 : return true;
531 : }
532 :
533 2 : void BleLayer::HandleAckReceived(BLE_CONNECTION_OBJECT connObj)
534 : {
535 : // Find matching connection end point.
536 2 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
537 2 : VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for received ack"));
538 :
539 2 : CHIP_ERROR err = endPoint->HandleGattSendConfirmationReceived();
540 2 : VerifyOrReturn(err == CHIP_NO_ERROR,
541 : ChipLogError(Ble, "Send ack confirmation failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
542 : }
543 :
544 8 : bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
545 : {
546 8 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe received on unknown svc"));
547 7 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
548 : ChipLogError(Ble, "Subscribe received on unknown char"));
549 :
550 : // Find end point already associated with BLE connection, if any.
551 6 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
552 6 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received subscribe"));
553 :
554 6 : endPoint->HandleSubscribeReceived();
555 6 : return true;
556 : }
557 :
558 3 : bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
559 : {
560 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe complete on unknown svc"));
561 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
562 : ChipLogError(Ble, "Subscribe complete on unknown char"));
563 :
564 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
565 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for subscribe complete"));
566 :
567 1 : endPoint->HandleSubscribeComplete();
568 1 : return true;
569 : }
570 :
571 3 : bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
572 : {
573 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe received on unknown svc"));
574 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
575 : ChipLogError(Ble, "Unsubscribe received on unknown char"));
576 :
577 : // Find end point already associated with BLE connection, if any.
578 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
579 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe received"));
580 :
581 1 : endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
582 1 : return true;
583 : }
584 :
585 3 : bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
586 : {
587 3 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe complete on unknown svc"));
588 2 : VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_UUID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_UUID, charId), false,
589 : ChipLogError(Ble, "Unsubscribe complete on unknown char"));
590 :
591 : // Find end point already associated with BLE connection, if any.
592 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
593 1 : VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe complete"));
594 :
595 1 : endPoint->HandleUnsubscribeComplete();
596 1 : return true;
597 : }
598 :
599 1 : void BleLayer::HandleConnectionError(BLE_CONNECTION_OBJECT connObj, CHIP_ERROR err)
600 : {
601 : // BLE connection has failed somehow, we must find and abort matching connection end point.
602 1 : BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
603 1 : VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for connection error"));
604 :
605 1 : if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
606 : {
607 : // If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
608 : // stops unsubscribe timer.
609 0 : endPoint->Free();
610 : }
611 : else
612 : {
613 1 : endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
614 : }
615 : }
616 :
617 12 : BleTransportProtocolVersion BleLayer::GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg)
618 : {
619 12 : BleTransportProtocolVersion retVersion = kBleTransportProtocolVersion_None;
620 :
621 12 : uint8_t shift_width = 4;
622 :
623 36 : for (int i = 0; i < NUM_SUPPORTED_PROTOCOL_VERSIONS; i++)
624 : {
625 36 : shift_width ^= 4;
626 :
627 36 : uint8_t version = reqMsg.mSupportedProtocolVersions[(i / 2)];
628 36 : version = static_cast<uint8_t>((version >> shift_width) & 0x0F); // Grab just the nibble we want.
629 :
630 36 : if ((version >= CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION) &&
631 12 : (version <= CHIP_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION) && (version > retVersion))
632 : {
633 12 : retVersion = static_cast<BleTransportProtocolVersion>(version);
634 : }
635 24 : else if (version == kBleTransportProtocolVersion_None) // Signifies end of supported versions list
636 : {
637 12 : break;
638 : }
639 : }
640 :
641 12 : return retVersion;
642 : }
643 :
644 0 : void BleLayer::OnConnectionComplete(void * appState, BLE_CONNECTION_OBJECT connObj)
645 : {
646 0 : BleLayer * layer = reinterpret_cast<BleLayer *>(appState);
647 0 : BLEEndPoint * endPoint = nullptr;
648 0 : CHIP_ERROR err = CHIP_NO_ERROR;
649 :
650 0 : SuccessOrExit(err = layer->NewBleEndPoint(&endPoint, connObj, kBleRole_Central, true));
651 0 : layer->mBleTransport->OnBleConnectionComplete(endPoint);
652 :
653 0 : exit:
654 0 : if (err != CHIP_NO_ERROR)
655 : {
656 0 : OnConnectionError(layer, err);
657 : }
658 0 : }
659 :
660 0 : void BleLayer::OnConnectionError(void * appState, CHIP_ERROR err)
661 : {
662 0 : BleLayer * layer = reinterpret_cast<BleLayer *>(appState);
663 0 : layer->mBleTransport->OnBleConnectionError(err);
664 0 : }
665 :
666 : } /* namespace Ble */
667 : } /* namespace chip */
|