emcyphal_driver/
link.rs

1//! Channels connecting driver and Emcyphal stack
2
3use core::future::poll_fn;
4use emcyphal_core::{NodeId, PrioritySet, SubjectId};
5
6use crate::frame::{Frame, Mtu};
7use crate::internal;
8
9/// Receiver filter update request
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum FilterUpdate {
12    AddSubject(SubjectId),
13    RemoveSubjectRange([SubjectId; 2]),
14    AddDestination(NodeId),
15    RemoveDestinationRange([NodeId; 2]),
16}
17
18/// Producer of receiver filter update requests
19///
20/// Range removal requests may cover the entire ID range. The driver should efficiently process
21/// range requests with complexity bounded by the number of removed or remaining entries, not the
22/// range size.
23pub struct RxFilter<'a>(&'a (dyn internal::DynamicRxFilter + Sync));
24
25impl<'a> RxFilter<'a> {
26    /// Asynchronously fetches the next filter update request. Safe to drop.
27    pub async fn pop(&mut self) -> FilterUpdate {
28        poll_fn(|cx| self.0.poll_pop(cx)).await
29    }
30}
31
32/// Consumer of received frames
33///
34/// The frame destination address should be consistent with the data specifier:
35/// * `None` for messages
36/// * `Some` for services
37///
38/// Frame timestamp encodes the instant it appeared on the bus:
39/// * reception time for regular frames
40/// * transmission time for loop-back frames
41///
42/// MTU must be constant for the link lifetime. A driver in FD mode should set FD MTU for
43/// Classic frames as well.
44///
45/// Drivers may push unsolicited frames, though such traffic affects performance.
46///
47/// The channel may block only for short periods.
48pub struct Rx<'a>(&'a (dyn internal::DynamicRx + Sync));
49
50impl<'a> Rx<'a> {
51    /// Asynchronously pushes a frame. Safe to drop.
52    pub async fn push(&mut self, frame: Frame, mtu: Mtu) {
53        poll_fn(|cx| self.0.poll_push(cx, &frame, mtu)).await;
54    }
55}
56
57/// Producer of frames for transmission
58///
59/// MTU must be constant for the link lifetime.
60///
61/// The frame destination address should be consistent with the data specifier:
62/// * `None` for messages
63/// * `Some` for services
64///
65/// Frame timestamp represents a transmission deadline. Driver should drop frames
66/// that were not transmitted in time.
67pub struct Tx<'a>(&'a (dyn internal::DynamicTx + Sync));
68
69impl<'a> Tx<'a> {
70    /// Asynchronously fetches the next frame. Safe to drop.
71    ///
72    /// Blocks until a frame with a priority matching the priority mask is available.
73    /// Returns the frame with the highest matching priority.
74    pub async fn pop(&mut self, priority_mask: PrioritySet, mtu: Mtu) -> Frame {
75        poll_fn(|cx| self.0.poll_pop(cx, priority_mask, mtu)).await
76    }
77}
78
79/// Channel container. A driver should consume it.
80pub struct Link<'a>(&'a (dyn internal::DynamicLink + Sync));
81
82impl<'a> Link<'a> {
83    pub fn new(access: &'a (dyn internal::DynamicLink + Sync)) -> Self {
84        Self(access)
85    }
86
87    pub fn split(self) -> (RxFilter<'a>, Rx<'a>, Tx<'a>) {
88        (RxFilter(self.0), Rx(self.0), Tx(self.0))
89    }
90}