1use core::fmt;
2
3use byteorder::{ByteOrder, LittleEndian};
4
5use super::{Error, Result};
6use crate::wire::{Ipv6Address, Ipv6AddressExt};
7
8enum_with_unknown! {
9 pub enum FrameType(u8) {
11 Beacon = 0b000,
12 Data = 0b001,
13 Acknowledgement = 0b010,
14 MacCommand = 0b011,
15 Multipurpose = 0b101,
16 FragmentOrFrak = 0b110,
17 Extended = 0b111,
18 }
19}
20
21impl fmt::Display for FrameType {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 match self {
24 FrameType::Beacon => write!(f, "Beacon"),
25 FrameType::Data => write!(f, "Data"),
26 FrameType::Acknowledgement => write!(f, "Ack"),
27 FrameType::MacCommand => write!(f, "MAC command"),
28 FrameType::Multipurpose => write!(f, "Multipurpose"),
29 FrameType::FragmentOrFrak => write!(f, "FragmentOrFrak"),
30 FrameType::Extended => write!(f, "Extended"),
31 FrameType::Unknown(id) => write!(f, "0b{id:04b}"),
32 }
33 }
34}
35enum_with_unknown! {
36 pub enum AddressingMode(u8) {
38 Absent = 0b00,
39 Short = 0b10,
40 Extended = 0b11,
41 }
42}
43
44impl AddressingMode {
45 const fn size(&self) -> usize {
47 match self {
48 AddressingMode::Absent => 0,
49 AddressingMode::Short => 2,
50 AddressingMode::Extended => 8,
51 AddressingMode::Unknown(_) => 0, }
53 }
54}
55
56impl fmt::Display for AddressingMode {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 match self {
59 AddressingMode::Absent => write!(f, "Absent"),
60 AddressingMode::Short => write!(f, "Short"),
61 AddressingMode::Extended => write!(f, "Extended"),
62 AddressingMode::Unknown(id) => write!(f, "0b{id:04b}"),
63 }
64 }
65}
66
67#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
69pub struct Pan(pub u16);
70
71impl Pan {
72 pub const BROADCAST: Self = Self(0xffff);
73
74 pub fn as_bytes(&self) -> [u8; 2] {
76 let mut pan = [0u8; 2];
77 LittleEndian::write_u16(&mut pan, self.0);
78 pan
79 }
80}
81
82impl fmt::Display for Pan {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 write!(f, "{:0x}", self.0)
85 }
86}
87
88#[cfg(feature = "defmt")]
89impl defmt::Format for Pan {
90 fn format(&self, fmt: defmt::Formatter) {
91 defmt::write!(fmt, "{:02x}", self.0)
92 }
93}
94
95#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
97pub enum Address {
98 Absent,
99 Short([u8; 2]),
100 Extended([u8; 8]),
101}
102
103#[cfg(feature = "defmt")]
104impl defmt::Format for Address {
105 fn format(&self, f: defmt::Formatter) {
106 match self {
107 Self::Absent => defmt::write!(f, "not-present"),
108 Self::Short(bytes) => defmt::write!(f, "{:02x}:{:02x}", bytes[0], bytes[1]),
109 Self::Extended(bytes) => defmt::write!(
110 f,
111 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
112 bytes[0],
113 bytes[1],
114 bytes[2],
115 bytes[3],
116 bytes[4],
117 bytes[5],
118 bytes[6],
119 bytes[7]
120 ),
121 }
122 }
123}
124
125#[cfg(test)]
126impl Default for Address {
127 fn default() -> Self {
128 Address::Extended([0u8; 8])
129 }
130}
131
132impl Address {
133 pub const BROADCAST: Address = Address::Short([0xff; 2]);
135
136 pub fn is_unicast(&self) -> bool {
138 !self.is_broadcast()
139 }
140
141 pub fn is_broadcast(&self) -> bool {
143 *self == Self::BROADCAST
144 }
145
146 const fn short_from_bytes(a: [u8; 2]) -> Self {
147 Self::Short(a)
148 }
149
150 const fn extended_from_bytes(a: [u8; 8]) -> Self {
151 Self::Extended(a)
152 }
153
154 pub fn from_bytes(a: &[u8]) -> Self {
155 if a.len() == 2 {
156 let mut b = [0u8; 2];
157 b.copy_from_slice(a);
158 Address::Short(b)
159 } else if a.len() == 8 {
160 let mut b = [0u8; 8];
161 b.copy_from_slice(a);
162 Address::Extended(b)
163 } else {
164 panic!("Not an IEEE802.15.4 address");
165 }
166 }
167
168 pub const fn as_bytes(&self) -> &[u8] {
169 match self {
170 Address::Absent => &[],
171 Address::Short(value) => value,
172 Address::Extended(value) => value,
173 }
174 }
175
176 pub fn as_eui_64(&self) -> Option<[u8; 8]> {
178 match self {
179 Address::Absent | Address::Short(_) => None,
180 Address::Extended(value) => {
181 let mut bytes = [0; 8];
182 bytes.copy_from_slice(&value[..]);
183
184 bytes[0] ^= 1 << 1;
185
186 Some(bytes)
187 }
188 }
189 }
190
191 pub fn as_link_local_address(&self) -> Option<Ipv6Address> {
194 let mut bytes = [0; 16];
195 bytes[0] = 0xfe;
196 bytes[1] = 0x80;
197 bytes[8..].copy_from_slice(&self.as_eui_64()?);
198
199 Some(Ipv6Address::from_bytes(&bytes))
200 }
201}
202
203impl fmt::Display for Address {
204 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
205 match self {
206 Self::Absent => write!(f, "not-present"),
207 Self::Short(bytes) => write!(f, "{:02x}:{:02x}", bytes[0], bytes[1]),
208 Self::Extended(bytes) => write!(
209 f,
210 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
211 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]
212 ),
213 }
214 }
215}
216
217enum_with_unknown! {
218 pub enum FrameVersion(u8) {
220 Ieee802154_2003 = 0b00,
221 Ieee802154_2006 = 0b01,
222 Ieee802154 = 0b10,
223 }
224}
225
226#[derive(Debug, Clone)]
228pub struct Frame<T: AsRef<[u8]>> {
229 buffer: T,
230}
231
232mod field {
233 use crate::wire::field::*;
234
235 pub const FRAMECONTROL: Field = 0..2;
236 pub const SEQUENCE_NUMBER: usize = 2;
237 pub const ADDRESSING: Rest = 3..;
238}
239
240macro_rules! fc_bit_field {
241 ($field:ident, $bit:literal) => {
242 #[inline]
243 pub fn $field(&self) -> bool {
244 let data = self.buffer.as_ref();
245 let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
246
247 ((raw >> $bit) & 0b1) == 0b1
248 }
249 };
250}
251
252macro_rules! set_fc_bit_field {
253 ($field:ident, $bit:literal) => {
254 #[inline]
255 pub fn $field(&mut self, val: bool) {
256 let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
257 let mut raw = LittleEndian::read_u16(data);
258 raw |= ((val as u16) << $bit);
259
260 data.copy_from_slice(&raw.to_le_bytes());
261 }
262 };
263}
264
265impl<T: AsRef<[u8]>> Frame<T> {
266 pub const fn new_unchecked(buffer: T) -> Frame<T> {
268 Frame { buffer }
269 }
270
271 pub fn new_checked(buffer: T) -> Result<Frame<T>> {
276 let packet = Self::new_unchecked(buffer);
277 packet.check_len()?;
278
279 if matches!(packet.frame_version(), FrameVersion::Unknown(_)) {
281 return Err(Error);
282 }
283
284 if matches!(packet.dst_addressing_mode(), AddressingMode::Unknown(_))
286 || matches!(packet.src_addressing_mode(), AddressingMode::Unknown(_))
287 {
288 return Err(Error);
289 }
290
291 if matches!(
293 packet.frame_version(),
294 FrameVersion::Ieee802154_2003 | FrameVersion::Ieee802154_2006
295 ) && packet.pan_id_compression()
296 && matches!(packet.dst_addressing_mode(), AddressingMode::Absent)
297 && matches!(packet.src_addressing_mode(), AddressingMode::Absent)
298 {
299 return Err(Error);
300 }
301
302 Ok(packet)
303 }
304
305 pub fn check_len(&self) -> Result<()> {
308 if self.buffer.as_ref().len() < 3 {
310 return Err(Error);
311 }
312
313 if self.buffer.as_ref().len() > 127 {
315 return Err(Error);
316 }
317
318 let mut offset = field::ADDRESSING.start
319 + if let Some((dst_pan_id, dst_addr, src_pan_id, src_addr)) = self.addr_present_flags()
320 {
321 let mut offset = if dst_pan_id { 2 } else { 0 };
322 offset += dst_addr.size();
323 offset += if src_pan_id { 2 } else { 0 };
324 offset += src_addr.size();
325
326 if offset > self.buffer.as_ref().len() {
327 return Err(Error);
328 }
329 offset
330 } else {
331 0
332 };
333
334 if self.security_enabled() {
335 if offset + 1 > self.buffer.as_ref().len() {
337 return Err(Error);
338 }
339
340 offset += self.security_header_len();
341 }
342
343 if offset > self.buffer.as_ref().len() {
344 return Err(Error);
345 }
346
347 Ok(())
348 }
349
350 pub fn into_inner(self) -> T {
352 self.buffer
353 }
354
355 #[inline]
357 pub fn frame_type(&self) -> FrameType {
358 let data = self.buffer.as_ref();
359 let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
360 let ft = (raw & 0b111) as u8;
361 FrameType::from(ft)
362 }
363
364 fc_bit_field!(security_enabled, 3);
365 fc_bit_field!(frame_pending, 4);
366 fc_bit_field!(ack_request, 5);
367 fc_bit_field!(pan_id_compression, 6);
368
369 fc_bit_field!(sequence_number_suppression, 8);
370 fc_bit_field!(ie_present, 9);
371
372 #[inline]
374 pub fn dst_addressing_mode(&self) -> AddressingMode {
375 let data = self.buffer.as_ref();
376 let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
377 let am = ((raw >> 10) & 0b11) as u8;
378 AddressingMode::from(am)
379 }
380
381 #[inline]
383 pub fn frame_version(&self) -> FrameVersion {
384 let data = self.buffer.as_ref();
385 let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
386 let fv = ((raw >> 12) & 0b11) as u8;
387 FrameVersion::from(fv)
388 }
389
390 #[inline]
392 pub fn src_addressing_mode(&self) -> AddressingMode {
393 let data = self.buffer.as_ref();
394 let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
395 let am = ((raw >> 14) & 0b11) as u8;
396 AddressingMode::from(am)
397 }
398
399 #[inline]
401 pub fn sequence_number(&self) -> Option<u8> {
402 match self.frame_type() {
403 FrameType::Beacon
404 | FrameType::Data
405 | FrameType::Acknowledgement
406 | FrameType::MacCommand
407 | FrameType::Multipurpose => {
408 let data = self.buffer.as_ref();
409 let raw = data[field::SEQUENCE_NUMBER];
410 Some(raw)
411 }
412 FrameType::Extended | FrameType::FragmentOrFrak | FrameType::Unknown(_) => None,
413 }
414 }
415
416 #[inline]
418 fn addressing_fields(&self) -> Option<&[u8]> {
419 match self.frame_type() {
420 FrameType::Beacon
421 | FrameType::Data
422 | FrameType::MacCommand
423 | FrameType::Multipurpose => (),
424 FrameType::Acknowledgement if self.frame_version() == FrameVersion::Ieee802154 => (),
425 FrameType::Acknowledgement
426 | FrameType::Extended
427 | FrameType::FragmentOrFrak
428 | FrameType::Unknown(_) => return None,
429 }
430
431 if let Some((dst_pan_id, dst_addr, src_pan_id, src_addr)) = self.addr_present_flags() {
432 let mut offset = if dst_pan_id { 2 } else { 0 };
433 offset += dst_addr.size();
434 offset += if src_pan_id { 2 } else { 0 };
435 offset += src_addr.size();
436
437 let data = self.buffer.as_ref();
438 Some(&data[field::ADDRESSING][..offset])
439 } else {
440 None
441 }
442 }
443
444 fn addr_present_flags(&self) -> Option<(bool, AddressingMode, bool, AddressingMode)> {
445 let dst_addr_mode = self.dst_addressing_mode();
446 let src_addr_mode = self.src_addressing_mode();
447 let pan_id_compression = self.pan_id_compression();
448
449 use AddressingMode::*;
450 match self.frame_version() {
451 FrameVersion::Ieee802154_2003 | FrameVersion::Ieee802154_2006 => {
452 match (dst_addr_mode, src_addr_mode) {
453 (Absent, src) => Some((false, Absent, true, src)),
454 (dst, Absent) => Some((true, dst, false, Absent)),
455
456 (dst, src) if pan_id_compression => Some((true, dst, false, src)),
457 (dst, src) if !pan_id_compression => Some((true, dst, true, src)),
458 _ => None,
459 }
460 }
461 FrameVersion::Ieee802154 => {
462 Some(match (dst_addr_mode, src_addr_mode, pan_id_compression) {
463 (Absent, Absent, false) => (false, Absent, false, Absent),
464 (Absent, Absent, true) => (true, Absent, false, Absent),
465 (dst, Absent, false) if !matches!(dst, Absent) => (true, dst, false, Absent),
466 (dst, Absent, true) if !matches!(dst, Absent) => (false, dst, false, Absent),
467 (Absent, src, false) if !matches!(src, Absent) => (false, Absent, true, src),
468 (Absent, src, true) if !matches!(src, Absent) => (false, Absent, true, src),
469 (Extended, Extended, false) => (true, Extended, false, Extended),
470 (Extended, Extended, true) => (false, Extended, false, Extended),
471 (Short, Short, false) => (true, Short, true, Short),
472 (Short, Extended, false) => (true, Short, true, Extended),
473 (Extended, Short, false) => (true, Extended, true, Short),
474 (Short, Extended, true) => (true, Short, false, Extended),
475 (Extended, Short, true) => (true, Extended, false, Short),
476 (Short, Short, true) => (true, Short, false, Short),
477 _ => return None,
478 })
479 }
480 _ => None,
481 }
482 }
483
484 #[inline]
486 pub fn dst_pan_id(&self) -> Option<Pan> {
487 if let Some((true, _, _, _)) = self.addr_present_flags() {
488 let addressing_fields = self.addressing_fields()?;
489 Some(Pan(LittleEndian::read_u16(&addressing_fields[..2])))
490 } else {
491 None
492 }
493 }
494
495 #[inline]
497 pub fn dst_addr(&self) -> Option<Address> {
498 if let Some((dst_pan_id, dst_addr, _, _)) = self.addr_present_flags() {
499 let addressing_fields = self.addressing_fields()?;
500 let offset = if dst_pan_id { 2 } else { 0 };
501
502 match dst_addr {
503 AddressingMode::Absent => Some(Address::Absent),
504 AddressingMode::Short => {
505 let mut raw = [0u8; 2];
506 raw.clone_from_slice(&addressing_fields[offset..offset + 2]);
507 raw.reverse();
508 Some(Address::short_from_bytes(raw))
509 }
510 AddressingMode::Extended => {
511 let mut raw = [0u8; 8];
512 raw.clone_from_slice(&addressing_fields[offset..offset + 8]);
513 raw.reverse();
514 Some(Address::extended_from_bytes(raw))
515 }
516 AddressingMode::Unknown(_) => None,
517 }
518 } else {
519 None
520 }
521 }
522
523 #[inline]
525 pub fn src_pan_id(&self) -> Option<Pan> {
526 if let Some((dst_pan_id, dst_addr, true, _)) = self.addr_present_flags() {
527 let mut offset = if dst_pan_id { 2 } else { 0 };
528 offset += dst_addr.size();
529 let addressing_fields = self.addressing_fields()?;
530 Some(Pan(LittleEndian::read_u16(
531 &addressing_fields[offset..][..2],
532 )))
533 } else {
534 None
535 }
536 }
537
538 #[inline]
540 pub fn src_addr(&self) -> Option<Address> {
541 if let Some((dst_pan_id, dst_addr, src_pan_id, src_addr)) = self.addr_present_flags() {
542 let addressing_fields = self.addressing_fields()?;
543 let mut offset = if dst_pan_id { 2 } else { 0 };
544 offset += dst_addr.size();
545 offset += if src_pan_id { 2 } else { 0 };
546
547 match src_addr {
548 AddressingMode::Absent => Some(Address::Absent),
549 AddressingMode::Short => {
550 let mut raw = [0u8; 2];
551 raw.clone_from_slice(&addressing_fields[offset..offset + 2]);
552 raw.reverse();
553 Some(Address::short_from_bytes(raw))
554 }
555 AddressingMode::Extended => {
556 let mut raw = [0u8; 8];
557 raw.clone_from_slice(&addressing_fields[offset..offset + 8]);
558 raw.reverse();
559 Some(Address::extended_from_bytes(raw))
560 }
561 AddressingMode::Unknown(_) => None,
562 }
563 } else {
564 None
565 }
566 }
567
568 fn aux_security_header_start(&self) -> usize {
570 let mut index = 3;
572 index += if let Some(addrs) = self.addressing_fields() {
573 addrs.len()
574 } else {
575 0
576 };
577 index
578 }
579
580 fn security_header_len(&self) -> usize {
582 let mut size = 1;
583 size += if self.frame_counter_suppressed() {
584 0
585 } else {
586 4
587 };
588 size += if let Some(len) = self.key_identifier_length() {
589 len as usize
590 } else {
591 0
592 };
593 size
594 }
595
596 fn payload_start(&self) -> usize {
598 let mut index = self.aux_security_header_start();
599
600 if self.security_enabled() {
601 index += self.security_header_len();
602 }
603
604 index
605 }
606
607 fn key_identifier_length(&self) -> Option<u8> {
609 Some(match self.key_identifier_mode() {
610 0 => 0,
611 1 => 1,
612 2 => 5,
613 3 => 9,
614 _ => return None,
615 })
616 }
617
618 pub fn security_level(&self) -> u8 {
620 let index = self.aux_security_header_start();
621 let b = self.buffer.as_ref()[index..][0];
622 b & 0b111
623 }
624
625 pub fn key_identifier_mode(&self) -> u8 {
627 let index = self.aux_security_header_start();
628 let b = self.buffer.as_ref()[index..][0];
629 (b >> 3) & 0b11
630 }
631
632 pub fn frame_counter_suppressed(&self) -> bool {
634 let index = self.aux_security_header_start();
635 let b = self.buffer.as_ref()[index..][0];
636 ((b >> 5) & 0b1) == 0b1
637 }
638
639 pub fn frame_counter(&self) -> Option<u32> {
641 if self.frame_counter_suppressed() {
642 None
643 } else {
644 let index = self.aux_security_header_start();
645 let b = &self.buffer.as_ref()[index..];
646 Some(LittleEndian::read_u32(&b[1..1 + 4]))
647 }
648 }
649
650 fn key_identifier(&self) -> &[u8] {
652 let index = self.aux_security_header_start();
653 let b = &self.buffer.as_ref()[index..];
654 let length = if let Some(len) = self.key_identifier_length() {
655 len as usize
656 } else {
657 0
658 };
659 &b[5..][..length]
660 }
661
662 pub fn key_source(&self) -> Option<&[u8]> {
664 let ki = self.key_identifier();
665 let len = ki.len();
666 if len > 1 {
667 Some(&ki[..len - 1])
668 } else {
669 None
670 }
671 }
672
673 pub fn key_index(&self) -> Option<u8> {
675 let ki = self.key_identifier();
676 let len = ki.len();
677
678 if len > 0 {
679 Some(ki[len - 1])
680 } else {
681 None
682 }
683 }
684
685 pub fn message_integrity_code(&self) -> Option<&[u8]> {
687 let mic_len = match self.security_level() {
688 0 | 4 => return None,
689 1 | 5 => 4,
690 2 | 6 => 8,
691 3 | 7 => 16,
692 _ => panic!(),
693 };
694
695 let data = &self.buffer.as_ref();
696 let len = data.len();
697
698 Some(&data[len - mic_len..])
699 }
700
701 pub fn mac_header(&self) -> &[u8] {
703 let data = &self.buffer.as_ref();
704 &data[..self.payload_start()]
705 }
706}
707
708impl<'a, T: AsRef<[u8]> + ?Sized> Frame<&'a T> {
709 #[inline]
711 pub fn payload(&self) -> Option<&'a [u8]> {
712 match self.frame_type() {
713 FrameType::Data => {
714 let index = self.payload_start();
715 let data = &self.buffer.as_ref();
716
717 Some(&data[index..])
718 }
719 _ => None,
720 }
721 }
722}
723
724impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
725 #[inline]
727 pub fn set_frame_type(&mut self, frame_type: FrameType) {
728 let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
729 let mut raw = LittleEndian::read_u16(data);
730
731 raw = (raw & !(0b111)) | (u8::from(frame_type) as u16 & 0b111);
732 data.copy_from_slice(&raw.to_le_bytes());
733 }
734
735 set_fc_bit_field!(set_security_enabled, 3);
736 set_fc_bit_field!(set_frame_pending, 4);
737 set_fc_bit_field!(set_ack_request, 5);
738 set_fc_bit_field!(set_pan_id_compression, 6);
739
740 #[inline]
742 pub fn set_frame_version(&mut self, version: FrameVersion) {
743 let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
744 let mut raw = LittleEndian::read_u16(data);
745
746 raw = (raw & !(0b11 << 12)) | ((u8::from(version) as u16 & 0b11) << 12);
747 data.copy_from_slice(&raw.to_le_bytes());
748 }
749
750 #[inline]
752 pub fn set_sequence_number(&mut self, value: u8) {
753 let data = self.buffer.as_mut();
754 data[field::SEQUENCE_NUMBER] = value;
755 }
756
757 #[inline]
759 pub fn set_dst_pan_id(&mut self, value: Pan) {
760 self.set_dst_addressing_mode(AddressingMode::Extended);
763
764 let data = self.buffer.as_mut();
765 data[field::ADDRESSING][..2].copy_from_slice(&value.as_bytes());
766 }
767
768 #[inline]
770 pub fn set_dst_addr(&mut self, value: Address) {
771 match value {
772 Address::Absent => self.set_dst_addressing_mode(AddressingMode::Absent),
773 Address::Short(mut value) => {
774 value.reverse();
775 self.set_dst_addressing_mode(AddressingMode::Short);
776 let data = self.buffer.as_mut();
777 data[field::ADDRESSING][2..2 + 2].copy_from_slice(&value);
778 value.reverse();
779 }
780 Address::Extended(mut value) => {
781 value.reverse();
782 self.set_dst_addressing_mode(AddressingMode::Extended);
783 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
784 data[2..2 + 8].copy_from_slice(&value);
785 value.reverse();
786 }
787 }
788 }
789
790 #[inline]
792 fn set_dst_addressing_mode(&mut self, value: AddressingMode) {
793 let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
794 let mut raw = LittleEndian::read_u16(data);
795
796 raw = (raw & !(0b11 << 10)) | ((u8::from(value) as u16 & 0b11) << 10);
797 data.copy_from_slice(&raw.to_le_bytes());
798 }
799
800 #[inline]
802 pub fn set_src_pan_id(&mut self, value: Pan) {
803 let offset = match self.dst_addressing_mode() {
804 AddressingMode::Absent => 0,
805 AddressingMode::Short => 2,
806 AddressingMode::Extended => 8,
807 _ => unreachable!(),
808 } + 2;
809
810 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
811 data[offset..offset + 2].copy_from_slice(&value.as_bytes());
812 }
813
814 #[inline]
816 pub fn set_src_addr(&mut self, value: Address) {
817 let offset = match self.dst_addressing_mode() {
818 AddressingMode::Absent => 0,
819 AddressingMode::Short => 2,
820 AddressingMode::Extended => 8,
821 _ => unreachable!(),
822 } + 2;
823
824 let offset = offset + if self.pan_id_compression() { 0 } else { 2 };
825
826 match value {
827 Address::Absent => self.set_src_addressing_mode(AddressingMode::Absent),
828 Address::Short(mut value) => {
829 value.reverse();
830 self.set_src_addressing_mode(AddressingMode::Short);
831 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
832 data[offset..offset + 2].copy_from_slice(&value);
833 value.reverse();
834 }
835 Address::Extended(mut value) => {
836 value.reverse();
837 self.set_src_addressing_mode(AddressingMode::Extended);
838 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
839 data[offset..offset + 8].copy_from_slice(&value);
840 value.reverse();
841 }
842 }
843 }
844
845 #[inline]
847 fn set_src_addressing_mode(&mut self, value: AddressingMode) {
848 let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
849 let mut raw = LittleEndian::read_u16(data);
850
851 raw = (raw & !(0b11 << 14)) | ((u8::from(value) as u16 & 0b11) << 14);
852 data.copy_from_slice(&raw.to_le_bytes());
853 }
854
855 #[inline]
857 pub fn payload_mut(&mut self) -> Option<&mut [u8]> {
858 match self.frame_type() {
859 FrameType::Data => {
860 let index = self.payload_start();
861 let data = self.buffer.as_mut();
862 Some(&mut data[index..])
863 }
864 _ => None,
865 }
866 }
867}
868
869impl<T: AsRef<[u8]>> fmt::Display for Frame<T> {
870 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
871 write!(f, "IEEE802.15.4 frame type={}", self.frame_type())?;
872
873 if let Some(seq) = self.sequence_number() {
874 write!(f, " seq={:02x}", seq)?;
875 }
876
877 if let Some(pan) = self.dst_pan_id() {
878 write!(f, " dst-pan={}", pan)?;
879 }
880
881 if let Some(pan) = self.src_pan_id() {
882 write!(f, " src-pan={}", pan)?;
883 }
884
885 if let Some(addr) = self.dst_addr() {
886 write!(f, " dst={}", addr)?;
887 }
888
889 if let Some(addr) = self.src_addr() {
890 write!(f, " src={}", addr)?;
891 }
892
893 Ok(())
894 }
895}
896
897#[cfg(feature = "defmt")]
898impl<T: AsRef<[u8]>> defmt::Format for Frame<T> {
899 fn format(&self, f: defmt::Formatter) {
900 defmt::write!(f, "IEEE802.15.4 frame type={}", self.frame_type());
901
902 if let Some(seq) = self.sequence_number() {
903 defmt::write!(f, " seq={:02x}", seq);
904 }
905
906 if let Some(pan) = self.dst_pan_id() {
907 defmt::write!(f, " dst-pan={}", pan);
908 }
909
910 if let Some(pan) = self.src_pan_id() {
911 defmt::write!(f, " src-pan={}", pan);
912 }
913
914 if let Some(addr) = self.dst_addr() {
915 defmt::write!(f, " dst={}", addr);
916 }
917
918 if let Some(addr) = self.src_addr() {
919 defmt::write!(f, " src={}", addr);
920 }
921 }
922}
923
924#[derive(Debug, PartialEq, Eq, Clone, Copy)]
926#[cfg_attr(feature = "defmt", derive(defmt::Format))]
927pub struct Repr {
928 pub frame_type: FrameType,
929 pub security_enabled: bool,
930 pub frame_pending: bool,
931 pub ack_request: bool,
932 pub sequence_number: Option<u8>,
933 pub pan_id_compression: bool,
934 pub frame_version: FrameVersion,
935 pub dst_pan_id: Option<Pan>,
936 pub dst_addr: Option<Address>,
937 pub src_pan_id: Option<Pan>,
938 pub src_addr: Option<Address>,
939}
940
941impl Repr {
942 pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Frame<&T>) -> Result<Repr> {
944 packet.check_len()?;
946
947 Ok(Repr {
948 frame_type: packet.frame_type(),
949 security_enabled: packet.security_enabled(),
950 frame_pending: packet.frame_pending(),
951 ack_request: packet.ack_request(),
952 sequence_number: packet.sequence_number(),
953 pan_id_compression: packet.pan_id_compression(),
954 frame_version: packet.frame_version(),
955 dst_pan_id: packet.dst_pan_id(),
956 dst_addr: packet.dst_addr(),
957 src_pan_id: packet.src_pan_id(),
958 src_addr: packet.src_addr(),
959 })
960 }
961
962 #[inline]
964 pub const fn buffer_len(&self) -> usize {
965 3 + 2
966 + match self.dst_addr {
967 Some(Address::Absent) | None => 0,
968 Some(Address::Short(_)) => 2,
969 Some(Address::Extended(_)) => 8,
970 }
971 + if !self.pan_id_compression { 2 } else { 0 }
972 + match self.src_addr {
973 Some(Address::Absent) | None => 0,
974 Some(Address::Short(_)) => 2,
975 Some(Address::Extended(_)) => 8,
976 }
977 }
978
979 pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, frame: &mut Frame<T>) {
981 frame.set_frame_type(self.frame_type);
982 frame.set_security_enabled(self.security_enabled);
983 frame.set_frame_pending(self.frame_pending);
984 frame.set_ack_request(self.ack_request);
985 frame.set_pan_id_compression(self.pan_id_compression);
986 frame.set_frame_version(self.frame_version);
987
988 if let Some(sequence_number) = self.sequence_number {
989 frame.set_sequence_number(sequence_number);
990 }
991
992 if let Some(dst_pan_id) = self.dst_pan_id {
993 frame.set_dst_pan_id(dst_pan_id);
994 }
995 if let Some(dst_addr) = self.dst_addr {
996 frame.set_dst_addr(dst_addr);
997 }
998
999 if !self.pan_id_compression && self.src_pan_id.is_some() {
1000 frame.set_src_pan_id(self.src_pan_id.unwrap());
1001 }
1002
1003 if let Some(src_addr) = self.src_addr {
1004 frame.set_src_addr(src_addr);
1005 }
1006 }
1007}
1008
1009#[cfg(test)]
1010mod test {
1011 use super::*;
1012
1013 #[test]
1014 fn test_broadcast() {
1015 assert!(Address::BROADCAST.is_broadcast());
1016 assert!(!Address::BROADCAST.is_unicast());
1017 }
1018
1019 #[test]
1020 fn prepare_frame() {
1021 let mut buffer = [0u8; 128];
1022
1023 let repr = Repr {
1024 frame_type: FrameType::Data,
1025 security_enabled: false,
1026 frame_pending: false,
1027 ack_request: true,
1028 pan_id_compression: true,
1029 frame_version: FrameVersion::Ieee802154,
1030 sequence_number: Some(1),
1031 dst_pan_id: Some(Pan(0xabcd)),
1032 dst_addr: Some(Address::BROADCAST),
1033 src_pan_id: None,
1034 src_addr: Some(Address::Extended([
1035 0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, 0x00,
1036 ])),
1037 };
1038
1039 let buffer_len = repr.buffer_len();
1040
1041 let mut frame = Frame::new_unchecked(&mut buffer[..buffer_len]);
1042 repr.emit(&mut frame);
1043
1044 println!("{frame:2x?}");
1045
1046 assert_eq!(frame.frame_type(), FrameType::Data);
1047 assert!(!frame.security_enabled());
1048 assert!(!frame.frame_pending());
1049 assert!(frame.ack_request());
1050 assert!(frame.pan_id_compression());
1051 assert_eq!(frame.frame_version(), FrameVersion::Ieee802154);
1052 assert_eq!(frame.sequence_number(), Some(1));
1053 assert_eq!(frame.dst_pan_id(), Some(Pan(0xabcd)));
1054 assert_eq!(frame.dst_addr(), Some(Address::BROADCAST));
1055 assert_eq!(frame.src_pan_id(), None);
1056 assert_eq!(
1057 frame.src_addr(),
1058 Some(Address::Extended([
1059 0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, 0x00
1060 ]))
1061 );
1062 }
1063
1064 macro_rules! vector_test {
1065 ($name:ident $bytes:expr ; $($test_method:ident -> $expected:expr,)*) => {
1066 #[test]
1067 #[allow(clippy::bool_assert_comparison)]
1068 fn $name() -> Result<()> {
1069 let frame = &$bytes;
1070 let frame = Frame::new_checked(frame)?;
1071
1072 $(
1073 assert_eq!(frame.$test_method(), $expected, stringify!($test_method));
1074 )*
1075
1076 Ok(())
1077 }
1078 }
1079 }
1080
1081 vector_test! {
1082 extended_addr
1083 [
1084 0b0000_0001, 0b1100_1100, 0b0, 0xcd, 0xab, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, ];
1091 frame_type -> FrameType::Data,
1092 dst_addr -> Some(Address::Extended([0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00])),
1093 src_addr -> Some(Address::Extended([0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00])),
1094 dst_pan_id -> Some(Pan(0xabcd)),
1095 }
1096
1097 vector_test! {
1098 short_addr
1099 [
1100 0x01, 0x98, 0x00, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a, ];
1105 frame_type -> FrameType::Data,
1106 security_enabled -> false,
1107 frame_pending -> false,
1108 ack_request -> false,
1109 pan_id_compression -> false,
1110 dst_addressing_mode -> AddressingMode::Short,
1111 frame_version -> FrameVersion::Ieee802154_2006,
1112 src_addressing_mode -> AddressingMode::Short,
1113 dst_pan_id -> Some(Pan(0x1234)),
1114 dst_addr -> Some(Address::Short([0x56, 0x78])),
1115 src_pan_id -> Some(Pan(0x1234)),
1116 src_addr -> Some(Address::Short([0x9a, 0xbc])),
1117 }
1118
1119 vector_test! {
1120 zolertia_remote
1121 [
1122 0x41, 0xd8, 0x01, 0xcd, 0xab, 0xff, 0xff, 0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, 0x00, 0x2b, 0x00, 0x00, 0x00, ];
1129 frame_type -> FrameType::Data,
1130 security_enabled -> false,
1131 frame_pending -> false,
1132 ack_request -> false,
1133 pan_id_compression -> true,
1134 dst_addressing_mode -> AddressingMode::Short,
1135 frame_version -> FrameVersion::Ieee802154_2006,
1136 src_addressing_mode -> AddressingMode::Extended,
1137 payload -> Some(&[0x2b, 0x00, 0x00, 0x00][..]),
1138 }
1139
1140 vector_test! {
1141 security
1142 [
1143 0x69,0xdc, 0x32, 0xcd,0xab, 0xbf,0x9b,0x15,0x06,0x00,0x4b,0x12,0x00, 0xc7,0xd9,0xb5,0x14,0x00,0x4b,0x12,0x00, 0x05, 0x31,0x01,0x00,0x00, 0x3e,0xe8,0xfb,0x85,0xe4,0xcc,0xf4,0x48,0x90,0xfe,0x56,0x66,0xf7,0x1c,0x65,0x9e,0xf9, 0x93,0xc8,0x34,0x2e,];
1153 frame_type -> FrameType::Data,
1154 security_enabled -> true,
1155 frame_pending -> false,
1156 ack_request -> true,
1157 pan_id_compression -> true,
1158 dst_addressing_mode -> AddressingMode::Extended,
1159 frame_version -> FrameVersion::Ieee802154_2006,
1160 src_addressing_mode -> AddressingMode::Extended,
1161 dst_pan_id -> Some(Pan(0xabcd)),
1162 dst_addr -> Some(Address::Extended([0x00,0x12,0x4b,0x00,0x06,0x15,0x9b,0xbf])),
1163 src_pan_id -> None,
1164 src_addr -> Some(Address::Extended([0x00,0x12,0x4b,0x00,0x14,0xb5,0xd9,0xc7])),
1165 security_level -> 5,
1166 key_identifier_mode -> 0,
1167 frame_counter -> Some(305),
1168 key_source -> None,
1169 key_index -> None,
1170 payload -> Some(&[0x3e,0xe8,0xfb,0x85,0xe4,0xcc,0xf4,0x48,0x90,0xfe,0x56,0x66,0xf7,0x1c,0x65,0x9e,0xf9,0x93,0xc8,0x34,0x2e][..]),
1171 message_integrity_code -> Some(&[0x93, 0xC8, 0x34, 0x2E][..]),
1172 mac_header -> &[
1173 0x69,0xdc, 0x32, 0xcd,0xab, 0xbf,0x9b,0x15,0x06,0x00,0x4b,0x12,0x00, 0xc7,0xd9,0xb5,0x14,0x00,0x4b,0x12,0x00, 0x05, 0x31,0x01,0x00,0x00, ][..],
1181 }
1182}