5 unstable releases
0.2.0 | Jul 13, 2021 |
---|---|
0.1.2 | Jun 4, 2021 |
0.1.1 | Dec 19, 2020 |
0.1.0 | Nov 26, 2020 |
0.0.0 | Oct 6, 2020 |
#1933 in Hardware support
47KB
706 lines
ps2
A general PS/2 device driver for nightly Rust.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/lucis-fluxum/ps2-rs.
License
This crate is available as open source under the terms of the MIT License.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
ps2-rs
by you shall be licensed as MIT, without any additional terms or conditions.
lib.rs
:
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.
Dependencies
~560KB
~11K SLoC