157 lines
3.7 KiB
Rust
157 lines
3.7 KiB
Rust
#![no_std]
|
|
|
|
extern crate alloc;
|
|
|
|
use core::task::{Context, Poll};
|
|
|
|
use alloc::{boxed::Box, sync::Arc};
|
|
use async_trait::async_trait;
|
|
use device_api::device::Device;
|
|
use libk::{device::char::CharDevice, vfs::FileReadiness};
|
|
use libk_util::{OneTimeInit, ring::LossyRingQueue};
|
|
use yggdrasil_abi::{
|
|
error::Error,
|
|
io::{KeyboardKeyEvent, MouseEvent},
|
|
};
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct KeyboardDevice;
|
|
#[derive(Clone, Copy)]
|
|
pub struct MouseDevice;
|
|
|
|
impl FileReadiness for KeyboardDevice {
|
|
fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
|
KEYBOARD_INPUT_QUEUE.poll_readable(cx).map(Ok)
|
|
}
|
|
}
|
|
|
|
impl Device for KeyboardDevice {
|
|
fn display_name(&self) -> &str {
|
|
"Keyboard input pseudo-device"
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl CharDevice for KeyboardDevice {
|
|
async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
|
if buf.len() < 4 {
|
|
return Ok(0);
|
|
}
|
|
|
|
let ev = KEYBOARD_INPUT_QUEUE.read().await;
|
|
|
|
buf[..4].copy_from_slice(&ev.as_bytes());
|
|
|
|
Ok(4)
|
|
}
|
|
|
|
fn read_nonblocking(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
|
if buf.len() < 4 {
|
|
return Ok(0);
|
|
}
|
|
|
|
let ev = KEYBOARD_INPUT_QUEUE.try_read().ok_or(Error::WouldBlock)?;
|
|
|
|
buf[..4].copy_from_slice(&ev.as_bytes());
|
|
|
|
Ok(4)
|
|
}
|
|
|
|
fn is_writeable(&self) -> bool {
|
|
false
|
|
}
|
|
|
|
fn device_request(&self, option: u32, buffer: &mut [u8], len: usize) -> Result<usize, Error> {
|
|
let _ = option;
|
|
let _ = buffer;
|
|
let _ = len;
|
|
Err(Error::InvalidOperation)
|
|
}
|
|
|
|
fn is_terminal(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
impl MouseDevice {
|
|
fn write_report(buf: &mut [u8], report: &MouseEvent) -> Result<usize, Error> {
|
|
buf[0] = report.dx as u8;
|
|
buf[1] = report.dy as u8;
|
|
buf[2] = report.buttons;
|
|
buf[3] = 0;
|
|
|
|
Ok(4)
|
|
}
|
|
}
|
|
|
|
impl FileReadiness for MouseDevice {
|
|
fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
|
MOUSE_INPUT_QUEUE.poll_readable(cx).map(Ok)
|
|
}
|
|
}
|
|
|
|
impl Device for MouseDevice {
|
|
fn display_name(&self) -> &str {
|
|
"Mouse input pseudo-device"
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl CharDevice for MouseDevice {
|
|
async fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
|
if buf.len() < 4 {
|
|
return Ok(0);
|
|
}
|
|
|
|
let ev = MOUSE_INPUT_QUEUE.read().await;
|
|
Self::write_report(buf, &ev)
|
|
}
|
|
|
|
fn read_nonblocking(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
|
if buf.len() < 4 {
|
|
return Ok(0);
|
|
}
|
|
|
|
let ev = MOUSE_INPUT_QUEUE.try_read().ok_or(Error::WouldBlock)?;
|
|
Self::write_report(buf, &ev)
|
|
}
|
|
|
|
fn is_writeable(&self) -> bool {
|
|
false
|
|
}
|
|
|
|
fn device_request(&self, option: u32, buffer: &mut [u8], len: usize) -> Result<usize, Error> {
|
|
let _ = option;
|
|
let _ = buffer;
|
|
let _ = len;
|
|
Err(Error::InvalidOperation)
|
|
}
|
|
|
|
fn is_terminal(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
static KEYBOARD_INPUT_QUEUE: LossyRingQueue<KeyboardKeyEvent> = LossyRingQueue::with_capacity(32);
|
|
static MOUSE_INPUT_QUEUE: LossyRingQueue<MouseEvent> = LossyRingQueue::with_capacity(64);
|
|
static KEYBOARD_DEVICE: OneTimeInit<Arc<KeyboardDevice>> = OneTimeInit::new();
|
|
static MOUSE_DEVICE: OneTimeInit<Arc<MouseDevice>> = OneTimeInit::new();
|
|
|
|
pub fn setup_keyboard() -> Arc<KeyboardDevice> {
|
|
KEYBOARD_DEVICE
|
|
.or_init_with(|| Arc::new(KeyboardDevice))
|
|
.clone()
|
|
}
|
|
|
|
pub fn setup_mouse() -> Arc<MouseDevice> {
|
|
MOUSE_DEVICE.or_init_with(|| Arc::new(MouseDevice)).clone()
|
|
}
|
|
|
|
pub fn send_mouse_event(ev: MouseEvent) {
|
|
MOUSE_INPUT_QUEUE.write(ev);
|
|
}
|
|
|
|
pub fn send_keyboard_event(ev: KeyboardKeyEvent) {
|
|
KEYBOARD_INPUT_QUEUE.write(ev);
|
|
}
|