ezsp 6.0.1

Ember ZNet Serial Protocol
Documentation
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
use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex};

use num_traits::FromPrimitive;

pub use self::adc::Adc;
pub use self::application::Application;
pub use self::eeprom::Eeprom;
pub use self::err::{Bootloader, Err, Flash};
pub use self::mac::Mac;
pub use self::phy::Phy;
pub use self::serial::Serial;
pub use self::sim_eeprom::SimEeprom;
use self::values::Values;

mod adc;
mod application;
mod eeprom;
mod err;
mod mac;
mod phy;
mod serial;
mod sim_eeprom;
mod values;

/// Ember status.
///
/// # Documentation
///
/// See <https://www.silabs.com/documents/public/miscellaneous/EmberZNet-API-EM260.pdf> for details.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Status {
    /// The generic 'no error' message.
    Success,

    /// The generic 'fatal error' message.
    ErrFatal,

    /// An invalid value was passed as an argument to a function.
    BadArgument,

    /// EEPROM status.
    Eeprom(Eeprom),

    /// There are no more buffers.
    NoBuffers,

    /// Serial status.
    Serial(Serial),

    /// MAC status.
    Mac(Mac),

    /// Simulated EEPROM status.
    SimEeprom(SimEeprom),

    /// Erroneous messages.
    Err(Err),

    /// The APS layer attempted to send or deliver a message, but it failed.
    DeliveryFailed,

    /// This binding index is out of range of the current binding table.
    BindingIndexOutOfRange,

    /// This address table index is out of range for the current address table.
    AddressTableIndexOutOfRange,

    /// An invalid binding table index was given to a function.
    InvalidBindingIndex,

    /// The API call is not allowed given the current state of the stack.
    InvalidCall,

    /// The link cost to a node is not known.
    CostNotKnown,

    // TODO: Where is `EMBER_APS_UNICAST_MESSAGE_COUNT` defined?
    /// The maximum number of in-flight messages (i.e. `EMBER_APS_UNICAST_MESSAGE_COUNT`) has been reached.
    MaxMessageLimitReached,

    /// The message to be transmitted is too big to fit into a single over-the-air packet.
    MessageTooLong,

    /// The application is trying to delete or overwrite a binding that is in use.
    BindingIsActive,

    /// The application is trying to overwrite an address table entry that is in use.
    AddressTableEntryIsActive,

    /// ADC status.
    Adc(Adc),

    /// Sleeping (for a duration) has been abnormally interrupted and exited prematurely.
    SleepInterrupted,

    /// PHY status.
    Phy(Phy),

    /// The stack software has completed initialization and is ready to send and receive packets over the air.
    NetworkUp,

    /// The network is not operating.
    NetworkDown,

    /// The node has not joined a network.
    NotJoined,

    /// An attempt to join a network failed.
    JoinFailed,

    /// The chosen security level (the value of `EMBER_SECURITY_LEVEL`) is not supported by the stack.
    InvalidSecurityLevel,

    /// After moving, a mobile node's attempt to re-establish contact with the network failed.
    MoveFailed,

    /// An attempt to join as a router failed due to a Zigbee versus Zigbee Pro incompatibility.
    ///
    /// Zigbee devices joining Zigbee Pro networks (or vice versa) must join as End Devices, not Routers.
    CannotJoinAsRouter,

    /// The local node ID has changed.
    ///
    /// The application can obtain the new node ID by calling `emberGetNodeId()`.
    NodeIdChanged,

    /// The local PAN ID has changed.
    ///
    /// The application can obtain the new PAN ID by calling `emberGetPanId()`.
    PanIdChanged,

    /// The network has been opened for joining.
    NetworkOpened,

    /// The network has been closed for joining.
    NetworkClosed,

    /// An attempt to join or rejoin the network failed because
    /// no router beacons could be heard by the joining node.
    NoBeacons,

    /// An attempt was made to join a Secured Network using a pre-configured key,
    /// but the Trust Center sent back a Network Key in-the-clear when an encrypted
    /// Network Key was required.
    ReceivedKeyInTheClear,

    /// An attempt was made to join a Secured Network, but the device did not receive a Network Key.
    NoNetworkKeyReceived,

    /// After a device joined a Secured Network, a Link Key was requested but no response was ever received.
    NoLinkKeyReceived,

    /// An attempt was made to join a Secured Network without a pre-configured key,
    /// but the Trust Center sent encrypted data using a pre-configured key.
    PreconfiguredKeyRequired,

    /// The passed key data is not valid.
    ///
    /// A key of all zeros or all F's are reserved values and cannot be used.
    KeyInvalid,

    /// A message cannot be sent because the network is currently overloaded.
    NetworkBusy,

    /// The application tried to send a message using an endpoint that it has not defined.
    InvalidEndpoint,

    /// The application tried to use a binding that has been remotely modified
    /// and the change has not yet been reported to the application.
    BindingHasChanged,

    /// An attempt to generate random bytes failed because of insufficient random data from the radio.
    InsufficientRandomData,

    /// There was an error in trying to encrypt at the APS  Level.
    ///
    /// This could result from either an inability to determine the long address of the
    /// recipient from the short address (no entry in the binding table) or there is no
    /// link key entry in the table associated with the destination, or there was a failure
    /// to load the correct key into the encryption core.
    ApsEncryptionError,

    /// There was an attempt to form or join a network with security
    /// without calling `emberSetInitialSecurityState()` first.
    SecurityStateNotSet,

    /// A Zigbee route error command frame was received indicating that
    /// a source routed message from this node failed en route
    SourceRouteFailure,

    /// A Zigbee route error command frame was received indicating that a message sent
    /// to this node along a many-to-one route failed en route.
    ///
    /// The route error frame was delivered by an ad-hoc search for a functioning route.
    ManyToOneRouteFailure,

    /// A critical and fatal error indicating that the version of the stack trying
    /// to run does not match with the chip it is running on.
    ///
    /// The software (stack) on the chip must be replaced with software
    /// that is compatible with the chip.
    StackAndHardwareMismatch,

    /// An index was passed into the function that was larger than the valid range.
    IndexOutOfRange,

    /// There was an attempt to set an entry in the key table  using an invalid long address.
    ///
    /// An entry cannot be set using either the local device's or Trust Center's IEEE address.
    /// Or an entry already exists in the table with the same IEEE address.
    /// An Address of all zeros or  all F's are not valid addresses in 802.15.4.
    KeyTableInvalidAddress,

    /// There are no empty entries left in the table.
    TableFull,

    /// The requested function cannot be executed because the library that contains
    /// the necessary functionality is not present.
    LibraryNotPresent,

    /// The requested table entry has been erased and contains no valid data.
    TableEntryErased,

    /// There was an attempt to set a security configuration that is not valid
    /// given the other security settings.
    SecurityConfigurationInvalid,

    /// There was an attempt to broadcast a key switch too quickly after broadcasting the next network key.
    ///
    /// The Trust Center must wait at least a period equal to the broadcast timeout
    /// so that all routers have a chance to receive the broadcast of the new network key.
    TooSoonForSwitchKey,

    /// The received signature corresponding to the message that was passed
    /// to the `CBKE` Library failed verification, it is not valid.
    SignatureVerifyFailure,

    /// The stack accepted the command and is currently processing the request.
    ///
    /// The results will be returned via an appropriate handler.
    OperationInProgress,

    /// The message could not be sent because the link key corresponding to the destination
    /// is not authorized for use in APS data messages.
    ///
    /// APS Commands (sent by the stack) are allowed.
    /// To use it for encryption of APS data messages it must be authorized using
    /// a key agreement protocol (such as `CBKE`).
    KeyNotAuthorized,

    /// The security data provided was not valid, or an integrity check failed.
    SecurityDataInvalid,

    /// Application status.
    Application(Application),
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        Display::fmt(&Values::from(*self), f)
    }
}

impl std::error::Error for Status {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Eeprom(eeprom) => Some(eeprom),
            Self::Serial(serial) => Some(serial),
            Self::Mac(mac) => Some(mac),
            Self::SimEeprom(sim_eeprom) => Some(sim_eeprom),
            Self::Err(err) => Some(err),
            Self::Adc(adc) => Some(adc),
            Self::Phy(phy) => Some(phy),
            Self::Application(application) => Some(application),
            _ => None,
        }
    }
}

impl From<Status> for Values {
    fn from(value: Status) -> Self {
        match value {
            Status::Success => Self::Success,
            Status::ErrFatal => Self::ErrFatal,
            Status::BadArgument => Self::BadArgument,
            Status::Eeprom(eeprom) => eeprom.into(),
            Status::NoBuffers => Self::NoBuffers,
            Status::Serial(serial) => serial.into(),
            Status::Mac(mac) => mac.into(),
            Status::SimEeprom(sim_eeprom) => sim_eeprom.into(),
            Status::Err(err) => err.into(),
            Status::DeliveryFailed => Self::DeliveryFailed,
            Status::BindingIndexOutOfRange => Self::BindingIndexOutOfRange,
            Status::AddressTableIndexOutOfRange => Self::AddressTableIndexOutOfRange,
            Status::InvalidBindingIndex => Self::InvalidBindingIndex,
            Status::InvalidCall => Self::InvalidCall,
            Status::CostNotKnown => Self::CostNotKnown,
            Status::MaxMessageLimitReached => Self::MaxMessageLimitReached,
            Status::MessageTooLong => Self::MessageTooLong,
            Status::BindingIsActive => Self::BindingIsActive,
            Status::AddressTableEntryIsActive => Self::AddressTableEntryIsActive,
            Status::Adc(adc) => adc.into(),
            Status::SleepInterrupted => Self::SleepInterrupted,
            Status::Phy(phy) => phy.into(),
            Status::NetworkUp => Self::NetworkUp,
            Status::NetworkDown => Self::NetworkDown,
            Status::NotJoined => Self::NotJoined,
            Status::JoinFailed => Self::JoinFailed,
            Status::InvalidSecurityLevel => Self::InvalidSecurityLevel,
            Status::MoveFailed => Self::MoveFailed,
            Status::CannotJoinAsRouter => Self::CannotJoinAsRouter,
            Status::NodeIdChanged => Self::NodeIdChanged,
            Status::PanIdChanged => Self::PanIdChanged,
            Status::NetworkOpened => Self::NetworkOpened,
            Status::NetworkClosed => Self::NetworkClosed,
            Status::NoBeacons => Self::NoBeacons,
            Status::ReceivedKeyInTheClear => Self::ReceivedKeyInTheClear,
            Status::NoNetworkKeyReceived => Self::NoNetworkKeyReceived,
            Status::NoLinkKeyReceived => Self::NoLinkKeyReceived,
            Status::PreconfiguredKeyRequired => Self::PreconfiguredKeyRequired,
            Status::KeyInvalid => Self::KeyInvalid,
            Status::NetworkBusy => Self::NetworkBusy,
            Status::InvalidEndpoint => Self::InvalidEndpoint,
            Status::BindingHasChanged => Self::BindingHasChanged,
            Status::InsufficientRandomData => Self::InsufficientRandomData,
            Status::ApsEncryptionError => Self::ApsEncryptionError,
            Status::SecurityStateNotSet => Self::SecurityStateNotSet,
            Status::SourceRouteFailure => Self::SourceRouteFailure,
            Status::ManyToOneRouteFailure => Self::ManyToOneRouteFailure,
            Status::StackAndHardwareMismatch => Self::StackAndHardwareMismatch,
            Status::IndexOutOfRange => Self::IndexOutOfRange,
            Status::KeyTableInvalidAddress => Self::KeyTableInvalidAddress,
            Status::TableFull => Self::TableFull,
            Status::LibraryNotPresent => Self::LibraryNotPresent,
            Status::TableEntryErased => Self::TableEntryErased,
            Status::SecurityConfigurationInvalid => Self::SecurityConfigurationInvalid,
            Status::TooSoonForSwitchKey => Self::TooSoonForSwitchKey,
            Status::SignatureVerifyFailure => Self::SignatureVerifyFailure,
            Status::OperationInProgress => Self::OperationInProgress,
            Status::KeyNotAuthorized => Self::KeyNotAuthorized,
            Status::SecurityDataInvalid => Self::SecurityDataInvalid,
            Status::Application(application) => application.into(),
        }
    }
}

impl From<Values> for Status {
    #[expect(clippy::too_many_lines)]
    fn from(value: Values) -> Self {
        match value {
            Values::Success => Self::Success,
            Values::ErrFatal => Self::ErrFatal,
            Values::BadArgument => Self::BadArgument,
            Values::EepromMfgStackVersionMismatch => Self::Eeprom(Eeprom::MfgStackVersionMismatch),
            Values::EepromMfgVersionMismatch => Self::Eeprom(Eeprom::MfgVersionMismatch),
            Values::EepromStackVersionMismatch => Self::Eeprom(Eeprom::StackVersionMismatch),
            Values::NoBuffers => Self::NoBuffers,
            Values::SerialInvalidBaudRate => Self::Serial(Serial::InvalidBaudRate),
            Values::SerialInvalidPort => Self::Serial(Serial::InvalidPort),
            Values::SerialTxOverflow => Self::Serial(Serial::TxOverflow),
            Values::SerialRxOverflow => Self::Serial(Serial::RxOverflow),
            Values::SerialRxFrameError => Self::Serial(Serial::RxFrameError),
            Values::SerialRxParityError => Self::Serial(Serial::RxParityError),
            Values::SerialRxEmpty => Self::Serial(Serial::RxEmpty),
            Values::SerialRxOverrunError => Self::Serial(Serial::RxOverrunError),
            Values::MacNoData => Self::Mac(Mac::NoData),
            Values::MacJoinedNetwork => Self::Mac(Mac::JoinedNetwork),
            Values::MacBadScanDuration => Self::Mac(Mac::BadScanDuration),
            Values::MacIncorrectScanType => Self::Mac(Mac::IncorrectScanType),
            Values::MacInvalidChannelMask => Self::Mac(Mac::InvalidChannelMask),
            Values::MacCommandTransmitFailure => Self::Mac(Mac::CommandTransmitFailure),
            Values::MacTransmitQueueFull => Self::Mac(Mac::TransmitQueueFull),
            Values::MacUnknownHeaderType => Self::Mac(Mac::UnknownHeaderType),
            Values::MacScanning => Self::Mac(Mac::Scanning),
            Values::MacNoAckReceived => Self::Mac(Mac::NoAckReceived),
            Values::MacIndirectTimeout => Self::Mac(Mac::IndirectTimeout),
            Values::SimEepromErasePageGreen => Self::SimEeprom(SimEeprom::ErasePageGreen),
            Values::SimEepromErasePageRed => Self::SimEeprom(SimEeprom::ErasePageRed),
            Values::SimEepromFull => Self::SimEeprom(SimEeprom::Full),
            Values::SimEepromInit1Failed => Self::SimEeprom(SimEeprom::Init1Failed),
            Values::SimEepromInit2Failed => Self::SimEeprom(SimEeprom::Init2Failed),
            Values::SimEepromInit3Failed => Self::SimEeprom(SimEeprom::Init3Failed),
            Values::ErrFlashWriteInhibited => Self::Err(Err::Flash(Flash::WriteInhibited)),
            Values::ErrFlashVerifyFailed => Self::Err(Err::Flash(Flash::VerifyFailed)),
            Values::ErrFlashProgFail => Self::Err(Err::Flash(Flash::ProgFail)),
            Values::ErrFlashEraseFail => Self::Err(Err::Flash(Flash::EraseFail)),
            Values::ErrBootloaderTrapTableBad => {
                Self::Err(Err::Bootloader(Bootloader::TrapTableBad))
            }
            Values::ErrBootloaderTrapUnknown => Self::Err(Err::Bootloader(Bootloader::TrapUnknown)),
            Values::ErrBootloaderNoImage => Self::Err(Err::Bootloader(Bootloader::NoImage)),
            Values::DeliveryFailed => Self::DeliveryFailed,
            Values::BindingIndexOutOfRange => Self::BindingIndexOutOfRange,
            Values::AddressTableIndexOutOfRange => Self::AddressTableIndexOutOfRange,
            Values::InvalidBindingIndex => Self::InvalidBindingIndex,
            Values::InvalidCall => Self::InvalidCall,
            Values::CostNotKnown => Self::CostNotKnown,
            Values::MaxMessageLimitReached => Self::MaxMessageLimitReached,
            Values::MessageTooLong => Self::MessageTooLong,
            Values::BindingIsActive => Self::BindingIsActive,
            Values::AddressTableEntryIsActive => Self::AddressTableEntryIsActive,
            Values::AdcConversionDone => Self::Adc(Adc::ConversionDone),
            Values::AdcConversionBusy => Self::Adc(Adc::ConversionBusy),
            Values::AdcConversionDeferred => Self::Adc(Adc::ConversionDeferred),
            Values::AdcNoConversionPending => Self::Adc(Adc::NoConversionPending),
            Values::SleepInterrupted => Self::SleepInterrupted,
            Values::PhyTxUnderflow => Self::Phy(Phy::TxUnderflow),
            Values::PhyTxIncomplete => Self::Phy(Phy::TxIncomplete),
            Values::PhyInvalidChannel => Self::Phy(Phy::InvalidChannel),
            Values::PhyInvalidPower => Self::Phy(Phy::InvalidPower),
            Values::PhyTxBusy => Self::Phy(Phy::TxBusy),
            Values::PhyTxCcaFail => Self::Phy(Phy::TxCcaFail),
            Values::PhyOscillatorCheckFailed => Self::Phy(Phy::OscillatorCheckFailed),
            Values::PhyAckReceived => Self::Phy(Phy::AckReceived),
            Values::NetworkUp => Self::NetworkUp,
            Values::NetworkDown => Self::NetworkDown,
            Values::NotJoined => Self::NotJoined,
            Values::JoinFailed => Self::JoinFailed,
            Values::InvalidSecurityLevel => Self::InvalidSecurityLevel,
            Values::MoveFailed => Self::MoveFailed,
            Values::CannotJoinAsRouter => Self::CannotJoinAsRouter,
            Values::NodeIdChanged => Self::NodeIdChanged,
            Values::PanIdChanged => Self::PanIdChanged,
            Values::NetworkOpened => Self::NetworkOpened,
            Values::NetworkClosed => Self::NetworkClosed,
            Values::NoBeacons => Self::NoBeacons,
            Values::ReceivedKeyInTheClear => Self::ReceivedKeyInTheClear,
            Values::NoNetworkKeyReceived => Self::NoNetworkKeyReceived,
            Values::NoLinkKeyReceived => Self::NoLinkKeyReceived,
            Values::PreconfiguredKeyRequired => Self::PreconfiguredKeyRequired,
            Values::KeyInvalid => Self::KeyInvalid,
            Values::NetworkBusy => Self::NetworkBusy,
            Values::InvalidEndpoint => Self::InvalidEndpoint,
            Values::BindingHasChanged => Self::BindingHasChanged,
            Values::InsufficientRandomData => Self::InsufficientRandomData,
            Values::ApsEncryptionError => Self::ApsEncryptionError,
            Values::SecurityStateNotSet => Self::SecurityStateNotSet,
            Values::SourceRouteFailure => Self::SourceRouteFailure,
            Values::ManyToOneRouteFailure => Self::ManyToOneRouteFailure,
            Values::StackAndHardwareMismatch => Self::StackAndHardwareMismatch,
            Values::IndexOutOfRange => Self::IndexOutOfRange,
            Values::KeyTableInvalidAddress => Self::KeyTableInvalidAddress,
            Values::TableFull => Self::TableFull,
            Values::LibraryNotPresent => Self::LibraryNotPresent,
            Values::TableEntryErased => Self::TableEntryErased,
            Values::SecurityConfigurationInvalid => Self::SecurityConfigurationInvalid,
            Values::TooSoonForSwitchKey => Self::TooSoonForSwitchKey,
            Values::SignatureVerifyFailure => Self::SignatureVerifyFailure,
            Values::OperationInProgress => Self::OperationInProgress,
            Values::KeyNotAuthorized => Self::KeyNotAuthorized,
            Values::SecurityDataInvalid => Self::SecurityDataInvalid,
            Values::ApplicationError0 => Self::Application(Application::Error0),
            Values::ApplicationError1 => Self::Application(Application::Error1),
            Values::ApplicationError2 => Self::Application(Application::Error2),
            Values::ApplicationError3 => Self::Application(Application::Error3),
            Values::ApplicationError4 => Self::Application(Application::Error4),
            Values::ApplicationError5 => Self::Application(Application::Error5),
            Values::ApplicationError6 => Self::Application(Application::Error6),
            Values::ApplicationError7 => Self::Application(Application::Error7),
            Values::ApplicationError8 => Self::Application(Application::Error8),
            Values::ApplicationError9 => Self::Application(Application::Error9),
            Values::ApplicationError10 => Self::Application(Application::Error10),
            Values::ApplicationError11 => Self::Application(Application::Error11),
            Values::ApplicationError12 => Self::Application(Application::Error12),
            Values::ApplicationError13 => Self::Application(Application::Error13),
            Values::ApplicationError14 => Self::Application(Application::Error14),
            Values::ApplicationError15 => Self::Application(Application::Error15),
        }
    }
}

impl From<Status> for u8 {
    fn from(status: Status) -> Self {
        Values::from(status).into()
    }
}

impl FromPrimitive for Status {
    fn from_i64(n: i64) -> Option<Self> {
        Values::from_i64(n).map(Self::from)
    }

    fn from_u8(n: u8) -> Option<Self> {
        Values::from_u8(n).map(Self::from)
    }

    fn from_u64(n: u64) -> Option<Self> {
        Values::from_u64(n).map(Self::from)
    }
}

impl LowerHex for Status {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        LowerHex::fmt(&Values::from(*self), f)
    }
}

impl UpperHex for Status {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        UpperHex::fmt(&Values::from(*self), f)
    }
}