blob: 07e9a5fc0ac2da8ae75f47a6108cef48dc161e8f [file]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg_attr(not(test), no_std)]
#![feature(build_hasher_simple_hash_one)]
use cantrip_os_common::camkes::seL4_CPath;
use cantrip_os_common::sel4_sys;
use cantrip_sdk_manager::SDKManagerError;
use cantrip_sdk_manager::SDKManagerInterface;
use sdk_interface::error::SDKError;
use sdk_interface::KeyValueData;
use sdk_interface::ModelId;
use sdk_interface::ModelInput;
use sdk_interface::ModelMask;
use sdk_interface::ModelOutput;
use sdk_interface::SDKAppId;
use sdk_interface::SDKRuntimeInterface;
use sdk_interface::TimerDuration;
use sdk_interface::TimerId;
use sdk_interface::TimerMask;
use spin::Mutex;
use spin::MutexGuard;
use sel4_sys::seL4_CPtr;
mod runtime;
use runtime::SDKRuntime;
/// Wrapper around SDKRuntime implementation. Because we have two CAmkES
/// interfaces there may be concurrent calls so we lock at this level.
pub struct CantripSDKRuntime {
runtime: Mutex<Option<SDKRuntime>>,
}
impl CantripSDKRuntime {
// Constructs a partially-initialized instance; to complete call init().
// This is needed because we need a const fn for static setup.
pub const fn empty() -> CantripSDKRuntime {
CantripSDKRuntime {
runtime: Mutex::new(None),
}
}
pub fn get(&self) -> Guard {
Guard {
runtime: self.runtime.lock(),
}
}
}
pub struct Guard<'a> {
runtime: MutexGuard<'a, Option<SDKRuntime>>,
}
impl Guard<'_> {
pub fn is_empty(&self) -> bool { self.runtime.is_none() }
// Finishes the setup started by empty():
pub fn init(&mut self, endpoint: &seL4_CPath) {
assert!(self.runtime.is_none());
*self.runtime = Some(SDKRuntime::new(endpoint));
}
// Returns the bundle capacity.
pub fn capacity(&self) -> usize { self.runtime.as_ref().unwrap().capacity() }
}
// These just lock accesses and handle the necessary indirection.
impl SDKManagerInterface for Guard<'_> {
fn get_endpoint(&mut self, app_id: &str) -> Result<seL4_CPtr, SDKManagerError> {
self.runtime.as_mut().unwrap().get_endpoint(app_id)
}
fn release_endpoint(&mut self, app_id: &str) -> Result<(), SDKManagerError> {
self.runtime.as_mut().unwrap().release_endpoint(app_id)
}
}
impl SDKRuntimeInterface for Guard<'_> {
fn ping(&self, app_id: SDKAppId) -> Result<(), SDKError> {
self.runtime.as_ref().unwrap().ping(app_id)
}
fn log(&self, app_id: SDKAppId, msg: &str) -> Result<(), SDKError> {
self.runtime.as_ref().unwrap().log(app_id, msg)
}
// Key-value store interfaces.
fn read_key(&self, app_id: SDKAppId, key: &str) -> Result<KeyValueData, SDKError> {
self.runtime.as_ref().unwrap().read_key(app_id, key)
}
fn write_key(&self, app_id: SDKAppId, key: &str, value: &KeyValueData) -> Result<(), SDKError> {
self.runtime.as_ref().unwrap().write_key(app_id, key, value)
}
fn delete_key(&self, app_id: SDKAppId, key: &str) -> Result<(), SDKError> {
self.runtime.as_ref().unwrap().delete_key(app_id, key)
}
// Timer interfaces.
fn timer_oneshot(
&mut self,
app_id: SDKAppId,
id: TimerId,
duration_ms: TimerDuration,
) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.timer_oneshot(app_id, id, duration_ms)
}
fn timer_periodic(
&mut self,
app_id: SDKAppId,
id: TimerId,
duration_ms: TimerDuration,
) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.timer_periodic(app_id, id, duration_ms)
}
fn timer_cancel(&mut self, app_id: SDKAppId, id: TimerId) -> Result<(), SDKError> {
self.runtime.as_mut().unwrap().timer_cancel(app_id, id)
}
fn timer_wait(&mut self, app_id: SDKAppId) -> Result<TimerMask, SDKError> {
self.runtime.as_mut().unwrap().timer_wait(app_id)
}
fn timer_poll(&mut self, app_id: SDKAppId) -> Result<TimerMask, SDKError> {
self.runtime.as_mut().unwrap().timer_poll(app_id)
}
// Model interfaces.
fn model_oneshot(&mut self, app_id: SDKAppId, model_id: &str) -> Result<ModelId, SDKError> {
self.runtime
.as_mut()
.unwrap()
.model_oneshot(app_id, model_id)
}
fn model_periodic(
&mut self,
app_id: SDKAppId,
model_id: &str,
duration_ms: TimerDuration,
) -> Result<ModelId, SDKError> {
self.runtime
.as_mut()
.unwrap()
.model_periodic(app_id, model_id, duration_ms)
}
fn model_cancel(&mut self, app_id: SDKAppId, id: ModelId) -> Result<(), SDKError> {
self.runtime.as_mut().unwrap().model_cancel(app_id, id)
}
fn model_wait(&mut self, app_id: SDKAppId) -> Result<ModelMask, SDKError> {
self.runtime.as_mut().unwrap().model_wait(app_id)
}
fn model_poll(&mut self, app_id: SDKAppId) -> Result<ModelMask, SDKError> {
self.runtime.as_mut().unwrap().model_poll(app_id)
}
fn model_output(&mut self, app_id: SDKAppId, id: ModelId) -> Result<ModelOutput, SDKError> {
self.runtime.as_mut().unwrap().model_output(app_id, id)
}
fn model_get_input_params(
&mut self,
app_id: SDKAppId,
model_id: &str,
) -> Result<(ModelId, ModelInput), SDKError> {
self.runtime
.as_mut()
.unwrap()
.model_get_input_params(app_id, model_id)
}
fn model_set_input(
&mut self,
app_id: SDKAppId,
id: ModelId,
input_data_offset: u32,
input_data: &[u8],
) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.model_set_input(app_id, id, input_data_offset, input_data)
}
fn audio_reset(
&mut self,
app_id: SDKAppId,
rxrst: bool,
txrst: bool,
rxilvl: u8,
txilvl: u8,
) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.audio_reset(app_id, rxrst, txrst, rxilvl, txilvl)
}
fn audio_record_start(
&mut self,
app_id: SDKAppId,
rate: usize,
buffer_size: usize,
stop_on_full: bool,
) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.audio_record_start(app_id, rate, buffer_size, stop_on_full)
}
fn audio_record_collect(
&mut self,
app_id: SDKAppId,
max_samples: usize,
wait_if_empty: bool,
) -> Result<&[u32], SDKError> {
self.runtime
.as_mut()
.unwrap()
.audio_record_collect(app_id, max_samples, wait_if_empty)
}
fn audio_record_stop(&mut self, app_id: SDKAppId) -> Result<(), SDKError> {
self.runtime.as_mut().unwrap().audio_record_stop(app_id)
}
fn audio_play_start(
&mut self,
app_id: SDKAppId,
rate: usize,
buffer_size: usize,
) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.audio_play_start(app_id, rate, buffer_size)
}
fn audio_play_write(&mut self, app_id: SDKAppId, data: &[u32]) -> Result<(), SDKError> {
self.runtime
.as_mut()
.unwrap()
.audio_play_write(app_id, data)
}
fn audio_play_stop(&mut self, app_id: SDKAppId) -> Result<(), SDKError> {
self.runtime.as_mut().unwrap().audio_play_stop(app_id)
}
}