can_socket/
filter.rs

1use crate::{sys, StandardId, ExtendedId, CanFrame, CanId};
2
3/// A CAN filter.
4///
5/// Can be used to have the kernel filter incoming frames before they are delivered to userspace,
6/// to avoid unnecessarily waking up just to ignore a frame.
7#[repr(transparent)]
8#[derive(Copy, Clone)]
9pub struct CanFilter {
10	filter: crate::sys::CanFilter,
11}
12
13impl CanFilter {
14	/// Create a new pass-all CAN filter with a standard or extended ID.
15	///
16	/// The mask is still set to zero when the filter is created.
17	/// You have to call additional methods to restrict what frames match filter.
18	#[inline]
19	pub const fn new(id: CanId) -> Self {
20		match id {
21			CanId::Standard(id) => Self::new_standard(id),
22			CanId::Extended(id) => Self::new_extended(id),
23		}
24	}
25
26	/// Create a new pass-all CAN filter with a standard ID.
27	///
28	/// The mask is still set to zero when the filter is created.
29	/// You have to call additional methods to restrict what frames match filter.
30	#[inline]
31	pub const fn new_standard(id: StandardId) -> Self {
32		Self {
33			filter: sys::CanFilter::new_standard(id),
34		}
35	}
36
37	/// Create a new pass-all CAN filter with an extended ID.
38	///
39	/// The mask is still set to zero when the filter is created.
40	/// You have to call additional methods to restrict what frames match filter.
41	#[inline]
42	pub const fn new_extended(id: ExtendedId) -> Self {
43		Self {
44			filter: sys::CanFilter::new_extended(id),
45		}
46	}
47
48	/// Restrict the filter to match only frames with the same numerical ID.
49	///
50	/// The filter will still accept extended and standard frames (if the numerical value is possible for standard frames).
51	///
52	/// Adds to any restrictions already applied to the filter.
53	#[inline]
54	#[must_use = "returns a new filter, does not modify the existing filter"]
55	pub const fn match_id_value(mut self) -> Self {
56		self.filter = self.filter.match_id_value();
57		self
58	}
59
60	/// Restrict the filter to match only frames where `frame.id & mask == filter.id & mask`.
61	///
62	/// Only the lower 29 bits of the mask are used.
63	#[inline]
64	#[must_use = "returns a new filter, does not modify the existing filter"]
65	pub const fn match_id_mask(mut self, mask: u32) -> Self {
66		self.filter = self.filter.match_id_mask(mask);
67		self
68	}
69
70	/// Restrict the filter to match only extended IDs or standard IDs (depending on the ID the filter was constructed with).
71	///
72	/// Adds to any restrictions already applied to the filter.
73	#[inline]
74	#[must_use = "returns a new filter, does not modify the existing filter"]
75	pub const fn match_frame_format(mut self) -> Self {
76		self.filter = self.filter.match_frame_format();
77		self
78	}
79
80	/// Restrict the filter to match only on exact ID matches.
81	///
82	/// This means the ID must match exactly, including the fact if it was an extended or standard ID.
83	///
84	/// This is equivalent to:
85	/// ```
86	/// # use can_socket::CanFilter;
87	/// # fn foo(filter: CanFilter) -> CanFilter {
88	/// filter.match_id_value().match_frame_format()
89	/// # }
90	/// ```
91	///
92	/// Adds to any restrictions already applied to the filter.
93	#[inline]
94	#[must_use = "returns a new filter, does not modify the existing filter"]
95	pub const fn match_exact_id(mut self) -> Self {
96		self.filter = self.filter.match_exact_id();
97		self
98	}
99
100	/// Restrict the filter to match only RTR frames.
101	#[inline]
102	#[must_use = "returns a new filter, does not modify the existing filter"]
103	pub const fn match_rtr_only(mut self) -> Self {
104		self.filter = self.filter.match_rtr_only();
105		self
106	}
107
108	/// Restrict the filter to match only data frames.
109	///
110	/// Overrides any previous calls to `Self::match_rtr_only()`.
111	#[inline]
112	#[must_use = "returns a new filter, does not modify the existing filter"]
113	pub const fn match_data_only(mut self) -> Self {
114		self.filter = self.filter.match_data_only();
115		self
116	}
117
118	/// Make the filter inverted or non-inverted.
119	///
120	/// When inverted, only frame that normally would not match the filter will match the filter.
121	#[inline]
122	#[must_use = "returns a new filter, does not modify the existing filter"]
123	pub const fn inverted(mut self, inverted: bool) -> Self {
124		self.filter = self.filter.inverted(inverted);
125		self
126	}
127
128	/// Check if the filter is inverted.
129	///
130	/// When inverted, only frame that normally would not match the filter will match the filter.
131	#[inline]
132	#[must_use = "returns a new filter, does not modify the existing filter"]
133	pub const fn is_inverted(self) -> bool {
134		self.filter.is_inverted()
135	}
136
137	/// Test if a frame matches the filter.
138	#[inline]
139	pub const fn test(&self, frame: &CanFrame) -> bool {
140		self.filter.test(&frame.inner)
141	}
142}
143
144impl std::fmt::Debug for CanFilter {
145	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146		f.debug_struct("CanFilter")
147			.field("id", &format_args!("{:02X}", self.filter.id()))
148			.field("mask", &format_args!("{:02X}", self.filter.id_mask()))
149			.field("extended_frames", &self.filter.matches_extended_frames())
150			.field("standard_frames", &self.filter.matches_standard_frames())
151			.field("data_frames", &self.filter.matches_data_frames())
152			.field("rtr_frames", &self.filter.matches_rtr_frames())
153			.field("inverted", &self.filter.is_inverted())
154			.finish()
155	}
156}