#keyboard #mouse #driver #no-std

nightly no-std ps2

nightly Rust 通用 PS/2 设备驱动程序

5 个不稳定版本

0.2.0 2021年7月13日
0.1.2 2021年6月4日
0.1.1 2020年12月19日
0.1.0 2020年11月26日
0.0.0 2020年10月6日

#1897硬件支持

MIT 许可证

47KB
706

ps2

CI MIT licensed crates.io API docs

nightly Rust 通用 PS/2 设备驱动程序。

贡献

欢迎在GitHub上提交错误报告和拉取请求:[https://github.com/lucis-fluxum/ps2-rs](https://github.com/lucis-fluxum/ps2-rs)。

许可证

本crate作为开源软件,根据[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) MIT许可证的条款提供。

除非你明确表示,否则你提交的任何有意包含在`ps2-rs`中的贡献,都应按MIT许可证许可,不附加任何额外的条款或条件。


lib.rs:

本crate提供了对PS/2控制器和PS/2设备的全面底层访问。它使用带超时的轮询方法来读写IO端口的请求数据。

示例

以下示例实现了OSDev wiki上概述的初始化过程[https://web.archive.org/web/20201112021519/https://wiki.osdev.org/%228042%22_PS/2_Controller#Initialising_the_PS.2F2_Controller](https://web.archive.org/web/20201112021519/https://wiki.osdev.org/%228042%22_PS/2_Controller#Initialising_the_PS.2F2_Controller)。我们通过假设PS/2控制器存在并且当前硬件支持它来跳过步骤1和2。

use ps2::{Controller, error::ControllerError, flags::ControllerConfigFlags};

fn initialize() -> Result<(), ControllerError> {
    let mut controller = unsafe { Controller::new() };

    // Step 3: Disable devices
    controller.disable_keyboard()?;
    controller.disable_mouse()?;

    // Step 4: Flush data buffer
    let _ = controller.read_data();

    // Step 5: Set config
    let mut config = controller.read_config()?;
    // Disable interrupts and scancode translation
    config.set(
        ControllerConfigFlags::ENABLE_KEYBOARD_INTERRUPT
            | ControllerConfigFlags::ENABLE_MOUSE_INTERRUPT
            | ControllerConfigFlags::ENABLE_TRANSLATE,
        false,
    );
    controller.write_config(config)?;

    // Step 6: Controller self-test
    controller.test_controller()?;
    // Write config again in case of controller reset
    controller.write_config(config)?;

    // Step 7: Determine if there are 2 devices
    let has_mouse = if config.contains(ControllerConfigFlags::DISABLE_MOUSE) {
        controller.enable_mouse()?;
        config = controller.read_config()?;
        // If mouse is working, this should now be unset
        !config.contains(ControllerConfigFlags::DISABLE_MOUSE)
    } else {
        false
    };
    // Disable mouse. If there's no mouse, this is ignored
    controller.disable_mouse()?;

    // Step 8: Interface tests
    let keyboard_works = controller.test_keyboard().is_ok();
    let mouse_works = has_mouse && controller.test_mouse().is_ok();

    // Step 9 - 10: Enable and reset devices
    config = controller.read_config()?;
    if keyboard_works {
        controller.enable_keyboard()?;
        config.set(ControllerConfigFlags::DISABLE_KEYBOARD, false);
        config.set(ControllerConfigFlags::ENABLE_KEYBOARD_INTERRUPT, true);
        controller.keyboard().reset_and_self_test().unwrap();
    }
    if mouse_works {
        controller.enable_mouse()?;
        config.set(ControllerConfigFlags::DISABLE_MOUSE, false);
        config.set(ControllerConfigFlags::ENABLE_MOUSE_INTERRUPT, true);
        controller.mouse().reset_and_self_test().unwrap();
        // This will start streaming events from the mouse
        controller.mouse().enable_data_reporting().unwrap();
    }

    // Write last configuration to enable devices and interrupts
    controller.write_config(config)?;

    Ok(())
}

一旦控制器初始化并设备正常工作,它们将输入放置在IO端口`0x60`的数据缓冲区中。您可以在任何时候使用Controller::read_data从该缓冲区读取。如果您计划使用基于轮询的方法处理设备输入,请注意,任一设备都可能随时向该缓冲区写入数据,并且据我所知,没有方法可以确定哪些字节来自哪个设备。

处理输入的一个更好的方法是使用中断:为IRQ1(键盘)和IRQ12(鼠标)定义处理程序,然后读取数据。您可以使用Controller::read_data来读取键盘和鼠标数据,或者您可以使用Mouse::read_data_packet,这是一个围绕Controller::read_data的方便包装器,用于鼠标数据包。

进一步阅读

以下是我开发这个库时使用的资源。请注意,一些描述PS/2协议的资源之间存在冲突,因此这个库是我对测试和验证这些资源准确性的最佳努力。如果您发现某些内容缺失或不完全正确,请随时提出问题

依赖项

~565KB
~11K SLoC