leodos_libcfs/cfe/es/
app.rs1use core::ffi::CStr;
7use core::mem::MaybeUninit;
8use core::ops::Deref;
9use core::str;
10
11use heapless::CString;
12use heapless::String;
13
14use crate::cstring;
15use crate::error::Result;
16use crate::error::{CfsError, OsalError};
17use crate::ffi;
18use crate::log;
19use crate::status::check;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23#[repr(u32)]
24pub enum RunStatus {
25 Undefined = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_UNDEFINED,
27 Run = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_APP_RUN,
29 Exit = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_APP_EXIT,
31 Error = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_APP_ERROR,
33 Exception = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_SYS_EXCEPTION,
35 Restart = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_SYS_RESTART,
37 Reload = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_SYS_RELOAD,
39 Delete = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_SYS_DELETE,
41 CoreAppInitError = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_CORE_APP_INIT_ERROR,
43 CoreAppRuntimeError = ffi::CFE_ES_RunStatus_CFE_ES_RunStatus_CORE_APP_RUNTIME_ERROR,
45}
46
47impl From<u32> for RunStatus {
48 fn from(value: u32) -> Self {
49 match value {
50 x if x == RunStatus::Undefined as u32 => RunStatus::Undefined,
51 x if x == RunStatus::Run as u32 => RunStatus::Run,
52 x if x == RunStatus::Exit as u32 => RunStatus::Exit,
53 x if x == RunStatus::Error as u32 => RunStatus::Error,
54 x if x == RunStatus::Exception as u32 => RunStatus::Exception,
55 x if x == RunStatus::Restart as u32 => RunStatus::Restart,
56 x if x == RunStatus::Reload as u32 => RunStatus::Reload,
57 x if x == RunStatus::Delete as u32 => RunStatus::Delete,
58 x if x == RunStatus::CoreAppInitError as u32 => RunStatus::CoreAppInitError,
59 x if x == RunStatus::CoreAppRuntimeError as u32 => RunStatus::CoreAppRuntimeError,
60 _ => RunStatus::Undefined, }
62 }
63}
64
65pub fn run_loop() -> core::result::Result<(), RunStatus> {
71 let mut status = RunStatus::Run as u32;
72 let should_run = unsafe { ffi::CFE_ES_RunLoop(&mut status) };
73 let status = RunStatus::from(status);
74 if should_run && status == RunStatus::Run {
75 Ok(())
76 } else {
77 Err(status)
78 }
79}
80
81pub fn exit_app(status: RunStatus) -> ! {
83 unsafe { ffi::CFE_ES_ExitApp(status as u32) };
84 loop {}
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92#[repr(transparent)]
93pub struct AppId(pub(crate) ffi::CFE_ES_AppId_t);
94
95impl AppId {
96 pub fn info(&self) -> Result<AppInfo> {
103 let mut app_info_uninit = MaybeUninit::uninit();
104 let status = unsafe { ffi::CFE_ES_GetAppInfo(app_info_uninit.as_mut_ptr(), self.0) };
105 check(status)?;
106 Ok(AppInfo {
107 inner: unsafe { app_info_uninit.assume_init() },
108 })
109 }
110
111 pub fn name(&self) -> Result<String<{ ffi::OS_MAX_API_NAME as usize }>> {
118 let mut buffer = [0u8; ffi::OS_MAX_API_NAME as usize];
119 let status = unsafe {
120 ffi::CFE_ES_GetAppName(
121 buffer.as_mut_ptr() as *mut libc::c_char,
122 self.0,
123 buffer.len(),
124 )
125 };
126 check(status)?;
127 let len = buffer.iter().position(|&b| b == 0).unwrap_or(buffer.len());
128 let vec = heapless::Vec::from_slice(&buffer[..len])
129 .map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
130 String::from_utf8(vec).map_err(|_| CfsError::InvalidString)
131 }
132
133 pub fn to_index(&self) -> Result<u32> {
140 let mut index = MaybeUninit::uninit();
141 check(unsafe { ffi::CFE_ES_AppID_ToIndex(self.0, index.as_mut_ptr()) })?;
142 Ok(unsafe { index.assume_init() })
143 }
144
145 pub fn restart(&self) -> Result<()> {
155 check(unsafe { ffi::CFE_ES_RestartApp(self.0) })?;
156 Ok(())
157 }
158
159 pub fn reload(&self, filename: &str) -> Result<()> {
173 let c_filename = cstring::<{ ffi::OS_MAX_PATH_LEN as usize }>(filename)
174 .map_err(|_| CfsError::Osal(OsalError::FsPathTooLong))?;
175 check(unsafe { ffi::CFE_ES_ReloadApp(self.0, c_filename.as_ptr()) })?;
176 Ok(())
177 }
178
179 pub fn delete(&self) -> Result<()> {
185 check(unsafe { ffi::CFE_ES_DeleteApp(self.0) })?;
186 Ok(())
187 }
188
189 pub fn from_name(name: &str) -> Result<AppId> {
199 let c_name = cstring::<{ ffi::OS_MAX_API_NAME as usize }>(name)?;
200
201 let mut app_id = MaybeUninit::uninit();
202 check(unsafe { ffi::CFE_ES_GetAppIDByName(app_id.as_mut_ptr(), c_name.as_ptr()) })?;
203 Ok(AppId(unsafe { app_id.assume_init() }))
204 }
205
206 pub fn this() -> Result<AppId> {
215 let mut app_id = MaybeUninit::uninit();
216 check(unsafe { ffi::CFE_ES_GetAppID(app_id.as_mut_ptr()) })?;
217 Ok(AppId(unsafe { app_id.assume_init() }))
218 }
219}
220
221impl Deref for AppId {
222 type Target = ffi::CFE_ES_AppId_t;
223 fn deref(&self) -> &Self::Target {
224 &self.0
225 }
226}
227
228#[derive(Debug, Clone)]
233pub struct AppInfo {
234 pub(crate) inner: ffi::CFE_ES_AppInfo_t,
236}
237
238impl AppInfo {
239 pub fn name(&self) -> Result<CString<{ ffi::OS_MAX_API_NAME as usize }>> {
246 let c_str = unsafe { CStr::from_ptr(self.inner.Name.as_ptr()) };
247 let bytes = c_str.to_bytes();
248 let mut s = CString::new();
249 s.extend_from_bytes(bytes)
250 .map_err(|_| CfsError::Osal(OsalError::NameTooLong))?;
251 Ok(s)
252 }
253
254 pub fn copy_entry_point<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a str> {
264 let c_str = unsafe { CStr::from_ptr(self.inner.EntryPoint.as_ptr()) };
265 let bytes = c_str.to_bytes();
266 if bytes.len() >= buffer.len() {
267 return Err(CfsError::Osal(OsalError::InvalidSize));
268 }
269 buffer[..bytes.len()].copy_from_slice(bytes);
270 buffer[bytes.len()] = 0;
271 str::from_utf8(&buffer[..bytes.len()]).map_err(|_| CfsError::InvalidString)
272 }
273
274 pub fn copy_file_name<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a str> {
284 let c_str = unsafe { CStr::from_ptr(self.inner.FileName.as_ptr()) };
285 let bytes = c_str.to_bytes();
286 if bytes.len() >= buffer.len() {
287 return Err(CfsError::Osal(OsalError::InvalidSize));
288 }
289 buffer[..bytes.len()].copy_from_slice(bytes);
290 buffer[bytes.len()] = 0;
291 str::from_utf8(&buffer[..bytes.len()]).map_err(|_| CfsError::InvalidString)
292 }
293}
294
295pub fn default_panic_handler(info: &core::panic::PanicInfo) -> ! {
307 if let Some(location) = info.location() {
308 log!("PANIC at {}:{}", location.file(), location.line()).ok();
309 } else {
310 log!("PANIC").ok();
311 }
312
313 unsafe { ffi::CFE_ES_ExitApp(RunStatus::Error as u32) };
314
315 loop {}
316}