Add general embedded controller impl

This commit is contained in:
NGnius (Graham) 2024-01-08 21:56:06 -05:00
parent 2a8a63e856
commit 3dd90f0a8b
4 changed files with 123 additions and 0 deletions

View file

@ -6,6 +6,12 @@ description = "Low-level hardware interfaces for Valve's Steam Deck"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
std = ["embedded-io/std"]
[dependencies]
# logging
log = "0.4"
# io
embedded-io = { version = "0.6" }

87
src/ec/controller.rs Normal file
View file

@ -0,0 +1,87 @@
pub struct EmbeddedController {
data_address: u16,
cmd_address: u16,
cursor: u16,
is_cmd_requested: bool,
}
impl EmbeddedController {
pub fn new(data_addr: u16, cmd_addr: u16) -> Self {
Self {
data_address: data_addr,
cmd_address: cmd_addr,
cursor: 0,
is_cmd_requested: false,
}
}
fn request_if_not_already(&mut self) {
if !self.is_cmd_requested {
super::ports::outb(self.data_address, 0x81);
self.is_cmd_requested = true;
}
}
}
impl embedded_io::ErrorType for EmbeddedController {
type Error = core::convert::Infallible;
}
impl embedded_io::Seek for EmbeddedController {
fn seek(&mut self, pos: embedded_io::SeekFrom) -> Result<u64, Self::Error> {
self.cursor = match pos {
embedded_io::SeekFrom::Start(x) => x as u16,
embedded_io::SeekFrom::End(x) => (u16::MAX as i64 + x) as u16,
embedded_io::SeekFrom::Current(x) => (self.cursor as i64 + x) as u16
};
Ok(self.cursor as _)
}
}
impl embedded_io::Write for EmbeddedController {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
use embedded_io::WriteReady;
for &b in buf {
while !self.write_ready()? { }
super::ports::outb(self.cursor, b);
}
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl embedded_io::WriteReady for EmbeddedController {
fn write_ready(&mut self) -> Result<bool, Self::Error> {
self.request_if_not_already();
let ready = super::ports::inb(self.cmd_address) & 2 == 0;
if ready {
self.is_cmd_requested = false;
}
Ok(ready)
}
}
impl embedded_io::Read for EmbeddedController {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
use embedded_io::ReadReady;
for b in buf.iter_mut() {
while !self.read_ready()? { }
*b = super::ports::inb(self.cursor)
}
Ok(buf.len())
}
}
impl embedded_io::ReadReady for EmbeddedController {
fn read_ready(&mut self) -> Result<bool, Self::Error> {
self.request_if_not_already();
let ready = super::ports::inb(self.cmd_address) & 1 != 0;
if ready {
self.is_cmd_requested = false;
}
Ok(ready)
}
}

View file

@ -7,6 +7,9 @@
pub mod raw_io;
pub mod led;
mod controller;
mod ports;
pub use controller::EmbeddedController;
use std::io::Error;

27
src/ec/ports.rs Normal file
View file

@ -0,0 +1,27 @@
// x86 and x86_64
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub(crate) fn outb(port: u16, val: u8) {
unsafe {
std::arch::asm!("outb", in("dx") port, in("al") val);
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub(crate) fn inb(port: u16) -> u8 {
let out: u8;
unsafe {
std::arch::asm!("inb", in("dx") port, lateout("al") out);
}
out
}
// Fallback (compiler error)
#[cfg(not(any(any(target_arch = "x86", target_arch = "x86_64"), )))]
pub(crate) fn outb(port: u16, val: u8) {
compile_error!("outb not supported on this platform")
}
#[cfg(not(any(any(target_arch = "x86", target_arch = "x86_64"), )))]
pub(crate) fn inb(port: u16) -> u8 {
compile_error!("inb not supported on this platform")
}