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}