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