diff --git a/crates/flipperzero/src/furi/thread.rs b/crates/flipperzero/src/furi/thread.rs index 44a6651..38a2cb0 100644 --- a/crates/flipperzero/src/furi/thread.rs +++ b/crates/flipperzero/src/furi/thread.rs @@ -17,7 +17,7 @@ use alloc::{ sync::Arc, }; -use flipperzero_sys::{self as sys, FuriFlagNoClear, FuriFlagWaitAll, FuriFlagWaitAny}; +use flipperzero_sys::{self as sys, FuriFlagNoClear, FuriFlagWaitAll, FuriFlagWaitAny, HasFlag}; use crate::furi::time::Duration; @@ -259,7 +259,7 @@ impl ThreadId { pub fn set_flags(thread_id: ThreadId, flags: u32) -> Result { let result = unsafe { sys::furi_thread_flags_set(thread_id.0, flags) }; - if result & sys::FuriFlagError.0 != 0 { + if sys::FuriFlag(result).has_flag(sys::FuriFlagError) { return Err((result as i32).into()); } @@ -272,7 +272,7 @@ pub fn set_flags(thread_id: ThreadId, flags: u32) -> Result Result { let result = unsafe { sys::furi_thread_flags_clear(flags) }; - if result & sys::FuriFlagError.0 != 0 { + if sys::FuriFlag(result).has_flag(sys::FuriFlagError) { return Err((result as i32).into()); } @@ -283,7 +283,7 @@ pub fn clear_flags(flags: u32) -> Result { pub fn get_flags() -> Result { let result = unsafe { sys::furi_thread_flags_get() }; - if result & sys::FuriFlagError.0 != 0 { + if sys::FuriFlag(result).has_flag(sys::FuriFlagError) { return Err((result as i32).into()); } @@ -301,7 +301,7 @@ pub fn wait_any_flags( let options = FuriFlagWaitAny.0 | (if clear { 0 } else { FuriFlagNoClear.0 }); let result = unsafe { sys::furi_thread_flags_wait(flags, options, timeout.0) }; - if result & sys::FuriFlagError.0 != 0 { + if sys::FuriFlag(result).has_flag(sys::FuriFlagError) { return Err((result as i32).into()); } @@ -319,7 +319,7 @@ pub fn wait_all_flags( let options = FuriFlagWaitAll.0 | (if clear { 0 } else { FuriFlagNoClear.0 }); let result = unsafe { sys::furi_thread_flags_wait(flags, options, timeout.0) }; - if result & sys::FuriFlagError.0 != 0 { + if sys::FuriFlag(result).has_flag(sys::FuriFlagError) { return Err((result as i32).into()); } diff --git a/crates/flipperzero/src/storage.rs b/crates/flipperzero/src/storage.rs index 4fb7a5d..ccce885 100644 --- a/crates/flipperzero/src/storage.rs +++ b/crates/flipperzero/src/storage.rs @@ -1,15 +1,15 @@ use core::ffi::{c_char, c_void, CStr}; use core::ptr::NonNull; -use flipperzero_sys as sys; use flipperzero_sys::furi::UnsafeRecord; +use flipperzero_sys::{self as sys, HasFlag}; use crate::io::*; #[derive(Debug, Default, Clone, Copy)] pub struct OpenOptions { - access_mode: u8, - open_mode: u8, + access_mode: sys::FS_AccessMode, + open_mode: sys::FS_OpenMode, } impl OpenOptions { @@ -17,7 +17,7 @@ impl OpenOptions { Self::default() } - fn from_parts(access_mode: u8, open_mode: u8) -> Self { + fn from_parts(access_mode: sys::FS_AccessMode, open_mode: sys::FS_OpenMode) -> Self { OpenOptions { access_mode, open_mode, @@ -28,9 +28,9 @@ impl OpenOptions { pub fn read(self, set: bool) -> Self { OpenOptions::from_parts( if set { - self.access_mode | sys::FSAM_READ.0 + self.access_mode | sys::FSAM_READ } else { - self.access_mode & !sys::FSAM_READ.0 + self.access_mode & !sys::FSAM_READ }, self.open_mode, ) @@ -40,9 +40,9 @@ impl OpenOptions { pub fn write(self, set: bool) -> Self { OpenOptions::from_parts( if set { - self.access_mode | sys::FSAM_WRITE.0 + self.access_mode | sys::FSAM_WRITE } else { - self.access_mode & !sys::FSAM_WRITE.0 + self.access_mode & !sys::FSAM_WRITE }, self.open_mode, ) @@ -53,9 +53,9 @@ impl OpenOptions { OpenOptions::from_parts( self.access_mode, if set { - self.open_mode | sys::FSOM_OPEN_EXISTING.0 + self.open_mode | sys::FSOM_OPEN_EXISTING } else { - self.open_mode & !sys::FSOM_OPEN_EXISTING.0 + self.open_mode & !sys::FSOM_OPEN_EXISTING }, ) } @@ -65,9 +65,9 @@ impl OpenOptions { OpenOptions::from_parts( self.access_mode, if set { - self.open_mode | sys::FSOM_OPEN_ALWAYS.0 + self.open_mode | sys::FSOM_OPEN_ALWAYS } else { - self.open_mode & !sys::FSOM_OPEN_ALWAYS.0 + self.open_mode & !sys::FSOM_OPEN_ALWAYS }, ) } @@ -77,9 +77,9 @@ impl OpenOptions { OpenOptions::from_parts( self.access_mode, if set { - self.open_mode | sys::FSOM_OPEN_APPEND.0 + self.open_mode | sys::FSOM_OPEN_APPEND } else { - self.open_mode & !sys::FSOM_OPEN_APPEND.0 + self.open_mode & !sys::FSOM_OPEN_APPEND }, ) } @@ -89,9 +89,9 @@ impl OpenOptions { OpenOptions::from_parts( self.access_mode, if set { - self.open_mode | sys::FSOM_CREATE_NEW.0 + self.open_mode | sys::FSOM_CREATE_NEW } else { - self.open_mode & !sys::FSOM_CREATE_NEW.0 + self.open_mode & !sys::FSOM_CREATE_NEW }, ) } @@ -101,9 +101,9 @@ impl OpenOptions { OpenOptions::from_parts( self.access_mode, if set { - self.open_mode | sys::FSOM_CREATE_ALWAYS.0 + self.open_mode | sys::FSOM_CREATE_ALWAYS } else { - self.open_mode & !sys::FSOM_CREATE_ALWAYS.0 + self.open_mode & !sys::FSOM_CREATE_ALWAYS }, ) } @@ -115,13 +115,13 @@ impl OpenOptions { // example, `create_new` is more specialized than `truncate`) so we // search for the first "on" bit in this sequence, and use that as the // open mode. - let canonicalized_open_mode = if self.open_mode & sys::FSOM_CREATE_NEW.0 != 0 { + let canonicalized_open_mode = if self.open_mode.has_flag(sys::FSOM_CREATE_NEW) { sys::FSOM_CREATE_NEW - } else if self.open_mode & sys::FSOM_CREATE_ALWAYS.0 != 0 { + } else if self.open_mode.has_flag(sys::FSOM_CREATE_ALWAYS) { sys::FSOM_CREATE_ALWAYS - } else if self.open_mode & sys::FSOM_OPEN_APPEND.0 != 0 { + } else if self.open_mode.has_flag(sys::FSOM_OPEN_APPEND) { sys::FSOM_OPEN_APPEND - } else if self.open_mode & sys::FSOM_OPEN_ALWAYS.0 != 0 { + } else if self.open_mode.has_flag(sys::FSOM_OPEN_ALWAYS) { sys::FSOM_OPEN_ALWAYS } else { sys::FSOM_OPEN_EXISTING @@ -132,7 +132,7 @@ impl OpenOptions { sys::storage_file_open( f.0.as_ptr(), path.as_ptr() as *const c_char, - sys::FS_AccessMode(self.access_mode), + self.access_mode, canonicalized_open_mode, ) } { diff --git a/crates/sys/src/lib.rs b/crates/sys/src/lib.rs index 2f0411f..dd08662 100644 --- a/crates/sys/src/lib.rs +++ b/crates/sys/src/lib.rs @@ -151,6 +151,79 @@ macro_rules! __halt_implementation { }; } +/// Check if flag is set. +/// +/// Typically implemented as `(self & flag) == flag`. +pub trait HasFlag { + fn has_flag(self, flag: Self) -> bool; +} + +/// Implement bitfield operations for "bitfield" enums. +#[doc(hidden)] +macro_rules! impl_bitfield_enum { + ($t:ty) => { + impl ::core::default::Default for $t { + #[inline] + fn default() -> Self { + Self(0) + } + } + impl ::core::ops::BitOr<$t> for $t { + type Output = Self; + + #[inline] + fn bitor(self, other: Self) -> Self { + Self(self.0 | other.0) + } + } + impl ::core::ops::BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, rhs: $t) { + self.0 |= rhs.0; + } + } + impl ::core::ops::BitAnd<$t> for $t { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Self(self.0 & other.0) + } + } + impl ::core::ops::BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, rhs: $t) { + self.0 &= rhs.0; + } + } + impl ::core::ops::Not for $t { + type Output = Self; + #[inline] + fn not(self) -> Self::Output { + Self(!self.0) + } + } + impl HasFlag for $t { + #[inline] + fn has_flag(self, flag: Self) -> bool { + (self.0 & flag.0) == flag.0 + } + } + }; +} + +impl_bitfield_enum!(CliCommandFlag); +impl_bitfield_enum!(FS_AccessMode); +impl_bitfield_enum!(FS_Flags); +impl_bitfield_enum!(FS_OpenMode); +impl_bitfield_enum!(FuriFlag); +impl_bitfield_enum!(FuriHalNfcEvent); +impl_bitfield_enum!(FuriHalRtcFlag); +impl_bitfield_enum!(FuriHalSerialRxEvent); +impl_bitfield_enum!(iButtonProtocolFeature); +impl_bitfield_enum!(Light); +impl_bitfield_enum!(MfUltralightFeatureSupport); +impl_bitfield_enum!(SubGhzProtocolFlag); + // Re-export bindings pub use bindings::*;