Skip to content

Commit e85f410

Browse files
committed
feat: Port missing IsoTpBehaviour flags
Extend API to add flags
1 parent a0b543a commit e85f410

File tree

1 file changed

+72
-35
lines changed

1 file changed

+72
-35
lines changed

src/lib.rs

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ bitflags! {
135135
const CAN_ISOTP_FORCE_RXSTMIN = 0x100;
136136
/// different rx extended addressing
137137
const CAN_ISOTP_RX_EXT_ADDR = 0x200;
138+
/// wait for tx completion
139+
const CAN_ISOTP_WAIT_TX_DONE = 0x0400;
140+
/// 1-to-N functional addressing
141+
const CAN_ISOTP_SF_BROADCAST = 0x0800;
142+
/// 1-to-N transmission w/o FC
143+
const CAN_ISOTP_CF_BROADCAST = 0x1000;
144+
/// dynamic FC parameters BS/STmin
145+
const CAN_ISOTP_DYN_FC_PARMS = 0x2000;
138146
}
139147
}
140148

@@ -220,7 +228,12 @@ impl IsoTpOptions {
220228
IsoTpBehaviour::from_bits(self.flags)
221229
}
222230

223-
/// set flags for isotp behaviour.
231+
/// add the given ISO-TP behavior flags to the current flags
232+
pub fn add_flags(&mut self, flags: IsoTpBehaviour) {
233+
self.flags |= flags.bits();
234+
}
235+
236+
/// replace the current ISO-TP behavior flags with the given flags
224237
pub fn set_flags(&mut self, flags: IsoTpBehaviour) {
225238
self.flags = flags.bits();
226239
}
@@ -412,6 +425,13 @@ pub struct IsoTpSocket {
412425
}
413426

414427
impl IsoTpSocket {
428+
fn new(fd: i32) -> Self {
429+
Self {
430+
fd,
431+
recv_buffer: [0x00; RECV_BUFFER_SIZE],
432+
}
433+
}
434+
415435
/// Open a named CAN ISO-TP device.
416436
///
417437
/// Usually the more common case, opens a socket can device by name, such
@@ -479,24 +499,28 @@ impl IsoTpSocket {
479499
rx_flow_control_options: Option<FlowControlOptions>,
480500
link_layer_options: Option<LinkLayerOptions>,
481501
) -> Result<Self, Error> {
482-
let rx_id = match rx_id.into() {
483-
Id::Standard(standard_id) => standard_id.as_raw() as u32,
484-
Id::Extended(extended_id) => extended_id.as_raw() | EFF_FLAG,
485-
};
486-
let tx_id = match tx_id.into() {
487-
Id::Standard(standard_id) => standard_id.as_raw() as u32,
488-
Id::Extended(extended_id) => extended_id.as_raw() | EFF_FLAG,
489-
};
490502
let addr = CanAddr {
491503
_af_can: AF_CAN,
492504
if_index,
493-
rx_id,
494-
tx_id,
505+
rx_id: Self::to_raw_can_id(rx_id),
506+
tx_id: Self::to_raw_can_id(tx_id),
495507
_pgn: 0,
496508
_addr: 0,
497509
};
498510

499-
// open socket
511+
let sock_fd = Self::open_socket()?;
512+
Self::set_socket_opts(
513+
sock_fd,
514+
isotp_options,
515+
rx_flow_control_options,
516+
link_layer_options,
517+
)?;
518+
Self::bind_addr(sock_fd, addr)?;
519+
520+
Ok(Self::new(sock_fd))
521+
}
522+
523+
fn open_socket() -> Result<i32, Error> {
500524
let sock_fd;
501525
unsafe {
502526
sock_fd = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP);
@@ -505,7 +529,37 @@ impl IsoTpSocket {
505529
if sock_fd == -1 {
506530
return Err(Error::from(io::Error::last_os_error()));
507531
}
532+
Ok(sock_fd)
533+
}
534+
535+
fn bind_addr(sock_fd: i32, addr: CanAddr) -> Result<(), Error> {
536+
let sockaddr_ptr = &addr as *const CanAddr;
508537

538+
let bind_rv = unsafe {
539+
bind(
540+
sock_fd,
541+
sockaddr_ptr as *const sockaddr,
542+
size_of::<CanAddr>().try_into().unwrap(),
543+
)
544+
};
545+
546+
// FIXME: on fail, close socket (do not leak socketfds)
547+
if bind_rv == -1 {
548+
let e = io::Error::last_os_error();
549+
unsafe {
550+
close(sock_fd);
551+
}
552+
return Err(Error::from(e));
553+
}
554+
Ok(())
555+
}
556+
557+
fn set_socket_opts(
558+
sock_fd: i32,
559+
isotp_options: Option<IsoTpOptions>,
560+
rx_flow_control_options: Option<FlowControlOptions>,
561+
link_layer_options: Option<LinkLayerOptions>,
562+
) -> Result<(), Error> {
509563
// Set IsoTpOptions
510564
if let Some(isotp_options) = isotp_options {
511565
let isotp_options_ptr: *const c_void = &isotp_options as *const _ as *const c_void;
@@ -558,31 +612,14 @@ impl IsoTpSocket {
558612
return Err(Error::from(io::Error::last_os_error()));
559613
}
560614
}
615+
Ok(())
616+
}
561617

562-
// bind it
563-
let bind_rv;
564-
unsafe {
565-
let sockaddr_ptr = &addr as *const CanAddr;
566-
bind_rv = bind(
567-
sock_fd,
568-
sockaddr_ptr as *const sockaddr,
569-
size_of::<CanAddr>().try_into().unwrap(),
570-
);
571-
}
572-
573-
// FIXME: on fail, close socket (do not leak socketfds)
574-
if bind_rv == -1 {
575-
let e = io::Error::last_os_error();
576-
unsafe {
577-
close(sock_fd);
578-
}
579-
return Err(Error::from(e));
618+
fn to_raw_can_id(id: impl Into<Id>) -> u32 {
619+
match id.into() {
620+
Id::Standard(standard_id) => standard_id.as_raw() as u32,
621+
Id::Extended(extended_id) => extended_id.as_raw() | EFF_FLAG,
580622
}
581-
582-
Ok(Self {
583-
fd: sock_fd,
584-
recv_buffer: [0x00; RECV_BUFFER_SIZE],
585-
})
586623
}
587624

588625
fn close(&mut self) -> io::Result<()> {

0 commit comments

Comments
 (0)