peak_can/socket/
mod.rs

1//!
2//!
3//!
4
5pub mod dng;
6pub mod isa;
7pub mod lan;
8pub mod pcc;
9pub mod pci;
10pub mod usb;
11
12use crate::bus::Bus;
13use crate::error::{CanError, CanOkError};
14use crate::peak_lib;
15use crate::peak_can;
16
17use std::ops::Deref;
18
19pub const STANDARD_MASK: u32 = 0x07_FF;
20pub const EXTENDED_MASK: u32 = 0x1F_FF_FF_FF;
21
22#[derive(Debug, PartialEq)]
23pub enum MessageType {
24    Standard,
25    Extended,
26}
27
28#[derive(Debug, PartialEq)]
29pub enum FrameConstructionError {
30    TooMuchData,
31    CanIdMessageTypeMismatch,
32}
33
34#[derive(Debug, Copy, Clone)]
35pub struct CanFrame {
36    frame: peak_can::TPEAKMsg,
37}
38
39impl CanFrame {
40    const MAX_DLC: usize = 8;
41
42    pub fn new(
43        can_id: u32,
44        msg_type: MessageType,
45        data: &[u8],
46    ) -> Result<CanFrame, FrameConstructionError> {
47        if data.len() > Self::MAX_DLC {
48            Err(FrameConstructionError::TooMuchData)
49        } else {
50            let mut frame_data: [u8; 8] = [0; 8];
51            for (i, v) in data.into_iter().enumerate() {
52                frame_data[i] = *v;
53            }
54
55            match msg_type {
56                MessageType::Standard => Ok(CanFrame {
57                    frame: peak_can::TPEAKMsg {
58                        ID: can_id & STANDARD_MASK,
59                        MSGTYPE: peak_can::PEAK_MESSAGE_STANDARD as u8,
60                        LEN: data.len() as u8,
61                        DATA: frame_data,
62                    },
63                }),
64                MessageType::Extended => Ok(CanFrame {
65                    frame: peak_can::TPEAKMsg {
66                        ID: can_id & EXTENDED_MASK,
67                        MSGTYPE: peak_can::PEAK_MESSAGE_EXTENDED as u8,
68                        LEN: data.len() as u8,
69                        DATA: frame_data,
70                    },
71                }),
72            }
73        }
74    }
75
76    pub fn is_standard_frame(&self) -> bool {
77        // PEAK_MESSAGE_STANDARD flag is denoted as 0, so check for extended frame flag instead
78        !self.is_extended_frame()
79    }
80
81    pub fn is_extended_frame(&self) -> bool {
82        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_EXTENDED as u8 != 0
83    }
84
85    pub fn is_error_frame(&self) -> bool {
86        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_ERRFRAME as u8 != 0
87    }
88
89    pub fn is_echo_frame(&self) -> bool {
90        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_ECHO as u8 != 0
91    }
92
93    pub fn can_id(&self) -> u32 {
94        if self.is_standard_frame() {
95            self.frame.ID & STANDARD_MASK
96        } else {
97            self.frame.ID & EXTENDED_MASK
98        }
99    }
100
101    pub fn dlc(&self) -> u8 {
102        self.frame.LEN
103    }
104
105    pub fn data(&self) -> &[u8] {
106        &self.frame.DATA[0..self.dlc() as usize]
107    }
108
109    pub fn mut_data(&mut self) -> &mut [u8] {
110        let dlc = self.dlc();
111        &mut self.frame.DATA[0..dlc as usize]
112    }
113}
114
115impl Default for CanFrame {
116    fn default() -> Self {
117        CanFrame::new(0, MessageType::Standard, &[]).unwrap()
118    }
119}
120
121impl PartialEq for CanFrame {
122    fn eq(&self, other: &Self) -> bool {
123        if self.frame.ID != other.frame.ID {
124            return false;
125        }
126
127        if self.frame.LEN != other.frame.LEN {
128            return false;
129        }
130
131        if self.frame.MSGTYPE != other.frame.MSGTYPE {
132            return false;
133        }
134
135        if self.data() != other.data() {
136            return false;
137        }
138
139        true
140    }
141}
142
143#[derive(Debug, Copy, Clone)]
144pub struct CanFdFrame {
145    frame: peak_can::TPEAKMsgFD,
146}
147
148impl CanFdFrame {
149    const MAX_DATA_LENGTH: usize = 64;
150
151    pub fn new(
152        can_id: u32,
153        msg_type: MessageType,
154        data: &[u8],
155        fd: bool,
156        brs: bool,
157    ) -> Result<CanFdFrame, FrameConstructionError> {
158        if data.len() > Self::MAX_DATA_LENGTH {
159            Err(FrameConstructionError::TooMuchData)
160        } else {
161            let mut frame_data: [u8; Self::MAX_DATA_LENGTH] = [0; Self::MAX_DATA_LENGTH];
162            for (i, v) in data.into_iter().enumerate() {
163                frame_data[i] = *v;
164            }
165
166            match msg_type {
167                MessageType::Standard => Ok(CanFdFrame {
168                    frame: peak_can::TPEAKMsgFD {
169                        ID: can_id & STANDARD_MASK,
170                        MSGTYPE: peak_can::PEAK_MESSAGE_STANDARD as u8 | 
171                            if fd { peak_can::PEAK_MESSAGE_FD as u8 } else { 0 } |
172                            if brs { peak_can::PEAK_MESSAGE_BRS as u8 } else { 0 },
173                        DLC: Self::calc_dlc(data.len()),
174                        DATA: frame_data,
175                    },
176                }),
177                MessageType::Extended => Ok(CanFdFrame {
178                    frame: peak_can::TPEAKMsgFD {
179                        ID: can_id & EXTENDED_MASK,
180                        MSGTYPE: peak_can::PEAK_MESSAGE_EXTENDED as u8 |
181                            if fd { peak_can::PEAK_MESSAGE_FD as u8 } else { 0 } |
182                            if brs { peak_can::PEAK_MESSAGE_BRS as u8 } else { 0 },
183                        DLC: Self::calc_dlc(data.len()),
184                        DATA: frame_data,
185                    },
186                }),
187            }
188        }
189    }
190
191    pub fn is_standard_frame(&self) -> bool {
192        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_STANDARD as u8 != 0
193    }
194
195    pub fn is_extended_frame(&self) -> bool {
196        if self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_EXTENDED as u8 != 0 {
197            true
198        } else {
199            false
200        }
201    }
202    
203    pub fn is_error_frame(&self) -> bool {
204        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_ERRFRAME as u8 != 0
205    }
206
207    pub fn is_echo_frame(&self) -> bool {
208        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_ECHO as u8 != 0
209    }
210
211    pub fn is_fd_frame(&self) -> bool {
212        self.frame.MSGTYPE & peak_can::PEAK_MESSAGE_FD as u8 != 0
213    }
214
215    pub fn can_id(&self) -> u32 {
216        if self.is_standard_frame() {
217            self.frame.ID & STANDARD_MASK
218        } else {
219            self.frame.ID & EXTENDED_MASK
220        }
221    }
222
223    pub fn dlc(&self) -> u8 {
224        self.frame.DLC
225    }
226
227    pub fn data(&self) -> &[u8] {
228        &self.frame.DATA[0..self.len() as usize]
229    }
230
231    pub fn mut_data(&mut self) -> &mut [u8] {
232        let len = self.len();
233        &mut self.frame.DATA[0..len as usize]
234    }
235
236    fn calc_dlc(len: usize) -> u8 {
237        match len {
238            0..=8 => len as u8,
239            9..=12 => 9,
240            13..=16 => 10,
241            17..=20 => 11,
242            21..=24 => 12,
243            25..=32 => 13,
244            33..=48 => 14,
245            49..=64 => 15,
246            _ => 15, // Max DLC for CAN FD is 64 bytes
247        }
248    }
249
250    pub fn len(&self) -> usize {
251        match self.dlc() {
252            0..=8 => self.dlc() as usize,
253            9 => 12,
254            10 => 16,
255            11 => 20,
256            12 => 24,
257            13 => 32,
258            14 => 48,
259            15 => 64,
260            _ => 64, // Max DLC for CAN FD is 64 bytes
261        }
262    }
263
264    pub fn is_empty(&self) -> bool {
265        self.len() == 0
266    }
267}
268
269impl Default for CanFdFrame {
270    fn default() -> Self {
271        CanFdFrame::new(0, MessageType::Standard, &[], false, false).unwrap()
272    }
273}
274
275impl PartialEq for CanFdFrame {
276    fn eq(&self, other: &Self) -> bool {
277        if self.frame.ID != other.frame.ID {
278            return false;
279        }
280
281        if self.frame.DLC != other.frame.DLC {
282            return false;
283        }
284
285        if self.frame.MSGTYPE != other.frame.MSGTYPE {
286            return false;
287        }
288
289        if self.data() != other.data() {
290            return false;
291        }
292
293        true
294    }
295}
296
297#[derive(Debug, Copy, Clone)]
298pub struct Timestamp {
299    timestamp: peak_can::TPEAKTimestamp,
300}
301
302impl Deref for Timestamp {
303    type Target = peak_can::TPEAKTimestamp;
304
305    fn deref(&self) -> &Self::Target {
306        &self.timestamp
307    }
308}
309
310impl Default for Timestamp {
311    fn default() -> Timestamp {
312        Timestamp {
313            timestamp: peak_can::TPEAKTimestamp {
314                micros: 0,
315                millis: 0,
316                millis_overflow: 0,
317            },
318        }
319    }
320}
321
322impl PartialEq for Timestamp {
323    fn eq(&self, other: &Self) -> bool {
324        if self.timestamp.micros != other.timestamp.micros {
325            return false;
326        }
327
328        if self.timestamp.millis != other.timestamp.millis {
329            return false;
330        }
331
332        if self.timestamp.millis_overflow != other.timestamp.millis_overflow {
333            return false;
334        }
335
336        true
337    }
338}
339
340#[derive(Debug, PartialEq)]
341pub struct CanSocket {
342    handle: u16,
343}
344
345impl CanSocket {
346    pub fn open<T: Bus>(bus: T, baud: Baudrate) -> Result<CanSocket, CanError> {
347        let handle = bus.channel();
348        let code = unsafe { peak_lib()?.CAN_Initialize(handle, baud.into(), 0, 0, 0) };
349
350        match CanOkError::try_from(code) {
351            Ok(CanOkError::Ok) => Ok(CanSocket { handle }),
352            Ok(CanOkError::Err(err)) => Err(err),
353            Err(_) => Err(CanError::Unknown),
354        }
355    }
356}
357
358trait HasRecvCan {}
359
360pub trait RecvCan {
361    fn recv(&self) -> Result<(CanFrame, Timestamp), CanError>;
362    fn recv_frame(&self) -> Result<CanFrame, CanError>;
363}
364
365trait HasRecvCanFd {}
366
367pub trait RecvCanFd {
368    fn recv_fd(&self) -> Result<(CanFdFrame, u64), CanError>;
369    fn recv_fd_frame(&self) -> Result<CanFdFrame, CanError>;
370}
371
372trait HasSendCan {}
373
374pub trait SendCan {
375    fn send(&self, frame: CanFrame) -> Result<(), CanError>;
376}
377
378trait HasSendCanFd {}
379
380pub trait SendCanFd {
381    fn send_fd(&self, frame: CanFdFrame) -> Result<(), CanError>;
382}
383
384trait Socket {
385    fn handle(&self) -> u16;
386}
387
388/* Baudrate */
389
390#[derive(Debug, PartialEq)]
391pub enum Baudrate {
392    Baud1M,
393    Baud800K,
394    Baud500K,
395    Baud250K,
396    Baud125K,
397    Baud100K,
398    Baud95K,
399    Baud83K,
400    Baud50K,
401    Baud47K,
402    Baud33K,
403    Baud20K,
404    Baud10K,
405    Baud5K,
406}
407
408impl From<Baudrate> for u16 {
409    fn from(value: Baudrate) -> Self {
410        let ret = match value {
411            Baudrate::Baud1M => peak_can::PEAK_BAUD_1M,
412            Baudrate::Baud800K => peak_can::PEAK_BAUD_800K,
413            Baudrate::Baud500K => peak_can::PEAK_BAUD_500K,
414            Baudrate::Baud250K => peak_can::PEAK_BAUD_250K,
415            Baudrate::Baud125K => peak_can::PEAK_BAUD_125K,
416            Baudrate::Baud100K => peak_can::PEAK_BAUD_100K,
417            Baudrate::Baud95K => peak_can::PEAK_BAUD_95K,
418            Baudrate::Baud83K => peak_can::PEAK_BAUD_83K,
419            Baudrate::Baud50K => peak_can::PEAK_BAUD_50K,
420            Baudrate::Baud47K => peak_can::PEAK_BAUD_47K,
421            Baudrate::Baud33K => peak_can::PEAK_BAUD_33K,
422            Baudrate::Baud20K => peak_can::PEAK_BAUD_20K,
423            Baudrate::Baud10K => peak_can::PEAK_BAUD_10K,
424            Baudrate::Baud5K => peak_can::PEAK_BAUD_5K,
425        } as u16;
426        ret
427    }
428}
429
430/// Hardware-specific timing parameter boundaries for classical CAN 2.0 bit timing.
431///
432/// These boundaries define the valid ranges for CAN bit timing parameters and are
433/// hardware-specific to PEAK-System CAN devices. The values constrain the configuration
434/// of the CAN controller's bit timing to ensure it operates within hardware capabilities.
435///
436/// # Timing Parameters
437///
438/// - **prescaler**: Clock prescaler that divides the CAN controller's base clock
439/// - **sjw** (Synchronization Jump Width): Maximum time by which the bit sampling point
440///   can be shifted to resynchronize with the bus
441/// - **tseg1** (Time Segment 1): Duration before the sample point, includes propagation
442///   delay and phase segment 1
443/// - **tseg2** (Time Segment 2): Duration after the sample point (phase segment 2)
444///
445/// # Usage
446///
447/// These boundaries are used internally by [`CanBitTiming::new()`] to validate timing
448/// parameters. Users should reference [`CAN_TIMING_BOUNDARIES`] to ensure their custom
449/// timing configurations fall within acceptable ranges.
450/// ```
451pub struct TimingBoundaries {
452    pub prescaler_min: u16,
453    pub prescaler_max: u16,
454    pub sjw_min: u8,
455    pub sjw_max: u8,
456    pub tseg1_min: u8,
457    pub tseg1_max: u8,
458    pub tseg2_min: u8,
459    pub tseg2_max: u8,
460}
461
462/// Hardware-specific timing parameter boundaries for CAN FD bit timing.
463///
464/// These boundaries define the valid ranges for CAN FD bit timing parameters and are
465/// hardware-specific to PEAK-System CAN FD devices. CAN FD supports dual bit rates:
466/// a nominal (arbitration) bit rate and a faster data bit rate, each with their own
467/// timing parameters.
468///
469/// # Timing Parameters
470///
471/// ## Nominal (Arbitration) Phase
472/// Used during arbitration and control fields:
473/// - **nom_prescaler**: Nominal phase clock prescaler
474/// - **nom_sjw**: Nominal phase synchronization jump width
475/// - **nom_tseg1**: Nominal phase time segment 1
476/// - **nom_tseg2**: Nominal phase time segment 2
477///
478/// ## Data Phase
479/// Used during the data field for higher throughput:
480/// - **data_prescaler**: Data phase clock prescaler
481/// - **data_sjw**: Data phase synchronization jump width
482/// - **data_tseg1**: Data phase time segment 1
483/// - **data_tseg2**: Data phase time segment 2
484///
485/// # Usage
486///
487/// These boundaries are used internally by [`CanFdBitTiming::new()`] to validate timing
488/// parameters. Users should reference [`CANFD_TIMING_BOUNDARIES`] to ensure their custom
489/// CAN FD timing configurations fall within acceptable ranges for PEAK hardware.
490///
491/// # Note
492///
493/// The data phase bit rate must be equal to or higher than the nominal bit rate. Typical
494/// configurations use 500 kbit/s for nominal and 2-8 Mbit/s for data phases.
495pub struct FdTimingBoundaries {
496    pub nom_prescaler_min: u16,
497    pub nom_prescaler_max: u16,
498    pub nom_sjw_min: u8,
499    pub nom_sjw_max: u8,
500    pub nom_tseg1_min: u16,
501    pub nom_tseg1_max: u16,
502    pub nom_tseg2_min: u8,
503    pub nom_tseg2_max: u8,
504    pub data_prescaler_min: u16,
505    pub data_prescaler_max: u16,
506    pub data_sjw_min: u8,
507    pub data_sjw_max: u8,
508    pub data_tseg1_min: u8,
509    pub data_tseg1_max: u8,
510    pub data_tseg2_min: u8,
511    pub data_tseg2_max: u8,
512}
513
514/// Hardware timing parameter boundaries for PEAK-System classical CAN 2.0 devices.
515///
516/// This constant defines the valid ranges for bit timing parameters on PEAK CAN hardware.
517/// These limits are enforced when creating [`CanBitTiming`] instances to ensure
518/// configurations are compatible with the hardware.
519///
520/// # Values
521///
522/// - Prescaler: 1-64
523/// - SJW: 1-4
524/// - TSEG1: 1-16
525/// - TSEG2: 1-8
526///
527/// # See Also
528///
529/// - [`TimingBoundaries`] - Structure definition and detailed parameter descriptions
530/// - [`CanBitTiming::new()`] - Uses these boundaries for validation
531pub const CAN_TIMING_BOUNDARIES: TimingBoundaries = TimingBoundaries {
532    prescaler_min: 1,
533    prescaler_max: 64,
534    sjw_min: 1,
535    sjw_max: 4,
536    tseg1_min: 1,
537    tseg1_max: 16,
538    tseg2_min: 1,
539    tseg2_max: 8,
540};
541
542/// Hardware timing parameter boundaries for PEAK-System CAN FD devices.
543///
544/// This constant defines the valid ranges for CAN FD bit timing parameters on PEAK
545/// hardware. These limits are enforced when creating [`CanFdBitTiming`] instances to
546/// ensure configurations are compatible with the hardware's dual bit rate capabilities.
547///
548/// # Values
549///
550/// ## Nominal (Arbitration) Phase
551/// - Prescaler: 1-1024
552/// - SJW: 1-128
553/// - TSEG1: 1-256
554/// - TSEG2: 1-128
555///
556/// ## Data Phase
557/// - Prescaler: 1-1024
558/// - SJW: 1-16
559/// - TSEG1: 1-32
560/// - TSEG2: 1-16
561///
562/// # See Also
563///
564/// - [`FdTimingBoundaries`] - Structure definition and detailed parameter descriptions
565/// - [`CanFdBitTiming::new()`] - Uses these boundaries for validation
566pub const CANFD_TIMING_BOUNDARIES: FdTimingBoundaries = FdTimingBoundaries {
567    nom_prescaler_min: 1,
568    nom_prescaler_max: 1024,
569    nom_sjw_min: 1,
570    nom_sjw_max: 128,
571    nom_tseg1_min: 1,
572    nom_tseg1_max: 256,
573    nom_tseg2_min: 1,
574    nom_tseg2_max: 128,
575    data_prescaler_min: 1,
576    data_prescaler_max: 1024,
577    data_sjw_min: 1,
578    data_sjw_max: 16,
579    data_tseg1_min: 1,
580    data_tseg1_max: 32,
581    data_tseg2_min: 1,
582    data_tseg2_max: 16,
583};
584
585pub struct CanBitTiming {
586    pub prescaler: u16,
587    pub sjw: u8,
588    pub tseg1: u8,
589    pub tseg2: u8,
590}
591
592impl CanBitTiming {
593    pub fn new(prescaler: u16, sjw: u8, tseg1: u8, tseg2: u8) -> Result<Self, Box<dyn std::error::Error>> {
594        let timing = CanBitTiming {
595            prescaler,
596            sjw,
597            tseg1,
598            tseg2,
599        };
600
601        if Self::validate(&timing) {
602            Ok(timing)
603        } else {
604            Err("Timing parameters are out of bounds".into())
605        }
606    }
607
608    fn validate(timing: &CanBitTiming) -> bool {
609        if timing.prescaler < CAN_TIMING_BOUNDARIES.prescaler_min
610            || timing.prescaler > CAN_TIMING_BOUNDARIES.prescaler_max
611        {
612            return false;
613        }
614        if timing.sjw < CAN_TIMING_BOUNDARIES.sjw_min
615            || timing.sjw > CAN_TIMING_BOUNDARIES.sjw_max
616        {
617            return false;
618        }
619        if timing.tseg1 < CAN_TIMING_BOUNDARIES.tseg1_min
620            || timing.tseg1 > CAN_TIMING_BOUNDARIES.tseg1_max
621        {
622            return false;
623        }
624        if timing.tseg2 < CAN_TIMING_BOUNDARIES.tseg2_min
625            || timing.tseg2 > CAN_TIMING_BOUNDARIES.tseg2_max
626        {
627            return false;
628        }
629        true
630    }
631}
632
633pub struct CanFdBitTiming {
634    pub nom_prescaler: u16,
635    pub nom_sjw: u8,
636    pub nom_tseg1: u16,
637    pub nom_tseg2: u8,
638    pub data_prescaler: u16,
639    pub data_sjw: u8,
640    pub data_tseg1: u8,
641    pub data_tseg2: u8,
642}
643
644impl CanFdBitTiming {
645    pub fn new(nom_prescaler: u16, nom_sjw: u8, nom_tseg1: u16, nom_tseg2: u8, data_prescaler: u16, data_sjw: u8, data_tseg1: u8, data_tseg2: u8) -> Result<Self, Box<dyn std::error::Error>> {
646        let timing = CanFdBitTiming {
647            nom_prescaler,
648            nom_sjw,
649            nom_tseg1,
650            nom_tseg2,
651            data_prescaler,
652            data_sjw,
653            data_tseg1,
654            data_tseg2,
655        };
656
657        if Self::validate(&timing) {
658            Ok(timing)
659        } else {
660            Err("Timing parameters are out of bounds".into())
661        }
662    }
663
664    fn validate(timing: &CanFdBitTiming) -> bool {
665        if timing.nom_prescaler < CANFD_TIMING_BOUNDARIES.nom_prescaler_min
666            || timing.nom_prescaler > CANFD_TIMING_BOUNDARIES.nom_prescaler_max
667        {
668            return false;
669        }
670        if timing.nom_sjw < CANFD_TIMING_BOUNDARIES.nom_sjw_min
671            || timing.nom_sjw > CANFD_TIMING_BOUNDARIES.nom_sjw_max
672        {
673            return false;
674        }
675        if timing.nom_tseg1 < CANFD_TIMING_BOUNDARIES.nom_tseg1_min
676            || timing.nom_tseg1 > CANFD_TIMING_BOUNDARIES.nom_tseg1_max
677        {
678            return false;
679        }
680        if timing.nom_tseg2 < CANFD_TIMING_BOUNDARIES.nom_tseg2_min
681            || timing.nom_tseg2 > CANFD_TIMING_BOUNDARIES.nom_tseg2_max
682        {
683            return false;
684        }
685        if timing.data_prescaler < CANFD_TIMING_BOUNDARIES.data_prescaler_min
686            || timing.data_prescaler > CANFD_TIMING_BOUNDARIES.data_prescaler_max
687        {
688            return false;
689        }
690        if timing.data_sjw < CANFD_TIMING_BOUNDARIES.data_sjw_min
691            || timing.data_sjw > CANFD_TIMING_BOUNDARIES.data_sjw_max
692        {
693            return false;
694        }
695        if timing.data_tseg1 < CANFD_TIMING_BOUNDARIES.data_tseg1_min
696            || timing.data_tseg1 > CANFD_TIMING_BOUNDARIES.data_tseg1_max
697        {
698            return false;
699        }
700        if timing.data_tseg2 < CANFD_TIMING_BOUNDARIES.data_tseg2_min
701            || timing.data_tseg2 > CANFD_TIMING_BOUNDARIES.data_tseg2_max
702        {
703            return false;
704        }
705        true
706    }
707}
708
709/* CanRead trait implementation */
710
711impl<T: HasRecvCan + Socket> RecvCan for T {
712    fn recv(&self) -> Result<(CanFrame, Timestamp), CanError> {
713        let mut frame = CanFrame::default();
714        let mut timestamp = Timestamp::default();
715
716        let error_code = unsafe {
717            peak_lib()?.CAN_Read(
718                self.handle(),
719                &mut frame.frame as *mut peak_can::TPEAKMsg,
720                &mut timestamp.timestamp as *mut peak_can::TPEAKTimestamp,
721            )
722        };
723
724        match CanOkError::try_from(error_code) {
725            Ok(CanOkError::Ok) => Ok((frame, timestamp)),
726            Ok(CanOkError::Err(err)) => Err(err),
727            Err(_) => Err(CanError::Unknown),
728        }
729    }
730
731    fn recv_frame(&self) -> Result<CanFrame, CanError> {
732        let mut frame = CanFrame::default();
733
734        let error_code = unsafe {
735            peak_lib()?.CAN_Read(
736                self.handle(),
737                &mut frame.frame as *mut peak_can::TPEAKMsg,
738                0 as *mut peak_can::TPEAKTimestamp,
739            )
740        };
741
742        match CanOkError::try_from(error_code) {
743            Ok(CanOkError::Ok) => Ok(frame),
744            Ok(CanOkError::Err(err)) => Err(err),
745            Err(_) => Err(CanError::Unknown),
746        }
747    }
748}
749
750/* CanRecvFd trait implementation */
751
752impl<T: HasRecvCanFd + Socket> RecvCanFd for T {
753    fn recv_fd(&self) -> Result<(CanFdFrame, u64), CanError> {
754        let mut frame = CanFdFrame::default();
755        let mut timestamp = 0u64;
756
757        let error_code = unsafe {
758            peak_lib()?.CAN_ReadFD(
759                self.handle(),
760                &mut frame.frame as *mut peak_can::TPEAKMsgFD,
761                &mut timestamp as *mut u64,
762            )
763        };
764
765        match CanOkError::try_from(error_code) {
766            Ok(CanOkError::Ok) => Ok((frame, timestamp)),
767            Ok(CanOkError::Err(err)) => Err(err),
768            Err(_) => Err(CanError::Unknown),
769        }
770    }
771
772    fn recv_fd_frame(&self) -> Result<CanFdFrame, CanError> {
773        let mut frame = CanFdFrame::default();
774
775        let error_code = unsafe {
776            peak_lib()?.CAN_ReadFD(
777                self.handle(),
778                &mut frame.frame as *mut peak_can::TPEAKMsgFD,
779                0 as *mut u64,
780            )
781        };
782
783        match CanOkError::try_from(error_code) {
784            Ok(CanOkError::Ok) => Ok(frame),
785            Ok(CanOkError::Err(err)) => Err(err),
786            Err(_) => Err(CanError::Unknown),
787        }
788    }
789}
790
791/* CanSend trait implementations */
792
793impl<T: HasSendCan + Socket> SendCan for T {
794    fn send(&self, frame: CanFrame) -> Result<(), CanError> {
795        let mut frame = frame;
796        let error_code = unsafe {
797            peak_lib()?.CAN_Write(self.handle(), &mut frame.frame as *mut peak_can::TPEAKMsg)
798        };
799
800        match CanOkError::try_from(error_code) {
801            Ok(CanOkError::Ok) => Ok(()),
802            Ok(CanOkError::Err(err)) => Err(err),
803            Err(_) => Err(CanError::Unknown),
804        }
805    }
806}
807
808/* CanSendFd trait implementation */
809
810impl<T: HasSendCanFd + Socket> SendCanFd for T {
811    fn send_fd(&self, frame: CanFdFrame) -> Result<(), CanError> {
812        let mut frame = frame;
813        let error_code = unsafe {
814            peak_lib()?.CAN_WriteFD(self.handle(), &mut frame.frame as *mut peak_can::TPEAKMsgFD)
815        };
816
817        match CanOkError::try_from(error_code) {
818            Ok(CanOkError::Ok) => Ok(()),
819            Ok(CanOkError::Err(err)) => Err(err),
820            Err(_) => Err(CanError::Unknown),
821        }
822    }
823}
824
825#[cfg(test)]
826mod tests {
827    use super::*;
828
829    #[test]
830    fn can_frame_new_001() {
831        let can_frame_1 =
832            CanFrame::new(0x20, MessageType::Standard, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
833
834        let can_frame_2 =
835            CanFrame::new(0x20, MessageType::Standard, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
836
837        assert_eq!(can_frame_1, can_frame_2);
838    }
839
840    #[test]
841    fn can_frame_new_002() {
842        let can_frame_1 =
843            CanFrame::new(0x20, MessageType::Extended, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
844
845        let can_frame_2 =
846            CanFrame::new(0x20, MessageType::Extended, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
847
848        assert_eq!(can_frame_1, can_frame_2);
849    }
850
851    #[test]
852    #[should_panic]
853    fn can_frame_new_003() {
854        let _can_frame_1 =
855            CanFrame::new(0x20, MessageType::Standard, &[0, 1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
856    }
857
858    #[test]
859    #[should_panic]
860    fn can_frame_new_004() {
861        let _can_frame_1 =
862            CanFrame::new(0x20, MessageType::Extended, &[0, 1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
863    }
864
865    #[test]
866    fn can_frame_new_005() {
867        let extended_id = 0x1E_C5_7E_D0;
868        // Extended id bitwise and with standard mask
869        let standard_id = 0x06_D0;
870
871        let can_frame_1 = CanFrame::new(extended_id, MessageType::Standard, &[0, 1, 2]).unwrap();
872        assert_eq!(can_frame_1.can_id(), standard_id);
873
874        let can_frame_2 = CanFrame::new(extended_id, MessageType::Extended, &[0, 1, 2]).unwrap();
875        assert_eq!(can_frame_2.can_id(), extended_id);
876    }
877
878    #[test]
879    fn can_frame_new_006() {
880        let can_frame_1 = CanFrame::new(0x01_23, MessageType::Standard, &[0, 1, 2]).unwrap();
881        assert!(can_frame_1.is_standard_frame());
882
883        let can_frame_2 = CanFrame::new(0x1f_ff_00_ff, MessageType::Extended, &[0, 1, 2]).unwrap();
884        assert!(can_frame_2.is_extended_frame());
885    }
886
887    /* CAN FD FRAME */
888
889    #[test]
890    fn can_fd_frame_new_001() {
891        let can_frame_1 =
892            CanFdFrame::new(0x20, MessageType::Standard, &(0..64u8).collect::<Vec<_>>(), false, false).unwrap();
893
894        let can_frame_2 =
895            CanFdFrame::new(0x20, MessageType::Standard, &(0..64u8).collect::<Vec<_>>(), false, false).unwrap();
896
897        assert_eq!(can_frame_1, can_frame_2);
898    }
899
900    #[test]
901    fn can_fd_frame_new_002() {
902        let can_frame_1 =
903            CanFdFrame::new(0x20, MessageType::Extended, &(0..64u8).collect::<Vec<_>>(), false, false).unwrap();
904
905        let can_frame_2 =
906            CanFdFrame::new(0x20, MessageType::Extended, &(0..64u8).collect::<Vec<_>>(), false, false).unwrap();
907
908        assert_eq!(can_frame_1, can_frame_2);
909    }
910
911    #[test]
912    #[should_panic]
913    fn can_fd_frame_new_003() {
914        let _can_frame_1 =
915            CanFdFrame::new(0x20, MessageType::Standard, &(0..65u8).collect::<Vec<_>>(), false, false).unwrap();
916    }
917
918    #[test]
919    #[should_panic]
920    fn can_fd_frame_new_004() {
921        let _can_frame_1 =
922            CanFdFrame::new(0x20, MessageType::Extended, &(0..65u8).collect::<Vec<_>>(), false, false).unwrap();
923    }
924
925    #[test]
926    fn can_fd_frame_new_005() {
927        let extended_id = 0x1E_C5_7E_D0;
928        // Extended id bitwise and with standard mask
929        let standard_id = 0x06_D0;
930
931        let can_frame_1 = CanFdFrame::new(
932            extended_id,
933            MessageType::Standard,
934            &(0..64u8).collect::<Vec<_>>(),
935            false,
936            false,
937        )
938        .unwrap();
939        assert_eq!(can_frame_1.can_id(), standard_id);
940
941        let can_frame_2 = CanFdFrame::new(
942            extended_id,
943            MessageType::Extended,
944            &(0..64u8).collect::<Vec<_>>(),
945            false,
946            false,
947        )
948        .unwrap();
949
950        assert_eq!(can_frame_2.can_id(), extended_id);
951    }
952
953    /* calc_dlc TESTS */
954
955    #[test]
956    fn calc_dlc_encoding() {
957        // Test all critical boundary points for CAN FD DLC encoding
958        let test_cases = vec![
959            (0, 0), (1, 1), (8, 8),           // 0-8: DLC equals length
960            (9, 9), (12, 9),                   // 9-12: DLC 9
961            (13, 10), (16, 10),                // 13-16: DLC 10
962            (17, 11), (20, 11),                // 17-20: DLC 11
963            (21, 12), (24, 12),                // 21-24: DLC 12
964            (25, 13), (32, 13),                // 25-32: DLC 13
965            (33, 14), (48, 14),                // 33-48: DLC 14
966            (49, 15), (64, 15),                // 49-64: DLC 15
967            (65, 15), (100, 15),               // >64: DLC 15 (max)
968        ];
969
970        for (len, expected_dlc) in test_cases {
971            assert_eq!(CanFdFrame::calc_dlc(len), expected_dlc, "Failed for length {}", len);
972        }
973    }
974
975    /* len (DLC to data length) TESTS */
976
977    #[test]
978    fn len_decoding() {
979        // Test all valid DLC values decode to correct data lengths
980        let test_cases = vec![
981            (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8),
982            (12, 12), (16, 16), (20, 20), (24, 24), (32, 32), (48, 48), (64, 64),
983        ];
984
985        for (data_len, expected_len) in test_cases {
986            let data = vec![0u8; data_len];
987            let frame = CanFdFrame::new(0x123, MessageType::Standard, &data, false, false).unwrap();
988            assert_eq!(frame.len(), expected_len, "Failed for data length {}", data_len);
989        }
990    }
991
992    #[test]
993    fn len_calc_dlc_inverse() {
994        // Verify len and calc_dlc are proper inverses, and non-standard lengths round up
995        let test_cases = vec![
996            (0, 0), (8, 8),                    // Standard 0-8
997            (9, 12), (12, 12),                 // 9-12 rounds to 12
998            (13, 16), (16, 16),                // 13-16 rounds to 16
999            (20, 20), (24, 24),                // Standard boundaries
1000            (25, 32), (32, 32),                // 25-32 rounds to 32
1001            (40, 48), (48, 48),                // 33-48 rounds to 48
1002            (50, 64), (64, 64),                // 49-64 rounds to 64
1003        ];
1004
1005        for (input_len, expected_frame_len) in test_cases {
1006            let data = vec![0u8; input_len];
1007            let frame = CanFdFrame::new(0x123, MessageType::Standard, &data, false, false).unwrap();
1008            assert_eq!(frame.len(), expected_frame_len, "Failed for input length {}", input_len);
1009        }
1010    }
1011
1012    /* CanBitTiming TESTS */
1013
1014    #[test]
1015    fn can_bit_timing_valid_parameters() {
1016        // Test valid parameters within bounds are accepted
1017        let test_cases = vec![
1018            (1, 1, 1, 1),      // All minimum values
1019            (64, 4, 16, 8),    // All maximum values
1020            (8, 1, 13, 2),     // Common 500 kbit/s configuration
1021            (32, 2, 8, 4),     // Mid-range values
1022        ];
1023
1024        for (prescaler, sjw, tseg1, tseg2) in test_cases {
1025            let result = CanBitTiming::new(prescaler, sjw, tseg1, tseg2);
1026            assert!(result.is_ok(), "Should accept valid parameters: prescaler={}, sjw={}, tseg1={}, tseg2={}", 
1027                    prescaler, sjw, tseg1, tseg2);
1028            
1029            let timing = result.unwrap();
1030            assert_eq!(timing.prescaler, prescaler);
1031            assert_eq!(timing.sjw, sjw);
1032            assert_eq!(timing.tseg1, tseg1);
1033            assert_eq!(timing.tseg2, tseg2);
1034        }
1035    }
1036
1037    #[test]
1038    fn can_bit_timing_invalid_prescaler() {
1039        // Test prescaler out of bounds (valid: 1-64)
1040        assert!(CanBitTiming::new(0, 1, 1, 1).is_err(), "Should reject prescaler=0");
1041        assert!(CanBitTiming::new(65, 1, 1, 1).is_err(), "Should reject prescaler=65");
1042        assert!(CanBitTiming::new(100, 1, 1, 1).is_err(), "Should reject prescaler=100");
1043    }
1044
1045    #[test]
1046    fn can_bit_timing_invalid_sjw() {
1047        // Test SJW out of bounds (valid: 1-4)
1048        assert!(CanBitTiming::new(8, 0, 1, 1).is_err(), "Should reject sjw=0");
1049        assert!(CanBitTiming::new(8, 5, 1, 1).is_err(), "Should reject sjw=5");
1050        assert!(CanBitTiming::new(8, 10, 1, 1).is_err(), "Should reject sjw=10");
1051    }
1052
1053    #[test]
1054    fn can_bit_timing_invalid_tseg1() {
1055        // Test TSEG1 out of bounds (valid: 1-16)
1056        assert!(CanBitTiming::new(8, 1, 0, 1).is_err(), "Should reject tseg1=0");
1057        assert!(CanBitTiming::new(8, 1, 17, 1).is_err(), "Should reject tseg1=17");
1058        assert!(CanBitTiming::new(8, 1, 20, 1).is_err(), "Should reject tseg1=20");
1059    }
1060
1061    #[test]
1062    fn can_bit_timing_invalid_tseg2() {
1063        // Test TSEG2 out of bounds (valid: 1-8)
1064        assert!(CanBitTiming::new(8, 1, 1, 0).is_err(), "Should reject tseg2=0");
1065        assert!(CanBitTiming::new(8, 1, 1, 9).is_err(), "Should reject tseg2=9");
1066        assert!(CanBitTiming::new(8, 1, 1, 15).is_err(), "Should reject tseg2=15");
1067    }
1068
1069    #[test]
1070    fn can_bit_timing_boundary_values() {
1071        // Test exact boundary values are accepted
1072        assert!(CanBitTiming::new(1, 1, 1, 1).is_ok(), "Should accept all minimum boundaries");
1073        assert!(CanBitTiming::new(64, 4, 16, 8).is_ok(), "Should accept all maximum boundaries");
1074        
1075        // Test just outside boundaries are rejected
1076        assert!(CanBitTiming::new(0, 1, 1, 1).is_err());
1077        assert!(CanBitTiming::new(65, 1, 1, 1).is_err());
1078        assert!(CanBitTiming::new(1, 0, 1, 1).is_err());
1079        assert!(CanBitTiming::new(1, 5, 1, 1).is_err());
1080        assert!(CanBitTiming::new(1, 1, 0, 1).is_err());
1081        assert!(CanBitTiming::new(1, 1, 17, 1).is_err());
1082        assert!(CanBitTiming::new(1, 1, 1, 0).is_err());
1083        assert!(CanBitTiming::new(1, 1, 1, 9).is_err());
1084    }
1085
1086    /* CanFdBitTiming TESTS */
1087
1088    #[test]
1089    fn can_fd_bit_timing_valid_parameters() {
1090        // Test valid parameters within bounds are accepted
1091        let test_cases = vec![
1092            // (nom_prescaler, nom_sjw, nom_tseg1, nom_tseg2, data_prescaler, data_sjw, data_tseg1, data_tseg2)
1093            (1, 1, 1, 1, 1, 1, 1, 1),          // All minimum values
1094            (1024, 128, 256, 128, 1024, 16, 32, 16), // All maximum values
1095            (2, 10, 127, 32, 2, 5, 25, 8),     // Common 500k/2M configuration
1096            (500, 50, 100, 50, 100, 8, 16, 8), // Mid-range values
1097        ];
1098
1099        for (np, ns, nt1, nt2, dp, ds, dt1, dt2) in test_cases {
1100            let result = CanFdBitTiming::new(np, ns, nt1, nt2, dp, ds, dt1, dt2);
1101            assert!(result.is_ok(), "Should accept valid parameters: nom({},{},{},{}), data({},{},{},{})", 
1102                    np, ns, nt1, nt2, dp, ds, dt1, dt2);
1103            
1104            let timing = result.unwrap();
1105            assert_eq!(timing.nom_prescaler, np);
1106            assert_eq!(timing.nom_sjw, ns);
1107            assert_eq!(timing.nom_tseg1, nt1);
1108            assert_eq!(timing.nom_tseg2, nt2);
1109            assert_eq!(timing.data_prescaler, dp);
1110            assert_eq!(timing.data_sjw, ds);
1111            assert_eq!(timing.data_tseg1, dt1);
1112            assert_eq!(timing.data_tseg2, dt2);
1113        }
1114    }
1115
1116    #[test]
1117    fn can_fd_bit_timing_invalid_nom_prescaler() {
1118        // Nominal prescaler out of bounds (valid: 1-1024)
1119        assert!(CanFdBitTiming::new(0, 1, 1, 1, 1, 1, 1, 1).is_err(), "Should reject nom_prescaler=0");
1120        assert!(CanFdBitTiming::new(1025, 1, 1, 1, 1, 1, 1, 1).is_err(), "Should reject nom_prescaler=1025");
1121        assert!(CanFdBitTiming::new(2000, 1, 1, 1, 1, 1, 1, 1).is_err(), "Should reject nom_prescaler=2000");
1122    }
1123
1124    #[test]
1125    fn can_fd_bit_timing_invalid_nom_sjw() {
1126        // Nominal SJW out of bounds (valid: 1-128)
1127        assert!(CanFdBitTiming::new(1, 0, 1, 1, 1, 1, 1, 1).is_err(), "Should reject nom_sjw=0");
1128        assert!(CanFdBitTiming::new(1, 129, 1, 1, 1, 1, 1, 1).is_err(), "Should reject nom_sjw=129");
1129        assert!(CanFdBitTiming::new(1, 200, 1, 1, 1, 1, 1, 1).is_err(), "Should reject nom_sjw=200");
1130    }
1131
1132    #[test]
1133    fn can_fd_bit_timing_invalid_nom_tseg1() {
1134        // Nominal TSEG1 out of bounds (valid: 1-256)
1135        assert!(CanFdBitTiming::new(1, 1, 0, 1, 1, 1, 1, 1).is_err(), "Should reject nom_tseg1=0");
1136        assert!(CanFdBitTiming::new(1, 1, 257, 1, 1, 1, 1, 1).is_err(), "Should reject nom_tseg1=257");
1137        assert!(CanFdBitTiming::new(1, 1, 300, 1, 1, 1, 1, 1).is_err(), "Should reject nom_tseg1=300");
1138    }
1139
1140    #[test]
1141    fn can_fd_bit_timing_invalid_nom_tseg2() {
1142        // Nominal TSEG2 out of bounds (valid: 1-128)
1143        assert!(CanFdBitTiming::new(1, 1, 1, 0, 1, 1, 1, 1).is_err(), "Should reject nom_tseg2=0");
1144        assert!(CanFdBitTiming::new(1, 1, 1, 129, 1, 1, 1, 1).is_err(), "Should reject nom_tseg2=129");
1145        assert!(CanFdBitTiming::new(1, 1, 1, 200, 1, 1, 1, 1).is_err(), "Should reject nom_tseg2=200");
1146    }
1147
1148    #[test]
1149    fn can_fd_bit_timing_invalid_data_prescaler() {
1150        // Data prescaler out of bounds (valid: 1-1024)
1151        assert!(CanFdBitTiming::new(1, 1, 1, 1, 0, 1, 1, 1).is_err(), "Should reject data_prescaler=0");
1152        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1025, 1, 1, 1).is_err(), "Should reject data_prescaler=1025");
1153        assert!(CanFdBitTiming::new(1, 1, 1, 1, 2000, 1, 1, 1).is_err(), "Should reject data_prescaler=2000");
1154    }
1155
1156    #[test]
1157    fn can_fd_bit_timing_invalid_data_sjw() {
1158        // Data SJW out of bounds (valid: 1-16)
1159        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 0, 1, 1).is_err(), "Should reject data_sjw=0");
1160        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 17, 1, 1).is_err(), "Should reject data_sjw=17");
1161        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 50, 1, 1).is_err(), "Should reject data_sjw=50");
1162    }
1163
1164    #[test]
1165    fn can_fd_bit_timing_invalid_data_tseg1() {
1166        // Data TSEG1 out of bounds (valid: 1-32)
1167        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 0, 1).is_err(), "Should reject data_tseg1=0");
1168        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 33, 1).is_err(), "Should reject data_tseg1=33");
1169        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 50, 1).is_err(), "Should reject data_tseg1=50");
1170    }
1171
1172    #[test]
1173    fn can_fd_bit_timing_invalid_data_tseg2() {
1174        // Data TSEG2 out of bounds (valid: 1-16)
1175        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 1, 0).is_err(), "Should reject data_tseg2=0");
1176        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 1, 17).is_err(), "Should reject data_tseg2=17");
1177        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 1, 50).is_err(), "Should reject data_tseg2=50");
1178    }
1179
1180    #[test]
1181    fn can_fd_bit_timing_boundary_values() {
1182        // Test exact boundary values are accepted
1183        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 1, 1).is_ok(), 
1184                "Should accept all minimum boundaries");
1185        assert!(CanFdBitTiming::new(1024, 128, 256, 128, 1024, 16, 32, 16).is_ok(), 
1186                "Should accept all maximum boundaries");
1187        
1188        // Test just outside nominal boundaries are rejected
1189        assert!(CanFdBitTiming::new(0, 1, 1, 1, 1, 1, 1, 1).is_err());
1190        assert!(CanFdBitTiming::new(1025, 1, 1, 1, 1, 1, 1, 1).is_err());
1191        assert!(CanFdBitTiming::new(1, 0, 1, 1, 1, 1, 1, 1).is_err());
1192        assert!(CanFdBitTiming::new(1, 129, 1, 1, 1, 1, 1, 1).is_err());
1193        assert!(CanFdBitTiming::new(1, 1, 0, 1, 1, 1, 1, 1).is_err());
1194        assert!(CanFdBitTiming::new(1, 1, 257, 1, 1, 1, 1, 1).is_err());
1195        assert!(CanFdBitTiming::new(1, 1, 1, 0, 1, 1, 1, 1).is_err());
1196        assert!(CanFdBitTiming::new(1, 1, 1, 129, 1, 1, 1, 1).is_err());
1197        
1198        // Test just outside data boundaries are rejected
1199        assert!(CanFdBitTiming::new(1, 1, 1, 1, 0, 1, 1, 1).is_err());
1200        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1025, 1, 1, 1).is_err());
1201        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 0, 1, 1).is_err());
1202        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 17, 1, 1).is_err());
1203        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 0, 1).is_err());
1204        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 33, 1).is_err());
1205        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 1, 0).is_err());
1206        assert!(CanFdBitTiming::new(1, 1, 1, 1, 1, 1, 1, 17).is_err());
1207    }
1208}