1use embedded_can::ExtendedId;
4use embedded_can_interface::Id;
5
6use crate::config::IsoTpConfig;
7use crate::errors::IsoTpError;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum TargetAddressType {
12 Physical,
14 Functional,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct TxAddress {
21 pub id: Id,
23 pub addr: Option<u8>,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct RxAddress {
32 pub id: Id,
34 pub addr: Option<u8>,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub struct AsymmetricAddress {
43 pub tx: TxAddress,
45 pub rx: RxAddress,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub struct IsoTpAddress {
55 pub tx_id: Id,
57 pub rx_id: Id,
59 pub tx_addr: Option<u8>,
61 pub rx_addr: Option<u8>,
63}
64
65fn ext_id(raw: u32) -> Result<Id, IsoTpError<()>> {
66 ExtendedId::new(raw)
67 .map(Id::Extended)
68 .ok_or(IsoTpError::InvalidConfig)
69}
70
71fn fixed_base(target_type: TargetAddressType, physical_base: u32, functional_base: u32) -> u32 {
72 match target_type {
73 TargetAddressType::Physical => physical_base,
74 TargetAddressType::Functional => functional_base,
75 }
76}
77
78impl TxAddress {
79 pub fn normal(id: Id) -> Self {
81 Self { id, addr: None }
82 }
83
84 pub fn extended(id: Id, target_address: u8) -> Self {
86 Self {
87 id,
88 addr: Some(target_address),
89 }
90 }
91
92 pub fn mixed_11(id: Id, address_extension: u8) -> Self {
94 Self {
95 id,
96 addr: Some(address_extension),
97 }
98 }
99
100 pub fn normal_fixed_29(
104 source_address: u8,
105 target_address: u8,
106 target_type: TargetAddressType,
107 ) -> Result<Self, IsoTpError<()>> {
108 let base = fixed_base(target_type, 0x18DA0000, 0x18DB0000);
109 let raw = base | ((target_address as u32) << 8) | source_address as u32;
110 Ok(Self {
111 id: ext_id(raw)?,
112 addr: None,
113 })
114 }
115
116 pub fn mixed_29(
118 source_address: u8,
119 target_address: u8,
120 address_extension: u8,
121 target_type: TargetAddressType,
122 ) -> Result<Self, IsoTpError<()>> {
123 let base = fixed_base(target_type, 0x18CE0000, 0x18CD0000);
124 let raw = base | ((target_address as u32) << 8) | source_address as u32;
125 Ok(Self {
126 id: ext_id(raw)?,
127 addr: Some(address_extension),
128 })
129 }
130}
131
132impl RxAddress {
133 pub fn normal(id: Id) -> Self {
135 Self { id, addr: None }
136 }
137
138 pub fn extended(id: Id, source_address: u8) -> Self {
140 Self {
141 id,
142 addr: Some(source_address),
143 }
144 }
145
146 pub fn mixed_11(id: Id, address_extension: u8) -> Self {
148 Self {
149 id,
150 addr: Some(address_extension),
151 }
152 }
153
154 pub fn normal_fixed_29(
158 source_address: u8,
159 target_address: u8,
160 target_type: TargetAddressType,
161 ) -> Result<Self, IsoTpError<()>> {
162 let base = fixed_base(target_type, 0x18DA0000, 0x18DB0000);
163 let raw = base | ((source_address as u32) << 8) | target_address as u32;
164 Ok(Self {
165 id: ext_id(raw)?,
166 addr: None,
167 })
168 }
169
170 pub fn mixed_29(
172 source_address: u8,
173 target_address: u8,
174 address_extension: u8,
175 target_type: TargetAddressType,
176 ) -> Result<Self, IsoTpError<()>> {
177 let base = fixed_base(target_type, 0x18CE0000, 0x18CD0000);
178 let raw = base | ((source_address as u32) << 8) | target_address as u32;
179 Ok(Self {
180 id: ext_id(raw)?,
181 addr: Some(address_extension),
182 })
183 }
184}
185
186impl AsymmetricAddress {
187 pub fn new(tx: TxAddress, rx: RxAddress) -> Self {
189 Self { tx, rx }
190 }
191}
192
193impl From<AsymmetricAddress> for IsoTpAddress {
194 fn from(value: AsymmetricAddress) -> Self {
195 Self {
196 tx_id: value.tx.id,
197 rx_id: value.rx.id,
198 tx_addr: value.tx.addr,
199 rx_addr: value.rx.addr,
200 }
201 }
202}
203
204impl IsoTpAddress {
205 pub fn normal(tx_id: Id, rx_id: Id) -> Self {
207 Self {
208 tx_id,
209 rx_id,
210 tx_addr: None,
211 rx_addr: None,
212 }
213 }
214
215 pub fn extended(tx_id: Id, rx_id: Id, source_address: u8, target_address: u8) -> Self {
217 Self {
218 tx_id,
219 rx_id,
220 tx_addr: Some(target_address),
221 rx_addr: Some(source_address),
222 }
223 }
224
225 pub fn mixed_11(tx_id: Id, rx_id: Id, address_extension: u8) -> Self {
227 Self {
228 tx_id,
229 rx_id,
230 tx_addr: Some(address_extension),
231 rx_addr: Some(address_extension),
232 }
233 }
234
235 pub fn normal_fixed_29(
237 source_address: u8,
238 target_address: u8,
239 target_type: TargetAddressType,
240 ) -> Result<Self, IsoTpError<()>> {
241 Ok(Self::from(AsymmetricAddress::new(
242 TxAddress::normal_fixed_29(source_address, target_address, target_type)?,
243 RxAddress::normal_fixed_29(source_address, target_address, target_type)?,
244 )))
245 }
246
247 pub fn mixed_29(
249 source_address: u8,
250 target_address: u8,
251 address_extension: u8,
252 target_type: TargetAddressType,
253 ) -> Result<Self, IsoTpError<()>> {
254 Ok(Self::from(AsymmetricAddress::new(
255 TxAddress::mixed_29(
256 source_address,
257 target_address,
258 address_extension,
259 target_type,
260 )?,
261 RxAddress::mixed_29(
262 source_address,
263 target_address,
264 address_extension,
265 target_type,
266 )?,
267 )))
268 }
269}
270
271impl From<IsoTpAddress> for IsoTpConfig {
272 fn from(value: IsoTpAddress) -> Self {
273 Self {
274 tx_id: value.tx_id,
275 rx_id: value.rx_id,
276 tx_addr: value.tx_addr,
277 rx_addr: value.rx_addr,
278 ..IsoTpConfig::default()
279 }
280 }
281}