Skip to content

Instantly share code, notes, and snippets.

@sigmaSd
Last active November 4, 2020 16:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sigmaSd/393d8c8ce201e04b1df6fda4898a71f8 to your computer and use it in GitHub Desktop.
Save sigmaSd/393d8c8ce201e04b1df6fda4898a71f8 to your computer and use it in GitHub Desktop.
[dependencies] ctrlc = "3.1.7" libc = "0.2.80" scopeguard = "1.1.0" termios = "0.3.3"
use std::io;
use std::io::prelude::*;
use std::os::unix::io::AsRawFd;
use termios::*;
const KDSKBMODE: u64 = 0x4B45;
fn main() {
if let Err(e) = try_main() {
eprintln!("Something happened: {}", e);
}
}
fn try_main() -> io::Result<()> {
let tty0_f = std::fs::File::open("/dev/tty0")?;
let tty0 = tty0_f.as_raw_fd();
let old_termios = Termios::from_fd(tty0)?;
let oldkbmode: libc::c_int = unsafe { get_mode(tty0) }?;
// cleanup
scopeguard::defer! {
clean_up(tty0, old_termios, oldkbmode);
}
let running = Arc::new(AtomicBool::new(true));
let flag = running.clone();
ctrlc::set_handler(move || {
flag.store(false, Ordering::SeqCst);
})
.expect("Error setting Ctrl-C handler");
showkey(&tty0_f, tty0, running)?;
Ok(())
}
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
fn showkey(mut tty0_f: &std::fs::File, tty0: i32, running: Arc<AtomicBool>) -> io::Result<()> {
let mut buf = [0u8; 18];
let mut new = Termios::from_fd(tty0)?;
new.c_lflag &= !(ICANON | ECHO | ISIG);
new.c_iflag = 0;
new.c_cc[VMIN] = 18;
new.c_cc[VTIME] = 1;
tcsetattr(tty0, TCSAFLUSH, &new)?;
const K_RAW: u64 = 0x0;
unsafe {
if libc::ioctl(tty0, KDSKBMODE, K_RAW) != 0 {
return Err(io::Error::last_os_error());
}
}
while running.load(Ordering::SeqCst) {
let n = tty0_f.read(&mut buf)?;
print(&buf, n);
}
Ok(())
}
fn print(buf: &[u8], n: usize) {
let mut i = 0;
while i < n {
let kc;
let s: String;
s = if (buf[i] & 0x80) != 0 {
"release".into()
} else {
"press".into()
};
if i + 2 < n
&& buf[i].trailing_zeros() >= 7
&& (buf[i + 1] & 0x80) != 0
&& (buf[i + 2] & 0x80) != 0
{
kc = ((buf[i + 1] & 0x7f) << 7) | (buf[i + 2] & 0x7f);
i += 3;
} else {
kc = buf[i] & 0x7f;
i += 1;
}
println!("keycode {} {}", kc, s);
}
}
unsafe fn get_mode(tty0: i32) -> io::Result<libc::c_int> {
const KDGKBMODE: u64 = 0x4B44;
const K_XLATE: i32 = 0x01;
const K_MEDIUMRAW: i32 = 0x02;
const K_UNICODE: i32 = 0x03;
const K_RAW: i32 = 0x0;
let mut kbm = 1;
let oldkbmode: &mut libc::c_int = &mut kbm;
let m: String;
if libc::ioctl(tty0, KDGKBMODE, &mut *oldkbmode) != 0 {
return Err(io::Error::last_os_error());
}
match *oldkbmode {
x if x == K_RAW => {
m = "RAW".into();
}
x if x == K_XLATE => {
m = "XLATE".into();
}
x if x == K_MEDIUMRAW => {
m = "MEDIUMRAW".into();
}
x if x == K_UNICODE => {
m = "UNICODE".into();
}
_ => {
m = "?UNKNOWN?".into();
}
}
println!("Old keyboard mode was: {}\n", m);
Ok(*oldkbmode)
}
fn clean_up(tty0: i32, old_termios: Termios, oldkbmode: libc::c_int) {
unsafe {
if libc::ioctl(tty0, KDSKBMODE, oldkbmode) != 0 {
eprintln!(
"Could not restore orignal keyboard mode. error: {}",
io::Error::last_os_error()
)
};
if let Err(e) = tcsetattr(tty0, 0, &old_termios) {
eprintln!(
"Could not restore original termios attributes. Error: {}",
e
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment