mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 18:03:25 +00:00
Reorganize the codebase
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
888853a6de
commit
271a16d492
90
services/comps/input/src/lib.rs
Normal file
90
services/comps/input/src/lib.rs
Normal file
@ -0,0 +1,90 @@
|
||||
//! The input device of jinux
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![feature(fn_traits)]
|
||||
|
||||
mod virtio;
|
||||
|
||||
extern crate alloc;
|
||||
use core::any::Any;
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use component::init_component;
|
||||
use component::ComponentInitError;
|
||||
use jinux_virtio::VirtioDeviceType;
|
||||
|
||||
use spin::{Mutex, Once};
|
||||
use virtio::VirtioInputDevice;
|
||||
use virtio_input_decoder::DecodeType;
|
||||
|
||||
pub trait INPUTDevice: Send + Sync + Any {
|
||||
fn handle_irq(&self) -> Option<()>;
|
||||
fn register_callbacks(&self, function: &'static (dyn Fn(DecodeType) + Send + Sync));
|
||||
fn name(&self) -> &String;
|
||||
}
|
||||
|
||||
pub static INPUT_COMPONENT: Once<INPUTComponent> = Once::new();
|
||||
|
||||
#[init_component]
|
||||
fn input_component_init() -> Result<(), ComponentInitError> {
|
||||
let a = INPUTComponent::init()?;
|
||||
INPUT_COMPONENT.call_once(|| a);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct INPUTComponent {
|
||||
/// Input device map, key is the irq number, value is the Input device
|
||||
input_device_map: Mutex<BTreeMap<u8, Arc<dyn INPUTDevice>>>,
|
||||
}
|
||||
|
||||
impl INPUTComponent {
|
||||
pub fn init() -> Result<Self, ComponentInitError> {
|
||||
let mut input_device_map: BTreeMap<u8, Arc<dyn INPUTDevice>> = BTreeMap::new();
|
||||
let virtio = jinux_virtio::VIRTIO_COMPONENT.get().unwrap();
|
||||
let devices = virtio.get_device(VirtioDeviceType::Input);
|
||||
for device in devices {
|
||||
let (v_device, irq_num) = VirtioInputDevice::new(device);
|
||||
input_device_map.insert(irq_num, Arc::new(v_device));
|
||||
}
|
||||
Ok(Self {
|
||||
input_device_map: Mutex::new(input_device_map),
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn name() -> &'static str {
|
||||
"Input Device"
|
||||
}
|
||||
// 0~65535
|
||||
pub const fn priority() -> u16 {
|
||||
8192
|
||||
}
|
||||
}
|
||||
|
||||
impl INPUTComponent {
|
||||
fn call(self: &Self, irq_number: u8) -> Result<(), InputDeviceHandleError> {
|
||||
// FIXME: use Result instead
|
||||
let binding = self.input_device_map.lock();
|
||||
let device = binding
|
||||
.get(&irq_number)
|
||||
.ok_or(InputDeviceHandleError::DeviceNotExists)?;
|
||||
device.handle_irq();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_input_device(self: &Self) -> Vec<Arc<dyn INPUTDevice>> {
|
||||
self.input_device_map
|
||||
.lock()
|
||||
.iter()
|
||||
.map(|(_, device)| device.clone())
|
||||
.collect::<Vec<Arc<dyn INPUTDevice>>>()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum InputDeviceHandleError {
|
||||
DeviceNotExists,
|
||||
Unknown,
|
||||
}
|
123
services/comps/input/src/virtio.rs
Normal file
123
services/comps/input/src/virtio.rs
Normal file
@ -0,0 +1,123 @@
|
||||
//! Input device based on Virtio
|
||||
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use jinux_frame::offset_of;
|
||||
use jinux_frame::trap::TrapFrame;
|
||||
use jinux_pci::msix::MSIX;
|
||||
use jinux_util::frame_ptr::InFramePtr;
|
||||
use jinux_virtio::device::input::device::InputProp;
|
||||
use jinux_virtio::VitrioPciCommonCfg;
|
||||
use jinux_virtio::{
|
||||
device::input::{device::InputDevice, InputConfigSelect},
|
||||
PCIVirtioDevice,
|
||||
};
|
||||
use log::{debug, info};
|
||||
use spin::Mutex;
|
||||
use virtio_input_decoder::{DecodeType, Decoder};
|
||||
|
||||
use crate::INPUTDevice;
|
||||
pub struct VirtioInputDevice {
|
||||
input_device: InputDevice,
|
||||
common_cfg: InFramePtr<VitrioPciCommonCfg>,
|
||||
msix: Mutex<MSIX>,
|
||||
name: String,
|
||||
callbacks: Mutex<Vec<Arc<dyn Fn(DecodeType) + Send + Sync + 'static>>>,
|
||||
}
|
||||
|
||||
impl VirtioInputDevice {
|
||||
/// Create a new Virtio Input Device, return value contains the irq number it will use
|
||||
pub(crate) fn new(virtio_device: PCIVirtioDevice) -> (Self, u8) {
|
||||
let input_device = match virtio_device.device {
|
||||
jinux_virtio::device::VirtioDevice::Input(dev) => dev,
|
||||
_ => {
|
||||
panic!("Error when creating new input device, the input device is other type of virtio device");
|
||||
}
|
||||
};
|
||||
let mut raw_name: [u8; 128] = [0; 128];
|
||||
input_device.query_config_select(InputConfigSelect::IdName, 0, &mut raw_name);
|
||||
let name = String::from_utf8(raw_name.to_vec()).unwrap();
|
||||
info!("input device name:{}", name);
|
||||
|
||||
let mut prop: [u8; 128] = [0; 128];
|
||||
input_device.query_config_select(InputConfigSelect::PropBits, 0, &mut prop);
|
||||
|
||||
let input_prop = InputProp::from_bits(prop[0]).unwrap();
|
||||
debug!("input device prop:{:?}", input_prop);
|
||||
|
||||
fn handle_input(frame: &TrapFrame) {
|
||||
debug!("in handle input");
|
||||
let input_component = crate::INPUT_COMPONENT.get().unwrap();
|
||||
input_component.call(frame.trap_num as u8);
|
||||
}
|
||||
fn config_space_change(_: &TrapFrame) {
|
||||
debug!("input device config space change");
|
||||
}
|
||||
|
||||
let common_cfg = virtio_device.common_cfg;
|
||||
let mut msix = virtio_device.msix;
|
||||
|
||||
let config_msix_vector =
|
||||
common_cfg.read_at(offset_of!(VitrioPciCommonCfg, config_msix_vector)) as usize;
|
||||
|
||||
let mut event_irq_number = 0;
|
||||
for i in 0..msix.table_size as usize {
|
||||
let msix = msix.table.get_mut(i).unwrap();
|
||||
if !msix.irq_handle.is_empty() {
|
||||
panic!("msix already have irq functions");
|
||||
}
|
||||
if config_msix_vector == i {
|
||||
msix.irq_handle.on_active(config_space_change);
|
||||
} else {
|
||||
event_irq_number = msix.irq_handle.num();
|
||||
msix.irq_handle.on_active(handle_input);
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
Self {
|
||||
input_device,
|
||||
common_cfg,
|
||||
msix: Mutex::new(msix),
|
||||
name,
|
||||
callbacks: Mutex::new(Vec::new()),
|
||||
},
|
||||
event_irq_number,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl INPUTDevice for VirtioInputDevice {
|
||||
fn handle_irq(&self) -> Option<()> {
|
||||
let input = &self.input_device;
|
||||
// one interrupt may contains serval input, so it should loop
|
||||
loop {
|
||||
let event = input.pop_pending_event()?;
|
||||
let dtype = match Decoder::decode(
|
||||
event.event_type as usize,
|
||||
event.code as usize,
|
||||
event.value as usize,
|
||||
) {
|
||||
Ok(dtype) => dtype,
|
||||
Err(_) => return Some(()),
|
||||
};
|
||||
let lock = self.callbacks.lock();
|
||||
for callback in lock.iter() {
|
||||
callback.call((dtype,));
|
||||
}
|
||||
match dtype {
|
||||
virtio_input_decoder::DecodeType::Key(key, r#type) => {
|
||||
info!("{:?} {:?}", key, r#type);
|
||||
}
|
||||
virtio_input_decoder::DecodeType::Mouse(mouse) => info!("{:?}", mouse),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn register_callbacks(&self, function: &'static (dyn Fn(DecodeType) + Send + Sync)) {
|
||||
self.callbacks.lock().push(Arc::new(function))
|
||||
}
|
||||
|
||||
fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user