Skip to content

Commit b7f29c8

Browse files
authored
Merge pull request #630 from betrusted-io/modals-refactor
First modals are now integrated on baosec target, drop it into CI to look for uninintentional breakage in precursor targets.
2 parents 35f42b9 + c49c416 commit b7f29c8

File tree

28 files changed

+597
-95
lines changed

28 files changed

+597
-95
lines changed

Cargo.lock

+4-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/cramium-hal/src/axp2101.rs

+34
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use cramium_api::*;
33
pub const AXP2101_DEV: u8 = 0x34;
44

55
const REG_DCDC_ENA: usize = 0x80;
6+
const REG_DCDC_PWM: usize = 0x81;
67
const REG_DCDC1_V: usize = 0x82;
78
const REG_DCDC2_V: usize = 0x83;
89
const REG_DCDC3_V: usize = 0x84;
@@ -281,6 +282,39 @@ impl Axp2101 {
281282
let data = VBUS_INSERT_MASK | VBUS_REMOVE_MASK;
282283
i2c.i2c_write(AXP2101_DEV, REG_IRQ_STATUS1, &[data]).map(|_| ())
283284
}
285+
286+
pub fn set_pwm_mode(
287+
&mut self,
288+
i2c: &mut dyn I2cApi,
289+
which: WhichDcDc,
290+
always: bool,
291+
) -> Result<(), xous::Error> {
292+
match which {
293+
WhichDcDc::Dcdc5 => Err(xous::Error::BadAddress),
294+
_ => {
295+
let mut buf = [0u8];
296+
i2c.i2c_read(AXP2101_DEV, REG_DCDC_PWM as u8, &mut buf, false).map(|_| ())?;
297+
if always {
298+
buf[0] |= 4u8 << (which as usize as u8);
299+
} else {
300+
buf[0] &= !(4u8 << (which as usize as u8));
301+
}
302+
i2c.i2c_write(AXP2101_DEV, REG_DCDC_PWM as u8, &buf).map(|_| ())
303+
}
304+
}
305+
}
306+
307+
pub fn debug(&mut self, i2c: &mut dyn I2cApi) {
308+
let mut buf = [0u8, 0u8];
309+
i2c.i2c_read(AXP2101_DEV, REG_DCDC_ENA as u8, &mut buf, false).unwrap();
310+
crate::println!("ena|pwm bef: {:x?}", buf);
311+
// force CCM mode
312+
i2c.i2c_write(AXP2101_DEV, REG_DCDC_ENA as u8, &[buf[0] | 0b0100_0000]).unwrap();
313+
// disable spreading, force PWM on DCDC2
314+
i2c.i2c_write(AXP2101_DEV, REG_DCDC_PWM as u8, &[(buf[1] & 0b0011_1111) | 0b0000_1000]).unwrap();
315+
i2c.i2c_read(AXP2101_DEV, REG_DCDC_ENA as u8, &mut buf, false).unwrap();
316+
crate::println!("ena|pwm aft: {:x?}", buf);
317+
}
284318
}
285319

286320
pub fn parse_dcdc_ena(d: u8) -> ([bool; 4], bool, bool) {

libs/ux-api/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub mod cursor;
55
mod fontmap;
66
pub mod minigfx;
77
pub mod platform;
8-
#[cfg(all(feature = "std", any(feature = "cramium-soc", feature = "hosted-baosec")))]
8+
#[cfg(all(feature = "std", any(feature = "board-baosec", feature = "hosted-baosec")))]
99
pub mod widgets;
1010
#[cfg(feature = "std")]
1111
pub mod wordwrap;

libs/ux-api/src/minigfx/clip.rs

+32
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,35 @@ impl ClipObjectList {
4141
}
4242
}
4343
}
44+
45+
#[cfg_attr(feature = "derive-rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
46+
#[derive(Debug, Clone)]
47+
/// This API relies on an upgraded version of rkyv that was not available when the ClipObjectList
48+
/// API was defined: we can now just use a `Vec` to do the trick.
49+
#[cfg(feature = "std")]
50+
pub struct ObjectList {
51+
pub list: Vec<ClipObjectType>,
52+
}
53+
#[cfg(feature = "std")]
54+
impl ObjectList {
55+
pub fn new() -> Self { Self { list: Vec::new() } }
56+
57+
/// The intent was for the push() to be infalliable, but in practice, draw lists could get
58+
/// arbitrarily large and some back-pressure is needed to keep the memory allocation within
59+
/// bounds that the system can handle. Thus, this method can fail returning the pushed object,
60+
/// at which point one should send the draw list to the graphics engine, and retry the push.
61+
pub fn push(&mut self, item: ClipObjectType) -> Result<(), ClipObjectType> {
62+
// TODO: export the capacity limit of a buffer. The origin of the capacity limit is equal to
63+
// the size of a page of memory, plus 256 bytes for "scratch" area for rkyv to work in. I did
64+
// try to use the .replace() method with an allocation of a large enough buffer to hold the whole
65+
// Vec, but it seems to fail. I think it could be that the scratch space hard-coded into the IPC
66+
// library is not big enough...
67+
if self.list.capacity() * size_of::<ClipObjectType>() + size_of::<Vec<ClipObjectType>>() < 4096 - 256
68+
{
69+
self.list.push(item);
70+
Ok(())
71+
} else {
72+
Err(item)
73+
}
74+
}
75+
}

libs/ux-api/src/minigfx/handlers.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,34 @@ pub fn draw_clip_object_list<T: FrameBuffer>(display: &mut T, msg: &mut xous::en
7070
}
7171
}
7272

73+
pub fn draw_object_list<T: FrameBuffer>(display: &mut T, msg: &mut xous::envelope::Envelope) {
74+
let buffer = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) };
75+
let list_ipc = buffer.to_original::<ObjectList, _>().unwrap();
76+
for &item in list_ipc.list.iter() {
77+
match item {
78+
ClipObjectType::Line(line) => {
79+
op::line(display, line, None, false);
80+
}
81+
ClipObjectType::XorLine(line) => {
82+
op::line(display, line, None, true);
83+
}
84+
ClipObjectType::Circ(circ) => {
85+
op::circle(display, circ, None);
86+
}
87+
ClipObjectType::Rect(rect) => {
88+
op::rectangle(display, rect, None, false);
89+
}
90+
ClipObjectType::RoundRect(rr) => {
91+
op::rounded_rectangle(display, rr, None);
92+
}
93+
#[cfg(feature = "ditherpunk")]
94+
_ => {
95+
unimplemented!("Object type not yet implemented");
96+
}
97+
}
98+
}
99+
}
100+
73101
pub fn line<T: FrameBuffer>(
74102
display: &mut T,
75103
screen_clip: Option<Rectangle>,
@@ -166,7 +194,12 @@ pub fn draw_text_view<T: FrameBuffer>(display: &mut T, msg: &mut xous::envelope:
166194
let mut tv = buffer.to_original::<TextView, _>().unwrap();
167195

168196
if tv.clip_rect.is_none() {
169-
return;
197+
if cfg!(feature = "hosted-baosec") || cfg!(feature = "cramium-soc") || cfg!(feature = "board-baosec")
198+
{
199+
tv.clip_rect = Some(Rectangle::new(Point::new(0, 0), display.dimensions()));
200+
} else {
201+
return;
202+
}
170203
} // if no clipping rectangle is specified, nothing to draw
171204

172205
// this is the clipping rectangle of the canvas in screen coordinates

libs/ux-api/src/service/api.rs

+8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ impl Gid {
1212
pub fn new(id: [u32; 4]) -> Self { Gid { gid: id } }
1313

1414
pub fn gid(&self) -> [u32; 4] { self.gid }
15+
16+
pub fn dummy() -> Self { Gid { gid: [0xdead, 0xbeef, 0xdead, 0xbeef] } }
1517
}
1618
impl Hash for Gid {
1719
fn hash<H>(&self, state: &mut H)
@@ -89,6 +91,12 @@ pub enum GfxOpcode {
8991
/// Handle Camera IRQs
9092
CamIrq,
9193

94+
/// V2 API for claiming ownership of screen for modal operation
95+
AcquireModal,
96+
ReleaseModal,
97+
/// V2 API for fast drawing of multiple objects
98+
UnclippedObjectList,
99+
92100
/// Gutter for invalid calls
93101
InvalidCall,
94102

libs/ux-api/src/service/gfx.rs

+52
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,31 @@ impl Gfx {
310310
Ok(())
311311
}
312312

313+
/// Bounds computation does no checks on security since it's a non-drawing operation. While normal drawing
314+
/// always takes the bounds from the canvas, the caller can specify a clip_rect in this tv, instead of
315+
/// drawing the clip_rect from the Canvas associated with the tv.
316+
pub fn bounds_compute_textview(&self, tv: &mut TextView) -> Result<(), xous::Error> {
317+
let mut tv_query = tv.clone();
318+
tv_query.set_dry_run(true);
319+
let mut buf = Buffer::into_buf(tv_query).or(Err(xous::Error::InternalError))?;
320+
buf.lend_mut(self.conn, GfxOpcode::DrawTextView.to_u32().unwrap())
321+
.or(Err(xous::Error::InternalError))?;
322+
let tvr = buf.to_original::<TextView, _>().unwrap();
323+
324+
tv.cursor = tvr.cursor;
325+
tv.bounds_computed = tvr.bounds_computed;
326+
tv.overflow = tvr.overflow;
327+
// don't update the animation state when just computing the textview bounds
328+
// tv.busy_animation_state = tvr.busy_animation_state;
329+
Ok(())
330+
}
331+
332+
/// Clear the screen in a device-optimized fashion. The exact background color depends on the device.
333+
pub fn clear(&self) -> Result<(), xous::Error> {
334+
send_message(self.conn, Message::new_scalar(GfxOpcode::Clear.to_usize().unwrap(), 0, 0, 0, 0))
335+
.map(|_| ())
336+
}
337+
313338
/// Draws a line with clipping.
314339
///
315340
/// This function sends a message to the graphics server to draw the specified `Line` within the specified
@@ -665,6 +690,33 @@ impl Gfx {
665690
.expect("couldn't pop");
666691
}
667692
}
693+
694+
/// This will cause the caller to block until it is granted a lock on the modal state.
695+
///
696+
/// This is a v2-only API. Calling it on a v1 system will cause a panic.
697+
pub fn acquire_modal(&self) -> Result<xous::Result, xous::Error> {
698+
send_message(
699+
self.conn,
700+
Message::new_blocking_scalar(GfxOpcode::AcquireModal.to_usize().unwrap(), 0, 0, 0, 0),
701+
)
702+
}
703+
704+
/// This is a v2-only API. Calling it on a v1 system will cause a panic.
705+
pub fn release_modal(&self) -> Result<xous::Result, xous::Error> {
706+
send_message(self.conn, Message::new_scalar(GfxOpcode::ReleaseModal.to_usize().unwrap(), 0, 0, 0, 0))
707+
}
708+
709+
/// V2-only API
710+
pub fn draw_object_list(&self, list: ObjectList) -> Result<(), xous::Error> {
711+
let buf = match Buffer::into_buf(list) {
712+
Ok(b) => b,
713+
Err(e) => {
714+
log::error!("err: {:?}", e);
715+
panic!("error")
716+
}
717+
};
718+
buf.lend(self.conn, GfxOpcode::UnclippedObjectList.to_u32().unwrap()).map(|_| ())
719+
}
668720
}
669721

670722
use core::sync::atomic::{AtomicU32, Ordering};

libs/ux-api/src/widgets/action.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ pub enum ActionType {
2424

2525
#[enum_dispatch]
2626
pub trait ActionApi {
27-
fn height(&self, glyph_height: i16, margin: i16, _modal: &Modal) -> i16 { glyph_height + margin * 2 }
28-
fn redraw(&self, _at_height: i16, _modal: &Modal) { unimplemented!() }
27+
fn height(&self, glyph_height: isize, margin: isize, _modal: &Modal) -> isize {
28+
glyph_height + margin * 2
29+
}
30+
fn redraw(&self, _at_height: isize, _modal: &Modal) { unimplemented!() }
2931
fn close(&mut self) {}
3032
fn is_password(&self) -> bool { false }
3133
/// navigation is one of '∴' | '←' | '→' | '↑' | '↓'

0 commit comments

Comments
 (0)