sel4_shared_ring_buffer_smoltcp/
lib.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7#![no_std]
8
9extern crate alloc;
10
11use lock_api::{Mutex, RawMutex};
12use one_shot_mutex::unsync::RawOneShotMutex;
13use smoltcp::phy::{self, Device, DeviceCapabilities};
14use smoltcp::time::Instant;
15
16use sel4_abstract_allocator::AbstractAllocator;
17use sel4_abstract_rc::{AbstractRcT, RcT};
18use sel4_shared_memory::SharedMemoryRef;
19use sel4_shared_ring_buffer::{roles::Provide, RingBuffers};
20
21mod inner;
22
23pub use inner::{Error, PeerMisbehaviorError};
24use inner::{Inner, RxBufferIndex, TxBufferIndex};
25
26pub struct DeviceImpl<A: AbstractAllocator, R: RawMutex = RawOneShotMutex, P: AbstractRcT = RcT> {
27    inner: P::Rc<Mutex<R, Inner<A>>>,
28}
29
30impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> Clone for DeviceImpl<A, R, P> {
31    fn clone(&self) -> Self {
32        Self {
33            inner: self.inner.clone(),
34        }
35    }
36}
37
38impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> DeviceImpl<A, R, P> {
39    #[allow(clippy::too_many_arguments)]
40    pub fn new(
41        raw_mutex: R,
42        dma_region: SharedMemoryRef<'static, [u8]>,
43        bounce_buffer_allocator: A,
44        rx_ring_buffers: RingBuffers<'static, Provide, fn()>,
45        tx_ring_buffers: RingBuffers<'static, Provide, fn()>,
46        num_rx_buffers: usize,
47        rx_buffer_size: usize,
48        caps: DeviceCapabilities,
49    ) -> Result<Self, Error> {
50        Ok(Self {
51            inner: P::Rc::from(Mutex::from_raw(
52                raw_mutex,
53                Inner::new(
54                    dma_region,
55                    bounce_buffer_allocator,
56                    rx_ring_buffers,
57                    tx_ring_buffers,
58                    num_rx_buffers,
59                    rx_buffer_size,
60                    caps,
61                )?,
62            )),
63        })
64    }
65
66    fn inner(&self) -> &P::Rc<Mutex<R, Inner<A>>> {
67        &self.inner
68    }
69
70    pub fn poll(&self) -> bool {
71        self.inner().lock().poll().unwrap()
72    }
73
74    pub fn can_receive(&self) -> bool {
75        self.inner().lock().can_receive()
76    }
77
78    pub fn can_transmit(&self) -> bool {
79        self.inner().lock().can_transmit()
80    }
81
82    fn new_rx_token(&self, rx_buffer: RxBufferIndex) -> RxToken<A, R, P> {
83        RxToken {
84            buffer: rx_buffer,
85            shared: self.clone(),
86        }
87    }
88
89    fn new_tx_token(&self, tx_buffer: TxBufferIndex) -> TxToken<A, R, P> {
90        TxToken {
91            buffer: tx_buffer,
92            shared: self.clone(),
93        }
94    }
95}
96
97impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> Device for DeviceImpl<A, R, P> {
98    type RxToken<'a>
99        = RxToken<A, R, P>
100    where
101        A: 'a,
102        R: 'a,
103        P: 'a;
104    type TxToken<'a>
105        = TxToken<A, R, P>
106    where
107        A: 'a,
108        R: 'a,
109        P: 'a;
110
111    fn capabilities(&self) -> DeviceCapabilities {
112        self.inner().lock().caps().clone()
113    }
114
115    fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
116        self.inner()
117            .lock()
118            .receive()
119            .map(|(rx_ix, tx_ix)| (self.new_rx_token(rx_ix), self.new_tx_token(tx_ix)))
120    }
121
122    fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
123        self.inner()
124            .lock()
125            .transmit()
126            .map(|ix| self.new_tx_token(ix))
127    }
128}
129
130pub struct RxToken<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> {
131    buffer: RxBufferIndex,
132    shared: DeviceImpl<A, R, P>,
133}
134
135impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> phy::RxToken for RxToken<A, R, P> {
136    fn consume<T, F>(self, f: F) -> T
137    where
138        F: FnOnce(&mut [u8]) -> T,
139    {
140        let mut ptr = self.shared.inner().lock().consume_rx_start(self.buffer);
141        let r = f(unsafe { ptr.as_mut() });
142        self.shared.inner().lock().consume_rx_finish(self.buffer);
143        r
144    }
145}
146
147impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> Drop for RxToken<A, R, P> {
148    fn drop(&mut self) {
149        self.shared.inner().lock().drop_rx(self.buffer).unwrap()
150    }
151}
152
153pub struct TxToken<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> {
154    buffer: TxBufferIndex,
155    shared: DeviceImpl<A, R, P>,
156}
157
158impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> phy::TxToken for TxToken<A, R, P> {
159    fn consume<T, F>(self, len: usize, f: F) -> T
160    where
161        F: FnOnce(&mut [u8]) -> T,
162    {
163        self.shared
164            .inner()
165            .lock()
166            .consume_tx(self.buffer, len, f)
167            .unwrap()
168    }
169}
170
171impl<A: AbstractAllocator, R: RawMutex, P: AbstractRcT> Drop for TxToken<A, R, P> {
172    fn drop(&mut self) {
173        self.shared.inner().lock().drop_tx(self.buffer)
174    }
175}