From 895fd551a9ecb91fce4e7f0bbd333950216cc80c Mon Sep 17 00:00:00 2001 From: CosminGGeorgescu Date: Thu, 5 Oct 2023 13:51:41 +0300 Subject: [PATCH 1/3] setup --- Cargo.toml | 10 ++++++---- apis/rng/Cargo.toml | 15 +++++++++++++++ apis/rng/src/lib.rs | 2 ++ apis/rng/src/tests.rs | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 apis/rng/Cargo.toml create mode 100644 apis/rng/src/lib.rs create mode 100644 apis/rng/src/tests.rs diff --git a/Cargo.toml b/Cargo.toml index 808c43492..752ddc714 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,12 +16,12 @@ version = "0.1.0" rust-version = "1.70" [dependencies] -libtock_adc = { path = "apis/adc"} +libtock_adc = { path = "apis/adc" } libtock_air_quality = { path = "apis/air_quality" } libtock_alarm = { path = "apis/alarm" } libtock_ambient_light = { path = "apis/ambient_light" } libtock_buttons = { path = "apis/buttons" } -libtock_buzzer = {path = "apis/buzzer"} +libtock_buzzer = { path = "apis/buzzer" } libtock_console = { path = "apis/console" } libtock_debug_panic = { path = "panic_handlers/debug_panic" } libtock_gpio = { path = "apis/gpio" } @@ -30,12 +30,13 @@ libtock_low_level_debug = { path = "apis/low_level_debug" } libtock_ninedof = { path = "apis/ninedof" } libtock_platform = { path = "platform" } libtock_proximity = { path = "apis/proximity" } +libtock_rng = { path = "apis/rng" } libtock_runtime = { path = "runtime" } -libtock_sound_pressure = {path = "apis/sound_pressure"} +libtock_sound_pressure = { path = "apis/sound_pressure" } libtock_temperature = { path = "apis/temperature" } [build-dependencies] -libtock_build_scripts = { path = "build_scripts"} +libtock_build_scripts = { path = "build_scripts" } [profile.dev] debug = true @@ -62,6 +63,7 @@ members = [ "apis/low_level_debug", "apis/ninedof", "apis/proximity", + "apis/rng", "apis/temperature", "panic_handlers/debug_panic", "panic_handlers/small_panic", diff --git a/apis/rng/Cargo.toml b/apis/rng/Cargo.toml new file mode 100644 index 000000000..8f7d24933 --- /dev/null +++ b/apis/rng/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "libtock_rng" +version = "0.1.0" +authors = ["Tock Project Developers "] +license = "Apache-2.0 OR MIT" +edition = "2021" +repository = "https://www.github.com/tock/libtock-rs" +rust-version.workspace = true +description = "libtock buttons driver" + +[dependencies] +libtock_platform = { path = "../../platform" } + +[dev-dependencies] +libtock_unittest = { path = "../../unittest" } diff --git a/apis/rng/src/lib.rs b/apis/rng/src/lib.rs new file mode 100644 index 000000000..87c277195 --- /dev/null +++ b/apis/rng/src/lib.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +mod tests; diff --git a/apis/rng/src/tests.rs b/apis/rng/src/tests.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/apis/rng/src/tests.rs @@ -0,0 +1 @@ + From a89873ee50d37f8b43c50d2b29467d14a4c0abbb Mon Sep 17 00:00:00 2001 From: CosminGGeorgescu Date: Mon, 9 Oct 2023 01:56:11 +0300 Subject: [PATCH 2/3] synchronous api + example --- apis/rng/src/lib.rs | 43 ++++++++++++++++++ examples/rng.rs | 49 ++++++++++++++++++++ src/lib.rs | 4 ++ unittest/src/fake/mod.rs | 2 + unittest/src/fake/rng/mod.rs | 83 ++++++++++++++++++++++++++++++++++ unittest/src/fake/rng/tests.rs | 52 +++++++++++++++++++++ 6 files changed, 233 insertions(+) create mode 100644 examples/rng.rs create mode 100644 unittest/src/fake/rng/mod.rs create mode 100644 unittest/src/fake/rng/tests.rs diff --git a/apis/rng/src/lib.rs b/apis/rng/src/lib.rs index 87c277195..1bce88d75 100644 --- a/apis/rng/src/lib.rs +++ b/apis/rng/src/lib.rs @@ -1,2 +1,45 @@ +#![no_std] + #[cfg(test)] mod tests; + +use core::cell::Cell; +use libtock_platform::{share, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls}; + +const DRIVER_NUM: u32 = 0x40001; +const EXISTS: u32 = 0; +const GET_BYTES: u32 = 1; + +pub struct Rng(S); + +impl Rng { + /// Check if the RNG kernel driver exists + pub fn exists() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() + } + + /// Ask to fill the provided `buf` with `n` random bytes. + /// If `n > buf.len()`, it will simply fill the whole buffer. + pub fn get_bytes_sync(buf: &mut [u8], n: u32) -> Result<(), ErrorCode> { + let called = Cell::new(false); + share::scope::<(AllowRw, Subscribe), _, _>(|handle| { + let (allow_ro, subscribe) = handle.split(); + + // Share the provided buffer with the kernel + S::allow_rw::(allow_ro, buf)?; + + // Subscribe for an upcall with the kernel + S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &called)?; + + // Send the command to the kernel driver to fill the allowed_readwrite buffer + S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result()?; + + // Wait for a callback to happen + while !called.get() { + S::yield_wait(); + } + + Ok(()) + }) + } +} diff --git a/examples/rng.rs b/examples/rng.rs new file mode 100644 index 000000000..034c42f51 --- /dev/null +++ b/examples/rng.rs @@ -0,0 +1,49 @@ +#![no_main] +#![no_std] + +use core::fmt::Write; +use libtock::alarm::Alarm; +use libtock::console::Console; +use libtock::rng::Rng; +use libtock::runtime::{set_main, stack_size}; +use libtock_alarm::Milliseconds; + +set_main! {main} +stack_size! {0x300} + +struct Randomness<'a, const N: usize>(&'a [u8; N]); + +impl<'a, const N: usize> core::fmt::Display for Randomness<'a, N> { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut console_writer = Console::writer(); + let mut bytes = self.0.iter(); + while let Some(&byte) = bytes.next() { + write!(console_writer, "{byte:02x}")?; + } + Ok(()) + } +} + +fn main() { + if let Err(e) = Rng::exists() { + writeln!( + Console::writer(), + "RNG DRIVER DOESN'T EXIST\nERROR: {e:?}\n" + ) + .unwrap(); + return; + } + + let mut buffer: [u8; 32] = Default::default(); + let n: u32 = 32; + let mut console_writer = Console::writer(); + loop { + match Rng::get_bytes_sync(&mut buffer, n) { + Ok(()) => { + write!(console_writer, "Randomness: {}\n", Randomness(&buffer)).unwrap(); + } + Err(e) => writeln!(console_writer, "Error while getting bytes {e:?}\n").unwrap(), + } + Alarm::sleep_for(Milliseconds(2000)).unwrap(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 5d6f32e0f..864732eff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,6 +69,10 @@ pub mod proximity { use libtock_proximity as proximity; pub type Proximity = proximity::Proximity; } +pub mod rng { + use libtock_rng as rng; + pub type Rng = rng::Rng; +} pub mod sound_pressure { use libtock_sound_pressure as sound_pressure; pub type SoundPressure = sound_pressure::SoundPressure; diff --git a/unittest/src/fake/mod.rs b/unittest/src/fake/mod.rs index 72d3f5b87..78b1a4410 100644 --- a/unittest/src/fake/mod.rs +++ b/unittest/src/fake/mod.rs @@ -22,6 +22,7 @@ mod leds; mod low_level_debug; mod ninedof; mod proximity; +mod rng; mod sound_pressure; mod syscall_driver; mod syscalls; @@ -40,6 +41,7 @@ pub use leds::Leds; pub use low_level_debug::{LowLevelDebug, Message}; pub use ninedof::{NineDof, NineDofData}; pub use proximity::Proximity; +pub use rng::Rng; pub use sound_pressure::SoundPressure; pub use syscall_driver::SyscallDriver; pub use syscalls::Syscalls; diff --git a/unittest/src/fake/rng/mod.rs b/unittest/src/fake/rng/mod.rs new file mode 100644 index 000000000..ac7df3f48 --- /dev/null +++ b/unittest/src/fake/rng/mod.rs @@ -0,0 +1,83 @@ +use libtock_platform::ErrorCode; + +use crate::{DriverInfo, DriverShareRef, RwAllowBuffer}; +use std::cell::{Cell, RefCell}; +use std::ops::DerefMut; + +pub struct Rng { + busy: Cell, + share_ref: DriverShareRef, + buffer: RefCell, + bytes: Cell>, +} + +impl Rng { + pub fn new() -> std::rc::Rc { + std::rc::Rc::new(Rng { + busy: Cell::new(false), + share_ref: Default::default(), + buffer: Default::default(), + bytes: Default::default(), + }) + } + + pub fn is_busy(&self) -> bool { + self.busy.get() + } +} + +impl crate::fake::SyscallDriver for Rng { + fn info(&self) -> crate::DriverInfo { + DriverInfo::new(DRIVER_NUM).upcall_count(1) + } + + fn register(&self, share_ref: DriverShareRef) { + self.share_ref.replace(share_ref); + } + + fn command(&self, command_id: u32, argument0: u32, _: u32) -> libtock_platform::CommandReturn { + match command_id { + EXISTS => crate::command_return::success(), + GET_BYTES => { + if self.busy.get() { + return crate::command_return::failure(ErrorCode::Busy); + } + self.busy.set(true); + // Mutably borrows RwAllowBuffer from the RefCell as to not take the buffer out + let mut allow_rw_buffer = self.buffer.borrow_mut(); + let inner_buffer = (*allow_rw_buffer).deref_mut(); + inner_buffer.copy_from_slice( + &self.bytes.take()[0..core::cmp::min(inner_buffer.len(), argument0 as usize)], + ); + crate::command_return::success() + } + _ => crate::command_return::failure(ErrorCode::NoSupport), + } + } + + fn allow_readwrite( + &self, + buffer_num: u32, + buffer: crate::RwAllowBuffer, + ) -> Result { + if buffer_num == 0 { + Ok(self.buffer.replace(buffer)) + } else { + Err((buffer, ErrorCode::Invalid)) + } + } +} + +#[cfg(test)] +mod tests; + +// ----------------- +// RNG DRIVER NUMBER +// ----------------- +const DRIVER_NUM: u32 = 0x40001; + +// ------------------- +// RNG COMMAND NUMBERS +// ------------------- +const EXISTS: u32 = 0; +const GET_BYTES: u32 = 1; diff --git a/unittest/src/fake/rng/tests.rs b/unittest/src/fake/rng/tests.rs new file mode 100644 index 000000000..ee59511eb --- /dev/null +++ b/unittest/src/fake/rng/tests.rs @@ -0,0 +1,52 @@ +use libtock_platform::{share, DefaultConfig}; + +use crate::{fake, RwAllowBuffer}; + +// Tests the command implementation. +#[test] +fn command() { + use fake::SyscallDriver; + + let rng = fake::Rng::new(); + + // Test driver response to an existence check request + assert!(rng.command(fake::rng::EXISTS, 0, 0).is_success()); + + // Test driver response for sharing a buffer + // to a valid and invalid buffer index, respectively + assert!(rng.allow_readwrite(0, RwAllowBuffer::default()).is_ok()); + assert!(rng.allow_readwrite(1, RwAllowBuffer::default()).is_err()); +} + +// Integration test that verifies Console works with fake::Kernel and +// libtock_platform::Syscalls. +#[test] +fn kernel_integration() { + use libtock_platform::Syscalls; + + let kernel = fake::Kernel::new(); + let rng = fake::Rng::new(); + // Predetermined sample of RNG data "read" from the RNG low-level driver + // that will be put into the shared buffer + let bytes = [0_u8, 1_u8, 2_u8, 3_u8, 4_u8]; + rng.bytes.set(bytes.to_vec()); + kernel.add_driver(&rng); + + // Test driver response to an existence check request + assert!(fake::Syscalls::command(fake::rng::DRIVER_NUM, 0, 0, 0).is_success()); + + // Buffer to be shared with the kernel and filled with random bytes + let mut buffer: [u8; 5] = [0; 5]; + share::scope(|allow_rw| { + // Register the provided buffer + fake::Syscalls::allow_rw::( + allow_rw, + &mut buffer, + ) + .unwrap(); + // Test driver response to buffer fill requests + assert!(fake::Syscalls::command(fake::rng::DRIVER_NUM, 1, 5, 0).is_success()); + }); + // Additionally check that the buffer has been correctly filled + assert_eq!(buffer.cmp(&bytes), core::cmp::Ordering::Equal); +} From 9695aeda5c27cad524c51788351f6f237b0c2024 Mon Sep 17 00:00:00 2001 From: CosminGGeorgescu Date: Thu, 7 Dec 2023 03:01:21 +0200 Subject: [PATCH 3/3] async api + example --- apis/rng/Cargo.toml | 7 ++- apis/rng/src/lib.rs | 68 ++++++++++++++++++++++++---- apis/rng/src/tests.rs | 1 - examples/rng.rs | 29 ++++++------ examples/rng_async.rs | 44 ++++++++++++++++++ src/lib.rs | 1 + unittest/src/fake/mod.rs | 2 - unittest/src/fake/rng/mod.rs | 83 ---------------------------------- unittest/src/fake/rng/tests.rs | 52 --------------------- 9 files changed, 121 insertions(+), 166 deletions(-) delete mode 100644 apis/rng/src/tests.rs create mode 100644 examples/rng_async.rs delete mode 100644 unittest/src/fake/rng/mod.rs delete mode 100644 unittest/src/fake/rng/tests.rs diff --git a/apis/rng/Cargo.toml b/apis/rng/Cargo.toml index 8f7d24933..e5a2a22af 100644 --- a/apis/rng/Cargo.toml +++ b/apis/rng/Cargo.toml @@ -1,12 +1,15 @@ [package] name = "libtock_rng" version = "0.1.0" -authors = ["Tock Project Developers "] +authors = [ + "Tock Project Developers ", + "Cosmin Gabriel Georgescu ", +] license = "Apache-2.0 OR MIT" edition = "2021" repository = "https://www.github.com/tock/libtock-rs" rust-version.workspace = true -description = "libtock buttons driver" +description = "libtock rng driver" [dependencies] libtock_platform = { path = "../../platform" } diff --git a/apis/rng/src/lib.rs b/apis/rng/src/lib.rs index 1bce88d75..e25478f20 100644 --- a/apis/rng/src/lib.rs +++ b/apis/rng/src/lib.rs @@ -1,14 +1,9 @@ #![no_std] -#[cfg(test)] -mod tests; - use core::cell::Cell; -use libtock_platform::{share, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls}; - -const DRIVER_NUM: u32 = 0x40001; -const EXISTS: u32 = 0; -const GET_BYTES: u32 = 1; +use libtock_platform::{ + share, subscribe::OneId, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, +}; pub struct Rng(S); @@ -18,15 +13,47 @@ impl Rng { S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() } + /// Request `n` bytes of randomness in an asynchronous way. + /// Users must first share a buffer slice with the kernel and register an Rng listener + pub fn get_bytes_async(n: u32) -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result() + } + + /// Share a buffer slice with the kernel. + /// Must be used in conjunction with the `share::scope` function + pub fn allow_buffer<'share>( + buf: &'share mut [u8], + allow_rw: share::Handle>, + ) -> Result<(), ErrorCode> { + S::allow_rw::(allow_rw, buf) + } + + pub fn unallow_buffer() { + S::unallow_rw(DRIVER_NUM, 0) + } + + /// Register an Rng listener to be called when an upcall is serviced + /// Must be used in conjunction with the `share::scope` function + pub fn register_listener<'share, F: Fn(u32)>( + listener: &'share RngListener, + subscribe: share::Handle>, + ) -> Result<(), ErrorCode> { + S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener) + } + + pub fn unregister_listener() { + S::unsubscribe(DRIVER_NUM, 0) + } + /// Ask to fill the provided `buf` with `n` random bytes. /// If `n > buf.len()`, it will simply fill the whole buffer. pub fn get_bytes_sync(buf: &mut [u8], n: u32) -> Result<(), ErrorCode> { let called = Cell::new(false); share::scope::<(AllowRw, Subscribe), _, _>(|handle| { - let (allow_ro, subscribe) = handle.split(); + let (allow_rw, subscribe) = handle.split(); // Share the provided buffer with the kernel - S::allow_rw::(allow_ro, buf)?; + S::allow_rw::(allow_rw, buf)?; // Subscribe for an upcall with the kernel S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &called)?; @@ -43,3 +70,24 @@ impl Rng { }) } } + +/// The provided listener to be called. +/// Interior function operates on the number of random bytes filled into the buffer +pub struct RngListener(pub F); + +impl Upcall> for RngListener { + fn upcall(&self, _: u32, arg1: u32, _: u32) { + (self.0)(arg1) + } +} + +// ------------- +// DRIVER NUMBER +// ------------- +const DRIVER_NUM: u32 = 0x40001; + +// --------------- +// COMMAND NUMBERS +// --------------- +const EXISTS: u32 = 0; +const GET_BYTES: u32 = 1; diff --git a/apis/rng/src/tests.rs b/apis/rng/src/tests.rs deleted file mode 100644 index 8b1378917..000000000 --- a/apis/rng/src/tests.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/rng.rs b/examples/rng.rs index 034c42f51..620ab1383 100644 --- a/examples/rng.rs +++ b/examples/rng.rs @@ -1,24 +1,22 @@ -#![no_main] #![no_std] +#![no_main] use core::fmt::Write; -use libtock::alarm::Alarm; +use libtock::alarm::{Alarm, Milliseconds}; use libtock::console::Console; use libtock::rng::Rng; use libtock::runtime::{set_main, stack_size}; -use libtock_alarm::Milliseconds; -set_main! {main} stack_size! {0x300} +set_main! {main} struct Randomness<'a, const N: usize>(&'a [u8; N]); impl<'a, const N: usize> core::fmt::Display for Randomness<'a, N> { - fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let mut console_writer = Console::writer(); + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut bytes = self.0.iter(); while let Some(&byte) = bytes.next() { - write!(console_writer, "{byte:02x}")?; + write!(f, "{byte:02x}")?; } Ok(()) } @@ -26,24 +24,23 @@ impl<'a, const N: usize> core::fmt::Display for Randomness<'a, N> { fn main() { if let Err(e) = Rng::exists() { - writeln!( - Console::writer(), - "RNG DRIVER DOESN'T EXIST\nERROR: {e:?}\n" - ) - .unwrap(); + writeln!(Console::writer(), "RNG DRIVER ERROR: {e:?}").unwrap(); return; } + let mut console_writer = Console::writer(); let mut buffer: [u8; 32] = Default::default(); let n: u32 = 32; - let mut console_writer = Console::writer(); + loop { match Rng::get_bytes_sync(&mut buffer, n) { Ok(()) => { - write!(console_writer, "Randomness: {}\n", Randomness(&buffer)).unwrap(); + let _ = writeln!(console_writer, "Randomness: {}", Randomness(&buffer)); + } + Err(e) => { + let _ = writeln!(console_writer, "Error while getting bytes {e:?}"); } - Err(e) => writeln!(console_writer, "Error while getting bytes {e:?}\n").unwrap(), } - Alarm::sleep_for(Milliseconds(2000)).unwrap(); + let _ = Alarm::sleep_for(Milliseconds(2000)); } } diff --git a/examples/rng_async.rs b/examples/rng_async.rs new file mode 100644 index 000000000..76fd3456d --- /dev/null +++ b/examples/rng_async.rs @@ -0,0 +1,44 @@ +#![no_std] +#![no_main] + +use core::fmt::Write; +use libtock::alarm::{Alarm, Milliseconds}; +use libtock::rng::RngListener; +use libtock::{console::Console, rng::Rng}; +use libtock_platform::{share, Syscalls}; +use libtock_runtime::{set_main, stack_size, TockSyscalls}; + +stack_size! {0x300} +set_main! {main} + +fn main() { + if let Err(e) = Rng::exists() { + writeln!(Console::writer(), "RNG DRIVER ERROR: {e:?}").unwrap(); + return; + } + + let mut console_writer = Console::writer(); + let rng_listener = RngListener(|_| write!(Console::writer(), "Randomness: ").unwrap()); + let mut buffer: [u8; 32] = Default::default(); + let n: u32 = 32; + + loop { + share::scope(|allow_rw| { + Rng::allow_buffer(&mut buffer, allow_rw).unwrap(); + + share::scope(|subscribe| { + Rng::register_listener(&rng_listener, subscribe).unwrap(); + + Rng::get_bytes_async(n).unwrap(); + TockSyscalls::yield_wait(); + }); + }); + + buffer.iter().for_each(|&byte| { + let _ = write!(console_writer, "{byte:02x}"); + }); + let _ = writeln!(console_writer, ""); + + let _ = Alarm::sleep_for(Milliseconds(2000)); + } +} diff --git a/src/lib.rs b/src/lib.rs index 864732eff..47559c788 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,7 @@ pub mod proximity { pub mod rng { use libtock_rng as rng; pub type Rng = rng::Rng; + pub use rng::RngListener; } pub mod sound_pressure { use libtock_sound_pressure as sound_pressure; diff --git a/unittest/src/fake/mod.rs b/unittest/src/fake/mod.rs index 78b1a4410..72d3f5b87 100644 --- a/unittest/src/fake/mod.rs +++ b/unittest/src/fake/mod.rs @@ -22,7 +22,6 @@ mod leds; mod low_level_debug; mod ninedof; mod proximity; -mod rng; mod sound_pressure; mod syscall_driver; mod syscalls; @@ -41,7 +40,6 @@ pub use leds::Leds; pub use low_level_debug::{LowLevelDebug, Message}; pub use ninedof::{NineDof, NineDofData}; pub use proximity::Proximity; -pub use rng::Rng; pub use sound_pressure::SoundPressure; pub use syscall_driver::SyscallDriver; pub use syscalls::Syscalls; diff --git a/unittest/src/fake/rng/mod.rs b/unittest/src/fake/rng/mod.rs deleted file mode 100644 index ac7df3f48..000000000 --- a/unittest/src/fake/rng/mod.rs +++ /dev/null @@ -1,83 +0,0 @@ -use libtock_platform::ErrorCode; - -use crate::{DriverInfo, DriverShareRef, RwAllowBuffer}; -use std::cell::{Cell, RefCell}; -use std::ops::DerefMut; - -pub struct Rng { - busy: Cell, - share_ref: DriverShareRef, - buffer: RefCell, - bytes: Cell>, -} - -impl Rng { - pub fn new() -> std::rc::Rc { - std::rc::Rc::new(Rng { - busy: Cell::new(false), - share_ref: Default::default(), - buffer: Default::default(), - bytes: Default::default(), - }) - } - - pub fn is_busy(&self) -> bool { - self.busy.get() - } -} - -impl crate::fake::SyscallDriver for Rng { - fn info(&self) -> crate::DriverInfo { - DriverInfo::new(DRIVER_NUM).upcall_count(1) - } - - fn register(&self, share_ref: DriverShareRef) { - self.share_ref.replace(share_ref); - } - - fn command(&self, command_id: u32, argument0: u32, _: u32) -> libtock_platform::CommandReturn { - match command_id { - EXISTS => crate::command_return::success(), - GET_BYTES => { - if self.busy.get() { - return crate::command_return::failure(ErrorCode::Busy); - } - self.busy.set(true); - // Mutably borrows RwAllowBuffer from the RefCell as to not take the buffer out - let mut allow_rw_buffer = self.buffer.borrow_mut(); - let inner_buffer = (*allow_rw_buffer).deref_mut(); - inner_buffer.copy_from_slice( - &self.bytes.take()[0..core::cmp::min(inner_buffer.len(), argument0 as usize)], - ); - crate::command_return::success() - } - _ => crate::command_return::failure(ErrorCode::NoSupport), - } - } - - fn allow_readwrite( - &self, - buffer_num: u32, - buffer: crate::RwAllowBuffer, - ) -> Result { - if buffer_num == 0 { - Ok(self.buffer.replace(buffer)) - } else { - Err((buffer, ErrorCode::Invalid)) - } - } -} - -#[cfg(test)] -mod tests; - -// ----------------- -// RNG DRIVER NUMBER -// ----------------- -const DRIVER_NUM: u32 = 0x40001; - -// ------------------- -// RNG COMMAND NUMBERS -// ------------------- -const EXISTS: u32 = 0; -const GET_BYTES: u32 = 1; diff --git a/unittest/src/fake/rng/tests.rs b/unittest/src/fake/rng/tests.rs deleted file mode 100644 index ee59511eb..000000000 --- a/unittest/src/fake/rng/tests.rs +++ /dev/null @@ -1,52 +0,0 @@ -use libtock_platform::{share, DefaultConfig}; - -use crate::{fake, RwAllowBuffer}; - -// Tests the command implementation. -#[test] -fn command() { - use fake::SyscallDriver; - - let rng = fake::Rng::new(); - - // Test driver response to an existence check request - assert!(rng.command(fake::rng::EXISTS, 0, 0).is_success()); - - // Test driver response for sharing a buffer - // to a valid and invalid buffer index, respectively - assert!(rng.allow_readwrite(0, RwAllowBuffer::default()).is_ok()); - assert!(rng.allow_readwrite(1, RwAllowBuffer::default()).is_err()); -} - -// Integration test that verifies Console works with fake::Kernel and -// libtock_platform::Syscalls. -#[test] -fn kernel_integration() { - use libtock_platform::Syscalls; - - let kernel = fake::Kernel::new(); - let rng = fake::Rng::new(); - // Predetermined sample of RNG data "read" from the RNG low-level driver - // that will be put into the shared buffer - let bytes = [0_u8, 1_u8, 2_u8, 3_u8, 4_u8]; - rng.bytes.set(bytes.to_vec()); - kernel.add_driver(&rng); - - // Test driver response to an existence check request - assert!(fake::Syscalls::command(fake::rng::DRIVER_NUM, 0, 0, 0).is_success()); - - // Buffer to be shared with the kernel and filled with random bytes - let mut buffer: [u8; 5] = [0; 5]; - share::scope(|allow_rw| { - // Register the provided buffer - fake::Syscalls::allow_rw::( - allow_rw, - &mut buffer, - ) - .unwrap(); - // Test driver response to buffer fill requests - assert!(fake::Syscalls::command(fake::rng::DRIVER_NUM, 1, 5, 0).is_success()); - }); - // Additionally check that the buffer has been correctly filled - assert_eq!(buffer.cmp(&bytes), core::cmp::Ordering::Equal); -}