1use 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
41pub(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
89pub(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
176pub(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
208pub(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
242pub(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
270pub(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
298pub 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
350pub(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}