peak_can/
hw.rs

1//!
2//!
3//!
4
5use crate::channel::Channel;
6use crate::error::{CanError, CanOkError};
7use crate::peak_lib;
8use crate::peak_can;
9use std::ffi::c_void;
10use std::mem::size_of;
11use std::net::Ipv4Addr;
12use std::os::raw::c_char;
13
14#[derive(Debug, PartialEq)]
15pub enum ChannelConditionStatus {
16    Unavailable,
17    Available,
18    Occupied,
19    CanView,
20}
21
22impl From<ChannelConditionStatus> for u32 {
23    fn from(value: ChannelConditionStatus) -> Self {
24        match value {
25            ChannelConditionStatus::Unavailable => peak_can::PEAK_CHANNEL_UNAVAILABLE,
26            ChannelConditionStatus::Available => peak_can::PEAK_CHANNEL_AVAILABLE,
27            ChannelConditionStatus::Occupied => peak_can::PEAK_CHANNEL_OCCUPIED,
28            ChannelConditionStatus::CanView => peak_can::PEAK_CHANNEL_PEAKVIEW,
29        }
30    }
31}
32
33impl TryFrom<u32> for ChannelConditionStatus {
34    type Error = ();
35
36    fn try_from(value: u32) -> Result<Self, Self::Error> {
37        match value {
38            peak_can::PEAK_CHANNEL_AVAILABLE => Ok(ChannelConditionStatus::Available),
39            peak_can::PEAK_CHANNEL_UNAVAILABLE => Ok(ChannelConditionStatus::Unavailable),
40            peak_can::PEAK_CHANNEL_OCCUPIED => Ok(ChannelConditionStatus::Occupied),
41            peak_can::PEAK_CHANNEL_PEAKVIEW => Ok(ChannelConditionStatus::CanView),
42            _ => Err(()),
43        }
44    }
45}
46
47/* ChannelCondition trait */
48
49pub(crate) trait HasChannelCondition {}
50
51pub trait ChannelCondition {
52    fn channel_condition(&self) -> Result<ChannelConditionStatus, CanError>;
53}
54
55impl<T: HasChannelCondition + Channel> ChannelCondition for T {
56    fn channel_condition(&self) -> Result<ChannelConditionStatus, CanError> {
57        let mut data = [0u8; 4];
58        let code = unsafe {
59            peak_lib()?.CAN_GetValue(
60                self.channel(),
61                peak_can::PEAK_CHANNEL_CONDITION as u8,
62                data.as_mut_ptr() as *mut c_void,
63                4,
64            )
65        };
66
67        let value: u32 = u32::from_le_bytes(data);
68        match CanOkError::try_from(code) {
69            Ok(CanOkError::Ok) => match ChannelConditionStatus::try_from(value) {
70                Ok(status) => Ok(status),
71                Err(_) => Err(CanError::Unknown),
72            },
73            Ok(CanOkError::Err(err)) => Err(err),
74            Err(_) => Err(CanError::Unknown),
75        }
76    }
77}
78
79/* ChannelIdentifying trait */
80
81pub(crate) trait HasChannelIdentifying {}
82
83pub trait ChannelIdentifying {
84    fn set_channel_identifying(&self, value: bool) -> Result<(), CanError>;
85    fn is_channel_identifying(&self) -> Result<bool, CanError>;
86}
87
88impl<T: HasChannelIdentifying + Channel> ChannelIdentifying for T {
89    fn set_channel_identifying(&self, value: bool) -> Result<(), CanError> {
90        let mut data = match value {
91            true => peak_can::PEAK_PARAMETER_ON.to_le_bytes(),
92            false => peak_can::PEAK_PARAMETER_OFF.to_le_bytes(),
93        };
94
95        let code = unsafe {
96            peak_lib()?.CAN_SetValue(
97                self.channel(),
98                peak_can::PEAK_CHANNEL_IDENTIFYING as u8,
99                data.as_mut_ptr() as *mut c_void,
100                data.len() as u32,
101            )
102        };
103
104        match CanOkError::try_from(code) {
105            Ok(CanOkError::Ok) => Ok(()),
106            Ok(CanOkError::Err(err)) => Err(err),
107            Err(_) => Err(CanError::Unknown),
108        }
109    }
110
111    fn is_channel_identifying(&self) -> Result<bool, CanError> {
112        let mut data = [0u8; 4];
113        let code = unsafe {
114            peak_lib()?.CAN_GetValue(
115                self.channel(),
116                peak_can::PEAK_CHANNEL_IDENTIFYING as u8,
117                data.as_mut_ptr() as *mut c_void,
118                data.len() as u32,
119            )
120        };
121
122        match CanOkError::try_from(code) {
123            Ok(CanOkError::Ok) => {
124                let value = u32::from_le_bytes(data);
125                if value & peak_can::PEAK_PARAMETER_ON == peak_can::PEAK_PARAMETER_ON {
126                    Ok(true)
127                } else {
128                    Ok(false)
129                }
130            }
131            Ok(CanOkError::Err(err)) => Err(err),
132            Err(_) => Err(CanError::Unknown),
133        }
134    }
135}
136
137/* Device Id */
138
139pub(crate) trait HasDeviceId {}
140
141pub trait DeviceId {
142    fn device_id(&self) -> Result<u32, CanError>;
143}
144
145impl<T: HasDeviceId + Channel> DeviceId for T {
146    fn device_id(&self) -> Result<u32, CanError> {
147        let mut data = [0u8; 4];
148        let code = unsafe {
149            peak_lib()?.CAN_GetValue(
150                self.channel(),
151                peak_can::PEAK_DEVICE_ID as u8,
152                data.as_mut_ptr() as *mut c_void,
153                data.len() as u32,
154            )
155        };
156
157        match CanOkError::try_from(code) {
158            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
159            Ok(CanOkError::Err(err)) => Err(err),
160            Err(_) => Err(CanError::Unknown),
161        }
162    }
163}
164
165pub(crate) trait HasSetDeviceId {}
166
167pub trait SetDeviceId {
168    type Item;
169    fn set_device_id(&self, value: Self::Item) -> Result<(), CanError>;
170}
171
172impl<T: HasSetDeviceId + Channel> SetDeviceId for T {
173    type Item = u32;
174    fn set_device_id(&self, value: Self::Item) -> Result<(), CanError> {
175        let mut data = value.to_le_bytes();
176        let code = unsafe {
177            peak_lib()?.CAN_SetValue(
178                self.channel(),
179                peak_can::PEAK_DEVICE_ID as u8,
180                data.as_mut_ptr() as *mut c_void,
181                data.len() as u32,
182            )
183        };
184
185        match CanOkError::try_from(code) {
186            Ok(CanOkError::Ok) => Ok(()),
187            Ok(CanOkError::Err(err)) => Err(err),
188            Err(_) => Err(CanError::Unknown),
189        }
190    }
191}
192
193/* Hardware Name */
194
195pub(crate) trait HasHardwareName {}
196
197pub trait HardwareName {
198    fn hardware_name(&self) -> Result<String, CanError>;
199}
200
201impl<T: HasHardwareName + Channel> HardwareName for T {
202    fn hardware_name(&self) -> Result<String, CanError> {
203        let mut data = [0u8; peak_can::MAX_LENGTH_HARDWARE_NAME as usize];
204        let code = unsafe {
205            peak_lib()?.CAN_GetValue(
206                self.channel(),
207                peak_can::PEAK_HARDWARE_NAME as u8,
208                data.as_mut_ptr() as *mut c_void,
209                data.len() as u32,
210            )
211        };
212
213        match CanOkError::try_from(code) {
214            Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
215                Ok(s) => {
216                    let s = s.trim_matches(char::from(0));
217                    Ok(String::from(s))
218                }
219                Err(_) => Err(CanError::Unknown),
220            },
221            Ok(CanOkError::Err(err)) => Err(err),
222            Err(_) => Err(CanError::Unknown),
223        }
224    }
225}
226
227/* Controller Number */
228
229pub(crate) trait HasControllerNumber {}
230
231pub trait ControllerNumber {
232    fn controller_number(&self) -> Result<u32, CanError>;
233}
234
235impl<T: HasControllerNumber + Channel> ControllerNumber for T {
236    fn controller_number(&self) -> Result<u32, CanError> {
237        let mut data = [0u8; 4];
238        let code = unsafe {
239            peak_lib()?.CAN_GetValue(
240                self.channel(),
241                peak_can::PEAK_CONTROLLER_NUMBER as u8,
242                data.as_mut_ptr() as *mut c_void,
243                data.len() as u32,
244            )
245        };
246
247        match CanOkError::try_from(code) {
248            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
249            Ok(CanOkError::Err(err)) => Err(err),
250            Err(_) => Err(CanError::Unknown),
251        }
252    }
253}
254
255pub(crate) trait HasSetControllerNumber {}
256
257pub trait SetControllerNumber {
258    type Item;
259    fn set_controller_number(&self, value: Self::Item) -> Result<(), CanError>;
260}
261
262impl<T: HasSetControllerNumber + Channel> SetControllerNumber for T {
263    type Item = u32;
264    fn set_controller_number(&self, value: Self::Item) -> Result<(), CanError> {
265        let mut data = value.to_le_bytes();
266        let code = unsafe {
267            peak_lib()?.CAN_SetValue(
268                self.channel(),
269                peak_can::PEAK_CONTROLLER_NUMBER as u8,
270                data.as_mut_ptr() as *mut c_void,
271                data.len() as u32,
272            )
273        };
274
275        match CanOkError::try_from(code) {
276            Ok(CanOkError::Ok) => Ok(()),
277            Ok(CanOkError::Err(err)) => Err(err),
278            Err(_) => Err(CanError::Unknown),
279        }
280    }
281}
282
283/* IpAddress trait */
284
285pub(crate) trait HasIpAddress {}
286
287pub trait IpAddress {
288    fn ip_address(&self) -> Result<Ipv4Addr, CanError>;
289}
290
291impl<T: HasIpAddress + Channel> IpAddress for T {
292    fn ip_address(&self) -> Result<Ipv4Addr, CanError> {
293        let mut data = [0u8; 20];
294        let code = unsafe {
295            peak_lib()?.CAN_GetValue(
296                self.channel(),
297                peak_can::PEAK_IP_ADDRESS as u8,
298                data.as_mut_ptr() as *mut c_void,
299                data.len() as u32,
300            )
301        };
302
303        match CanOkError::try_from(code) {
304            Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
305                Ok(s) => {
306                    let s = s.trim_matches(char::from(0));
307                    match s.parse() {
308                        Ok(ip) => Ok(ip),
309                        Err(_) => Err(CanError::Unknown),
310                    }
311                }
312                Err(_) => Err(CanError::Unknown),
313            },
314            Ok(CanOkError::Err(err)) => Err(err),
315            _ => Err(CanError::Unknown),
316        }
317    }
318}
319
320/* ATTACHED CHANNEL COUNT */
321
322pub fn attached_channels_count() -> Result<u32, CanError> {
323    let mut data = [0u8; 4];
324    let code = unsafe {
325        peak_lib()?.CAN_GetValue(
326            peak_can::PEAK_NONEBUS as u16,
327            peak_can::PEAK_ATTACHED_CHANNELS_COUNT as u8,
328            data.as_mut_ptr() as *mut c_void,
329            data.len() as u32,
330        )
331    };
332
333    match CanOkError::try_from(code) {
334        Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
335        Ok(CanOkError::Err(err)) => Err(err),
336        Err(_) => Err(CanError::Unknown),
337    }
338}
339
340/* ATTACHED CHANNELS */
341
342#[derive(Debug)]
343pub struct ChannelInformation {
344    pub channel_information: peak_can::tagTPEAKChannelInformation,
345}
346
347impl ChannelInformation {
348    pub fn new() -> Self {
349        ChannelInformation {
350            channel_information: peak_can::tagTPEAKChannelInformation {
351                channel_handle: 0,
352                device_type: 0,
353                controller_number: 0,
354                device_features: 0,
355                device_name: [c_char::default(); 33usize],
356                device_id: 0,
357                channel_condition: 0,
358            },
359        }
360    }
361
362    pub fn device_name(&self) -> String {
363        let string = self
364            .channel_information
365            .device_name
366            .as_slice()
367            .iter()
368            .map(|c| char::from(*c as u8))
369            .collect::<Vec<_>>()
370            .as_slice()
371            .iter()
372            .collect::<String>();
373
374        let s = string.trim_matches(char::from(0));
375        String::from(s)
376    }
377
378    pub fn is_fd_capable(&self) -> bool {
379        (self.channel_information.device_features & peak_can::FEATURE_FD_CAPABLE) != 0
380    }
381}
382
383pub fn attached_channels() -> Result<Vec<ChannelInformation>, CanError> {
384    let attached_channels_count = attached_channels_count()?;
385    let mut channel_information_list = Vec::new();
386
387    for _ in 0..attached_channels_count {
388        channel_information_list.push(ChannelInformation::new());
389    }
390
391    let code = unsafe {
392        peak_lib()?.CAN_GetValue(
393            peak_can::PEAK_NONEBUS as u16,
394            peak_can::PEAK_ATTACHED_CHANNELS as u8,
395            channel_information_list.as_mut_ptr() as *mut c_void,
396            attached_channels_count * size_of::<peak_can::tagTPEAKChannelInformation>() as u32,
397        )
398    };
399
400    match CanOkError::try_from(code) {
401        Ok(CanOkError::Ok) => Ok(channel_information_list),
402        Ok(CanOkError::Err(err)) => Err(err),
403        Err(_) => Err(CanError::Unknown),
404    }
405}
406
407/* DevicePartNumber trait */
408
409pub(crate) trait HasDevicePartNumber {}
410
411pub trait DevicePartNumber {
412    fn device_part_number(&self) -> Result<String, CanError>;
413}
414
415impl<T: HasDevicePartNumber + Channel> DevicePartNumber for T {
416    fn device_part_number(&self) -> Result<String, CanError> {
417        let mut data = [0u8; 100];
418        let code = unsafe {
419            peak_lib()?.CAN_GetValue(
420                self.channel(),
421                peak_can::PEAK_DEVICE_NUMBER as u8,
422                data.as_mut_ptr() as *mut c_void,
423                data.len() as u32,
424            )
425        };
426
427        match CanOkError::try_from(code) {
428            Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
429                Ok(s) => {
430                    let s = s.trim_matches(char::from(0));
431                    Ok(String::from(s))
432                }
433                Err(_) => Err(CanError::Unknown),
434            },
435            Ok(CanOkError::Err(err)) => Err(err),
436            Err(_) => Err(CanError::Unknown),
437        }
438    }
439}