1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
use crate;
use ;
/// Mask component of a filter.
;
/// An identifier filter.
///
/// Often times when communicating on a bus with many devices, it can be useful to filter which
/// messages are captured and which are ignored. This can dramatically speed up processing times
/// and reduce the overhead of having to receive and then discard every single message transmitted
/// on the bus.
///
/// A [`Filter`] takes an identifier and a mask, which when used together and applied to an incoming
/// message's identifier, is used to decide if that message should be discarded or not, using the
/// following logic:
///
/// <message identifier> & mask == <filter identifier> & mask
///
/// ## Usage
///
/// For example, the caller maybe interested in responses from a single standard identifier, 0x246.
/// We'll assume that they don't care whether it's a standard identifier or extended. Internally, a
/// filter for this would have an identifier value of 0x246 and a mask of 0x1FFFFFFF. Let's apply
/// this filter to a few theoretical message identifiers:
///
/// - 0x132 & 0x1FFFFFFF (0x132) does not match 0x246 & 0x1FFFFFFF (0x246), so we discard this
/// message
/// - 0x80000246 & 0x1FFFFFFF (0x246) does match 0x246 & 0x1FFFFFFF (0x246), so we keep the message
///
/// We can tweak this example further, as well. Maybe we know that we only specifically care about
/// the standard identifier 0x246, and not the extended version of it. If we change our mask to
/// 0xFFFFFFFF, and recheck the previous message, we get the following result:
///
/// - 0x80000246 & 0xFFFFFFFF (0x80000246) does not match 0x246 & 0xFFFFFFFF (0x246), so we discard
/// the message
///
/// As another example, we may want to sometimes only pay attention to a few specific bytes in the
/// identifier. This is common when filtering certain ranges of addresses, like those used for
/// legislated OBD devices, as they're contiguously and we can capture multiple identifiers with one
/// filter, like so:
///
/// - we want to filter addresses 0x7E8 to 0x7EF (0b11111101000 to 0b11111101111, respectively)
/// - thus, we know that everything between them, inclusive, is something we care about
/// - we take the "none" mask -- 0xFFFFFFFF -- as our base mask, to ensure we don't accidentally
/// match extended identifiers
/// - we take the difference between the higher address and lower address (0x7EF - 0x7E8 == 0x7) and
/// subtract it from our base mask, which gives us a mask of 0xFFFFFFFF - 0x7, or 0xFFFFFFF8
/// - we use the lower address as our identifier
///
/// Let's apply this mask to some more theoretical message identifiers:
///
/// - 0x7E8 & 0xFFFFFFF8 (0x7E8) does match 0x7E8 & 0xFFFFFFF8 (0x7E8), so we keep this message
/// - 0x7EF & 0xFFFFFFF8 (0x7E8) does match 0x7E8 & 0xFFFFFFF8 (0x7E8), so we keep the message
/// - 0x7F0 & 0xFFFFFFF8 (0x7F0) does not match 0x7E8 & 0xFFFFFFF8 (0x7E0), so we discard this
/// message
/// - 0x800007E8 & 0xFFFFFFF8 (0x800007E8) does not match 0x7E8 & 0xFFFFFFF8 (0x7E8), so we discard
/// the message
///
/// ## Caveats
///
/// Internally, [`Filter`] uses a format that maps to the identifier format used by
/// [SocketCAN][socketcan], where both the identifier (the logical address itself) and the
/// identifier flags (error frame, remote frame, etc) are encoded into a single 32-bit unsigned
/// integer.
///
/// While the identifier type ([`Id`]) encodes these flags directly, [`Mask`] allows more direct
/// control. Despite this, it is often best to utilize the flags-based helper methods for defining
/// masks. These make it easier to construct filters based on functional need: match a single
/// identifier, match error frames only, etc.
///
/// [socketcan]: https://www.kernel.org/doc/Documentation/networking/can.txt