hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use crate::input::hw;
use core::sync::atomic::{AtomicU8, Ordering};

static DRIVER_STATE: AtomicU8 = AtomicU8::new(0);

pub struct InputDriver {
    pub base: usize,
    pub has_ps2: bool,
    pub has_mmio: bool,
}

pub fn probe(base: usize) -> InputDriver {
    let has_ps2 = hw::read_port8(hw::PS2_STATUS) != 0xFF;
    let has_mmio = base != 0;
    DRIVER_STATE.store(1, Ordering::Release);
    InputDriver {
        base,
        has_ps2,
        has_mmio,
    }
}

pub fn init(driver: &InputDriver) -> bool {
    if driver.has_ps2 {
        hw::ps2_send_command(0xAD);
        hw::ps2_send_command(0xA7);
        hw::ps2_send_command(0xAA);
        loop {
            if hw::ps2_data_available() {
                let resp = hw::ps2_read_data();
                if resp == 0x55 {
                    break;
                }
                break;
            }
        }
        hw::ps2_send_command(0xAE);
    }
    if driver.has_mmio {
        hw::mmio_reset(driver.base);
        hw::mmio_enable(driver.base);
    }
    DRIVER_STATE.store(2, Ordering::Release);
    true
}

pub fn poll_scancode(driver: &InputDriver) -> Option<u8> {
    if driver.has_ps2 && hw::ps2_data_available() {
        return Some(hw::ps2_read_data());
    }
    if driver.has_mmio && hw::mmio_fifo_level(driver.base) > 0 {
        return Some(hw::mmio_read_scancode(driver.base) as u8);
    }
    None
}

pub fn state() -> u8 {
    DRIVER_STATE.load(Ordering::Acquire)
}