server/
move.rs

1// SPDX-FileCopyrightText: 2023 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use whence::WhenceExt;
5
6use crate::{Server, ServerContext, SimpleMemoryMessage};
7
8/// A [`Move`] message handler.
9pub trait MoveHandler<M: Move>
10where
11    Self: Server,
12{
13    const LEAK_MESSAGE: bool;
14    fn handle(&mut self, msg: M, sender: xous::PID, context: &mut ServerContext<Self>);
15}
16
17/// A message which is simply a to-be-sent memory range
18pub trait Move: crate::MessageId + From<SimpleMemoryMessage> + Into<SimpleMemoryMessage> {}
19
20/// Message handler, used by ServerMessages::messages()
21pub fn handle_move<M: Move, S: MoveHandler<M>>(
22    handler: &mut S,
23    raw: xous::MessageEnvelope,
24    context: &mut ServerContext<S>,
25) {
26    let sender = raw.sender.pid().unwrap();
27    let msg = if S::LEAK_MESSAGE {
28        let message = raw.take_message();
29        let xous::Message::Move(mem) = message else {
30            log::warn!("invalid message: {message:?}");
31            return;
32        };
33        M::from(SimpleMemoryMessage::from(&mem))
34    } else {
35        let xous::Message::Move(mem) = &raw.body else {
36            log::warn!("invalid message: {raw:?}");
37            return;
38        };
39        M::from(SimpleMemoryMessage::from(mem))
40    };
41
42    handler.handle(msg, sender, context);
43}
44
45/// Send a [`Move`] message (panics on failure)
46pub fn send_move<M: Move>(cid: xous::CID, msg: M) { try_send_move(cid, msg).unwrap(); }
47
48/// Send a [`Move`] message (fallible)
49pub fn try_send_move<M: Move>(cid: xous::CID, msg: M) -> whence::Result<(), xous::Error> {
50    let msg: SimpleMemoryMessage = msg.into();
51    xous::send_message(
52        cid,
53        xous::Message::Move(xous::MemoryMessage {
54            id: M::ID,
55            buf: msg.buf,
56            offset: xous::MemoryAddress::new(msg.arg1),
57            valid: xous::MemoryAddress::new(msg.arg2),
58        }),
59    )
60    .whence()?;
61    Ok(())
62}
63
64/// Try sending a [`Move`] message. Does not block if the message queue is full.
65/// Can be used in an IRQ handler.
66pub fn send_move_nowait<M>(cid: xous::CID, msg: M) -> whence::Result<(), xous::Error>
67where
68    M: Move,
69{
70    let msg: SimpleMemoryMessage = msg.into();
71    xous::try_send_message(
72        cid,
73        xous::Message::Move(xous::MemoryMessage {
74            id: M::ID,
75            buf: msg.buf,
76            offset: xous::MemoryAddress::new(msg.arg1),
77            valid: xous::MemoryAddress::new(msg.arg2),
78        }),
79    )
80    .whence()?;
81    Ok(())
82}