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