aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/mac/driver.rs
blob: 41cca09e3236c40073a6f7fcc713f45f258c2fa1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#![deny(unused_must_use)]

use core::task::Context;

use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;

use crate::mac::event::MacEvent;
use crate::mac::runner::Runner;
use crate::mac::MTU;

pub struct Driver<'d> {
    runner: &'d Runner<'d>,
}

impl<'d> Driver<'d> {
    pub(crate) fn new(runner: &'d Runner<'d>) -> Self {
        Self { runner: runner }
    }
}

impl<'d> embassy_net_driver::Driver for Driver<'d> {
    // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a;
    // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a;
    type RxToken<'a>
        = RxToken<'d>
    where
        Self: 'a;
    type TxToken<'a>
        = TxToken<'d>
    where
        Self: 'a;

    fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
        if self.runner.rx_channel.poll_ready_to_receive(cx).is_ready()
            && self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready()
        {
            Some((
                RxToken {
                    rx: &self.runner.rx_channel,
                },
                TxToken {
                    tx: &self.runner.tx_channel,
                    tx_buf: &self.runner.tx_buf_channel,
                },
            ))
        } else {
            None
        }
    }

    fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
        if self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready() {
            Some(TxToken {
                tx: &self.runner.tx_channel,
                tx_buf: &self.runner.tx_buf_channel,
            })
        } else {
            None
        }
    }

    fn capabilities(&self) -> Capabilities {
        let mut caps = Capabilities::default();
        caps.max_transmission_unit = MTU;
        // caps.max_burst_size = Some(self.tx.len());
        caps
    }

    fn link_state(&mut self, _cx: &mut Context) -> LinkState {
        LinkState::Down
    }

    fn hardware_address(&self) -> HardwareAddress {
        // self.mac_addr
        HardwareAddress::Ieee802154([0; 8])
    }
}

pub struct RxToken<'d> {
    rx: &'d Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>,
}

impl<'d> embassy_net_driver::RxToken for RxToken<'d> {
    fn consume<R, F>(self, f: F) -> R
    where
        F: FnOnce(&mut [u8]) -> R,
    {
        // Only valid data events should be put into the queue

        let data_event = match self.rx.try_receive().unwrap() {
            MacEvent::McpsDataInd(data_event) => data_event,
            _ => unreachable!(),
        };

        f(&mut data_event.payload())
    }
}

pub struct TxToken<'d> {
    tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), 5>,
    tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], 5>,
}

impl<'d> embassy_net_driver::TxToken for TxToken<'d> {
    fn consume<R, F>(self, len: usize, f: F) -> R
    where
        F: FnOnce(&mut [u8]) -> R,
    {
        // Only valid tx buffers should be put into the queue
        let buf = self.tx_buf.try_receive().unwrap();
        let r = f(&mut buf[..len]);

        // The tx channel should always be of equal capacity to the tx_buf channel
        self.tx.try_send((buf, len)).unwrap();

        r
    }
}