zigbee_cluster_library/header/
frame_control.rs1use core::fmt;
3use core::fmt::Debug;
4use core::mem;
5
6use zigbee::internal::macros::impl_byte;
7
8impl_byte! {
9 #[derive(Clone, Copy, PartialEq, Eq)]
11 pub struct FrameControl(pub u8);
12}
13
14#[allow(missing_docs)]
18#[repr(u8)]
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum FrameType {
21 GlobalCommand = 0b00,
22 ClusterCommand = 0b01,
23 Reserved = 0b10,
24}
25
26impl FrameControl {
27 pub fn frame_type(self) -> FrameType {
31 unsafe { mem::transmute((self.0 & mask::FRAME_TYPE) >> offset::FRAME_TYPE) }
33 }
34
35 pub fn is_manufacturer_specific(self) -> bool {
43 ((self.0 & mask::MANUFACTURER_SPECIFIC) >> offset::MANUFACTURER_SPECIFIC) != 0
44 }
45
46 pub fn direction(self) -> bool {
52 (self.0 & mask::DIRECTION) != 0
53 }
54
55 pub fn disable_default_response(self) -> bool {
57 (self.0 & mask::DEFAULT_RESPONSE) != 0
58 }
59}
60
61mod mask {
62 pub(super) const FRAME_TYPE: u8 = 0b0000_0011; pub(super) const MANUFACTURER_SPECIFIC: u8 = 0b0000_0100; pub(super) const DIRECTION: u8 = 0b0000_1000; pub(super) const DEFAULT_RESPONSE: u8 = 0b0001_0000; }
67mod offset {
68 pub(super) const FRAME_TYPE: u8 = 0;
69 pub(super) const MANUFACTURER_SPECIFIC: u8 = 2;
70}
71
72impl Debug for FrameControl {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 f.debug_struct("FrameControl")
75 .field("frame_type", &self.frame_type())
76 .field("manufacturer_specific", &self.is_manufacturer_specific())
77 .field("direction", &self.direction())
78 .field("disable_default_response", &self.disable_default_response())
79 .finish()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85
86 use byte::TryRead;
87
88 use super::*;
89
90 #[test]
91 fn unpack_frame_control() {
92 let input = [0x18];
94
95 let (frame_control, _) =
97 FrameControl::try_read(&input, ()).expect("Could not read FrameControl in test.");
98
99 assert_eq!(frame_control.frame_type(), FrameType::GlobalCommand);
101 assert!(!frame_control.is_manufacturer_specific());
102 assert!(frame_control.direction());
103 assert!(frame_control.disable_default_response());
104 }
105
106 #[test]
107 fn frame_control_with_local_command() {
108 let input = [0x19];
110
111 let (frame_control, _) =
113 FrameControl::try_read(&input, ()).expect("Could not read FrameControl in test.");
114
115 assert_eq!(frame_control.frame_type(), FrameType::ClusterCommand);
117 assert!(!frame_control.is_manufacturer_specific());
118 assert!(frame_control.direction());
119 assert!(frame_control.disable_default_response());
120 }
121
122 #[test]
123 fn frame_control_with_manufacturer_specific_flag() {
124 let input = [0x1d];
126
127 let (frame_control, _) =
129 FrameControl::try_read(&input, ()).expect("Could not read FrameControl in test.");
130
131 assert_eq!(frame_control.frame_type(), FrameType::ClusterCommand);
133 assert!(frame_control.is_manufacturer_specific());
134 assert!(frame_control.direction());
135 assert!(frame_control.disable_default_response());
136 }
137 #[test]
138 fn frame_control_with_direction_server_to_client() {
139 let input = [0x0d];
141
142 let (frame_control, _) =
144 FrameControl::try_read(&input, ()).expect("Could not read FrameControl in test.");
145
146 assert_eq!(frame_control.frame_type(), FrameType::ClusterCommand);
148 assert!(frame_control.is_manufacturer_specific());
149 assert!(frame_control.direction());
150 assert!(!frame_control.disable_default_response());
151 }
152}