peak_can/
info.rs

1//!
2//!
3
4use crate::channel::Channel;
5use crate::error::{CanError, CanOkError};
6use crate::peak_lib;
7use crate::peak_can;
8use std::ffi::c_void;
9
10pub fn api_version() -> Result<String, CanError> {
11    let mut data = [0u8; peak_can::MAX_LENGTH_VERSION_STRING as usize];
12    let code = unsafe {
13        peak_lib()?.CAN_GetValue(
14            peak_can::PEAK_NONEBUS as u16,
15            peak_can::PEAK_API_VERSION as u8,
16            data.as_mut_ptr() as *mut c_void,
17            data.len() as u32,
18        )
19    };
20
21    match CanOkError::try_from(code) {
22        Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
23            Ok(s) => {
24                let s = s.trim_matches(char::from(0));
25                Ok(String::from(s))
26            }
27            Err(_) => Err(CanError::Unknown),
28        },
29        Ok(CanOkError::Err(err)) => Err(err),
30        Err(_) => Err(CanError::Unknown),
31    }
32}
33
34#[derive(Debug, PartialEq, Clone)]
35pub struct Version {
36    pub device_driver_name_and_version: String,
37    pub year_of_copyright: String,
38    pub company_name_and_city: String,
39}
40
41/* ChannelVersion trait */
42
43pub(crate) trait HasChannelVersion {}
44
45pub trait ChannelVersion {
46    fn channel_version(&self) -> Result<Version, CanError>;
47}
48
49impl<T: HasChannelVersion + Channel> ChannelVersion for T {
50    fn channel_version(&self) -> Result<Version, CanError> {
51        let mut data = [0u8; peak_can::MAX_LENGTH_VERSION_STRING as usize];
52        let code = unsafe {
53            peak_lib()?.CAN_GetValue(
54                self.channel(),
55                peak_can::PEAK_CHANNEL_VERSION as u8,
56                data.as_mut_ptr() as *mut c_void,
57                data.len() as u32,
58            )
59        };
60
61        match CanOkError::try_from(code) {
62            Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
63                Ok(s) => {
64                    let newlines = s.lines().collect::<Vec<_>>();
65
66                    if newlines.len() == 3 {
67                        let newlines = newlines
68                            .iter()
69                            .map(|s| s.trim_matches(char::from(0)))
70                            .collect::<Vec<_>>();
71
72                        Ok(Version {
73                            device_driver_name_and_version: String::from(newlines[0]),
74                            year_of_copyright: String::from(newlines[1]),
75                            company_name_and_city: String::from(newlines[2]),
76                        })
77                    } else {
78                        Err(CanError::Unknown)
79                    }
80                }
81                Err(_) => Err(CanError::Unknown),
82            },
83            Ok(CanOkError::Err(err)) => Err(err),
84            Err(_) => Err(CanError::Unknown),
85        }
86    }
87}
88
89/* ChannelFeatures trait */
90
91pub(crate) trait HasChannelFeatures {}
92
93pub trait ChannelFeatures {
94    fn is_fd_capable(&self) -> Result<bool, CanError>;
95    fn is_delay_capable(&self) -> Result<bool, CanError>;
96    fn is_io_capable(&self) -> Result<bool, CanError>;
97}
98
99impl<T: HasChannelFeatures + Channel> ChannelFeatures for T {
100    fn is_fd_capable(&self) -> Result<bool, CanError> {
101        let mut data = [0u8; 4];
102        let code = unsafe {
103            peak_lib()?.CAN_GetValue(
104                self.channel(),
105                peak_can::PEAK_CHANNEL_FEATURES as u8,
106                data.as_mut_ptr() as *mut c_void,
107                data.len() as u32,
108            )
109        };
110
111        match CanOkError::try_from(code) {
112            Ok(CanOkError::Ok) => {
113                let value = u32::from_le_bytes(data);
114                if value & peak_can::FEATURE_FD_CAPABLE == peak_can::FEATURE_FD_CAPABLE {
115                    Ok(true)
116                } else {
117                    Ok(false)
118                }
119            }
120            Ok(CanOkError::Err(err)) => Err(err),
121            Err(_) => Err(CanError::Unknown),
122        }
123    }
124
125    fn is_delay_capable(&self) -> Result<bool, CanError> {
126        let mut data = [0u8; 4];
127        let code = unsafe {
128            peak_lib()?.CAN_GetValue(
129                self.channel(),
130                peak_can::PEAK_CHANNEL_FEATURES as u8,
131                data.as_mut_ptr() as *mut c_void,
132                data.len() as u32,
133            )
134        };
135
136        match CanOkError::try_from(code) {
137            Ok(CanOkError::Ok) => {
138                let value = u32::from_le_bytes(data);
139                if value & peak_can::FEATURE_DELAY_CAPABLE == peak_can::FEATURE_DELAY_CAPABLE {
140                    Ok(true)
141                } else {
142                    Ok(false)
143                }
144            }
145            Ok(CanOkError::Err(err)) => Err(err),
146            Err(_) => Err(CanError::Unknown),
147        }
148    }
149
150    fn is_io_capable(&self) -> Result<bool, CanError> {
151        let mut data = [0u8; 4];
152        let code = unsafe {
153            peak_lib()?.CAN_GetValue(
154                self.channel(),
155                peak_can::PEAK_CHANNEL_FEATURES as u8,
156                data.as_mut_ptr() as *mut c_void,
157                data.len() as u32,
158            )
159        };
160
161        match CanOkError::try_from(code) {
162            Ok(CanOkError::Ok) => {
163                let value = u32::from_le_bytes(data);
164                if value & peak_can::FEATURE_IO_CAPABLE == peak_can::FEATURE_IO_CAPABLE {
165                    Ok(true)
166                } else {
167                    Ok(false)
168                }
169            }
170            Ok(CanOkError::Err(err)) => Err(err),
171            Err(_) => Err(CanError::Unknown),
172        }
173    }
174}
175
176/* BitrateInfo trait */
177
178pub(crate) trait HasBitrateInfo {}
179
180pub trait BitrateInfo {
181    fn bitrate_info(&self) -> Result<(u16, u16), CanError>;
182}
183
184impl<T: HasBitrateInfo + Channel> BitrateInfo for T {
185    fn bitrate_info(&self) -> Result<(u16, u16), CanError> {
186        let mut data = [0u8; 4];
187        let code = unsafe {
188            peak_lib()?.CAN_GetValue(
189                self.channel(),
190                peak_can::PEAK_BITRATE_INFO as u8,
191                data.as_mut_ptr() as *mut c_void,
192                data.len() as u32,
193            )
194        };
195
196        match CanOkError::try_from(code) {
197            Ok(CanOkError::Ok) => {
198                let btr0 = u16::from_le_bytes([data[0], data[1]]);
199                let btr1 = u16::from_le_bytes([data[2], data[3]]);
200                Ok((btr0, btr1))
201            }
202            Ok(CanOkError::Err(err)) => Err(err),
203            Err(_) => Err(CanError::Unknown),
204        }
205    }
206}
207
208/* BitrateFdInfo trait */
209
210pub(crate) trait HasBitrateInfoFd {}
211
212pub trait BitrateInfoFd {
213    fn bitrate_info_fd(&self) -> Result<String, CanError>;
214}
215
216impl<T: HasBitrateInfoFd + Channel> BitrateInfoFd for T {
217    fn bitrate_info_fd(&self) -> Result<String, CanError> {
218        let mut data = [0u8; peak_can::MAX_LENGTH_VERSION_STRING as usize];
219        let code = unsafe {
220            peak_lib()?.CAN_GetValue(
221                self.channel(),
222                peak_can::PEAK_BITRATE_INFO_FD as u8,
223                data.as_mut_ptr() as *mut c_void,
224                data.len() as u32,
225            )
226        };
227
228        match CanOkError::try_from(code) {
229            Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
230                Ok(s) => {
231                    let s = s.trim_matches(char::from(0));
232                    Ok(String::from(s))
233                }
234                Err(_) => Err(CanError::Unknown),
235            },
236            Ok(CanOkError::Err(err)) => Err(err),
237            Err(_) => Err(CanError::Unknown),
238        }
239    }
240}
241
242/* NominalBusSpeed trait */
243
244pub(crate) trait HasNominalBusSpeed {}
245
246pub trait NominalBusSpeed {
247    fn nominal_bus_speed(&self) -> Result<u32, CanError>;
248}
249
250impl<T: HasNominalBusSpeed + Channel> NominalBusSpeed for T {
251    fn nominal_bus_speed(&self) -> Result<u32, CanError> {
252        let mut data = [0u8; 4];
253        let code = unsafe {
254            peak_lib()?.CAN_GetValue(
255                self.channel(),
256                peak_can::PEAK_BUSSPEED_NOMINAL as u8,
257                data.as_mut_ptr() as *mut c_void,
258                data.len() as u32,
259            )
260        };
261
262        match CanOkError::try_from(code) {
263            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
264            Ok(CanOkError::Err(err)) => Err(err),
265            Err(_) => Err(CanError::Unknown),
266        }
267    }
268}
269
270/* DataBusSpeed trait */
271
272pub(crate) trait HasDataBusSpeed {}
273
274pub trait DataBusSpeed {
275    fn data_bus_speed(&self) -> Result<u32, CanError>;
276}
277
278impl<T: HasDataBusSpeed + Channel> DataBusSpeed for T {
279    fn data_bus_speed(&self) -> Result<u32, CanError> {
280        let mut data = [0u8; 4];
281        let code = unsafe {
282            peak_lib()?.CAN_GetValue(
283                self.channel(),
284                peak_can::PEAK_BUSSPEED_DATA as u8,
285                data.as_mut_ptr() as *mut c_void,
286                data.len() as u32,
287            )
288        };
289
290        match CanOkError::try_from(code) {
291            Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
292            Ok(CanOkError::Err(err)) => Err(err),
293            Err(_) => Err(CanError::Unknown),
294        }
295    }
296}
297
298/* LAN SERVICE RUNNING / STOPPED */
299
300pub fn lan_service_is_running() -> Result<bool, CanError> {
301    let mut data = [0u8; 4];
302    let code = unsafe {
303        peak_lib()?.CAN_GetValue(
304            peak_can::PEAK_NONEBUS as u16,
305            peak_can::PEAK_LAN_SERVICE_STATUS as u8,
306            data.as_mut_ptr() as *mut c_void,
307            data.len() as u32,
308        )
309    };
310
311    match CanOkError::try_from(code) {
312        Ok(CanOkError::Ok) => {
313            let code = u32::from_le_bytes(data);
314            if code & peak_can::SERVICE_STATUS_RUNNING == peak_can::SERVICE_STATUS_RUNNING {
315                Ok(true)
316            } else {
317                Ok(false)
318            }
319        }
320        Ok(CanOkError::Err(err)) => Err(err),
321        Err(_) => Err(CanError::Unknown),
322    }
323}
324
325pub fn lan_service_is_stopped() -> Result<bool, CanError> {
326    let mut data = [0u8; 4];
327    let code = unsafe {
328        peak_lib()?.CAN_GetValue(
329            peak_can::PEAK_NONEBUS as u16,
330            peak_can::PEAK_LAN_SERVICE_STATUS as u8,
331            data.as_mut_ptr() as *mut c_void,
332            data.len() as u32,
333        )
334    };
335
336    match CanOkError::try_from(code) {
337        Ok(CanOkError::Ok) => {
338            let code = u32::from_le_bytes(data);
339            if code & peak_can::SERVICE_STATUS_STOPPED == peak_can::SERVICE_STATUS_STOPPED {
340                Ok(true)
341            } else {
342                Ok(false)
343            }
344        }
345        Ok(CanOkError::Err(err)) => Err(err),
346        Err(_) => Err(CanError::Unknown),
347    }
348}
349
350/* FirmwareVersion trait */
351
352pub(crate) trait HasFirmwareVersion {}
353
354pub trait FirmwareVersion {
355    fn firmware_version(&self) -> Result<String, CanError>;
356}
357
358impl<T: HasFirmwareVersion + Channel> FirmwareVersion for T {
359    fn firmware_version(&self) -> Result<String, CanError> {
360        let mut data = [0u8; 18usize];
361        let code = unsafe {
362            peak_lib()?.CAN_GetValue(
363                self.channel(),
364                peak_can::PEAK_FIRMWARE_VERSION as u8,
365                data.as_mut_ptr() as *mut c_void,
366                data.len() as u32,
367            )
368        };
369
370        match CanOkError::try_from(code) {
371            Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
372                Ok(s) => {
373                    let s = s.trim_matches(char::from(0));
374                    Ok(String::from(s))
375                }
376                Err(_) => Err(CanError::Unknown),
377            },
378            Ok(CanOkError::Err(err)) => Err(err),
379            Err(_) => Err(CanError::Unknown),
380        }
381    }
382}