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
use std::collections::VecDeque;

use async_std::{io, io::prelude::*, task};
use lock::Mutex;

use crate::scheme::{impl_event_scheme, Scheme, UartScheme};
use crate::utils::EventListener;
use crate::DeviceResult;

const UART_BUF_LEN: usize = 256;

lazy_static::lazy_static! {
    static ref UART_BUF: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::with_capacity(UART_BUF_LEN));
}

pub struct MockUart {
    listener: EventListener,
}

impl_event_scheme!(MockUart);

impl MockUart {
    pub fn new() -> Self {
        Self {
            listener: EventListener::new(),
        }
    }

    pub fn start_irq_service(irq_handler: impl Fn() + Send + Sync + 'static) {
        task::spawn(async move {
            loop {
                let mut buf = [0; UART_BUF_LEN];
                let remains = UART_BUF_LEN - UART_BUF.lock().len();
                if remains > 0 {
                    if let Ok(n) = io::stdin().read(&mut buf[..remains]).await {
                        {
                            let mut uart_buf = UART_BUF.lock();
                            for c in &buf[..n] {
                                uart_buf.push_back(*c);
                            }
                        }
                        irq_handler();
                    }
                }
                task::yield_now().await;
            }
        });
    }
}

impl Default for MockUart {
    fn default() -> Self {
        Self::new()
    }
}

impl Scheme for MockUart {
    fn name(&self) -> &str {
        "mock-uart"
    }

    fn handle_irq(&self, _irq_num: usize) {
        self.listener.trigger(());
    }
}

impl UartScheme for MockUart {
    fn try_recv(&self) -> DeviceResult<Option<u8>> {
        if let Some(c) = UART_BUF.lock().pop_front() {
            Ok(Some(c))
        } else {
            Ok(None)
        }
    }

    fn send(&self, ch: u8) -> DeviceResult {
        eprint!("{}", ch as char);
        Ok(())
    }

    fn write_str(&self, s: &str) -> DeviceResult {
        eprint!("{}", s);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::Arc;

    #[test]
    fn test_mock_uart() {
        let uart = Arc::new(MockUart::new());
        let u = uart.clone();
        MockUart::start_irq_service(move || u.handle_irq(0));

        uart.write_str("Hello, World!\n").unwrap();
        uart.write_str(format!("{} + {} = {}\n", 1, 2, 1 + 2).as_str())
            .unwrap();

        std::thread::sleep(std::time::Duration::from_millis(100));
        if let Some(ch) = uart.try_recv().unwrap() {
            uart.write_str(format!("received data: {:?}({:#x})\n", ch as char, ch).as_str())
                .unwrap();
        } else {
            uart.write_str("no data to receive\n").unwrap();
        }
    }
}