Skip to main content

prns_runtime_embassy/manifold/driver/interface_seam/
mod.rs

1use embassy_sync::blocking_mutex::raw::RawMutex;
2use embassy_sync::channel::Sender;
3
4use crate::interfaces::{FrameSink, InterfaceId, PacketPhyStats};
5use crate::manifold::grant::{FrameTarget, GrantConsumer, GrantProducer};
6use crate::manifold::interface_seam::{InterfaceSeam, OutboundDisposition};
7
8use super::{EmbassyGrantConsumer, EmbassyGrantProducer};
9
10pub struct EmbassyInterfaceSeam<'a, M: RawMutex, const NOTIFY: usize, const FRAME: usize> {
11    id: InterfaceId,
12    inbound: EmbassyGrantProducer<'a, M, FRAME>,
13    notify: Sender<'a, M, InterfaceId, NOTIFY>,
14    outbound: EmbassyGrantConsumer<'a, M, FRAME>,
15    fill_entropy: fn(&mut [u8]),
16}
17
18impl<'a, M: RawMutex, const NOTIFY: usize, const FRAME: usize>
19    EmbassyInterfaceSeam<'a, M, NOTIFY, FRAME>
20{
21    #[must_use]
22    pub fn new(
23        id: InterfaceId,
24        inbound: EmbassyGrantProducer<'a, M, FRAME>,
25        notify: Sender<'a, M, InterfaceId, NOTIFY>,
26        outbound: EmbassyGrantConsumer<'a, M, FRAME>,
27        fill_entropy: fn(&mut [u8]),
28    ) -> Self {
29        Self {
30            id,
31            inbound,
32            notify,
33            outbound,
34            fill_entropy,
35        }
36    }
37}
38
39impl<M: RawMutex, const NOTIFY: usize, const FRAME: usize> InterfaceSeam
40    for EmbassyInterfaceSeam<'_, M, NOTIFY, FRAME>
41{
42    fn fill_entropy(&mut self, bytes: &mut [u8]) {
43        (self.fill_entropy)(bytes);
44    }
45
46    async fn inbound_sink(&mut self) -> &mut dyn FrameSink {
47        let slot = self.inbound.grant().await;
48        slot.target = FrameTarget::Direct(self.id);
49        slot
50    }
51
52    async fn commit_inbound(&mut self) {
53        let slot = self.inbound.grant().await;
54        if slot.len == 0 {
55            return;
56        }
57        self.inbound.commit();
58        let _ = self.notify.try_send(self.id);
59    }
60
61    async fn next_inbound_with_phy(&mut self, frame: &[u8], packet_phy: PacketPhyStats) {
62        let slot = self.inbound.grant().await;
63        slot.clear();
64        if slot.extend_from_slice(frame).is_err() {
65            return;
66        }
67        slot.packet_phy = packet_phy;
68        self.commit_inbound().await;
69    }
70
71    async fn next_outbound(&mut self) -> &[u8] {
72        self.outbound.release();
73        self.outbound.peek().await.frame()
74    }
75
76    fn accept_outbound_custody(&mut self) {
77        self.outbound.release();
78    }
79
80    fn complete_outbound(&mut self, _disposition: OutboundDisposition) {
81        self.outbound.release();
82    }
83}
84
85#[cfg(test)]
86mod tests;