1use core::ffi::c_void;
2use core::ptr::addr_of_mut;
3use uefi::{Char16, Event, Result, StatusExt};
4use uefi::proto::console::text::{Key};
5use uefi::proto::unsafe_protocol;
6use uefi_raw::Status;
7use crate::simple_text_input_ex::{KeyNotifyFunction, KeyState, KeyToggleState,
8 RawKeyData, SimpleTextInputExProtocol, Boolean, InputKey};
9
10#[derive(Debug, Copy, Clone)]
12pub struct KeyData {
13 pub key: Key,
14 pub key_state: KeyState,
15}
16
17impl From<KeyData> for RawKeyData {
19 fn from(value: KeyData) -> Self {
20 let input_key = match value.key {
21 Key::Printable(c) => InputKey {
22 scan_code: 0,
23 unicode_char: u16::from(c),
24 },
25 Key::Special(code) => InputKey {
26 scan_code: code.0,
27 unicode_char: 0,
28 },
29 };
30
31 Self {
32 key: input_key,
33 key_state: value.key_state,
34 }
35 }
36}
37
38impl From<RawKeyData> for KeyData {
40 fn from(raw: RawKeyData) -> Self {
41 Self {
42 key: Key::from(raw.key),
43 key_state: raw.key_state,
45 }
46 }
47}
48
49impl KeyData {
50 pub fn new(c: char) -> Result<Self> {
52 let c = Char16::try_from(c).map_err(|_| Status::INVALID_PARAMETER)?;
53
54 Ok(Self {
55 key: Key::Printable(c),
56 key_state: KeyState::default(),
57 })
58 }
59}
60
61#[derive(Debug)]
63#[repr(transparent)]
64#[unsafe_protocol(SimpleTextInputExProtocol::GUID)]
65pub struct Input(SimpleTextInputExProtocol);
66
67impl Input {
68 pub fn reset(&mut self, extended_verification: bool) -> Result {
70 let this = addr_of_mut!(self.0);
71 unsafe {
72 (self.0.reset)(this, Boolean::from(extended_verification)).to_result()
73 }
74 }
75
76 pub fn read_key_stroke_ex(&mut self) -> Option<KeyData> {
78 let mut raw = RawKeyData::default();
79 let this = addr_of_mut!(self.0);
80
81 let status = unsafe {
82 (self.0.read_key_stroke_ex)(this, &mut raw)
84 };
85
86 status.is_success().then_some(KeyData::from(raw))
88 }
89
90 pub fn wait_for_key_event(&self) -> Option<Event> {
95 unsafe { Event::from_ptr(self.0.wait_for_key_ex) }
96 }
97
98 pub fn set_state(&mut self, mut state: KeyToggleState) -> Result {
99 let this = addr_of_mut!(self.0);
100 unsafe {
101 (self.0.set_state)(this, &mut state).to_result()
102 }
103 }
104
105 pub fn on_key_callback(
127 &mut self,
128 key_data: &KeyData,
129 notification_function: KeyNotifyFunction,
130 ) -> Result<KeyNotifyHandle<'_>> {
131 let this = addr_of_mut!(self.0);
132
133 let mut handle = core::ptr::null_mut();
134 let mut raw_data = RawKeyData::from(*key_data);
135
136 unsafe {
137 ((*this).register_key_notify)(
138 this,
139 &mut raw_data,
140 notification_function,
141 &mut handle,
142 )
143 .to_result_with_val(|| KeyNotifyHandle {
144 proto: &mut *this,
147 handle,
148 })
149 }
150 }
151}
152
153pub struct KeyNotifyHandle<'a> {
155 proto: &'a mut SimpleTextInputExProtocol,
157 handle: *mut c_void,
159}
160
161impl Drop for KeyNotifyHandle<'_> {
162 fn drop(&mut self) {
165 let this = addr_of_mut!(*self.proto);
166 unsafe {
167 let _ = ((*this).unregister_key_notify)(this, self.handle);
168 }
169 }
170}