Crate ps2[−][src]
Expand description
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.
- Adam Chapweske’s old site, which has several detailed write-ups.
- Andries Brouwer’s “Keyboard scancodes”, which is about much more than just scancodes.
- The OSDev wiki’s pages on the PS/2 controller, keyboard, mouse, and mouse input.
- This PDF from what appears to be an operating systems development course. I found the language very approachable and helpful for learning a lot of the relevant terminology.
- This summary of the PS/2 registers and commands. See here for keyboard commands.
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. |