Add KDGKBMODE and KDSKBMODE ioctl support
This commit is contained in:
parent
2ba05a1673
commit
2d74e69b4b
|
|
@ -59,6 +59,21 @@ pub trait AnyConsoleDevice: Send + Sync + Any + Debug {
|
|||
fn mode(&self) -> Option<mode::ConsoleMode> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Sets the keyboard mode (see [`mode::KeyboardMode`]).
|
||||
///
|
||||
/// Returns true if the mode was changed, false if the mode is not supported.
|
||||
#[must_use]
|
||||
fn set_keyboard_mode(&self, _mode: mode::KeyboardMode) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Gets the current keyboard mode.
|
||||
///
|
||||
/// Returns the current keyboard mode, or `None` if mode switching is not supported.
|
||||
fn keyboard_mode(&self) -> Option<mode::KeyboardMode> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_device(name: String, device: Arc<dyn AnyConsoleDevice>) {
|
||||
|
|
|
|||
|
|
@ -16,3 +16,24 @@ pub enum ConsoleMode {
|
|||
/// and may be used for graphical output (e.g., by X server).
|
||||
Graphics = 1,
|
||||
}
|
||||
|
||||
/// The keyboard mode.
|
||||
///
|
||||
/// This mode determines how a console behaves when it receives input from the keyboard. For more
|
||||
/// details, see <https://lct.sourceforge.net/lct/x60.html>.
|
||||
///
|
||||
/// Reference: <https://elixir.bootlin.com/linux/v6.17.4/source/include/uapi/linux/kd.h#L81-L85>.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromInt)]
|
||||
#[repr(i32)]
|
||||
pub enum KeyboardMode {
|
||||
/// The scancode mode (`K_RAW` in Linux).
|
||||
Raw = 0,
|
||||
/// The ASCII mode (`K_XLATE` in Linux).
|
||||
Xlate = 1,
|
||||
/// The keycode mode (`K_MEDIUMRAW` in Linux).
|
||||
MediumRaw = 2,
|
||||
/// The Unicode mode (`K_UNICODE` in Linux).
|
||||
Unicode = 3,
|
||||
/// The off mode (`K_OFF` in Linux).
|
||||
Off = 4,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
use alloc::{sync::Arc, vec::Vec};
|
||||
|
||||
use aster_console::{
|
||||
font::BitmapFont, mode::ConsoleMode, AnyConsoleDevice, ConsoleCallback, ConsoleSetFontError,
|
||||
font::BitmapFont,
|
||||
mode::{ConsoleMode, KeyboardMode},
|
||||
AnyConsoleDevice, ConsoleCallback, ConsoleSetFontError,
|
||||
};
|
||||
use aster_keyboard::InputKey;
|
||||
use ostd::{
|
||||
|
|
@ -19,7 +21,7 @@ use crate::{
|
|||
|
||||
/// A text console rendered onto the framebuffer.
|
||||
pub struct FramebufferConsole {
|
||||
callbacks: SpinLock<Vec<&'static ConsoleCallback>, LocalIrqDisabled>,
|
||||
callbacks: SpinLock<ConsoleCallbacks, LocalIrqDisabled>,
|
||||
inner: SpinLock<(ConsoleState, EscapeFsm), LocalIrqDisabled>,
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +60,7 @@ impl AnyConsoleDevice for FramebufferConsole {
|
|||
}
|
||||
|
||||
fn register_callback(&self, callback: &'static ConsoleCallback) {
|
||||
self.callbacks.lock().push(callback);
|
||||
self.callbacks.lock().callbacks.push(callback);
|
||||
}
|
||||
|
||||
fn set_font(&self, font: BitmapFont) -> Result<(), ConsoleSetFontError> {
|
||||
|
|
@ -73,11 +75,33 @@ impl AnyConsoleDevice for FramebufferConsole {
|
|||
fn mode(&self) -> Option<ConsoleMode> {
|
||||
Some(self.inner.lock().0.mode())
|
||||
}
|
||||
|
||||
fn set_keyboard_mode(&self, mode: KeyboardMode) -> bool {
|
||||
match mode {
|
||||
KeyboardMode::Xlate => self.callbacks.lock().is_input_enabled = true,
|
||||
KeyboardMode::Off => self.callbacks.lock().is_input_enabled = false,
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn keyboard_mode(&self) -> Option<KeyboardMode> {
|
||||
if self.callbacks.lock().is_input_enabled {
|
||||
Some(KeyboardMode::Xlate)
|
||||
} else {
|
||||
Some(KeyboardMode::Off)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FramebufferConsole {
|
||||
/// Creates a new framebuffer console.
|
||||
pub(self) fn new(framebuffer: Arc<FrameBuffer>) -> Self {
|
||||
let callbacks = ConsoleCallbacks {
|
||||
callbacks: Vec::new(),
|
||||
is_input_enabled: true,
|
||||
};
|
||||
|
||||
let state = ConsoleState {
|
||||
x_pos: 0,
|
||||
y_pos: 0,
|
||||
|
|
@ -93,10 +117,23 @@ impl FramebufferConsole {
|
|||
let esc_fsm = EscapeFsm::new();
|
||||
|
||||
Self {
|
||||
callbacks: SpinLock::new(Vec::new()),
|
||||
callbacks: SpinLock::new(callbacks),
|
||||
inner: SpinLock::new((state, esc_fsm)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Triggers the registered input callbacks with the given data.
|
||||
pub(self) fn trigger_input_callbacks(&self, bytes: &[u8]) {
|
||||
let callbacks = self.callbacks.lock();
|
||||
if !callbacks.is_input_enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
let reader = VmReader::from(bytes);
|
||||
for callback in callbacks.callbacks.iter() {
|
||||
callback(reader.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for FramebufferConsole {
|
||||
|
|
@ -105,6 +142,12 @@ impl core::fmt::Debug for FramebufferConsole {
|
|||
}
|
||||
}
|
||||
|
||||
struct ConsoleCallbacks {
|
||||
callbacks: Vec<&'static ConsoleCallback>,
|
||||
/// Whether the input characters will be handled by the callbacks.
|
||||
is_input_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ConsoleState {
|
||||
x_pos: usize,
|
||||
|
|
@ -280,8 +323,5 @@ fn handle_keyboard_input(key: InputKey) {
|
|||
};
|
||||
|
||||
let buffer = key.as_xterm_control_sequence();
|
||||
for callback in console.callbacks.lock().iter() {
|
||||
let reader = VmReader::from(buffer);
|
||||
callback(reader);
|
||||
}
|
||||
console.trigger_input_callbacks(buffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use aster_console::{font::BitmapFont, mode::ConsoleMode, AnyConsoleDevice};
|
||||
use aster_console::{
|
||||
font::BitmapFont,
|
||||
mode::{ConsoleMode, KeyboardMode},
|
||||
AnyConsoleDevice,
|
||||
};
|
||||
use ostd::sync::LocalIrqDisabled;
|
||||
|
||||
use self::{line_discipline::LineDiscipline, termio::CFontOp};
|
||||
|
|
@ -323,6 +327,20 @@ impl<D: TtyDriver> FileIo for Tty<D> {
|
|||
let mode = console.mode().unwrap_or(ConsoleMode::Text);
|
||||
current_userspace!().write_val(arg, &(mode as i32))?;
|
||||
}
|
||||
IoctlCmd::KDSKBMODE => {
|
||||
let console = self.console()?;
|
||||
|
||||
let mode = KeyboardMode::try_from(arg as i32)?;
|
||||
if !console.set_keyboard_mode(mode) {
|
||||
return_errno_with_message!(Errno::EINVAL, "the keyboard mode is not supported");
|
||||
}
|
||||
}
|
||||
IoctlCmd::KDGKBMODE => {
|
||||
let console = self.console()?;
|
||||
|
||||
let mode = console.keyboard_mode().unwrap_or(KeyboardMode::Xlate);
|
||||
current_userspace!().write_val(arg, &(mode as i32))?;
|
||||
}
|
||||
_ => (self.weak_self.upgrade().unwrap() as Arc<dyn Terminal>)
|
||||
.job_ioctl(cmd, arg, false)?,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use crate::prelude::*;
|
|||
pub enum IoctlCmd {
|
||||
/// Get terminal attributes
|
||||
TCGETS = 0x5401,
|
||||
/// Set terminal attributes
|
||||
TCSETS = 0x5402,
|
||||
/// Drain the output buffer and set attributes
|
||||
TCSETSW = 0x5403,
|
||||
|
|
@ -21,8 +22,9 @@ pub enum IoctlCmd {
|
|||
TIOCSPGRP = 0x5410,
|
||||
/// Get the number of bytes in the input buffer.
|
||||
FIONREAD = 0x541B,
|
||||
/// Set window size
|
||||
/// Get window size
|
||||
TIOCGWINSZ = 0x5413,
|
||||
/// Set window size
|
||||
TIOCSWINSZ = 0x5414,
|
||||
/// Enable or disable non-blocking I/O mode.
|
||||
FIONBIO = 0x5421,
|
||||
|
|
@ -48,6 +50,10 @@ pub enum IoctlCmd {
|
|||
KDGETMODE = 0x4B3B,
|
||||
/// Set console mode
|
||||
KDSETMODE = 0x4B3A,
|
||||
/// Get keyboard mode
|
||||
KDGKBMODE = 0x4B44,
|
||||
/// Set keyboard mode
|
||||
KDSKBMODE = 0x4B45,
|
||||
/// Get tdx report using TDCALL
|
||||
TDXGETREPORT = 0xc4405401,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue