Skip to content

增加serio总线和相关trait #488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
2 changes: 2 additions & 0 deletions kernel/src/driver/base/init.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::driver::input::serio::serio_bus_init;
use system_error::SystemError;

use super::{
Expand All @@ -16,6 +17,7 @@ pub(super) fn driver_init() -> Result<(), SystemError> {
firmware_init()?;
hypervisor_init()?;
platform_bus_init()?;
serio_bus_init()?;
cpu_device_manager().init()?;

// 至此,已完成设备驱动模型的初始化
Expand Down
2 changes: 2 additions & 0 deletions kernel/src/driver/input/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod ps2_dev;
pub mod serio;
1 change: 1 addition & 0 deletions kernel/src/driver/input/ps2_dev/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod ps2_device;
4 changes: 4 additions & 0 deletions kernel/src/driver/input/ps2_dev/ps2_device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use crate::driver::{base::device::Device, input::serio::serio_device::SerioDevice};

// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/libps2.h#33
pub trait Ps2Device: Device + SerioDevice {}
31 changes: 31 additions & 0 deletions kernel/src/driver/input/serio/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use alloc::sync::Arc;
use system_error::SystemError;

use crate::driver::base::device::bus::{bus_register, Bus};

use self::subsys::SerioBus;

pub mod serio_device;
pub mod serio_driver;
pub mod subsys;

static mut SERIO_BUS: Option<Arc<SerioBus>> = None;

#[allow(dead_code)]
#[inline(always)]
pub fn serio_bus() -> Arc<SerioBus> {
unsafe { SERIO_BUS.clone().unwrap() }
}

/// # 函数的功能
///
/// 初始化serio bus
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#1024
pub fn serio_bus_init() -> Result<(), SystemError> {
let serio_bus = SerioBus::new();
let r = bus_register(serio_bus.clone() as Arc<dyn Bus>);
unsafe { SERIO_BUS = Some(serio_bus) };

return r;
}
70 changes: 70 additions & 0 deletions kernel/src/driver/input/serio/serio_device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use alloc::sync::Arc;
use system_error::SystemError;

use crate::driver::base::device::{bus::Bus, Device};

use super::serio_bus;

/// 串行设备,实现该trait的设备实例挂载在serio总线上,同时应该实现Device trait
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serio.h#20
pub trait SerioDevice: Device {
/// # 函数功能
///
/// Serio设备写入数据
///
/// ## 参数
///
/// - data 写入的数据
///
/// ## 返回值
///
/// 无
fn write(&self, device: &Arc<dyn SerioDevice>, data: u8) -> Result<(), SystemError>;
/// Serio设备连接驱动时调用
fn open(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// Serio设备断开驱动时调用
fn close(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// Serio设备初始化时调用
fn start(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// Serio设备销毁时调用
fn stop(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
}

#[allow(dead_code)]
#[inline(always)]
pub fn serio_device_manager() -> &'static SerioDeviceManager {
&SerioDeviceManager
}

pub struct SerioDeviceManager;

#[allow(dead_code)]
impl SerioDeviceManager {
/// # 函数功能
/// 注册Serio设备
///
/// ## 参数
/// - device 待注册的设备
///
/// ## 返回值
/// 无
pub fn register_port(&self, device: Arc<dyn SerioDevice>) -> Result<(), SystemError> {
self.init_port(device)
}

/// # 函数功能
/// 初始化Serio设备
///
/// ## 参数
/// - device 待初始化的Serio设备
///
/// ## 返回值
/// 无
///
/// todo:https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#494
pub fn init_port(&self, device: Arc<dyn SerioDevice>) -> Result<(), SystemError> {
device.set_bus(Some(Arc::downgrade(&(serio_bus() as Arc<dyn Bus>))));
Ok(())
}
}
75 changes: 75 additions & 0 deletions kernel/src/driver/input/serio/serio_driver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use alloc::sync::Arc;
use system_error::SystemError;

use crate::driver::base::device::{
bus::Bus,
driver::{driver_manager, Driver},
};

use super::{serio_bus, serio_device::SerioDevice};

/// 实现该trait的设备驱动实例应挂载在serio总线上,同时应该实现Driver trait
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/serio.h#67
pub trait SerioDriver: Driver {
// 写入时唤醒设备
fn write_wakeup(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// # 函数功能
/// 中断函数
///
/// ## 参数
/// - device: Serio设备
/// - data: 端口数据
/// - flag: 状态掩码
///
/// ## 返回值
/// 无
fn interrupt(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

每个接口的含义要标明一下

&self,
device: &Arc<dyn SerioDevice>,
data: u8,
flag: u8,
) -> Result<(), SystemError>;
/// Serio驱动连接设备
fn connect(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// 重新连接设备
fn reconnect(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// 快速重连设备
fn fast_reconnect(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// 驱动断开设备
fn disconnect(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
/// 清除设备状态
fn cleanup(&self, device: &Arc<dyn SerioDevice>) -> Result<(), SystemError>;
}

///todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#810
pub struct SerioDriverManager;

#[allow(dead_code)]
impl SerioDriverManager {
/// # 函数功能
/// 注册Serio驱动
///
/// ## 参数
/// - driver 待注册的Serio驱动
///
/// ## 返回值
/// 无
pub fn register(&self, driver: Arc<dyn SerioDriver>) -> Result<(), SystemError> {
driver.set_bus(Some(Arc::downgrade(&(serio_bus() as Arc<dyn Bus>))));
return driver_manager().register(driver as Arc<dyn Driver>);
}

/// # 函数功能
/// 卸载Serio驱动
///
/// ## 参数
/// - driver 待卸载的Serio驱动
///
/// ## 返回值
/// 无
#[allow(dead_code)]
pub fn unregister(&self, driver: &Arc<dyn SerioDriver>) {
driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
}
}
140 changes: 140 additions & 0 deletions kernel/src/driver/input/serio/subsys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
};
use intertrait::cast::CastArc;
use system_error::SystemError;

use crate::{
driver::{
acpi::acpi_manager,
base::{
device::{bus::Bus, driver::Driver, Device},
kobject::KObject,
subsys::SubSysPrivate,
},
},
filesystem::{
sysfs::{Attribute, AttributeGroup},
vfs::syscall::ModeType,
},
};

use super::{serio_device::SerioDevice, serio_driver::SerioDriver};

#[derive(Debug)]
pub struct SerioBus {
private: SubSysPrivate,
}

impl SerioBus {
pub fn new() -> Arc<Self> {
let w: Weak<Self> = Weak::new();
let private = SubSysPrivate::new("serio".to_string(), Some(w), None, &[]);
let bus = Arc::new(Self { private });
bus.subsystem()
.set_bus(Some(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>))));

return bus;
}
}

impl Bus for SerioBus {
fn name(&self) -> String {
return "serio".to_string();
}

fn dev_name(&self) -> String {
return self.name();
}

fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&SerioDeviceAttrGroup];
}

fn subsystem(&self) -> &SubSysPrivate {
return &self.private;
}

fn probe(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
let drv = device.driver().ok_or(SystemError::EINVAL)?;
let pdrv = drv.cast::<dyn SerioDriver>().map_err(|_| {
kerror!(
"SerioBus::probe() failed: device.driver() is not a SerioDriver. Device: '{:?}'",
device.name()
);
SystemError::EINVAL
})?;

let pdev = device.clone().cast::<dyn SerioDevice>().map_err(|_| {
kerror!(
"SerioBus::probe() failed: device is not a SerioDevice. Device: '{:?}'",
device.name()
);
SystemError::EINVAL
})?;

return pdrv.connect(&pdev);
}

fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!()
}

fn sync_state(&self, _device: &Arc<dyn Device>) {
todo!()
}

fn shutdown(&self, _device: &Arc<dyn Device>) {
todo!()
}

fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
todo!()
}

fn match_device(
&self,
device: &Arc<dyn Device>,
driver: &Arc<dyn Driver>,
) -> Result<bool, SystemError> {
// 尝试从 ACPI 中匹配
if let Ok(x) = acpi_manager().driver_match_device(driver, device) {
if x {
return Ok(true);
}
}

// 尝试从 ID table 中匹配
if let Some(drv_id_table) = driver.id_table() {
let pdev = device
.clone()
.cast::<dyn SerioDevice>()
.map_err(|_| SystemError::EINVAL)?;
if drv_id_table.name().eq(&pdev.name()) {
return Ok(true);
}
}

// 尝试根据设备名称匹配
return Ok(device.name().eq(&driver.name()));
}
}

#[derive(Debug)]
pub struct SerioDeviceAttrGroup;

impl AttributeGroup for SerioDeviceAttrGroup {
fn name(&self) -> Option<&str> {
None
}

/// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#473
fn attrs(&self) -> &[&'static dyn Attribute] {
return &[];
}

fn is_visible(&self, _kobj: Arc<dyn KObject>, _attr: &dyn Attribute) -> Option<ModeType> {
None
}
}
1 change: 1 addition & 0 deletions kernel/src/driver/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod acpi;
pub mod base;
pub mod disk;
pub mod input;
pub mod keyboard;
pub mod net;
pub mod open_firmware;
Expand Down