[][src]Crate ps2

This crate provides comprehensive low-level access to the PS/2 controller and PS/2 devices. It uses a poll-based approach with a timeout to read and write data to the IO ports.

Examples

The below example implements the initialization process outlined on the OSDev wiki. We skip steps 1 and 2 by assuming the PS/2 controller exists and is supported on the current hardware.

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(())
}

Once the controller is initialized and the devices are working properly, they will place input in the data buffer at IO port 0x60. You can read from this buffer at any time using Controller::read_data. If you plan on using a poll-based approach to handle device input, be aware that either device may write data to this buffer at any time, and as far as I know there is no way to tell which bytes come from which device.

A much better way of handling input is to use interrupts: define handlers for IRQ1 (keyboard) and IRQ12 (mouse) and read the data then. You can use Controller::read_data for both keyboard and mouse data, or you can use Mouse::read_data_packet which is a convenient wrapper around Controller::read_data for mouse packets.

Further Reading

Below are some resources I used to develop this library. Note that some resources describing the PS/2 protocol conflict with each other, so this library is my best effort at testing and verifying the accuracy of these resources. If you find that something is missing or doesn't seem quite right, feel free to open an issue.

Modules

error
flags

Structs

Controller

The PS/2 controller.

Keyboard

A PS/2 keyboard.

Mouse

A PS/2 mouse.

Enums

KeyboardType

PS/2 keyboard device type. For more details, read the section titled "Keyboard IDs" on this page.

MouseType

PS/2 mouse device type. For more details, see here.