Skip to content

Commit

Permalink
Merge pull request #524 from CosminGGeorgescu/rng_api
Browse files Browse the repository at this point in the history
Rng API
  • Loading branch information
jrvanwhy committed Jan 10, 2024
2 parents 4d14230 + 9695aed commit 089f5c6
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 4 deletions.
10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -31,12 +31,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
Expand Down Expand Up @@ -64,6 +65,7 @@ members = [
"apis/low_level_debug",
"apis/ninedof",
"apis/proximity",
"apis/rng",
"apis/temperature",
"panic_handlers/debug_panic",
"panic_handlers/small_panic",
Expand Down
18 changes: 18 additions & 0 deletions apis/rng/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "libtock_rng"
version = "0.1.0"
authors = [
"Tock Project Developers <tock-dev@googlegroups.com>",
"Cosmin Gabriel Georgescu <cosmingg2013@gmail.com>",
]
license = "Apache-2.0 OR MIT"
edition = "2021"
repository = "https://www.github.com/tock/libtock-rs"
rust-version.workspace = true
description = "libtock rng driver"

[dependencies]
libtock_platform = { path = "../../platform" }

[dev-dependencies]
libtock_unittest = { path = "../../unittest" }
93 changes: 93 additions & 0 deletions apis/rng/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#![no_std]

use core::cell::Cell;
use libtock_platform::{
share, subscribe::OneId, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,
};

pub struct Rng<S: Syscalls>(S);

impl<S: Syscalls> Rng<S> {
/// Check if the RNG kernel driver exists
pub fn exists() -> Result<(), ErrorCode> {
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<AllowRw<'share, S, DRIVER_NUM, 0>>,
) -> Result<(), ErrorCode> {
S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(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<F>,
subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,
) -> 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<S, DRIVER_NUM, 0>, Subscribe<S, DRIVER_NUM, 0>), _, _>(|handle| {
let (allow_rw, subscribe) = handle.split();

// Share the provided buffer with the kernel
S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, 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(())
})
}
}

/// The provided listener to be called.
/// Interior function operates on the number of random bytes filled into the buffer
pub struct RngListener<F: Fn(u32)>(pub F);

impl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for RngListener<F> {
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;
46 changes: 46 additions & 0 deletions examples/rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#![no_std]
#![no_main]

use core::fmt::Write;
use libtock::alarm::{Alarm, Milliseconds};
use libtock::console::Console;
use libtock::rng::Rng;
use libtock::runtime::{set_main, stack_size};

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 bytes = self.0.iter();
while let Some(&byte) = bytes.next() {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}

fn main() {
if let Err(e) = Rng::exists() {
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;

loop {
match Rng::get_bytes_sync(&mut buffer, n) {
Ok(()) => {
let _ = writeln!(console_writer, "Randomness: {}", Randomness(&buffer));
}
Err(e) => {
let _ = writeln!(console_writer, "Error while getting bytes {e:?}");
}
}
let _ = Alarm::sleep_for(Milliseconds(2000));
}
}
44 changes: 44 additions & 0 deletions examples/rng_async.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ pub mod proximity {
use libtock_proximity as proximity;
pub type Proximity = proximity::Proximity<super::runtime::TockSyscalls>;
}
pub mod rng {
use libtock_rng as rng;
pub type Rng = rng::Rng<super::runtime::TockSyscalls>;
pub use rng::RngListener;
}
pub mod sound_pressure {
use libtock_sound_pressure as sound_pressure;
pub type SoundPressure = sound_pressure::SoundPressure<super::runtime::TockSyscalls>;
Expand Down

0 comments on commit 089f5c6

Please sign in to comment.