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
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Test virtual rng for a single device
//! Gets a specified number of random numbers by making sequential calls to get()
//! Full test harness for this can be found in nano33ble/test/virtual_rng_test

use crate::virtualizers::virtual_rng::VirtualRngMasterDevice;

use core::cell::Cell;

use kernel::debug;
use kernel::hil::rng::{Client, Continue, Rng};
use kernel::ErrorCode;

const NUM_REQUESTS: usize = 2;

// Use this test to test an Rng
pub struct TestRng<'a> {
    device_id: usize,
    device: &'a VirtualRngMasterDevice<'a>,
    num_requests: Cell<usize>,
}

impl<'a> TestRng<'a> {
    pub fn new(device_id: usize, device: &'a VirtualRngMasterDevice<'a>) -> TestRng<'a> {
        TestRng {
            device_id,
            device,
            num_requests: Cell::new(NUM_REQUESTS),
        }
    }

    pub fn get_random_nums(&self) {
        match self.device.get() {
            Ok(()) => debug!("Virtual RNG device {}: get Ok(())", self.device_id),
            _ => panic!("Virtual RNG test: unable to get random numbers"),
        }
    }
}

impl<'a> Client for TestRng<'a> {
    fn randomness_available(
        &self,
        randomness: &mut dyn Iterator<Item = u32>,
        error: Result<(), ErrorCode>,
    ) -> Continue {
        let val = randomness.next();
        if error != Ok(()) {
            panic!(
                "Virtual RNG device {}: randomness_available called with error {:?}",
                self.device_id, error
            );
        }

        let num_requests_remaining = self.num_requests.get();
        let data = val.unwrap();
        debug!("Random Number from device {}: {:08x}", self.device_id, data);
        self.num_requests.set(num_requests_remaining - 1);
        if num_requests_remaining == 1 {
            Continue::Done
        } else {
            let _ = self.device.get();
            Continue::More
        }
    }
}