Skip to content

Commit 9f31f96

Browse files
committed
Adds Notification
1 parent 2539101 commit 9f31f96

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub mod lock;
2727
pub mod malloc;
2828
pub mod mount;
2929
pub mod namei;
30+
pub mod notification;
3031
pub mod pcpu;
3132
pub mod queue;
3233
pub mod socket;

src/notification/mod.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
use crate::fd::{openat, write_all, OpenFlags, AT_FDCWD};
2+
use crate::pcpu::Pcpu;
3+
use crate::uio::UioSeg;
4+
use crate::Kernel;
5+
use core::ffi::c_int;
6+
use core::fmt::Write;
7+
8+
/// Notification to send to the PlayStation 4 shell.
9+
///
10+
/// Use [write](core::write) macro to write the message.
11+
///
12+
/// [`Write`] implementation on this type never return [`Err`]. Instead, it will discard all writes
13+
/// after the buffer is full.
14+
pub struct Notification {
15+
data: OrbisNotificationRequest,
16+
next: usize,
17+
}
18+
19+
impl Notification {
20+
pub fn new() -> Self {
21+
Self {
22+
data: OrbisNotificationRequest {
23+
ty: 0,
24+
req_id: 0,
25+
priority: 0,
26+
msg_id: 0,
27+
target_id: -1,
28+
user_id: 0,
29+
unk1: 0,
30+
unk2: 0,
31+
app_id: 0,
32+
error_num: 0,
33+
unk3: 0,
34+
use_icon_image_uri: 1,
35+
message: [0; 1024],
36+
icon_uri: [0; 1024],
37+
unk: [0; 1024],
38+
},
39+
next: 0,
40+
}
41+
}
42+
43+
#[inline(never)]
44+
pub fn send<K: Kernel>(self, k: K) {
45+
// Open notification device.
46+
let devs = [c"/dev/notification0", c"/dev/notification1"];
47+
let mut fd = None;
48+
49+
for dev in devs.into_iter().map(|v| v.as_ptr()) {
50+
if let Ok(v) =
51+
unsafe { openat(k, AT_FDCWD, dev, UioSeg::Kernel, OpenFlags::O_WRONLY, 0) }
52+
{
53+
fd = Some(v);
54+
break;
55+
}
56+
}
57+
58+
// Check if we have a device to write to.
59+
let fd = match fd {
60+
Some(v) => v,
61+
None => return,
62+
};
63+
64+
// Write notification.
65+
let len = size_of_val(&self.data);
66+
let data = &self.data as *const OrbisNotificationRequest as *const u8;
67+
let data = unsafe { core::slice::from_raw_parts(data, len) };
68+
let td = K::Pcpu::curthread();
69+
70+
unsafe { write_all(k, fd.as_raw_fd(), data, td).ok() };
71+
}
72+
}
73+
74+
impl Default for Notification {
75+
fn default() -> Self {
76+
Self::new()
77+
}
78+
}
79+
80+
impl Write for Notification {
81+
#[inline(never)]
82+
fn write_str(&mut self, s: &str) -> core::fmt::Result {
83+
// Get end offset.
84+
let end = match self.next.checked_add(s.len()) {
85+
Some(v) => v,
86+
None => {
87+
// Instead of error we discard all subsequence write.
88+
self.next = self.data.message.len();
89+
return Ok(());
90+
}
91+
};
92+
93+
// Get location to write to.
94+
let dst = match self.data.message.get_mut(self.next..end) {
95+
Some(v) => v,
96+
None => {
97+
// Same as the above.
98+
self.next = self.data.message.len();
99+
return Ok(());
100+
}
101+
};
102+
103+
dst.copy_from_slice(s.as_bytes());
104+
self.next = end;
105+
106+
Ok(())
107+
}
108+
109+
#[inline(never)]
110+
fn write_char(&mut self, c: char) -> core::fmt::Result {
111+
self.write_str(c.encode_utf8(&mut [0; 4]))
112+
}
113+
}
114+
115+
/// By OSM-Made.
116+
#[repr(C)]
117+
struct OrbisNotificationRequest {
118+
ty: c_int,
119+
req_id: c_int,
120+
priority: c_int,
121+
msg_id: c_int,
122+
target_id: c_int,
123+
user_id: c_int,
124+
unk1: c_int,
125+
unk2: c_int,
126+
app_id: c_int,
127+
error_num: c_int,
128+
unk3: c_int,
129+
use_icon_image_uri: u8,
130+
message: [u8; 1024],
131+
icon_uri: [u8; 1024],
132+
unk: [u8; 1024],
133+
}

0 commit comments

Comments
 (0)