Coverage Report

Created: 2025-10-26 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openweave-core/src/ble/BleLayer.cpp
Line
Count
Source
1
/*
2
 *
3
 *    Copyright (c) 2014-2017 Nest Labs, Inc.
4
 *    All rights reserved.
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 Weave
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 Weave message via a BLE GATT
28
 *      characteristic interface, and drives incoming messages up the Weave
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 Weave 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 Weave to inform
41
 *      the application when it has finished using a given BLE connection,
42
 *      i.e when the WeaveConnection 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-Weave purposes.
45
 *
46
 *      To enable Weave 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 <BleLayer/BleConfig.h>
54
55
#if CONFIG_NETWORK_LAYER_BLE
56
57
#include <string.h>
58
59
#include <BleLayer/BlePlatformDelegate.h>
60
#include <BleLayer/BleApplicationDelegate.h>
61
#include <BleLayer/BleLayer.h>
62
#include <BleLayer/BleUUID.h>
63
#include <BleLayer/BLEEndPoint.h>
64
65
#include <Weave/Core/WeaveEncoding.h>
66
#include <Weave/Support/logging/WeaveLogging.h>
67
#include <Weave/Support/CodeUtils.h>
68
69
// clang-format off
70
71
0
#define CAPABILITIES_REQUEST_MAGICNUM_LEN 2
72
0
#define CAPABILITIES_REQUEST_L2CAP_MTU_LEN 2
73
0
#define CAPABILITIES_REQUEST_SUPPORTED_VERSIONS_LEN 4
74
0
#define CAPABILITIES_REQUEST_WINDOW_SIZE_LEN 1
75
0
#define CAPABILITIES_REQUEST_LEN (CAPABILITIES_REQUEST_MAGICNUM_LEN + \
76
0
                                  CAPABILITIES_REQUEST_L2CAP_MTU_LEN + \
77
0
                                  CAPABILITIES_REQUEST_SUPPORTED_VERSIONS_LEN + \
78
0
                                  CAPABILITIES_REQUEST_WINDOW_SIZE_LEN)
79
80
0
#define CAPABILITIES_RESPONSE_MAGICNUM_LEN 2
81
0
#define CAPABILITIES_RESPONSE_L2CAP_MTU_LEN 2
82
0
#define CAPABILITIES_RESPONSE_SELECTED_PROTOCOL_VERSION_LEN 1
83
0
#define CAPABILITIES_RESPONSE_WINDOW_SIZE_LEN 1
84
0
#define CAPABILITIES_RESPONSE_LEN (CAPABILITIES_RESPONSE_MAGICNUM_LEN + \
85
0
                                   CAPABILITIES_RESPONSE_L2CAP_MTU_LEN + \
86
0
                                   CAPABILITIES_RESPONSE_SELECTED_PROTOCOL_VERSION_LEN + \
87
0
                                   CAPABILITIES_RESPONSE_WINDOW_SIZE_LEN)
88
89
// Magic values expected in first 2 bytes of valid BLE transport capabilities request or response:
90
0
#define CAPABILITIES_MSG_CHECK_BYTE_1 'n'
91
0
#define CAPABILITIES_MSG_CHECK_BYTE_2 'l'
92
93
// clang-format on
94
95
namespace nl {
96
namespace Ble {
97
98
class BleEndPointPool
99
{
100
public:
101
0
    int Size() const { return BLE_LAYER_NUM_BLE_ENDPOINTS; }
102
103
    BLEEndPoint * Get(int i) const
104
0
    {
105
0
        static union
106
0
        {
107
0
            uint8_t Pool[sizeof(BLEEndPoint) * BLE_LAYER_NUM_BLE_ENDPOINTS];
108
0
            BLEEndPoint::AlignT ForceAlignment;
109
0
        } sEndPointPool;
110
111
0
        if (i < BLE_LAYER_NUM_BLE_ENDPOINTS)
112
0
        {
113
0
            return (BLEEndPoint *) (sEndPointPool.Pool + (sizeof(BLEEndPoint) * i));
114
0
        }
115
0
        else
116
0
        {
117
0
            return NULL;
118
0
        }
119
0
    }
120
121
    BLEEndPoint * Find(BLE_CONNECTION_OBJECT c)
122
0
    {
123
0
        if (c == BLE_CONNECTION_UNINITIALIZED)
124
0
        {
125
0
            return NULL;
126
0
        }
127
128
0
        for (int i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
129
0
        {
130
0
            BLEEndPoint * elem = Get(i);
131
0
            if (elem->mBle != NULL && elem->mConnObj == c)
132
0
            {
133
0
                return elem;
134
0
            }
135
0
        }
136
137
0
        return NULL;
138
0
    }
139
140
    BLEEndPoint * GetFree() const
141
0
    {
142
0
        for (int i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
143
0
        {
144
0
            BLEEndPoint * elem = Get(i);
145
0
            if (elem->mBle == NULL)
146
0
            {
147
0
                return elem;
148
0
            }
149
0
        }
150
0
        return NULL;
151
0
    }
152
};
153
154
// EndPoint Pools
155
//
156
static BleEndPointPool sBLEEndPointPool;
157
158
// UUIDs used internally by BleLayer:
159
160
const WeaveBleUUID BleLayer::WEAVE_BLE_CHAR_1_ID = { { // 18EE2EF5-263D-4559-959F-4F9C429F9D11
161
                                                       0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42,
162
                                                       0x9F, 0x9D, 0x11 } };
163
164
const WeaveBleUUID BleLayer::WEAVE_BLE_CHAR_2_ID = { { // 18EE2EF5-263D-4559-959F-4F9C429F9D12
165
                                                       0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42,
166
                                                       0x9F, 0x9D, 0x12 } };
167
168
void BleLayerObject::Release()
169
0
{
170
    // Decrement the ref count.  When it reaches zero, NULL out the pointer to the Weave::System::Layer
171
    // object. This effectively declared the object free and ready for re-allocation.
172
0
    mRefCount--;
173
0
    if (mRefCount == 0)
174
0
    {
175
0
        mBle = NULL;
176
0
    }
177
0
}
178
179
// BleTransportCapabilitiesRequestMessage implementation:
180
181
void BleTransportCapabilitiesRequestMessage::SetSupportedProtocolVersion(uint8_t index, uint8_t version)
182
0
{
183
0
    uint8_t mask;
184
185
    // If even-index, store version in lower 4 bits; else, higher 4 bits.
186
0
    if (index % 2 == 0)
187
0
    {
188
0
        mask = 0x0F;
189
0
    }
190
0
    else
191
0
    {
192
0
        mask    = 0xF0;
193
0
        version = version << 4;
194
0
    }
195
196
0
    version &= mask;
197
198
0
    mSupportedProtocolVersions[(index / 2)] &= ~mask; // Clear version at index; leave other version in same byte alone
199
0
    mSupportedProtocolVersions[(index / 2)] |= version;
200
0
}
201
202
BLE_ERROR BleTransportCapabilitiesRequestMessage::Encode(PacketBuffer * msgBuf) const
203
0
{
204
0
    uint8_t * p   = msgBuf->Start();
205
0
    BLE_ERROR err = BLE_NO_ERROR;
206
207
    // Verify we can write the fixed-length request without running into the end of the buffer.
208
0
    VerifyOrExit(msgBuf->MaxDataLength() >= CAPABILITIES_REQUEST_LEN, err = BLE_ERROR_NO_MEMORY);
209
210
0
    nl::Weave::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_1);
211
0
    nl::Weave::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_2);
212
213
0
    for (int i = 0; i < CAPABILITIES_REQUEST_SUPPORTED_VERSIONS_LEN; i++)
214
0
    {
215
0
        nl::Weave::Encoding::Write8(p, mSupportedProtocolVersions[i]);
216
0
    }
217
218
0
    nl::Weave::Encoding::LittleEndian::Write16(p, mMtu);
219
0
    nl::Weave::Encoding::Write8(p, mWindowSize);
220
221
0
    msgBuf->SetDataLength(CAPABILITIES_REQUEST_LEN);
222
223
0
exit:
224
0
    return err;
225
0
}
226
227
BLE_ERROR BleTransportCapabilitiesRequestMessage::Decode(const PacketBuffer & msgBuf, BleTransportCapabilitiesRequestMessage & msg)
228
0
{
229
0
    const uint8_t * p = msgBuf.Start();
230
0
    BLE_ERROR err     = BLE_NO_ERROR;
231
232
    // Verify we can read the fixed-length request without running into the end of the buffer.
233
0
    VerifyOrExit(msgBuf.DataLength() >= CAPABILITIES_REQUEST_LEN, err = BLE_ERROR_MESSAGE_INCOMPLETE);
234
235
0
    VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_1 == nl::Weave::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
236
0
    VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_2 == nl::Weave::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
237
238
0
    for (int i = 0; i < CAPABILITIES_REQUEST_SUPPORTED_VERSIONS_LEN; i++)
239
0
    {
240
0
        msg.mSupportedProtocolVersions[i] = nl::Weave::Encoding::Read8(p);
241
0
    }
242
243
0
    msg.mMtu        = nl::Weave::Encoding::LittleEndian::Read16(p);
244
0
    msg.mWindowSize = nl::Weave::Encoding::Read8(p);
245
246
0
exit:
247
0
    return err;
248
0
}
249
250
// BleTransportCapabilitiesResponseMessage implementation:
251
252
BLE_ERROR BleTransportCapabilitiesResponseMessage::Encode(PacketBuffer * msgBuf) const
253
0
{
254
0
    uint8_t * p   = msgBuf->Start();
255
0
    BLE_ERROR err = BLE_NO_ERROR;
256
257
    // Verify we can write the fixed-length request without running into the end of the buffer.
258
0
    VerifyOrExit(msgBuf->MaxDataLength() >= CAPABILITIES_RESPONSE_LEN, err = BLE_ERROR_NO_MEMORY);
259
260
0
    nl::Weave::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_1);
261
0
    nl::Weave::Encoding::Write8(p, CAPABILITIES_MSG_CHECK_BYTE_2);
262
263
0
    nl::Weave::Encoding::Write8(p, mSelectedProtocolVersion);
264
0
    nl::Weave::Encoding::LittleEndian::Write16(p, mFragmentSize);
265
0
    nl::Weave::Encoding::Write8(p, mWindowSize);
266
267
0
    msgBuf->SetDataLength(CAPABILITIES_RESPONSE_LEN);
268
269
0
exit:
270
0
    return err;
271
0
}
272
273
BLE_ERROR BleTransportCapabilitiesResponseMessage::Decode(const PacketBuffer & msgBuf,
274
                                                          BleTransportCapabilitiesResponseMessage & msg)
275
0
{
276
0
    const uint8_t * p = msgBuf.Start();
277
0
    BLE_ERROR err     = BLE_NO_ERROR;
278
279
    // Verify we can read the fixed-length response without running into the end of the buffer.
280
0
    VerifyOrExit(msgBuf.DataLength() >= CAPABILITIES_RESPONSE_LEN, err = BLE_ERROR_MESSAGE_INCOMPLETE);
281
282
0
    VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_1 == nl::Weave::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
283
0
    VerifyOrExit(CAPABILITIES_MSG_CHECK_BYTE_2 == nl::Weave::Encoding::Read8(p), err = BLE_ERROR_INVALID_MESSAGE);
284
285
0
    msg.mSelectedProtocolVersion = nl::Weave::Encoding::Read8(p);
286
0
    msg.mFragmentSize            = nl::Weave::Encoding::LittleEndian::Read16(p);
287
0
    msg.mWindowSize              = nl::Weave::Encoding::Read8(p);
288
289
0
exit:
290
0
    return err;
291
0
}
292
293
// BleLayer implementation:
294
295
BleLayer::BleLayer()
296
10
{
297
10
    mState = kState_NotInitialized;
298
10
}
299
300
BLE_ERROR BleLayer::Init(BlePlatformDelegate * platformDelegate, BleApplicationDelegate * appDelegate,
301
                         Weave::System::Layer * systemLayer)
302
0
{
303
0
    BLE_ERROR err = BLE_NO_ERROR;
304
305
0
    RegisterBleLayerErrorFormatter();
306
307
0
    VerifyOrExit(platformDelegate != NULL, err = BLE_ERROR_BAD_ARGS);
308
0
    VerifyOrExit(appDelegate != NULL, err = BLE_ERROR_BAD_ARGS);
309
0
    VerifyOrExit(systemLayer != NULL, err = BLE_ERROR_BAD_ARGS);
310
311
0
    if (mState != kState_NotInitialized)
312
0
    {
313
0
        return BLE_ERROR_INCORRECT_STATE;
314
0
    }
315
316
0
    mPlatformDelegate    = platformDelegate;
317
0
    mApplicationDelegate = appDelegate;
318
0
    mSystemLayer         = systemLayer;
319
320
0
    memset(&sBLEEndPointPool, 0, sizeof(sBLEEndPointPool));
321
322
0
    mState = kState_Initialized;
323
324
#if WEAVE_ENABLE_WOBLE_TEST
325
    mTestBleEndPoint = NULL;
326
#endif
327
328
0
exit:
329
0
    return err;
330
0
}
331
332
BLE_ERROR BleLayer::Shutdown()
333
0
{
334
0
    mState = kState_NotInitialized;
335
336
    // Close and free all BLE end points.
337
0
    for (int i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
338
0
    {
339
0
        BLEEndPoint * elem = sBLEEndPointPool.Get(i);
340
341
        // If end point was initialized, and has not since been freed...
342
0
        if (elem->mBle != NULL)
343
0
        {
344
            // If end point hasn't already been closed...
345
0
            if (elem->mState != BLEEndPoint::kState_Closed)
346
0
            {
347
                // Close end point such that callbacks are suppressed and pending transmissions aborted.
348
0
                elem->Abort();
349
0
            }
350
351
            // If end point was closed, but is still waiting for GATT unsubscribe to complete, free it anyway.
352
            // This cancels the unsubscribe timer (plus all the end point's other timers).
353
0
            if (elem->IsUnsubscribePending())
354
0
            {
355
0
                elem->Free();
356
0
            }
357
0
        }
358
0
    }
359
360
0
    return BLE_NO_ERROR;
361
0
}
362
363
BLE_ERROR BleLayer::NewBleEndPoint(BLEEndPoint ** retEndPoint, BLE_CONNECTION_OBJECT connObj, BleRole role, bool autoClose)
364
0
{
365
0
    *retEndPoint = NULL;
366
367
0
    if (mState != kState_Initialized)
368
0
    {
369
0
        return BLE_ERROR_INCORRECT_STATE;
370
0
    }
371
372
0
    if (connObj == BLE_CONNECTION_UNINITIALIZED)
373
0
    {
374
0
        return BLE_ERROR_BAD_ARGS;
375
0
    }
376
377
0
    *retEndPoint = sBLEEndPointPool.GetFree();
378
0
    if (*retEndPoint == NULL)
379
0
    {
380
0
        WeaveLogError(Ble, "%s endpoint pool FULL", "Ble");
381
0
        return BLE_ERROR_NO_ENDPOINTS;
382
0
    }
383
384
0
    (*retEndPoint)->Init(this, connObj, role, autoClose);
385
386
#if WEAVE_ENABLE_WOBLE_TEST
387
    mTestBleEndPoint = *retEndPoint;
388
#endif
389
390
0
    return BLE_NO_ERROR;
391
0
}
392
393
// Handle remote central's initiation of Weave over BLE protocol handshake.
394
BLE_ERROR BleLayer::HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, PacketBuffer * pBuf)
395
0
{
396
0
    BLE_ERROR err             = BLE_NO_ERROR;
397
0
    BLEEndPoint * newEndPoint = NULL;
398
399
    // Only BLE peripherals can receive GATT writes, so specify this role in our creation of the BLEEndPoint.
400
    // Set autoClose = false. Peripherals only notify the application when an end point releases a BLE connection.
401
0
    err = NewBleEndPoint(&newEndPoint, connObj, kBleRole_Peripheral, false);
402
0
    SuccessOrExit(err);
403
404
0
    newEndPoint->mAppState = mAppState;
405
406
0
    err  = newEndPoint->Receive(pBuf);
407
0
    pBuf = NULL;
408
0
    SuccessOrExit(err); // If we fail here, end point will have already released connection and freed itself.
409
410
0
exit:
411
0
    if (pBuf != NULL)
412
0
    {
413
0
        PacketBuffer::Free(pBuf);
414
0
    }
415
416
    // If we failed to allocate a new end point, release underlying BLE connection. Central's handshake will time out
417
    // if the application decides to keep the BLE connection open.
418
0
    if (newEndPoint == NULL)
419
0
    {
420
0
        mApplicationDelegate->NotifyWeaveConnectionClosed(connObj);
421
0
    }
422
423
0
    if (err != BLE_NO_ERROR)
424
0
    {
425
0
        WeaveLogError(Ble, "HandleWeaveConnectionReceived failed, err = %d", err);
426
0
    }
427
428
0
    return err;
429
0
}
430
431
bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId,
432
                                   PacketBuffer * pBuf)
433
0
{
434
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
435
0
    {
436
0
        WeaveLogError(Ble, "ble write rcvd on unknown svc id");
437
0
        ExitNow();
438
0
    }
439
440
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_1_ID, charId))
441
0
    {
442
0
        if (pBuf == NULL)
443
0
        {
444
0
            WeaveLogError(Ble, "rcvd null ble write");
445
0
            ExitNow();
446
0
        }
447
448
        // Find matching connection end point.
449
0
        BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
450
451
0
        if (endPoint != NULL)
452
0
        {
453
0
            BLE_ERROR status = endPoint->Receive(pBuf);
454
0
            pBuf             = NULL;
455
0
            if (status != BLE_NO_ERROR)
456
0
            {
457
0
                WeaveLogError(Ble, "BLEEndPoint rcv failed, err = %d", status);
458
0
            }
459
0
        }
460
0
        else
461
0
        {
462
0
            BLE_ERROR status = HandleBleTransportConnectionInitiated(connObj, pBuf);
463
0
            pBuf             = NULL;
464
0
            if (status != BLE_NO_ERROR)
465
0
            {
466
0
                WeaveLogError(Ble, "failed handle new Weave BLE connection, status = %d", status);
467
0
            }
468
0
        }
469
0
    }
470
0
    else
471
0
    {
472
0
        WeaveLogError(Ble, "ble write rcvd on unknown char");
473
0
    }
474
475
0
exit:
476
0
    if (pBuf != NULL)
477
0
    {
478
0
        PacketBuffer::Free(pBuf);
479
0
    }
480
481
0
    return true;
482
0
}
483
484
bool BleLayer::HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId,
485
                                        PacketBuffer * pBuf)
486
0
{
487
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
488
0
    {
489
0
        return false;
490
0
    }
491
492
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_2_ID, charId))
493
0
    {
494
0
        if (pBuf == NULL)
495
0
        {
496
0
            WeaveLogError(Ble, "rcvd null ble indication");
497
0
            ExitNow();
498
0
        }
499
500
        // find matching connection end point.
501
0
        BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
502
503
0
        if (endPoint != NULL)
504
0
        {
505
0
            BLE_ERROR status = endPoint->Receive(pBuf);
506
0
            pBuf             = NULL;
507
0
            if (status != BLE_NO_ERROR)
508
0
            {
509
0
                WeaveLogError(Ble, "BLEEndPoint rcv failed, err = %d", status);
510
0
            }
511
0
        }
512
0
        else
513
0
        {
514
0
            WeaveLogDetail(Ble, "no endpoint for rcvd indication");
515
0
        }
516
0
    }
517
0
    else
518
0
    {
519
0
        WeaveLogError(Ble, "ble ind rcvd on unknown char");
520
0
    }
521
522
0
exit:
523
0
    if (pBuf != NULL)
524
0
    {
525
0
        PacketBuffer::Free(pBuf);
526
0
    }
527
528
0
    return true;
529
0
}
530
531
bool BleLayer::HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId)
532
0
{
533
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
534
0
    {
535
0
        return false;
536
0
    }
537
538
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_1_ID, charId))
539
0
    {
540
0
        HandleAckReceived(connObj);
541
0
    }
542
0
    else
543
0
    {
544
0
        WeaveLogError(Ble, "ble write con rcvd on unknown char");
545
0
    }
546
547
0
    return true;
548
0
}
549
550
bool BleLayer::HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId)
551
0
{
552
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
553
0
    {
554
0
        return false;
555
0
    }
556
557
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_2_ID, charId))
558
0
    {
559
0
        HandleAckReceived(connObj);
560
0
    }
561
0
    else
562
0
    {
563
0
        WeaveLogError(Ble, "ble ind con rcvd on unknown char");
564
0
    }
565
566
0
    return true;
567
0
}
568
569
void BleLayer::HandleAckReceived(BLE_CONNECTION_OBJECT connObj)
570
0
{
571
    // find matching connection end point.
572
0
    BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
573
574
0
    if (endPoint != NULL)
575
0
    {
576
0
        BLE_ERROR status = endPoint->HandleGattSendConfirmationReceived();
577
578
0
        if (status != BLE_NO_ERROR)
579
0
        {
580
0
            WeaveLogError(Ble, "endpoint conf recvd failed, err = %d", status);
581
0
        }
582
0
    }
583
0
    else
584
0
    {
585
0
        WeaveLogError(Ble, "no endpoint for BLE sent data ack");
586
0
    }
587
0
}
588
589
bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId)
590
0
{
591
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
592
0
    {
593
0
        return false;
594
0
    }
595
596
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_2_ID, charId))
597
0
    {
598
        // Find end point already associated with BLE connection, if any.
599
0
        BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
600
601
0
        if (endPoint != NULL)
602
0
        {
603
0
            endPoint->HandleSubscribeReceived();
604
0
        }
605
0
        else
606
0
        {
607
0
            WeaveLogError(Ble, "no endpoint for sub recvd");
608
0
        }
609
0
    }
610
611
0
    return true;
612
0
}
613
614
bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId)
615
0
{
616
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
617
0
    {
618
0
        return false;
619
0
    }
620
621
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_2_ID, charId))
622
0
    {
623
0
        BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
624
625
0
        if (endPoint != NULL)
626
0
        {
627
0
            endPoint->HandleSubscribeComplete();
628
0
        }
629
0
        else
630
0
        {
631
0
            WeaveLogError(Ble, "no endpoint for sub complete");
632
0
        }
633
0
    }
634
635
0
    return true;
636
0
}
637
638
bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId)
639
0
{
640
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
641
0
    {
642
0
        return false;
643
0
    }
644
645
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_2_ID, charId))
646
0
    {
647
        // Find end point already associated with BLE connection, if any.
648
0
        BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
649
650
0
        if (endPoint != NULL)
651
0
        {
652
0
            endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
653
0
        }
654
0
        else
655
0
        {
656
0
            WeaveLogError(Ble, "no endpoint for unsub recvd");
657
0
        }
658
0
    }
659
660
0
    return true;
661
0
}
662
663
bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const WeaveBleUUID * svcId, const WeaveBleUUID * charId)
664
0
{
665
0
    if (!UUIDsMatch(&WEAVE_BLE_SVC_ID, svcId))
666
0
    {
667
0
        return false;
668
0
    }
669
670
0
    if (UUIDsMatch(&WEAVE_BLE_CHAR_2_ID, charId))
671
0
    {
672
        // Find end point already associated with BLE connection, if any.
673
0
        BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
674
675
0
        if (endPoint != NULL)
676
0
        {
677
0
            endPoint->HandleUnsubscribeComplete();
678
0
        }
679
0
        else
680
0
        {
681
0
            WeaveLogError(Ble, "no endpoint for unsub complete");
682
0
        }
683
0
    }
684
685
0
    return true;
686
0
}
687
688
void BleLayer::HandleConnectionError(BLE_CONNECTION_OBJECT connObj, BLE_ERROR err)
689
0
{
690
    // BLE connection has failed somehow, we must find and abort matching connection end point.
691
0
    BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
692
693
0
    if (endPoint != NULL)
694
0
    {
695
0
        if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
696
0
        {
697
            // If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
698
            // stops unsubscribe timer.
699
0
            endPoint->Free();
700
0
        }
701
0
        else
702
0
        {
703
0
            endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
704
0
        }
705
0
    }
706
0
}
707
708
BleTransportProtocolVersion BleLayer::GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg)
709
0
{
710
0
    BleTransportProtocolVersion retVersion = kBleTransportProtocolVersion_None;
711
712
0
    uint8_t shift_width = 4;
713
714
0
    for (int i = 0; i < NUM_SUPPORTED_PROTOCOL_VERSIONS; i++)
715
0
    {
716
0
        shift_width ^= 4;
717
718
0
        uint8_t version = reqMsg.mSupportedProtocolVersions[(i / 2)];
719
0
        version         = (version >> shift_width) & 0x0F; // Grab just the nibble we want.
720
721
0
        if ((version >= NL_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION) &&
722
0
            (version <= NL_BLE_TRANSPORT_PROTOCOL_MAX_SUPPORTED_VERSION) && (version > retVersion))
723
0
        {
724
0
            retVersion = static_cast<BleTransportProtocolVersion>(version);
725
0
        }
726
0
        else if (version == kBleTransportProtocolVersion_None) // Signifies end of supported versions list
727
0
        {
728
0
            break;
729
0
        }
730
0
    }
731
732
0
    return retVersion;
733
0
}
734
735
} /* namespace Ble */
736
} /* namespace nl */
737
738
#endif /* CONFIG_NETWORK_LAYER_BLE */