stackforge_core/layer/dot15d4/
crc.rs1#[must_use]
15pub fn crc_ccitt_kermit(data: &[u8]) -> u16 {
16 let mut crc: u16 = 0;
17 for &byte in data {
18 let c = u16::from(byte);
19 let q = (crc ^ c) & 0x0F;
21 crc = (crc >> 4) ^ (q * 4225);
22 let q = (crc ^ (c >> 4)) & 0x0F;
24 crc = (crc >> 4) ^ (q * 4225);
25 }
26 crc
27}
28
29#[must_use]
31pub fn compute_fcs(data: &[u8]) -> [u8; 2] {
32 crc_ccitt_kermit(data).to_le_bytes()
33}
34
35#[must_use]
40pub fn verify_fcs(data: &[u8], expected_fcs: u16) -> bool {
41 crc_ccitt_kermit(data) == expected_fcs
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn test_crc_empty() {
50 assert_eq!(crc_ccitt_kermit(&[]), 0x0000);
51 }
52
53 #[test]
54 fn test_crc_known_value() {
55 let data = b"123456789";
57 assert_eq!(crc_ccitt_kermit(data), 0x2189);
58 }
59
60 #[test]
61 fn test_compute_fcs_le_bytes() {
62 let data = b"123456789";
63 let fcs = compute_fcs(data);
64 assert_eq!(fcs, [0x89, 0x21]);
66 }
67
68 #[test]
69 fn test_verify_fcs() {
70 let data = b"123456789";
71 assert!(verify_fcs(data, 0x2189));
72 assert!(!verify_fcs(data, 0x0000));
73 }
74
75 #[test]
76 fn test_crc_single_byte() {
77 let crc = crc_ccitt_kermit(&[0x00]);
79 assert_eq!(crc, 0x0000);
80 }
81
82 #[test]
83 fn test_crc_802154_beacon_frame() {
84 let data = [0x00, 0x00, 0x01];
87 let crc = crc_ccitt_kermit(&data);
88 let fcs_bytes = compute_fcs(&data);
89 assert!(verify_fcs(&data, crc));
91 assert_eq!(fcs_bytes, crc.to_le_bytes());
92 }
93
94 #[test]
95 fn test_crc_deterministic() {
96 let data = [0x41, 0x88, 0x05, 0xFF, 0xFF, 0x34, 0x12];
97 let crc1 = crc_ccitt_kermit(&data);
98 let crc2 = crc_ccitt_kermit(&data);
99 assert_eq!(crc1, crc2);
100 }
101
102 #[test]
103 fn test_verify_fcs_wrong_data() {
104 let data1 = [0x01, 0x02, 0x03];
105 let crc = crc_ccitt_kermit(&data1);
106 let data2 = [0x01, 0x02, 0x04]; assert!(!verify_fcs(&data2, crc));
108 }
109}