Skip to content

Commit 4e03fb2

Browse files
committed
Implement embedded-hal traits
1 parent 678d174 commit 4e03fb2

File tree

2 files changed

+69
-23
lines changed

2 files changed

+69
-23
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ version = "2.0.0"
99

1010
[dependencies]
1111
byte_conv = "0.1.1"
12+
embedded-hal = { git = "https://github.com/timokroeger/embedded-hal.git", branch = "can" }
1213
hex = "^0.2"
1314
itertools = "^0.4"
1415
libc = "^0.2"
16+
nb = "1.0"
1517
neli = "0.5.0-rc1"
1618
nix = "^0.5"
1719
try_from = "0.2.0"

src/lib.rs

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@
4141
//! is available through the `AsRawFd`, `IntoRawFd` and `FromRawFd`
4242
//! implementations.
4343
44-
45-
4644
// clippy: do not warn about things like "SocketCAN" inside the docs
4745
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
4846

4947
extern crate byte_conv;
48+
extern crate embedded_hal;
5049
extern crate hex;
5150
extern crate itertools;
5251
extern crate libc;
52+
extern crate nb;
5353
extern crate neli;
5454
extern crate nix;
5555
extern crate try_from;
@@ -63,15 +63,17 @@ mod util;
6363
#[cfg(test)]
6464
mod tests;
6565

66-
use libc::{c_int, c_short, c_void, c_uint, c_ulong, socket, SOCK_RAW, close, bind, sockaddr, read,
67-
write, SOL_SOCKET, SO_RCVTIMEO, timespec, timeval, EINPROGRESS, SO_SNDTIMEO, time_t,
68-
suseconds_t, fcntl, F_GETFL, F_SETFL, O_NONBLOCK};
6966
use itertools::Itertools;
67+
use libc::{
68+
bind, c_int, c_short, c_uint, c_ulong, c_void, close, fcntl, read, sockaddr, socket,
69+
suseconds_t, time_t, timespec, timeval, write, EINPROGRESS, F_GETFL, F_SETFL, O_NONBLOCK,
70+
SOCK_RAW, SOL_SOCKET, SO_RCVTIMEO, SO_SNDTIMEO,
71+
};
7072
use nix::net::if_::if_nametoindex;
7173
pub use nl::CanInterface;
72-
use std::{error, fmt, io, time};
7374
use std::mem::{size_of, uninitialized};
7475
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
76+
use std::{error, fmt, io, time};
7577
use util::{set_socket_option, set_socket_option_mult};
7678

7779
/// Check an error return value for timeouts.
@@ -131,7 +133,6 @@ const CAN_RAW_RECV_OWN_MSGS: c_int = 4;
131133
// const CAN_RAW_FD_FRAMES: c_int = 5;
132134
const CAN_RAW_JOIN_FILTERS: c_int = 6;
133135

134-
135136
// get timestamp in a struct timeval (us accuracy)
136137
// const SIOCGSTAMP: c_int = 0x8906;
137138

@@ -156,7 +157,6 @@ pub const EFF_MASK: u32 = 0x1fffffff;
156157
/// valid bits in error frame
157158
pub const ERR_MASK: u32 = 0x1fffffff;
158159

159-
160160
/// an error mask that will cause SocketCAN to report all errors
161161
pub const ERR_MASK_ALL: u32 = ERR_MASK;
162162

@@ -214,7 +214,6 @@ impl error::Error for CanSocketOpenError {
214214
}
215215
}
216216

217-
218217
#[derive(Debug, Copy, Clone)]
219218
/// Error that occurs when creating CAN packets
220219
pub enum ConstructionError {
@@ -300,9 +299,11 @@ impl CanSocket {
300299
let bind_rv;
301300
unsafe {
302301
let sockaddr_ptr = &addr as *const CanAddr;
303-
bind_rv = bind(sock_fd,
304-
sockaddr_ptr as *const sockaddr,
305-
size_of::<CanAddr>() as u32);
302+
bind_rv = bind(
303+
sock_fd,
304+
sockaddr_ptr as *const sockaddr,
305+
size_of::<CanAddr>() as u32,
306+
);
306307
}
307308

308309
// FIXME: on fail, close socket (do not leak socketfds)
@@ -522,6 +523,23 @@ impl Drop for CanSocket {
522523
}
523524
}
524525

526+
impl embedded_hal::can::Transmitter for CanSocket {
527+
type Frame = CanFrame;
528+
type Error = io::Error;
529+
fn transmit(
530+
&mut self,
531+
frame: &Self::Frame,
532+
) -> Result<Option<Self::Frame>, nb::Error<Self::Error>> {
533+
self.write_frame(frame).map(|_| None).map_err(|io_err| {
534+
if io_err.kind() == io::ErrorKind::WouldBlock {
535+
nb::Error::WouldBlock
536+
} else {
537+
nb::Error::Other(io_err)
538+
}
539+
})
540+
}
541+
}
542+
525543
/// CanFrame
526544
///
527545
/// Uses the same memory layout as the underlying kernel struct for performance
@@ -565,7 +583,6 @@ impl CanFrame {
565583
_id |= EFF_FLAG;
566584
}
567585

568-
569586
if rtr {
570587
_id |= RTR_FLAG;
571588
}
@@ -582,13 +599,13 @@ impl CanFrame {
582599
}
583600

584601
Ok(CanFrame {
585-
_id: _id,
586-
_data_len: data.len() as u8,
587-
_pad: 0,
588-
_res0: 0,
589-
_res1: 0,
590-
_data: full_data,
591-
})
602+
_id: _id,
603+
_data_len: data.len() as u8,
604+
_pad: 0,
605+
_res0: 0,
606+
_res1: 0,
607+
_data: full_data,
608+
})
592609
}
593610

594611
/// Return the actual CAN ID (without EFF/RTR/ERR flags)
@@ -656,6 +673,33 @@ impl fmt::UpperHex for CanFrame {
656673
}
657674
}
658675

676+
impl embedded_hal::can::Frame for CanFrame {
677+
fn new_standard(id: u32, data: &[u8]) -> Self {
678+
CanFrame::new(id, data, false, false).unwrap()
679+
}
680+
fn new_extended(id: u32, data: &[u8]) -> Self {
681+
CanFrame::new(id, data, false, false).unwrap()
682+
}
683+
fn with_rtr(&mut self, dlc: usize) -> &mut Self {
684+
unimplemented!()
685+
}
686+
fn is_extended(&self) -> bool {
687+
self.is_extended()
688+
}
689+
fn is_remote_frame(&self) -> bool {
690+
self.is_rtr()
691+
}
692+
fn id(&self) -> u32 {
693+
self.id()
694+
}
695+
fn dlc(&self) -> usize {
696+
self._data_len as usize
697+
}
698+
fn data(&self) -> &[u8] {
699+
self.data()
700+
}
701+
}
702+
659703
/// CanFilter
660704
///
661705
/// Contains an internal id and mask. Packets are considered to be matched by
@@ -671,8 +715,8 @@ impl CanFilter {
671715
/// Construct a new CAN filter.
672716
pub fn new(id: u32, mask: u32) -> Result<CanFilter, ConstructionError> {
673717
Ok(CanFilter {
674-
_id: id,
675-
_mask: mask,
676-
})
718+
_id: id,
719+
_mask: mask,
720+
})
677721
}
678722
}

0 commit comments

Comments
 (0)