99//! - **shared_radio** enables [SharedCrazyradio] object that allows to share a radio between threads
1010//! - **async** enables async function to create a [Crazyradio] object and use the [SharedCrazyradio]
1111//! - **serde** emables [serde](https://crates.io/crates/serde) serialization/deserialization of the [Channel] struct
12+ //! - **packet_capture** enables functionality to capture packets by registering a callback which is called for each in/out packet
1213
1314#![ deny( missing_docs) ]
1415
@@ -17,6 +18,9 @@ mod shared_radio;
1718#[ cfg( feature = "shared_radio" ) ]
1819pub use crate :: shared_radio:: { SharedCrazyradio , WeakSharedCrazyradio } ;
1920
21+ #[ cfg( feature = "packet_capture" ) ]
22+ pub mod capture;
23+
2024use core:: time:: Duration ;
2125#[ cfg( feature = "serde_support" ) ]
2226use serde:: { Deserialize , Serialize } ;
@@ -138,6 +142,10 @@ pub struct Crazyradio {
138142 address : [ u8 ; 5 ] ,
139143 datarate : Datarate ,
140144 ack_enable : bool ,
145+
146+ /// Radio serial number (for capture identification)
147+ #[ cfg( feature = "packet_capture" ) ]
148+ serial : String ,
141149}
142150
143151impl Crazyradio {
@@ -190,6 +198,9 @@ impl Crazyradio {
190198 return Err ( Error :: DongleVersionNotSupported ) ;
191199 }
192200
201+ #[ cfg( feature = "packet_capture" ) ]
202+ let serial = get_serial ( & device_desciptor, & device_handle) . unwrap_or_default ( ) ;
203+
193204 let mut cr = Crazyradio {
194205 device_desciptor,
195206 device_handle,
@@ -202,6 +213,9 @@ impl Crazyradio {
202213 datarate : Datarate :: Dr2M ,
203214
204215 ack_enable : true ,
216+
217+ #[ cfg( feature = "packet_capture" ) ]
218+ serial,
205219 } ;
206220
207221 cr. reset ( ) ?;
@@ -517,8 +531,18 @@ impl Crazyradio {
517531 /// be truncated. The length of the ack payload is returned
518532 /// in Ack::length.
519533 pub fn send_packet ( & mut self , data : & [ u8 ] , ack_data : & mut [ u8 ] ) -> Result < Ack > {
520- if self . inline_mode {
521- self . send_inline ( data, Some ( ack_data) )
534+ // Capture TX packet
535+ #[ cfg( feature = "packet_capture" ) ]
536+ capture:: capture_packet (
537+ capture:: DIRECTION_TX ,
538+ self . channel . into ( ) ,
539+ & self . address ,
540+ & self . serial ,
541+ data,
542+ ) ;
543+
544+ let ack = if self . inline_mode {
545+ self . send_inline ( data, Some ( ack_data) ) ?
522546 } else {
523547 self . device_handle
524548 . write_bulk ( 0x01 , data, Duration :: from_secs ( 1 ) ) ?;
@@ -536,13 +560,27 @@ impl Crazyradio {
536560 . copy_from_slice ( & received_data[ 1 ..33 ] ) ;
537561 }
538562
539- Ok ( Ack {
563+ Ack {
540564 received : received_data[ 0 ] & 0x01 != 0 ,
541565 power_detector : received_data[ 0 ] & 0x02 != 0 ,
542566 retry : ( ( received_data[ 0 ] & 0xf0 ) >> 4 ) as usize ,
543567 length : received - 1 ,
544- } )
568+ }
569+ } ;
570+
571+ // Capture RX packet (ACK payload)
572+ #[ cfg( feature = "packet_capture" ) ]
573+ if ack. received && ack. length > 0 {
574+ capture:: capture_packet (
575+ capture:: DIRECTION_RX ,
576+ self . channel . into ( ) ,
577+ & self . address ,
578+ & self . serial ,
579+ & ack_data[ ..ack. length . min ( ack_data. len ( ) ) ] ,
580+ ) ;
545581 }
582+
583+ Ok ( ack)
546584 }
547585
548586 /// Send a data packet without caring for Ack (for broadcast communication).
@@ -551,6 +589,16 @@ impl Crazyradio {
551589 ///
552590 /// * `data`: Up to 32 bytes of data to be send.
553591 pub fn send_packet_no_ack ( & mut self , data : & [ u8 ] ) -> Result < ( ) > {
592+ // Capture TX packet
593+ #[ cfg( feature = "packet_capture" ) ]
594+ capture:: capture_packet (
595+ capture:: DIRECTION_TX ,
596+ self . channel . into ( ) ,
597+ & self . address ,
598+ & self . serial ,
599+ data,
600+ ) ;
601+
554602 if self . inline_mode {
555603 self . send_inline ( data, None ) ?;
556604 } else {
0 commit comments