1#[macro_use]
28extern crate bitflags;
29
30use std::ffi;
31use std::ffi::OsStr;
32use std::fmt;
33use std::fmt::Debug;
34use std::io;
35use std::marker::PhantomData;
36use std::path::Path;
37use std::str::Utf8Error;
38
39use bitflags::_core::fmt::Formatter;
40use libloading::{Library, Symbol};
41
42#[cfg(windows)]
43use winreg::{enums::*, RegKey};
44
45#[derive(thiserror::Error, Debug)]
46pub enum Error {
47 #[error(transparent)]
48 Utf8Error(#[from] Utf8Error),
49 #[error(transparent)]
50 Io(#[from] io::Error),
51
52 #[error("success")]
53 NoError,
54 #[error("option not supported')")]
55 NotSupported,
56 #[error("invalid channel id")]
57 InvalidChannelId,
58 #[error("invalid protocol id")]
59 InvalidProtocolId,
60 #[error("NULL was incorrectly passed as a parameter")]
61 NullParameter,
62 #[error("invalid ioctl parameter")]
63 InvalidIoctlValue,
64 #[error("invalid flags")]
65 InvalidFlags,
66 #[error("unspecified error")]
67 Failed,
68 #[error("a PassThru device is not connected")]
69 DeviceNotConnected,
70 #[error("timed out")]
71 Timeout,
72 #[error("invalid message")]
73 InvalidMessage,
74 #[error("invalid time interval")]
75 InvalidTimeInterval,
76 #[error("exceeded message limit")]
77 ExceededLimit,
78 #[error("invalid message id")]
79 InvalidMessageId,
80 #[error("device in use")]
81 DeviceInUse,
82 #[error("invalid ioctl id")]
83 InvalidIoctlId,
84 #[error("could not read messages")]
86 BufferEmpty,
87 #[error("transmit queue full")]
88 BufferFull,
89 #[error("receive buffer overflowed")]
91 BufferOverflow,
92 #[error("unknown pin number or resource in use")]
93 PinInvalid,
94 #[error("channel already in use")]
95 ChannelInUse,
96 #[error("message protocol does not match channel protocol")]
97 MessageProtocolId,
98 #[error("invalid filter id")]
99 InvalidFilterId,
100 #[error("no flow control filter matches outgoing message")]
101 NoFlowControl,
102 #[error("filter already exists")]
103 NotUnique,
104 #[error("unsupported baudrate")]
105 InvalidBaudrate,
106 #[error("invalid device id")]
107 InvalidDeviceId,
108 #[error("unknown j2534 error code {0}")]
109 Unknown(i32),
110}
111
112impl Error {
113 pub fn from_code(code: i32) -> Error {
114 match code {
115 0x00 => Error::NoError,
116 0x01 => Error::NotSupported,
117 0x02 => Error::InvalidChannelId,
118 0x03 => Error::InvalidProtocolId,
119 0x04 => Error::NullParameter,
120 0x05 => Error::InvalidIoctlValue,
121 0x06 => Error::InvalidFlags,
122 0x07 => Error::Failed,
123 0x08 => Error::DeviceNotConnected,
124 0x09 => Error::Timeout,
125 0x0A => Error::InvalidMessage,
126 0x0B => Error::InvalidTimeInterval,
127 0x0C => Error::ExceededLimit,
128 0x0D => Error::InvalidMessageId,
129 0x0E => Error::DeviceInUse,
130 0x0F => Error::InvalidIoctlId,
131 0x10 => Error::BufferEmpty,
132 0x11 => Error::BufferFull,
133 0x12 => Error::BufferOverflow,
134 0x13 => Error::PinInvalid,
135 0x14 => Error::ChannelInUse,
136 0x15 => Error::MessageProtocolId,
137 0x16 => Error::InvalidFilterId,
138 0x17 => Error::NoFlowControl,
139 0x18 => Error::NotUnique,
140 0x19 => Error::InvalidBaudrate,
141 0x1A => Error::InvalidDeviceId,
142 other => Error::Unknown(other),
143 }
144 }
145}
146
147type PassThruOpenFn =
148 unsafe extern "stdcall" fn(name: *const libc::c_void, device_id: *mut u32) -> i32;
149type PassThruCloseFn = unsafe extern "stdcall" fn(device_id: u32) -> i32;
150type PassThruConnectFn = unsafe extern "stdcall" fn(
151 device_id: u32,
152 protocol_id: u32,
153 flags: u32,
154 baudrate: u32,
155 channel_id: *mut u32,
156) -> i32;
157type PassThruDisconnectFn = unsafe extern "stdcall" fn(channel_id: u32) -> i32;
158type PassThruReadMsgsFn = unsafe extern "stdcall" fn(
159 channel_id: u32,
160 msgs: *mut PassThruMsg,
161 num_msgs: *mut u32,
162 timeout: u32,
163) -> i32;
164type PassThruWriteMsgsFn = unsafe extern "stdcall" fn(
165 channel_id: u32,
166 msgs: *mut PassThruMsg,
167 num_msgs: *mut u32,
168 timeout: u32,
169) -> i32;
170type PassThruStartPeriodicMsgFn = unsafe extern "stdcall" fn(
171 channel_id: u32,
172 msg: *const PassThruMsg,
173 msg_id: *mut u32,
174 time_interval: u32,
175) -> i32;
176type PassThruStopPeriodicMsgFn = unsafe extern "stdcall" fn(channel_id: u32, msg_id: u32) -> i32;
177type PassThruStartMsgFilterFn = unsafe extern "stdcall" fn(
178 channel_id: u32,
179 filter_type: u32,
180 msg_mask: *const PassThruMsg,
181 pattern_msg: *const PassThruMsg,
182 flow_control_msg: *const PassThruMsg,
183 filter_id: *mut u32,
184) -> i32;
185type PassThruStopMsgFilterFn = unsafe extern "stdcall" fn(channel_id: u32, filter_id: u32) -> i32;
186type PassThruSetProgrammingVoltageFn =
187 unsafe extern "stdcall" fn(device_id: u32, pin_number: u32, voltage: u32) -> i32;
188type PassThruReadVersionFn = unsafe extern "stdcall" fn(
189 device_id: u32,
190 firmware_version: *mut libc::c_char,
191 dll_version: *mut libc::c_char,
192 api_version: *mut libc::c_char,
193) -> i32;
194type PassThruGetLastErrorFn =
195 unsafe extern "stdcall" fn(error_description: *mut libc::c_char) -> i32;
196type PassThruIoctlFn = unsafe extern "stdcall" fn(
197 handle_id: u32,
198 ioctl_id: u32,
199 input: *mut libc::c_void,
200 output: *mut libc::c_void,
201) -> i32;
202
203#[derive(Copy, Clone)]
206#[repr(C, packed(1))]
207pub struct PassThruMsg {
209 pub protocol_id: u32,
210 pub rx_status: u32,
211 pub tx_flags: u32,
212 pub timestamp: u32,
213 pub data_size: u32,
214 pub extra_data_index: u32,
215 pub data: [u8; 4128],
216}
217
218#[repr(C, packed(1))]
219struct SConfig {
220 parameter: u32,
221 value: u32,
222}
223
224#[repr(C, packed(1))]
225struct SConfigList {
226 size: u32,
227 config_ptr: *const SConfig,
228}
229
230#[repr(C, packed(1))]
231struct SByteArray {
232 size: u32,
233 byte_ptr: *const u8,
234}
235
236impl PassThruMsg {
237 pub fn new_raw(
238 protocol: Protocol,
239 rx_status: RxStatus,
240 tx_flags: TxFlags,
241 timestamp: u32,
242 data_size: u32,
243 extra_data_index: u32,
244 data: [u8; 4128],
245 ) -> PassThruMsg {
246 PassThruMsg {
247 protocol_id: protocol as u32,
248 rx_status: rx_status.bits,
249 tx_flags: tx_flags.bits,
250 timestamp,
251 data_size,
252 extra_data_index,
253 data,
254 }
255 }
256
257 pub fn new(protocol: Protocol) -> PassThruMsg {
258 PassThruMsg {
259 protocol_id: protocol as u32,
260 rx_status: 0,
261 tx_flags: 0,
262 timestamp: 0,
263 data_size: 0,
264 extra_data_index: 0,
265 data: [0; 4128],
266 }
267 }
268
269 pub fn new_can(id: u32, data: &[u8]) -> PassThruMsg {
272 let mut msg_data = [0_u8; 4128];
273 msg_data[0] = ((id >> 24) & 0xFF) as u8;
275 msg_data[1] = ((id >> 16) & 0xFF) as u8;
276 msg_data[2] = ((id >> 8) & 0xFF) as u8;
277 msg_data[3] = (id & 0xFF) as u8;
278
279 &mut msg_data[4..data.len() + 4].copy_from_slice(data);
281
282 PassThruMsg {
283 data: msg_data,
284 data_size: (data.len() + 4) as u32,
285 ..Self::new(Protocol::CAN)
286 }
287 }
288
289 pub fn new_isotp(id: u32, data: &[u8]) -> PassThruMsg {
294 let mut msg_data = [0_u8; 4128];
295 msg_data[0] = ((id >> 24) & 0xFF) as u8;
297 msg_data[1] = ((id >> 16) & 0xFF) as u8;
298 msg_data[2] = ((id >> 8) & 0xFF) as u8;
299 msg_data[3] = (id & 0xFF) as u8;
300
301 &mut msg_data[4..data.len() + 4].copy_from_slice(data);
303
304 PassThruMsg {
305 data: msg_data,
306 data_size: (data.len() + 4) as u32,
307 ..Self::new(Protocol::ISO15765)
308 }
309 }
310
311 pub fn can_message(&self) -> Option<(u32, &[u8])> {
314 if (self.protocol_id == (Protocol::CAN as u32)
315 || self.protocol_id == (Protocol::ISO15765 as u32))
316 && self.data_size >= 4
317 {
318 let id = ((self.data[0] as u32) << 24)
319 | ((self.data[1] as u32) << 16)
320 | ((self.data[2] as u32) << 8)
321 | (self.data[3] as u32);
322 Some((id, &self.data[4..self.data_size as usize]))
323 } else {
324 None
325 }
326 }
327
328 #[inline]
330 pub fn isotp_message(&self) -> Option<(u32, &[u8])> {
331 self.can_message()
332 }
333
334 pub fn rx_status(mut self, rx_status: RxStatus) -> Self {
336 self.rx_status = rx_status.bits;
337 self
338 }
339
340 pub fn tx_flags(mut self, tx_flags: TxFlags) -> Self {
342 self.tx_flags = tx_flags.bits;
343 self
344 }
345
346 pub fn transmitted(&self) -> bool {
349 self.rx_status & (RxStatus::TX_MSG_TYPE).bits() != 0
350 }
351
352 pub fn first_frame(&self) -> bool {
355 self.rx_status & (RxStatus::ISO15765_FIRST_FRAME).bits() != 0
356 }
357}
358
359impl Default for PassThruMsg {
360 fn default() -> PassThruMsg {
361 PassThruMsg {
362 protocol_id: 0,
363 rx_status: 0,
364 tx_flags: 0,
365 timestamp: 0,
366 data_size: 0,
367 extra_data_index: 0,
368 data: [0; 4128],
369 }
370 }
371}
372
373impl Debug for PassThruMsg {
374 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
375 unsafe {
376 f.debug_struct("PassThruMsg")
377 .field("protocol_id", &self.protocol_id)
378 .field("rx_status", &self.rx_status)
379 .field("tx_flags", &self.tx_flags)
380 .field("timestamp", &self.timestamp)
381 .field("extra_data_index", &self.extra_data_index)
382 .field("data", &&self.data[..self.data_size as usize])
383 .finish()
384 }
385 }
386}
387
388#[derive(Copy, Clone, Debug)]
390struct ChannelId(u32);
391
392#[derive(Copy, Clone, Debug)]
394struct DeviceId(u32);
395
396#[derive(Copy, Clone, Debug)]
398pub struct MessageId(u32);
399
400#[derive(Copy, Clone, Debug)]
402pub struct FilterId(u32);
403
404pub struct Interface {
406 library: Library,
407
408 c_pass_thru_open: PassThruOpenFn,
409 c_pass_thru_close: PassThruCloseFn,
410 c_pass_thru_connect: PassThruConnectFn,
411 c_pass_thru_disconnect: PassThruDisconnectFn,
412 c_pass_thru_read_version: PassThruReadVersionFn,
413 c_pass_thru_get_last_error: PassThruGetLastErrorFn,
414 c_pass_thru_read_msgs: PassThruReadMsgsFn,
415 c_pass_thru_start_msg_filter: PassThruStartMsgFilterFn,
416 c_pass_thru_stop_msg_filter: PassThruStopMsgFilterFn,
417 c_pass_thru_write_msgs: PassThruWriteMsgsFn,
418 c_pass_thru_start_periodic_msg: PassThruStartPeriodicMsgFn,
419 c_pass_thru_stop_periodic_msg: PassThruStopPeriodicMsgFn,
420 c_pass_thru_set_programming_voltage: PassThruSetProgrammingVoltageFn,
421 c_pass_thru_ioctl: PassThruIoctlFn,
422
423 _marker: PhantomData<*mut ()>,
424}
425
426pub struct Device<'a> {
428 interface: &'a Interface,
429 id: DeviceId,
430}
431
432pub struct Channel<'a> {
434 device: &'a Device<'a>,
435 id: ChannelId,
436 protocol: Protocol,
437}
438
439impl Interface {
440 pub fn new<S: AsRef<OsStr>>(path: S) -> Result<Interface, libloading::Error> {
452 let library = Library::new(path)?;
453
454 let interface = unsafe {
455 let c_pass_thru_open: Symbol<PassThruOpenFn> = library.get(b"PassThruOpen\0")?;
456 let c_pass_thru_close: Symbol<PassThruCloseFn> = library.get(b"PassThruClose\0")?;
457 let c_pass_thru_connect: Symbol<PassThruConnectFn> =
458 library.get(b"PassThruConnect\0")?;
459 let c_pass_thru_disconnect: Symbol<PassThruDisconnectFn> =
460 library.get(b"PassThruDisconnect\0")?;
461 let c_pass_thru_read_version: Symbol<PassThruReadVersionFn> =
462 library.get(b"PassThruReadVersion\0")?;
463 let c_pass_thru_get_last_error: Symbol<PassThruGetLastErrorFn> =
464 library.get(b"PassThruGetLastError\0")?;
465 let c_pass_thru_read_msgs: Symbol<PassThruReadMsgsFn> =
466 library.get(b"PassThruReadMsgs\0")?;
467 let c_pass_thru_start_msg_filter: Symbol<PassThruStartMsgFilterFn> =
468 library.get(b"PassThruStartMsgFilter\0")?;
469 let c_pass_thru_stop_msg_filter: Symbol<PassThruStopMsgFilterFn> =
470 library.get(b"PassThruStopMsgFilter\0")?;
471 let c_pass_thru_write_msgs: Symbol<PassThruWriteMsgsFn> =
472 library.get(b"PassThruWriteMsgs\0")?;
473 let c_pass_thru_start_periodic_msg: Symbol<PassThruStartPeriodicMsgFn> =
474 library.get(b"PassThruStartPeriodicMsg\0")?;
475 let c_pass_thru_stop_periodic_msg: Symbol<PassThruStopPeriodicMsgFn> =
476 library.get(b"PassThruStopPeriodicMsg\0")?;
477 let c_pass_thru_set_programming_voltage: Symbol<PassThruSetProgrammingVoltageFn> =
478 library.get(b"PassThruSetProgrammingVoltage\0")?;
479 let c_pass_thru_ioctl: Symbol<PassThruIoctlFn> = library.get(b"PassThruIoctl\0")?;
480 Interface {
481 c_pass_thru_open: *c_pass_thru_open.into_raw(),
482 c_pass_thru_close: *c_pass_thru_close.into_raw(),
483 c_pass_thru_connect: *c_pass_thru_connect.into_raw(),
484 c_pass_thru_disconnect: *c_pass_thru_disconnect.into_raw(),
485 c_pass_thru_read_version: *c_pass_thru_read_version.into_raw(),
486 c_pass_thru_get_last_error: *c_pass_thru_get_last_error.into_raw(),
487 c_pass_thru_read_msgs: *c_pass_thru_read_msgs.into_raw(),
488 c_pass_thru_start_msg_filter: *c_pass_thru_start_msg_filter.into_raw(),
489 c_pass_thru_stop_msg_filter: *c_pass_thru_stop_msg_filter.into_raw(),
490 c_pass_thru_write_msgs: *c_pass_thru_write_msgs.into_raw(),
491 c_pass_thru_start_periodic_msg: *c_pass_thru_start_periodic_msg.into_raw(),
492 c_pass_thru_stop_periodic_msg: *c_pass_thru_stop_periodic_msg.into_raw(),
493 c_pass_thru_set_programming_voltage: *c_pass_thru_set_programming_voltage
494 .into_raw(),
495 c_pass_thru_ioctl: *c_pass_thru_ioctl.into_raw(),
496 library,
497
498 _marker: PhantomData,
499 }
500 };
501
502 Ok(interface)
505 }
506
507 pub fn get_last_error(&self) -> Result<String, Error> {
509 let mut error: [u8; 80] = [0; 80];
510 let res =
511 unsafe { (&self.c_pass_thru_get_last_error)(error.as_mut_ptr() as *mut libc::c_char) };
512 if res != 0 {
513 return Err(Error::from_code(res));
514 }
515
516 unsafe {
517 Ok(String::from(
518 ffi::CStr::from_ptr(error.as_mut_ptr() as *mut libc::c_char).to_str()?,
519 ))
520 }
521 }
522
523 pub fn open<S: Into<Vec<u8>>>(&self, port: S) -> Result<Device, Error> {
536 let s = ffi::CString::new(port).unwrap();
537 let raw = s.as_ptr() as *const libc::c_void;
538 let mut id = 0;
539
540 let res = unsafe { (&self.c_pass_thru_open)(raw, &mut id as *mut u32) };
541 if res != 0 {
542 return Err(Error::from_code(res));
543 }
544
545 Ok(Device {
546 interface: self,
547 id: DeviceId(id),
548 })
549 }
550
551 pub fn open_any(&self) -> Result<Device, Error> {
560 let raw = std::ptr::null() as *const libc::c_void;
561 let mut id = 0;
562 let res = unsafe { (&self.c_pass_thru_open)(raw, &mut id as *mut u32) };
563 if res != 0 {
564 return Err(Error::from_code(res));
565 }
566
567 Ok(Device {
568 interface: self,
569 id: DeviceId(id),
570 })
571 }
572
573 pub unsafe fn ioctl(
575 &self,
576 handle: u32,
577 id: IoctlId,
578 input: *mut libc::c_void,
579 output: *mut libc::c_void,
580 ) -> Result<i32, Error> {
581 let res = (&self.c_pass_thru_ioctl)(handle, id as u32, input, output);
582 if res != 0 {
583 return Err(Error::from_code(res));
584 }
585 Ok(res)
586 }
587}
588
589#[derive(Copy, Clone)]
590pub enum Protocol {
591 J1850VPW = 1,
592 J1850PWM = 2,
593 ISO9141 = 3,
594 ISO14230 = 4,
595 CAN = 5,
596 ISO15765 = 6,
597 SCI_A_ENGINE = 7,
598 SCI_A_TRANS = 8,
599 SCI_B_ENGINE = 9,
600 SCI_B_TRANS = 10,
601}
602
603bitflags! {
604 pub struct ConnectFlags: u32 {
606 const NONE = 0;
607 const CAN_29_BIT_ID = 0x100;
608 const ISO9141_NO_CHECKSUM = 0x200;
609 const CAN_ID_BOTH = 0x800;
610 const ISO9141_K_LINE_ONLY = 0x1000;
611 }
612}
613
614bitflags! {
615 pub struct TxFlags: u32 {
617 const NONE = 0;
618 const ISO15765_FRAME_PAD = 0x00000040;
621
622 const ISO15765_ADDR_TYPE = 0x00000080;
623 const CAN_29BIT_ID = 0x00000100;
624
625 const WAIT_P3_MIN_ONLY = 0x00000200;
629
630 const SW_CAN_HV_TX = 0x00000400;
631
632 const SCI_MODE = 0x00400000;
635
636 const SCI_TX_VOLTAGE = 0x00800000;
639
640 const DT_PERIODIC_UPDATE = 0x10000000;
641 }
642}
643
644bitflags! {
645 pub struct RxStatus: u32 {
647 const NONE = 0;
648 const TX_MSG_TYPE = 0x00000001;
651
652 const START_OF_MESSAGE = 0x00000002;
655 const ISO15765_FIRST_FRAME = 0x00000002 ;
656
657 const ISO15765_EXT_ADDR = 0x00000080;
658
659 const RX_BREAK = 0x00000004;
662
663 const TX_INDICATION = 0x00000008;
666 const TX_DONE = 0x00000008;
667
668 const ISO15765_PADDING_ERROR = 0x00000010;
671
672 const ISO15765_ADDR_TYPE = 0x00000080;
675
676 const CAN_29BIT_ID = 0x00000100;
677
678 const SW_CAN_NS_RX = 0x00040000;
679 const SW_CAN_HS_RX = 0x00020000;
680 const SW_CAN_HV_RX = 0x00010000;
681 }
682}
683
684#[derive(Copy, Clone)]
685pub enum IoctlId {
686 GET_CONFIG = 0x01,
687 SET_CONFIG = 0x02,
688 READ_VBATT = 0x03,
689 FIVE_BAUD_INIT = 0x04,
690 FAST_INIT = 0x05,
691 CLEAR_TX_BUFFER = 0x07,
693 CLEAR_RX_BUFFER = 0x08,
694 CLEAR_PERIODIC_MSGS = 0x09,
695 CLEAR_MSG_FILTERS = 0x0A,
696 CLEAR_FUNCT_MSG_LOOKUP_TABLE = 0x0B,
697 ADD_TO_FUNCT_MSG_LOOKUP_TABLE = 0x0C,
698 DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE = 0x0D,
699 READ_PROG_VOLTAGE = 0x0E,
700
701 SW_CAN_HS = 0x8000,
702 SW_CAN_NS = 0x8001,
703 SET_POLL_RESPONSE = 0x8002,
704 BECOME_MASTER = 0x8003,
705}
706
707#[derive(Copy, Clone)]
708pub enum ConfigId {
710 DATA_RATE = 0x01,
711 LOOPBACK = 0x03,
712 NODE_ADDRESS = 0x04,
713 NETWORK_LINE = 0x05,
714 P1_MIN = 0x06,
715 P1_MAX = 0x07,
716 P2_MIN = 0x08,
717 P2_MAX = 0x09,
718 P3_MIN = 0x0A,
719 P3_MAX = 0x0B,
720 P4_MIN = 0x0C,
721 P4_MAX = 0x0D,
722
723 W1 = 0x0E,
724 W2 = 0x0F,
725 W3 = 0x10,
726 W4 = 0x11,
727 W5 = 0x12,
728 TIDLE = 0x13,
729 TINIL = 0x14,
730 TWUP = 0x15,
731 PARITY = 0x16,
732 BIT_SAMPLE_POINT = 0x17,
733 SYNC_JUMP_WIDTH = 0x18,
734 W0 = 0x19,
735 T1_MAX = 0x1A,
736 T2_MAX = 0x1B,
737
738 T4_MAX = 0x1C,
739 T5_MAX = 0x1D,
740 ISO15765_BS = 0x1E,
741 ISO15765_STMIN = 0x1F,
742 DATA_BITS = 0x20,
743 FIVE_BAUD_MOD = 0x21,
744 BS_TX = 0x22,
745 STMIN_TX = 0x23,
746 T3_MAX = 0x24,
747 ISO15765_WFT_MAX = 0x25,
748
749 CAN_MIXED_FORMAT = 0x8000,
750
751 J1962_PINS = 0x8001,
752
753 SW_CAN_HS_DATA_RATE = 0x8010,
754 SW_CAN_SPEEDCHANGE_ENABLE = 0x8011,
755 SW_CAN_RES_SWITCH = 0x8012,
756 ACTIVE_CHANNELS = 0x8020,
757 SAMPLE_RATE = 0x8021,
758 SAMPLES_PER_READING = 0x8022,
759 READINGS_PER_MSG = 0x8023,
760 AVERAGING_METHOD = 0x8024,
761 SAMPLE_RESOLUTION = 0x8025,
762 INPUT_RANGE_LOW = 0x8026,
763 INPUT_RANGE_HIGH = 0x8027,
764}
765
766#[derive(Copy, Clone)]
767pub enum FilterType {
768 Pass = 1,
770 Block = 2,
772 FlowControl = 3,
775}
776
777#[derive(Debug)]
778pub struct VersionInfo {
780 pub firmware_version: String,
781 pub dll_version: String,
782 pub api_version: String,
783}
784
785pub const SHORT_TO_GROUND: u32 = 0xFFFFFFFE;
786pub const VOLTAGE_OFF: u32 = 0xFFFFFFFF;
787
788impl<'a> Device<'a> {
789 pub fn read_version(&self) -> Result<VersionInfo, Error> {
791 let mut firmware_version: [u8; 80] = [0; 80];
792 let mut dll_version: [u8; 80] = [0; 80];
793 let mut api_version: [u8; 80] = [0; 80];
794 let res = unsafe {
795 (&self.interface.c_pass_thru_read_version)(
796 self.id.0,
797 firmware_version.as_mut_ptr() as *mut libc::c_char,
798 dll_version.as_mut_ptr() as *mut libc::c_char,
799 api_version.as_mut_ptr() as *mut libc::c_char,
800 )
801 };
802 if res != 0 {
803 return Err(Error::from_code(res));
804 }
805 unsafe {
806 Ok(VersionInfo {
807 firmware_version: String::from(
808 ffi::CStr::from_ptr(firmware_version.as_mut_ptr() as *mut libc::c_char)
809 .to_str()?,
810 ),
811 api_version: String::from(
812 ffi::CStr::from_ptr(api_version.as_mut_ptr() as *mut libc::c_char).to_str()?,
813 ),
814 dll_version: String::from(
815 ffi::CStr::from_ptr(dll_version.as_mut_ptr() as *mut libc::c_char).to_str()?,
816 ),
817 })
818 }
819 }
820
821 pub fn set_programming_voltage(&self, pin_number: u32, voltage: u32) -> Result<(), Error> {
830 let res = unsafe {
831 (&self.interface.c_pass_thru_set_programming_voltage)(self.id.0, pin_number, voltage)
832 };
833 if res != 0 {
834 return Err(Error::from_code(res));
835 }
836 Ok(())
837 }
838
839 pub fn connect(
847 &self,
848 protocol: Protocol,
849 flags: ConnectFlags,
850 baudrate: u32,
851 ) -> Result<Channel, Error> {
852 let mut id: u32 = 0;
853 let res = unsafe {
854 (&self.interface.c_pass_thru_connect)(
855 self.id.0,
856 protocol as u32,
857 flags.bits,
858 baudrate,
859 &mut id as *mut u32,
860 )
861 };
862 if res != 0 {
863 return Err(Error::from_code(res));
864 }
865 Ok(Channel {
866 device: self,
867 id: ChannelId(id),
868 protocol: protocol as Protocol,
869 })
870 }
871
872 pub fn read_battery_voltage(&self) -> Result<u32, Error> {
874 let mut voltage: u32 = 0;
875 unsafe {
876 self.interface.ioctl(
877 self.id.0,
878 IoctlId::READ_VBATT,
879 std::ptr::null_mut::<libc::c_void>(),
880 (&mut voltage) as *mut _ as *mut libc::c_void,
881 )
882 }?;
883 Ok(voltage)
884 }
885
886 pub fn read_programming_voltage(&self) -> Result<u32, Error> {
888 let mut voltage: u32 = 0;
889 unsafe {
890 self.interface.ioctl(
891 self.id.0,
892 IoctlId::READ_PROG_VOLTAGE,
893 std::ptr::null_mut::<libc::c_void>(),
894 (&mut voltage) as *mut _ as *mut libc::c_void,
895 )
896 }?;
897 Ok(voltage)
898 }
899}
900
901impl<'a> Drop for Device<'a> {
902 fn drop(&mut self) {
903 unsafe { (&self.interface.c_pass_thru_close)(self.id.0) };
904 }
905}
906
907impl<'a> Channel<'a> {
908 pub fn read(&self, buf: &mut [PassThruMsg], timeout: u32) -> Result<usize, Error> {
917 for msg in buf.iter_mut() {
918 msg.protocol_id = self.protocol as u32;
919 }
920 let mut num_msgs: u32 = buf.len() as u32;
921 let res = unsafe {
922 (&self.device.interface.c_pass_thru_read_msgs)(
923 self.id.0,
924 buf.as_mut_ptr(),
925 &mut num_msgs as *mut u32,
926 timeout,
927 )
928 };
929 if res != 0 {
930 return Err(Error::from_code(res));
931 }
932 Ok(num_msgs as usize)
933 }
934
935 pub fn read_once(&self, timeout: u32) -> Result<PassThruMsg, Error> {
937 let mut msg = PassThruMsg::new(self.protocol);
938
939 let mut num_msgs = 1 as u32;
940 let res = unsafe {
941 (&self.device.interface.c_pass_thru_read_msgs)(
942 self.id.0,
943 &mut msg as *mut PassThruMsg,
944 &mut num_msgs as *mut u32,
945 timeout,
946 )
947 };
948 if num_msgs == 0 {
949 Err(Error::BufferEmpty)
951 } else if res != 0 {
952 Err(Error::from_code(res))
953 } else {
954 Ok(msg)
955 }
956 }
957
958 pub fn write(&self, msgs: &mut [PassThruMsg], timeout: u32) -> Result<usize, Error> {
965 let mut num_msgs: u32 = msgs.len() as u32;
966 let res = unsafe {
967 (&self.device.interface.c_pass_thru_write_msgs)(
968 self.id.0,
969 msgs.as_mut_ptr(),
970 &mut num_msgs as *mut u32,
971 timeout,
972 )
973 };
974 if res != 0 {
975 return Err(Error::from_code(res));
976 }
977 Ok(num_msgs as usize)
978 }
979
980 pub fn start_message_filter(
986 &self,
987 filter_type: FilterType,
988 mask_msg: Option<&PassThruMsg>,
989 pattern_msg: Option<&PassThruMsg>,
990 flow_control_msg: Option<&PassThruMsg>,
991 ) -> Result<FilterId, Error> {
992 let mut msg_id: u32 = 0;
993
994 let mask_ptr = match mask_msg {
995 Some(msg) => msg as *const PassThruMsg,
996 None => std::ptr::null() as *const PassThruMsg,
997 };
998
999 let pattern_ptr = match pattern_msg {
1000 Some(msg) => msg as *const PassThruMsg,
1001 None => std::ptr::null() as *const PassThruMsg,
1002 };
1003
1004 let flow_control_ptr = match flow_control_msg {
1005 Some(msg) => msg as *const PassThruMsg,
1006 None => std::ptr::null() as *const PassThruMsg,
1007 };
1008
1009 let res = unsafe {
1010 (&self.device.interface.c_pass_thru_start_msg_filter)(
1011 self.id.0,
1012 filter_type as u32,
1013 mask_ptr,
1014 pattern_ptr,
1015 flow_control_ptr,
1016 &mut msg_id as *mut u32,
1017 )
1018 };
1019 if res != 0 {
1020 return Err(Error::from_code(res));
1021 }
1022 Ok(FilterId(msg_id))
1023 }
1024
1025 pub fn stop_message_filter(&self, filter_id: FilterId) -> Result<(), Error> {
1031 let res =
1032 unsafe { (&self.device.interface.c_pass_thru_stop_msg_filter)(self.id.0, filter_id.0) };
1033 if res != 0 {
1034 return Err(Error::from_code(res));
1035 }
1036 Ok(())
1037 }
1038
1039 pub fn start_periodic_message(
1047 &self,
1048 msg: &PassThruMsg,
1049 time_interval: u32,
1050 ) -> Result<MessageId, Error> {
1051 let mut msg_id = 0;
1052 let res = unsafe {
1053 (&self.device.interface.c_pass_thru_start_periodic_msg)(
1054 self.id.0,
1055 msg as *const PassThruMsg,
1056 &mut msg_id as *mut u32,
1057 time_interval,
1058 )
1059 };
1060 if res != 0 {
1061 return Err(Error::from_code(res));
1062 }
1063 Ok(MessageId(msg_id))
1064 }
1065
1066 pub fn stop_periodic_message(&self, msg_id: MessageId) -> Result<(), Error> {
1072 let res =
1073 unsafe { (&self.device.interface.c_pass_thru_stop_periodic_msg)(self.id.0, msg_id.0) };
1074 if res != 0 {
1075 return Err(Error::from_code(res));
1076 }
1077 Ok(())
1078 }
1079
1080 pub fn clear_transmit_buffer(&self) -> Result<(), Error> {
1082 unsafe {
1083 self.device.interface.ioctl(
1084 self.id.0,
1085 IoctlId::CLEAR_TX_BUFFER,
1086 std::ptr::null_mut::<libc::c_void>(),
1087 std::ptr::null_mut::<libc::c_void>(),
1088 )
1089 }?;
1090 Ok(())
1091 }
1092
1093 pub fn clear_periodic_messages(&self) -> Result<(), Error> {
1095 unsafe {
1096 self.device.interface.ioctl(
1097 self.id.0,
1098 IoctlId::CLEAR_PERIODIC_MSGS,
1099 std::ptr::null_mut::<libc::c_void>(),
1100 std::ptr::null_mut::<libc::c_void>(),
1101 )
1102 }?;
1103 Ok(())
1104 }
1105
1106 pub fn clear_receive_buffer(&self) -> Result<(), Error> {
1108 unsafe {
1109 self.device.interface.ioctl(
1110 self.id.0,
1111 IoctlId::CLEAR_RX_BUFFER,
1112 std::ptr::null_mut::<libc::c_void>(),
1113 std::ptr::null_mut::<libc::c_void>(),
1114 )
1115 }?;
1116 Ok(())
1117 }
1118
1119 pub fn clear_message_filters(&self) -> Result<(), Error> {
1121 unsafe {
1122 self.device.interface.ioctl(
1123 self.id.0,
1124 IoctlId::CLEAR_MSG_FILTERS,
1125 std::ptr::null_mut::<libc::c_void>(),
1126 std::ptr::null_mut::<libc::c_void>(),
1127 )
1128 }?;
1129 Ok(())
1130 }
1131
1132 pub fn get_config(&self, id: ConfigId) -> Result<u32, Error> {
1134 let mut item = SConfig {
1135 parameter: id as u32,
1136 value: 0,
1137 };
1138 let mut input = SConfigList {
1139 size: 1,
1140 config_ptr: &mut item as *mut SConfig,
1141 };
1142 unsafe {
1143 self.device.interface.ioctl(
1144 self.id.0,
1145 IoctlId::GET_CONFIG,
1146 &mut input as *mut _ as *mut libc::c_void,
1147 std::ptr::null_mut::<libc::c_void>(),
1148 )
1149 }?;
1150 Ok(item.value)
1151 }
1152
1153 pub fn set_config(&self, id: ConfigId, value: u32) -> Result<(), Error> {
1155 let mut item = SConfig {
1156 parameter: id as u32,
1157 value,
1158 };
1159 let mut input = SConfigList {
1160 size: 1,
1161 config_ptr: &mut item as *mut SConfig,
1162 };
1163 unsafe {
1164 self.device.interface.ioctl(
1165 self.id.0,
1166 IoctlId::SET_CONFIG,
1167 &mut input as *mut _ as *mut libc::c_void,
1168 std::ptr::null_mut::<libc::c_void>(),
1169 )
1170 }?;
1171 Ok(())
1172 }
1173}
1174
1175impl<'a> Drop for Channel<'a> {
1176 fn drop(&mut self) {
1177 unsafe { (&self.device.interface.c_pass_thru_disconnect)(self.id.0) };
1178 }
1179}
1180
1181#[derive(Debug)]
1183pub struct Driver {
1184 pub name: String,
1185 pub vendor: String,
1186 pub path: String,
1187}
1188
1189#[cfg(windows)]
1190pub fn drivers() -> io::Result<Vec<Driver>> {
1192 let passthru = match RegKey::predef(HKEY_LOCAL_MACHINE)
1193 .open_subkey(Path::new("SOFTWARE").join("PassThruSupport.04.04"))
1194 {
1195 Err(err) if err.kind() == io::ErrorKind::NotFound => {
1196 return Ok(Vec::new());
1197 }
1198 other => other,
1199 }?;
1200 let mut listings = Vec::new();
1201
1202 for name in passthru.enum_keys() {
1203 let name = name?;
1204 let key = passthru.open_subkey(name)?;
1205
1206 let device_name: String = key.get_value("Name")?;
1207 let vendor: String = key.get_value("Vendor")?;
1208 let path: String = key.get_value("FunctionLibrary")?;
1209
1210 listings.push(Driver {
1211 name: device_name,
1212 vendor,
1213 path,
1214 });
1215 }
1216
1217 Ok(listings)
1218}
1219
1220#[cfg(not(windows))]
1221pub fn drivers() -> io::Result<Vec<Driver>> {
1223 Ok(Vec::new())
1224}