Welcome to mirror list, hosted at ThFree Co, Russian Federation.

zigbee.nwk.h « include « stack « zigbee « STM32_WPAN « ST « Middlewares - github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bface2329aac8869053f3d3898aa6c020fa9f43a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
/* Copyright [2009 - 2019] Exegin Technologies Limited. All rights reserved. */

#ifndef ZIGBEE_NWK_H
# define ZIGBEE_NWK_H

/*---------------------------------------------------------------
 * Misc. Definitions and Structures
 *---------------------------------------------------------------
 */
#define ZbNwkAddrIsBcast(_addr_) (((_addr_) >= (uint16_t)ZB_NWK_ADDR_BCAST_MIN) && ((_addr_) != (uint16_t)ZB_NWK_ADDR_USE_EXT))

/* Special NWK addresses. */
#define ZB_NWK_ADDR_COORDINATOR                     (uint16_t)0x0000U
#define ZB_NWK_ADDR_BCAST_MIN                       (uint16_t)0xfff8U
#define ZB_NWK_ADDR_BCAST_LOW_POWER_ROUTERS         (uint16_t)0xfffbU
#define ZB_NWK_ADDR_BCAST_ROUTERS                   (uint16_t)0xfffcU
#define ZB_NWK_ADDR_BCAST_RXON                      (uint16_t)0xfffdU
#define ZB_NWK_ADDR_USE_EXT                         (uint16_t)0xfffeU /* IEEE802154_ADDR_SHORT_NONE */
#define ZB_NWK_ADDR_BCAST_ALL                       (uint16_t)0xffffU /* IEEE802154_ADDR_SHORT_BCAST */
#define ZB_NWK_ADDR_UNDEFINED                       (uint16_t)0xffffU /* IEEE802154_ADDR_SHORT_BCAST */

/* ZigBee Stack Profiles (StackProfile or nwkStackProfile) */
enum {
    ZB_NWK_STACK_PROFILE_NWKSPFC = 0x00,
    ZB_NWK_STACK_PROFILE_HOME = 0x01,
    ZB_NWK_STACK_PROFILE_PRO = 0x02,
    ZB_NWK_STACK_PROFILE_PLANTCTRL = 0x03
};

/* Address allocation methods (nwkAddrAlloc) */
enum  nwkAddrAllocMethod {
    ZB_NWK_ADDR_ALLOC_DISTRIB = 0x00,
    ZB_NWK_ADDR_ALLOC_RESERVED = 0x01,
    ZB_NWK_ADDR_ALLOC_STOCHASTIC = 0x02
};

/* Status codes for network status indications. */
enum ZbNwkNetworkStatusCodeT {
    ZB_NWK_STATUS_CODE_NO_ROUTE_AVAILABLE = 0x00,
    ZB_NWK_STATUS_CODE_TREE_LINK_FAILURE = 0x01,
    ZB_NWK_STATUS_CODE_NON_TREE_LINK_FAILURE = 0x02,
    ZB_NWK_STATUS_CODE_LOW_BATTERY = 0x03,
    ZB_NWK_STATUS_CODE_NO_ROUTING_CAPACITY = 0x04,
    ZB_NWK_STATUS_CODE_NO_INDIRECT_CAPACITY = 0x05,
    ZB_NWK_STATUS_CODE_INDIRECT_EXPIRY = 0x06,
    ZB_NWK_STATUS_CODE_TARGET_UNAVAILABLE = 0x07,
    ZB_NWK_STATUS_CODE_TARGET_UNALLOCATED = 0x08,
    ZB_NWK_STATUS_CODE_PARENT_LINK_FAILURE = 0x09,
    ZB_NWK_STATUS_CODE_VALIDATE_ROUTE = 0x0a,
    ZB_NWK_STATUS_CODE_SOURCE_ROUTE_FAILURE = 0x0b,
    ZB_NWK_STATUS_CODE_MANY_TO_ONE_FAILURE = 0x0c,
    ZB_NWK_STATUS_CODE_ADDRESS_CONFLICT = 0x0d,
    ZB_NWK_STATUS_CODE_VERIFY_ADDRESS = 0x0e,
    ZB_NWK_STATUS_CODE_PANID_UPDATE = 0x0f,
    ZB_NWK_STATUS_CODE_ADDRESS_UPDATE = 0x10,
    ZB_NWK_STATUS_CODE_BAD_FRAME_COUNTER = 0x11,
    ZB_NWK_STATUS_CODE_BAD_KEY_SEQNUM = 0x12,
    ZB_NWK_STATUS_CODE_UNKNOWN_COMMAND = 0x13
};

/* NWK DstAddrMode values */
enum ZbNwkAddrModeT {
    ZB_NWK_ADDRMODE_NONE = 0,
    ZB_NWK_ADDRMODE_MCAST, /* 1 - deprecated by R23 */
    ZB_NWK_ADDRMODE_SHORT, /* 2 */
    ZB_NWK_ADDRMODE_EXT /* 3 - for InterPAN */
};

/* NWK IB Attributes */
enum ZbNwkNibAttrIdT {
    ZB_NWK_NIB_ID_PanId = 0x80, /* 0x80 ZigBee 2007+ */
    ZB_NWK_NIB_ID_SequenceNumber = 0x81,
    ZB_NWK_NIB_ID_PassiveAckTimeout = 0x82,
    ZB_NWK_NIB_ID_MaxBroadcastRetries = 0x83,
    ZB_NWK_NIB_ID_MaxChildren = 0x84,
    ZB_NWK_NIB_ID_MaxDepth = 0x85,
    ZB_NWK_NIB_ID_MaxRouters = 0x86,
    /* Warning, the stack implements the NNT as a sorted list by NWK Address.
     * If an entry is set through the NIB, it is inserted into the list sorted.
     * It is generally a bad idea for an application to modify the NNT directly.
     * Use ZbNwkNeighborClearAll to clear all entries (or all except parent, e.g.
     * before end-device rejoin).
     * EXEGIN - This NIB should be made read-only. */
    ZB_NWK_NIB_ID_NeighborTable = 0x87,
    /* Time duration in seconds (Note, the Spec defines this as OctetDurations) */
    ZB_NWK_NIB_ID_NetworkBroadcastDeliveryTime = 0x88,
    ZB_NWK_NIB_ID_ReportConstantCost = 0x89,
    ZB_NWK_NIB_ID_RouteDiscoveryRetriesPermitted = 0x8a,
    ZB_NWK_NIB_ID_RouteTable = 0x8b,
    ZB_NWK_NIB_ID_TimeStamp = 0x8c,
    ZB_NWK_NIB_ID_TxTotal = 0x8d, /* EXEGIN - make TxTotal a per interface thing */
    ZB_NWK_NIB_ID_SymLink = 0x8e,
    ZB_NWK_NIB_ID_CapabilityInformation = 0x8f,
    ZB_NWK_NIB_ID_AddrAlloc = 0x90,
    /* was ZB_NWK_NIB_ID_UseTreeRouting = 0x91 */
    ZB_NWK_NIB_ID_ManagerAddr = 0x92,
    ZB_NWK_NIB_ID_MaxSourceRoute = 0x93,
    ZB_NWK_NIB_ID_UpdateId = 0x94,
    ZB_NWK_NIB_ID_TransactionPersistenceTime = 0x95,
    /* ZigBee 2006+ Attributes */
    ZB_NWK_NIB_ID_NetworkAddress = 0x96,
    ZB_NWK_NIB_ID_StackProfile = 0x97,
    ZB_NWK_NIB_ID_BroadcastTransactionTable = 0x98,
    ZB_NWK_NIB_ID_GroupIdTable = 0x99,
    ZB_NWK_NIB_ID_ExtendedPanId = 0x9a,
    /* ZigBee 2007+ Attributes */
    ZB_NWK_NIB_ID_RouteRecordTable = 0x9c,
    ZB_NWK_NIB_ID_IsConcentrator = 0x9d,
    ZB_NWK_NIB_ID_ConcentratorRadius = 0x9e,
    ZB_NWK_NIB_ID_ConcentratorDiscoveryTime = 0x9f, /* units: seconds */
    /* ZigBee Security Attributes */
    ZB_NWK_NIB_ID_SecurityLevel = 0xa0,
    ZB_NWK_NIB_ID_SecurityMaterialSet = 0xa1,
    ZB_NWK_NIB_ID_ActiveKeySeqNumber = 0xa2,
    /* nwkAllFresh has been deprecated (0xa3) */
    /* ...discontinuity... */
    ZB_NWK_NIB_ID_SecureAllFrames = 0xa5,
    /* ZigBee 2007+ Attributes (cont'd). */
    ZB_NWK_NIB_ID_LinkStatusPeriod = 0xa6,
    ZB_NWK_NIB_ID_RouterAgeLimit = 0xa7,
    ZB_NWK_NIB_ID_UniqueAddr = 0xa8,
    ZB_NWK_NIB_ID_AddressMap = 0xa9,
    /* ...continued in zigbee.aps.h with ZB_APS_IB_ID_DEVICE_KEY_PAIR_SET... */

    /* R23+ attributes */
    ZB_NWK_NIB_ID_DiscoveryTable = 0xb4, /* ZbNwkDiscoveryInfoT - Get only. */
    /* 0x400 to 0x4ff reserved for custom NIBs. */
    ZB_NWK_NIB_ID_Depth = 0x0400,
    ZB_NWK_NIB_ID_FrameCounterSet,
    /* Adds a delay in milliseconds  between receiving the first RREP
     * and sending any pending packets awaiting the completion of route
     * discovery. Default is 0, meaning packets are sent after the
     * first RREP is received. If a better route is discovered later on,
     * subsequent packets will use the better route. */
    ZB_NWK_NIB_ID_RouteDiscoverySendDelay,
    ZB_NWK_NIB_ID_FastPollPeriod, /* Only used as sleepy end devices to set the fast polling inverval. */
    ZB_NWK_NIB_ID_SlowPollPeriod,
    ZB_NWK_NIB_ID_FrameCounterCooldown, /* Cooldown timer (in seconds) to apply to frame counter resets. */
    ZB_NWK_NIB_ID_OutgoingCounter, /* Global outgoing frame counter. */
    ZB_NWK_NIB_ID_PersistCounter, /* Persisted outgoing frame counter. */

    /* R21+ attributes */
    /* EXEGIN - The following NIBs should have IDs from 0xaa to 0xad, but
     * these are already being used by APS security. I think the only place
     * this would be a problem is the Gateway API which has a single generic
     * GET/SET API, which means attribute IDs must be unique and not overlap. */
    ZB_NWK_NIB_ID_LeaveRequestAllowed,
    ZB_NWK_NIB_ID_ParentInformation,
    ZB_NWK_NIB_ID_EndDeviceTimeoutDefault,
    ZB_NWK_NIB_ID_EdkaFailThreshold, /* Number of consecutive EDKA request failures before triggering a PARENT_LINK_FAILURE. Valid range is 1 to 4. Default is 1. */
    ZB_NWK_NIB_ID_LeaveRequestWithoutRejoinAllowed,
    ZB_NWK_NIB_ID_DisablePeriodicTimers, /* If set, NWK layer disables edka & link power timers. Default is 0 (enabled). */

    /* R22+ attributes */
    /* EXEGIN - nwkIeeeAddress (should be 0xae, but already being used by APS security) */
    /* EXEGIN - nwkMacInterfaceTable (should be 0xaf, but already being used by APS security) */
    ZB_NWK_NIB_ID_TxPowerMgmtSupported, /* not affected by nwk_reset_nib, keeps value. */
    ZB_NWK_NIB_ID_LinkPowerDeltaPeriod,

    /* R22 MAC PIB Attributes that are maintained by our NWK layer, since we support multiple interfaces. */
    ZB_NWK_NIB_ID_JoiningListUpdateId, /* IeeeJoiningListUpdateID [uint8_t] */
    ZB_NWK_NIB_ID_JoiningPolicy, /* mibJoiningPolicy [uint8_t] */
    ZB_NWK_NIB_ID_JoiningListTotal, /* IeeeJoiningListTotal [uint8_t] */
    ZB_NWK_NIB_ID_JoiningListExpiryInterval, /* mibIeeeExpiryInterval minutes [uint16_t] */
    /* mibIeeeExpiryIntervalCountdown is not externally accessible */

    ZB_NWK_NIB_ID_ActiveChannelList, /* struct ZbChannelListT - Get only. */
    ZB_NWK_NIB_ID_PermitJoinCounter, /* uint8_t - Get only. Set through ZbNlmePermitJoinReq */
    ZB_NWK_NIB_ID_PassiveAckEnabled /* uint8_t - Enable/Disable Broadcast Passive ACK */
};

/* Possible values for ZbNlmeJoinReqT.rejoinNetwork */
enum ZbNwkRejoinTypeT {
    ZB_NWK_REJOIN_TYPE_ASSOC = 0x00,
    ZB_NWK_REJOIN_TYPE_ORPHAN,
    ZB_NWK_REJOIN_TYPE_NWKREJOIN
};

/* Maximum link cost. */
#define ZB_NWK_LINK_COST_MAX                        7U

/* NWK Constants */
#if 0 /* not used */
#define ZB_NWK_CONST_COORDINATOR_CAPABLE            true
#endif
#define ZB_NWK_CONST_SECURITY_LEVEL                 0x05U
#define ZB_NWK_CONST_DISCOVERY_RETRY_LIMIT          0x03U
#define ZB_NWK_CONST_MAX_DEPTH                      0x0fU
#define ZB_NWK_CONST_MIN_HEADER_OVERHEAD            0x08U
#define ZB_NWK_CONST_PROTOCOL_VERSION               ZB_PROTOCOL_VERSION_2007
#define ZB_NWK_CONST_WAIT_BEFORE_VALIDATION         0x500U /* In ms. */
#define ZB_NWK_CONST_REPAIR_THRESHOLD               0x03U
#define ZB_NWK_CONST_ROUTE_DISCOVERY_TIME           0x2710U /* In ms. (10 seconds) */
#define ZB_NWK_CONST_MAX_BROADCAST_JITTER           0x40U /* In ms. */
#define ZB_NWK_CONST_INITIAL_RREQ_RETRIES           0x03U
#define ZB_NWK_CONST_RREQ_RETRIES                   0x02U
#define ZB_NWK_CONST_RREQ_RETRY_INTERVAL            0xfeU /* In ms. */
#define ZB_NWK_CONST_MIN_RREQ_JITTER                0x01U /* In 2 ms slots. */
#define ZB_NWK_CONST_MAX_RREQ_JITTER                0x40U /* In 2 ms slots. */
#define ZB_NWK_CONST_MAC_FRAME_OVERHEAD             0x0bU /* See D.4 of 053474r17. */
/* The following are added by Exegin */
#define ZB_NWK_CONST_SECURITY_OVERHEAD              (14U + ZB_SEC_MIC_LENGTH_5)
/* 127 - 8 - 11 = 108 bytes */
#define ZB_NWK_CONST_MAX_PAYLOAD_SIZE               (WPAN_CONST_MAX_PHY_PACKET_SIZE - ZB_NWK_CONST_MIN_HEADER_OVERHEAD - ZB_NWK_CONST_MAC_FRAME_OVERHEAD)

#define ZB_NWK_BCNPAYLOAD_MIN_SIZE                  15U
#define ZB_NWK_ENH_BCNPAYLOAD_SIZE                  19U

/* Upper bound on nwkMaxSourceRoute */
#define ZB_NWK_CONST_MAX_SOURCE_ROUTE               12U /* 0x0c */
/* The smaller the potential hop count, the larger packets we can send. */
#define ZB_NWK_CONST_DEFAULT_SOURCE_ROUTE           6U

#define ZB_NWK_CONST_ENDDEV_TIMEOUT_MAX             14U
#define ZB_NWK_CONST_ENDDEV_TIMEOUT_DEFAULT         8U
#define ZB_NWK_CONST_ENDDEV_TIMEOUT_DISABLED        0xffU

/* NWK Security Material Set (ZB_NWK_NIB_ID_SecurityMaterialSet) */
typedef struct {
    bool valid;
    uint8_t keySeqNumber;
    uint8_t key[ZB_SEC_KEYSIZE];
    enum ZbSecKeyTypeT keyType;
} ZbNwkSecMaterialT;

/* Frame Counter Attribute Set (ZB_NWK_NIB_ID_FrameCounterSet) */
typedef struct {
    uint8_t keySeqNumber;
    uint64_t senderAddr;
    uint32_t counter;
    ZbUptimeT cooldown; /* Cooldown timer for counter resets. */
    ZbUptimeT lastUsed; /* Timer for LRU evictions. */
    uint32_t persistCounter; /* Last saved counter value */
} ZbNwkFrameCounterT;

typedef struct {
    unsigned int recordsSent;
    bool doSendNext; /* Send Route Record before next tx */
    bool doRenew; /* Whether to renew sending a Route Record after renewTime. */
    ZbUptimeT renewTime;
} ZbNwkRouteRecordInfoT;

/* NNT Discovery Parameters (ZB_NWK_NIB_ID_DiscoveryTable) */
struct ZbNwkDiscoveryInfoT {
    uint16_t panId;
    uint64_t epid;
    uint8_t channelPage;
    uint16_t logicalChannel;
    uint8_t protocolVersion;
    uint8_t stackProfile;
    uint8_t nwkDepth;
    bool useSecurity;
    bool permitJoin;
    bool routerCapacity;
    bool endDevCapacity;
    bool potentialParent;
    uint8_t updateId;
    uint8_t lqi; /* mirror of ZbNwkNeighborT.lqi value */

    /* Exegin add-ons */
    uint8_t beaconOrder;
    uint8_t superframeOrder;
    /* Duplicates of ZbNwkNeighborT. Only used by ZB_NWK_NIB_ID_DiscoveryTable */
    uint16_t nwkAddr; /* Entry is empty if == ZB_NWK_ADDR_UNDEFINED */
};

/*
 * Neighbor Table Entry
 *
 * Contains all the mandatory fields that are used during normal
 * network operation. This is maintained in the NIB, all entries
 * are assumed to be on the same network as the local device.
 */

/* Device Type definitions. */
enum ZbNwkNeighborTypeT {
    ZB_NWK_NEIGHBOR_TYPE_COORD = 0x00,
    ZB_NWK_NEIGHBOR_TYPE_ROUTER = 0x01,
    ZB_NWK_NEIGHBOR_TYPE_END_DEV = 0x02,
    ZB_NWK_NEIGHBOR_TYPE_UNKNOWN = 0x03
};

/* Device Relationship definitions. */
enum ZbNwkNeighborRelT {
    ZB_NWK_NEIGHBOR_REL_PARENT = 0x00,
    ZB_NWK_NEIGHBOR_REL_CHILD = 0x01,
    ZB_NWK_NEIGHBOR_REL_SIBLING = 0x02,
    ZB_NWK_NEIGHBOR_REL_NONE = 0x03,
    ZB_NWK_NEIGHBOR_REL_PREV_CHILD = 0x04,
    ZB_NWK_NEIGHBOR_REL_UNAUTH_CHILD = 0x05,
    /* Temporary values to use during association. */
    ZB_NWK_NEIGHBOR_REL_PEND_ASSOCIATE = 0x06,
    ZB_NWK_NEIGHBOR_REL_PEND_ORPHAN = 0x07
};

/* Parent Information is one byte. We extend it to two bytes for internal state. */
#define ZB_NWK_PARENT_INFO_MASK                     0x0007U
#define ZB_NWK_PARENT_INFO_DATA_POLL                0x0001U /* MAC Data Poll Keepalive Supported */
#define ZB_NWK_PARENT_INFO_KEEP_ALIVE               0x0002U /* End Device Timeout Request Keepalive Supported */
#define ZB_NWK_PARENT_INFO_POWER_NEGOT              0x0004U /* Power Negotiation Supported (R22: Link Power Delta) */
/* Exegin add-on to track the status of parent info */
#define ZB_NWK_PARENT_INFO_START                    0x0100U
/* Exegin add-on to track a manual EDKA request. */
#define ZB_NWK_PARENT_INFO_MANUAL_EDKA_REQ          0x0200U

#define ZB_NWK_NEIGHBOR_TIMEOUT_SECONDS(_x_)        ((_x_ != 0U) ? ((ZbUptimeT)60U << (_x_)) : (ZbUptimeT)10U)
#define ZB_NWK_NEIGHBOR_TIMEOUT_MAX                 14U

#define ZB_NWK_NEIGHBOR_IFINDEX_UNKNOWN             0xffU

typedef struct {
    /*** Mandatory Neighbor Table Entries */
    uint64_t extAddr;
    uint16_t nwkAddr; /* Set to ZB_NWK_ADDR_UNDEFINED to invalidate entry */
    uint8_t capability;
    enum ZbNwkNeighborTypeT deviceType;
    bool rxOnWhenIdle; /* EXEGIN - why not just use capability? */
    enum ZbNwkNeighborRelT relationship;
    uint8_t txFailure;
    uint8_t lqi; /* Average LQI. */
    int8_t unicastRssi; /* Average RSSI when sent as unicast. For power control. */
    uint8_t outgoingCost; /* ZigBee 2007. */
    uint8_t age; /* ZigBee 2007. */
    uint8_t interval; /* R21 draft. */
    ZbUptimeT timeout; /* R21 draft. Disabled if zero. */
    uint8_t ifc_index; /* R22 - set to ZB_NWK_NEIGHBOR_IFINDEX_UNKNOWN if not known (e.g. after persistence) */
} ZbNwkNeighborT;

/*
 * Routing Table Entry
 */

/* Route status values (2.7.3.2) */
enum ZbNwkRouteStatusT {
    ZB_NWK_ROUTE_STATUS_ACTIVE = 0x00,
    ZB_NWK_ROUTE_STATUS_DISCOVERY_UNDERWAY = 0x01,
    ZB_NWK_ROUTE_STATUS_DISCOVERY_FAILED = 0x02,
    ZB_NWK_ROUTE_STATUS_INACTIVE = 0x03
};

#define ZB_NWK_ROUTE_RECORD_RENEWAL_TIMEOUT         (60U * 1000U) /* ms */
#define ZB_NWK_ROUTE_RECORD_POST_SLEEP              (20U) /* ms */

typedef struct {
    enum ZbNwkRouteStatusT status;
    bool noCache; /* flag indicating destination doesn't store source routes. */
    bool isManyToOne; /* flag indicating if destination is a concentrator */
    ZbNwkRouteRecordInfoT routeRecord;
    uint16_t destAddr;
    uint16_t nextAddr;
    ZbUptimeT lastUsed; /* Used to measure route table ageing. */
    uint8_t cost; /* Currently not being used. */
} ZbNwkRouteEntryT;

/*---------------------------------------------------------------
 * NLDE
 *---------------------------------------------------------------
 */
/* NLDE-DATA.request */
typedef struct {
    enum ZbNwkAddrModeT dstAddrMode;
    uint8_t nonMemberRadius;
    uint16_t dstAddr;
    const void *nsdu;
    uint8_t nsduLength;
    uint32_t handle;
    uint8_t radius;
    bool discoverRoute;
    bool security;
    /* Alias */
    bool useAlias;
    uint16_t aliasAddr;
    uint8_t aliasSeqnum;
} ZbNldeDataReqT;

/* NLDE-DATA.confirm */
typedef struct {
    uint32_t handle;
    enum ZbStatusCodeT status;
} ZbNldeDataConfT;

/* NLDE-DATA.indication */
typedef struct {
    enum ZbNwkAddrModeT dstAddrMode;
    uint16_t dstAddr;
    uint16_t srcAddr;
    uint16_t linkAddr; /* Exegin add-on for Intra-PAN portability. */
    uint8_t nsdu[ZB_NWK_CONST_MAX_PAYLOAD_SIZE];
    uint8_t nsduLength;
    uint8_t linkQuality;
    int8_t rssi;
    bool useSecurity;
} ZbNldeDataIndT;

void ZbNldeDataReqWait(struct ZigBeeT *zb, ZbNldeDataReqT *req, ZbNldeDataConfT *conf);
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNldeDataReqCallback(struct ZigBeeT *zb, ZbNldeDataReqT *req,
    void (*callback)(ZbNldeDataConfT *dataConf, void *cb_arg), void *arg);

/* NLDE-FRAME.request */
/* Exegin addon for RAW MAC frame transmission. */
typedef struct {
    enum ZbNwkAddrModeT dstAddrMode;
    enum ZbNwkAddrModeT srcAddrMode;
    uint16_t dstAddr16;
    uint64_t dstAddr64;
    uint16_t dstPanId;
    uint8_t txOptions;
    const void *msdu;
    uint8_t msduLength;
    uint32_t handle;
} ZbNldeFrameReqT;

typedef ZbNldeDataConfT ZbNldeFrameConfT;

void ZbNldeFrameReqWait(struct ZigBeeT *zb, ZbNldeFrameReqT *req, ZbNldeFrameConfT *conf);
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNldeFrameReqCallback(struct ZigBeeT *zb, ZbNldeFrameReqT *req,
    void (*callback)(ZbNldeFrameConfT *FrameConf, void *cb_arg), void *arg);

/*---------------------------------------------------------------
 * NLME
 *---------------------------------------------------------------
 */
/* NLME-GET.request */
typedef struct {
    enum ZbNwkNibAttrIdT attrId;
    void *attr; /* Buffer for attribute data */
    unsigned int attrLength; /* Max length of input, actual length returned */
    unsigned int attrIndex;
} ZbNlmeGetReqT;

/* NLME-GET.confirm */
typedef struct {
    enum ZbStatusCodeT status;
    enum ZbNwkNibAttrIdT attrId;
} ZbNlmeGetConfT;

/* NLME-SET.request */
typedef struct {
    enum ZbNwkNibAttrIdT attrId;
    const void *attr;
    unsigned int attrLength;
    unsigned int attrIndex;
} ZbNlmeSetReqT;

/* NLME-SET.confirm */
typedef struct {
    enum ZbStatusCodeT status;
    enum ZbNwkNibAttrIdT attrId;
} ZbNlmeSetConfT;

/* NLME-RESET.request */
typedef struct {
    bool warmStart;
} ZbNlmeResetReqT;

/* NLME-RESET.confirm */
typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmeResetConfT;

/* NLME-SYNC.request */
typedef struct {
    bool track;
} ZbNlmeSyncReqT;

/* NLME-SYNC.confirm */
typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmeSyncConfT;

/* NLME-SYNC.indication */
typedef struct {
    void *voidPtr; /* empty */
} ZbNlmeSyncIndT;

/* NLME-NETWORK-FORMATION.request */
typedef struct {
    struct ZbChannelListT scanChannels;
    uint8_t scanDuration;
    uint8_t beaconOrder;
    uint8_t superframeOrder;
    uint8_t batteryLifeExtension;
    bool distributed;
} ZbNlmeNetFormReqT;

/* NLME-NETWORK-FORMATION.confirm */
typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmeNetFormConfT;

/* NLME-NETWORK-DISCOVERY.request */
typedef struct {
    struct ZbChannelListT scanChannels;
    uint8_t scanDuration;
} ZbNlmeNetDiscReqT;

/* NLME-NETWORK-DISCOVERY.confirm */
typedef struct {
    enum ZbStatusCodeT status;
    /* Use ZB_NWK_NIB_ID_DiscoveryTable to retrieve the discovery table entries. */
} ZbNlmeNetDiscConfT;

/* NLME-PERMIT-JOIN.request */
typedef struct {
    uint8_t permitDuration;
} ZbNlmePermitJoinReqT;

/* NLME-PERMIT-JOIN.confirm */
typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmePermitJoinConfT;

/* NLME-JOIN.request */
typedef struct {
    uint64_t epid;
    enum ZbNwkRejoinTypeT rejoinNetwork;
    struct ZbChannelListT scanChannels;
    uint8_t scanDuration;
    uint8_t capabilityInformation; /* e.g. MCP_ASSOC_CAP_DEV_TYPE */
    bool securityEnable;
} ZbNlmeJoinReqT;

/* NLME-JOIN.confirm */
typedef struct {
    enum ZbStatusCodeT status;
    uint16_t nwkAddr;
} ZbNlmeJoinConfT;

/* NLME-JOIN.indication */
typedef struct {
    uint16_t nwkAddr;
    uint64_t extAddr;
    uint8_t capabilityInfo;
    enum ZbNwkRejoinTypeT rejoinNetwork;
    bool secureRejoin;
} ZbNlmeJoinIndT;

/* NLME-DIRECT-JOIN.request */
typedef struct {
    uint64_t deviceAddr;
    uint16_t nwkAddr; /* Exegin addon - set to ZB_NWK_ADDR_UNDEFINED if not used. */
    uint8_t capabilityInfo;
    uint8_t interval;
} ZbNlmeDirectJoinReqT;

/* NLME-DIRECT-JOIN.confirm */
typedef struct {
    uint64_t deviceAddr;
    enum ZbStatusCodeT status;
} ZbNlmeDirectJoinConfT;

/* NLME-LEAVE.request */
typedef struct ZbNlmeLeaveReqT {
    uint64_t deviceAddr;
    bool removeChildren;
    bool rejoin;
} ZbNlmeLeaveReqT;

/* NLME-LEAVE.confirm */
typedef struct ZbNlmeLeaveConfT {
    uint64_t deviceAddr;
    enum ZbStatusCodeT status;
} ZbNlmeLeaveConfT;

/* NLME-LEAVE.indication */
typedef struct {
    uint64_t deviceAddr;
    bool rejoin;
    /* Exegin extension */
    uint16_t shortAddr;
    /* Is one of our children leaving? By the time the NHLE has received this, the device
     * has likely been removed as one of our children from the NNT. */
    enum ZbNwkNeighborRelT relationship;
} ZbNlmeLeaveIndT;

/* NLME-START-ROUTER.request */
typedef struct {
    uint8_t beaconOrder;
    uint8_t superframeOrder;
    uint8_t battLifeExtension;
    struct ZbChannelListT scanChannels;
} ZbNlmeStartRouterReqT;

/* NLME-START-ROUTER.confirm */
typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmeStartRouterConfT;

/* NLME-ED-SCAN.request */
typedef struct {
    uint32_t channelMask; /* Channel Page Structure [PAGE|MASK] */
    uint8_t scanDuration;
} ZbNlmeEdScanReqT;

/* NLME-ED-SCAN.confirm */
typedef struct {
    uint32_t unscannedChannels;
    uint8_t energyDetectList[WPAN_PAGE_CHANNELS_MAX];
    enum ZbStatusCodeT status;
} ZbNlmeEdScanConfT;

/* NLME-ROUTE-DISCOVERY.request */
typedef struct {
    enum ZbNwkAddrModeT dstAddrMode;
    uint16_t dstAddr;
    uint8_t radius;
    uint8_t noRouteCache;
} ZbNlmeRouteDiscReqT;

/* NLME-ROUTE-DISCOVERY.confirm */
typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmeRouteDiscConfT;

/* NLME-NETWORK-STATUS.indication */
typedef struct {
    uint16_t shortAddr;
    enum ZbNwkNetworkStatusCodeT status;
} ZbNlmeNetworkStatusIndT;

/* NLME-SET-INTERFACE.request */
typedef struct {
    uint8_t ifcIndex;
    uint8_t state;
    uint32_t channelInUse;
    struct ZbChannelListT supportedChannels;
    bool routersAllowed;
} ZbNlmeSetInterfaceReqT;

typedef struct {
    enum ZbStatusCodeT status;
} ZbNlmeSetInterfaceConfT;

/* NLME-GET-INTERFACE.request */
typedef struct {
    uint8_t ifcIndex;
} ZbNlmeGetInterfaceReqT;

typedef struct {
    enum ZbStatusCodeT status;
    uint8_t ifcIndex;
    uint8_t state;
    uint32_t channelInUse;
    struct ZbChannelListT supportedChannels;
    bool routersAllowed;
    bool powerNegotSupported;
    /* Exegin add-on */
    struct WpanPublicT *mac;
} ZbNlmeGetInterfaceConfT;

/* Broadcast transaction table entry */
typedef struct {
    uint16_t srcAddr;
    uint8_t seqnum;
    /* EXEGIN - replace pAckCount with a list of router neighbors */
    uint8_t pAckCount; /* passive ack count for flood limiting. */
    ZbUptimeT expireTime; /* expiration time relative to ZbUptime. */
} ZbNwkBttEntryT;

/* NLME-GET.request */
void ZbNlmeGetReq(struct ZigBeeT *zb, ZbNlmeGetReqT *getReqPtr, ZbNlmeGetConfT *getConfPtr);

/* NLME-SET.request */
void ZbNlmeSetReq(struct ZigBeeT *zb, ZbNlmeSetReqT *setReqPtr, ZbNlmeSetConfT *setConfPtr);

/* NLME-RESET.request */
void ZbNlmeResetReq(struct ZigBeeT *zb, ZbNlmeResetReqT *resetReqPtr, ZbNlmeResetConfT *resetConfPtr);

/* NLME-SYNC.request */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeSyncReq(struct ZigBeeT *zb, ZbNlmeSyncReqT *syncReqPtr,
    void (*callback)(ZbNlmeSyncConfT *syncConfPtr, void *arg), void *arg);

/* NLME-NETWORK-DISCOVERY.request */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeNetDiscReq(struct ZigBeeT *zb, ZbNlmeNetDiscReqT *req,
    void (*callback)(ZbNlmeNetDiscConfT *conf, void *cbarg), void *cbarg);
void ZbNlmeNetDiscWait(struct ZigBeeT *zb, ZbNlmeNetDiscReqT *req, ZbNlmeNetDiscConfT *conf);

/* NLME-NETWORK-FORMATION.request */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeNetFormReq(struct ZigBeeT *zb, ZbNlmeNetFormReqT *req,
    void (*callback)(ZbNlmeNetFormConfT *formConf, void *arg), void *cbarg);
void ZbNlmeNetFormWait(struct ZigBeeT *zb, ZbNlmeNetFormReqT *req, ZbNlmeNetFormConfT *conf);

/* NLME-PERMIT-JOIN.request */
void ZbNlmePermitJoinReq(struct ZigBeeT *zb, ZbNlmePermitJoinReqT *permitReq, ZbNlmePermitJoinConfT *permitConf);

/* Exegin Custom API to manage the IEEE Joining List in the NWK layer.
 * Let the NWK layer manage configuring the individual MACs. */
enum WpanJoinPolicyT ZbNlmeJoiningPolicyGet(struct ZigBeeT *zb);
bool ZbNlmeJoiningPolicyConfigure(struct ZigBeeT *zb, enum WpanJoinPolicyT policy, uint64_t *extAddrList,
    unsigned int numExtAddr, uint8_t *updateIdOverride);
void ZbNlmeJoinPolicyTimeoutRefresh(struct ZigBeeT *zb);
void ZbNlmeIeeeJoiningListClear(struct ZigBeeT *zb);
bool ZbNlmeIeeeJoiningListRemove(struct ZigBeeT *zb, uint64_t extAddr);
bool ZbNwkIeeeJoiningListEnabled(struct ZigBeeT *zb);

/* NLME-JOIN.request */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeJoinReq(struct ZigBeeT *zb, ZbNlmeJoinReqT *joinReqPtr,
    void (*callback)(ZbNlmeJoinConfT *joinConf, void *arg), void *cbarg);
void ZbNlmeJoinWait(struct ZigBeeT *zb, ZbNlmeJoinReqT *req, ZbNlmeJoinConfT *conf);

/* NLME-DIRECT-JOIN.request */
void ZbNlmeDirectJoinReq(struct ZigBeeT *zb, ZbNlmeDirectJoinReqT *directJoinReqPtr, ZbNlmeDirectJoinConfT
    *directJoinConfPtr);

/* NLME-START-ROUTER.request */
void ZbNlmeStartRouterReq(struct ZigBeeT *zb, ZbNlmeStartRouterReqT *req, ZbNlmeStartRouterConfT *conf);

/* NLME-ED-SCAN.request */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeEdScanReq(struct ZigBeeT *zb, ZbNlmeEdScanReqT *req,
    void (*callback)(ZbNlmeEdScanConfT *scanConf, void *arg), void *cbarg);

/* NLME-LEAVE.request.
 * If the local device is being requested to leave, it may take some time
 * (hundreds of mS) to send the appropriate commands and reset the stack
 * before the callback is eventually called, or ZbNlmeLeaveWait returns. */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeLeaveReq(struct ZigBeeT *zb, struct ZbNlmeLeaveReqT *leaveReqPtr,
    void (*callback)(struct ZbNlmeLeaveConfT *leaveConfPtr, void *arg), void *cbarg);
void ZbNlmeLeaveWait(struct ZigBeeT *zb, struct ZbNlmeLeaveReqT *leaveReqPtr, struct ZbNlmeLeaveConfT *leaveConfPtr);

/* NLME-ROUTE-DISCOVERY.request */
enum ZbStatusCodeT ZB_WARN_UNUSED ZbNlmeRouteDiscReq(struct ZigBeeT *zb, ZbNlmeRouteDiscReqT *routeDiscReqPtr,
    void (*callback)(ZbNlmeRouteDiscConfT *discConf, void *cbarg), void *arg);
void ZbNlmeRouteDiscWait(struct ZigBeeT *zb, ZbNlmeRouteDiscReqT *req, ZbNlmeRouteDiscConfT *conf);

/* NLME-SET-INTERFACE.request */
void ZbNlmeSetInterface(struct ZigBeeT *zb, ZbNlmeSetInterfaceReqT *req, ZbNlmeSetInterfaceConfT *conf);
/* NLME-GET-INTERFACE.request */
void ZbNlmeGetInterface(struct ZigBeeT *zb, ZbNlmeGetInterfaceReqT *req, ZbNlmeGetInterfaceConfT *conf);

/* Helper to enable/disable interface */
bool ZbNwkIfToggleByName(struct ZigBeeT *zb, const char *name, bool enable);

bool ZbNwkIfSetTxPower(struct ZigBeeT *zb, const char *name, int8_t tx_power);
bool ZbNwkIfGetTxPower(struct ZigBeeT *zb, const char *name, int8_t *tx_power);

bool ZbNwkIfSetDsn(struct ZigBeeT *zb, const char *name, uint8_t macDsn);

/* ZbNwkToggleDutyCycle - Enable or disable Duty Cycle management in the MAC.
 * Disabling duty cycle will also clear the duty cycle history and set the status to
 * MCP_DUTYCYCLE_STATUS_NORMAL.
 * This function would typically be used in conjunction with ZB_NWK_NIB_ID_TxPowerMgmtSupported,
 * which configures TX Power Control in the NWK and MAC. */
bool ZbNwkToggleDutyCycle(struct ZigBeeT *zb, bool enable);

/* Network end device keep alive request command. */
bool ZbNwkSendEdkaReq(struct ZigBeeT *zb);

/* Network Link power delta request & notify commands. */
bool ZbNwkSendLinkPowerDeltaReq(struct ZigBeeT *zb);
bool ZbNwkSendLinkPowerDeltaNotify(struct ZigBeeT *zb);

/*---------------------------------------------------------------
 * NLME-GET and NLME-SET Helper Functions
 *---------------------------------------------------------------
 */
/* ZbNwkGet and ZbNwkSet return the confirm status byte (SUCCESS == 0x00) */
enum ZbStatusCodeT ZbNwkGet(struct ZigBeeT *zb, enum ZbNwkNibAttrIdT attrId, void *attrPtr, unsigned int attrSz);
enum ZbStatusCodeT ZbNwkSet(struct ZigBeeT *zb, enum ZbNwkNibAttrIdT attrId, void *attrPtr, unsigned int attrSz);

enum ZbStatusCodeT ZbNwkGetIndex(struct ZigBeeT *zb, enum ZbNwkNibAttrIdT attrId, void *attrPtr, unsigned int attrSz, unsigned int attrIndex);
enum ZbStatusCodeT ZbNwkSetIndex(struct ZigBeeT *zb, enum ZbNwkNibAttrIdT attrId, void *attrPtr, unsigned int attrSz, unsigned int attrIndex);

/*---------------------------------------------------------------
 * NIB Attribute Helper Functions
 *---------------------------------------------------------------
 */
bool ZbNwkAddrIsChildNwk(struct ZigBeeT *zb, uint16_t nwkAddr, uint64_t *extAddrPtr);
bool ZbNwkAddrIsChildExt(struct ZigBeeT *zb, uint64_t extAddr, uint16_t *nwkAddrPtr);
unsigned int ZbNwkAddrMapFreeSpace(struct ZigBeeT *zb);
bool ZbNwkAddrStoreMap(struct ZigBeeT *zb, uint16_t nwkAddr, uint64_t extAddr, bool resolve_conflict);
void ZbNwkAddrClearMap(struct ZigBeeT *zb, bool isShortAddr, uint64_t addr);

/* Returns the network address that corresponds to the extended address
 * if known, otherwise returns ZB_NWK_ADDR_UNDEFINED. */
uint16_t ZbNwkAddrLookupNwk(struct ZigBeeT *zb, uint64_t extAddr);
/* Returns the extended address that corresponds to the network address
 * if known, otherwise returns 0. */
uint64_t ZbNwkAddrLookupExt(struct ZigBeeT *zb, uint16_t nwkAddr);

bool ZbNwkGetSecMaterial(struct ZigBeeT *zb, uint8_t keySeqno, ZbNwkSecMaterialT *material);
bool ZbNwkSetFrameCounter(struct ZigBeeT *zb, uint8_t keySeqno, uint64_t srcAddr, uint32_t newFrameCount);
bool ZbNwkGetActiveKey(struct ZigBeeT *zb, ZbNwkSecMaterialT *active_key);
bool ZbNwkClearActiveKey(struct ZigBeeT *zb);

/*---------------------------------------------------------------
 * NNT Helper Functions
 *---------------------------------------------------------------
 */
const char * ZbNwkNeighborRelationshipToStr(enum ZbNwkNeighborRelT relationship);
const char * ZbNwkNeighborDeviceTypeToStr(enum ZbNwkNeighborTypeT deviceType);

/* Parent Functions */
uint64_t ZbNwkGetParentExtAddr(struct ZigBeeT *zb);
uint16_t ZbNwkGetParentShortAddr(struct ZigBeeT *zb);

/* Clear the NNT. For example, as a zigbee end-device performing a
 * network discovery scan before rejoin, it needs to first clear the
 * NNT except for it's parent entry (keep_parent = true). This way,
 * only potential parents that responded to the network discovery
 * scan will be attempted to rejoin the network to. */
void ZbNwkNeighborClearAll(struct ZigBeeT *zb, bool keep_parent, bool keep_children);

/*---------------------------------------------------------------
 * Fast Polling
 *---------------------------------------------------------------
 */
/* NLME-SYNC.request parent polling */
bool ZB_WARN_UNUSED ZbNwkFastPollRequest(struct ZigBeeT *zb);
bool ZbNwkFastPollRelease(struct ZigBeeT *zb);
unsigned int ZbNwkFastPollResourceCount(struct ZigBeeT *zb);

/*---------------------------------------------------------------
 * Status Code to String
 *---------------------------------------------------------------
 */
const char * ZbNwkStatusCodeStr(enum ZbNwkNetworkStatusCodeT status);
const char * ZbNwkStackProfileIdToStr(uint8_t stackProfile);
const char * ZbNwkRouteStatusToStr(enum ZbNwkRouteStatusT status);

#endif /* ZIGBEE_NWK_H */