nrf_modem/embassy_net_modem/
mod.rs

1// Modified from embassy-rs:
2// Licence: https://github.com/embassy-rs/embassy/blob/main/LICENSE-APACHE
3// Source file: https://github.com/embassy-rs/embassy/blob/a8cb8a7fe1f594b765dee4cfc6ff3065842c7c6e/embassy-net-nrf91/src/lib.rs
4
5use core::cell::RefCell;
6use core::mem::MaybeUninit;
7
8use embassy_futures::select::{select, Either};
9use embassy_net_driver_channel as ch;
10use embassy_time::Timer;
11
12pub mod context;
13
14use crate::socket::Socket;
15const MTU: usize = 1500;
16
17/// Network driver.
18///
19/// This is the type you have to pass to `embassy-net` when creating the network stack.
20pub type NetDriver<'a> = ch::Device<'a, MTU>;
21
22/// Create a new nrf-modem embassy-net driver.
23pub async fn new<'a>(state: &'a mut State) -> (NetDriver<'a>, Control<'a>, Runner<'a>) {
24    let state_inner = &*state
25        .inner
26        .write(RefCell::new(StateInner { net_socket: None }));
27
28    let control = Control { state: state_inner };
29
30    let (ch_runner, device) = ch::new(&mut state.ch, ch::driver::HardwareAddress::Ip);
31    let state_ch = ch_runner.state_runner();
32    state_ch.set_link_state(ch::driver::LinkState::Up);
33
34    let runner = Runner {
35        ch: ch_runner,
36        state: state_inner,
37    };
38
39    (device, control, runner)
40}
41
42/// Shared state for the driver.
43pub struct State {
44    ch: ch::State<MTU, 4, 4>,
45    inner: MaybeUninit<RefCell<StateInner>>,
46}
47
48impl State {
49    /// Create a new State.
50    pub const fn new() -> Self {
51        Self {
52            ch: ch::State::new(),
53            inner: MaybeUninit::uninit(),
54        }
55    }
56}
57
58impl Default for State {
59    fn default() -> Self {
60        Self::new()
61    }
62}
63
64struct StateInner {
65    net_socket: Option<Socket>,
66}
67
68/// Control handle for the driver.
69///
70/// You can use this object to control the modem at runtime, such as running AT commands.
71pub struct Control<'a> {
72    state: &'a RefCell<StateInner>,
73}
74
75pub(crate) const CAP_SIZE: usize = 256;
76
77impl<'a> Control<'a> {
78    /// Open the raw socket used for sending/receiving IP packets.
79    async fn open_raw_socket(&self) {
80        let socket = Socket::create(
81            crate::socket::SocketFamily::Raw,
82            crate::socket::SocketType::Raw,
83            crate::socket::SocketProtocol::IP,
84        )
85        .await
86        .unwrap();
87        self.state.borrow_mut().net_socket = Some(socket);
88    }
89
90    async fn close_raw_socket(&self) {
91        let sock = self.state.borrow_mut().net_socket.take();
92        if let Some(s) = sock {
93            s.deactivate().await.unwrap();
94        }
95    }
96    /// Run an AT command.
97    ///
98    /// The response is written in `resp` and its length returned.
99    pub async fn at_command(&self, commad: &[u8]) -> arrayvec::ArrayString<CAP_SIZE> {
100        crate::send_at(core::str::from_utf8(commad).unwrap())
101            .await
102            .unwrap()
103    }
104}
105
106/// Background runner for the driver.
107pub struct Runner<'a> {
108    ch: ch::Runner<'a, MTU>,
109    state: &'a RefCell<StateInner>,
110}
111
112impl<'a> Runner<'a> {
113    /// Run the driver operation in the background.
114    ///
115    /// You must run this in a background task, concurrently with all network operations.
116    pub async fn run(mut self) -> ! {
117        loop {
118            let (_, mut rx_chan, mut tx_chan) = self.ch.borrow_split();
119            let net_socket = self.state.borrow_mut().net_socket.take();
120
121            let mut rx_buf = [0; 2048];
122
123            let token: crate::CancellationToken = Default::default();
124
125            if let Some(socket) = net_socket {
126                let rx_fut = async {
127                    let size = socket
128                        .receive_with_cancellation(&mut rx_buf, &token)
129                        .await
130                        .unwrap();
131                    let buf = rx_chan.rx_buf().await;
132                    (size, buf)
133                };
134                let tx_fut = tx_chan.tx_buf();
135                match select(rx_fut, tx_fut).await {
136                    Either::First((size, buf)) => {
137                        if size > 0 {
138                            // Process received data
139                            buf[..size].copy_from_slice(&rx_buf[..size]);
140                            rx_chan.rx_done(size);
141                        }
142                    }
143                    Either::Second(buf) => {
144                        let size = buf.len();
145                        let mut remaining = size;
146                        while remaining > 0 {
147                            let size = socket
148                                .write_with_cancellation(&buf[size - remaining..], &token)
149                                .await
150                                .unwrap();
151                            remaining -= size;
152                        }
153                        tx_chan.tx_done();
154                    }
155                }
156
157                self.state.borrow_mut().net_socket.replace(socket);
158            } else {
159                Timer::after_millis(100).await
160            }
161        }
162    }
163}