aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/mac/control.rs
blob: e8d2f9f7b4c2b3f530ea698311c45374cf6d674e (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
use core::future::Future;
use core::task;
use core::task::Poll;

use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::MutexGuard;
use embassy_sync::signal::Signal;
use futures_util::FutureExt;

use super::commands::MacCommand;
use super::event::MacEvent;
use super::typedefs::MacError;
use crate::mac::runner::Runner;

pub struct Control<'a> {
    runner: &'a Runner<'a>,
}

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

    pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
    where
        T: MacCommand,
    {
        let _wm = self.runner.write_mutex.lock().await;

        self.runner.mac_subsystem.send_command(cmd).await
    }

    pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError>
    where
        T: MacCommand,
    {
        let rm = self.runner.read_mutex.lock().await;
        let _wm = self.runner.write_mutex.lock().await;
        let token = EventToken::new(self.runner, rm);

        self.runner.mac_subsystem.send_command(cmd).await?;

        Ok(token)
    }
}

pub struct EventToken<'a> {
    runner: &'a Runner<'a>,
    _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>,
}

impl<'a> EventToken<'a> {
    pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self {
        // Enable event receiving
        runner.rx_event_channel.lock(|s| {
            *s.borrow_mut() = Some(Signal::new());
        });

        Self {
            runner: runner,
            _mutex_guard: mutex_guard,
        }
    }
}

impl<'a> Future for EventToken<'a> {
    type Output = MacEvent<'a>;

    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        self.get_mut().runner.rx_event_channel.lock(|s| {
            let signal = s.borrow_mut();
            let signal = match &*signal {
                Some(s) => s,
                _ => unreachable!(),
            };

            let result = match signal.wait().poll_unpin(cx) {
                Poll::Ready(mac_event) => Poll::Ready(mac_event),
                Poll::Pending => Poll::Pending,
            };

            result
        })
    }
}

impl<'a> Drop for EventToken<'a> {
    fn drop(&mut self) {
        // Disable event receiving
        // This will also drop the contained event, if it exists, and will free up receiving the next event
        self.runner.rx_event_channel.lock(|s| {
            *s.borrow_mut() = None;
        });
    }
}