Add general embedded controller impl
This commit is contained in:
parent
2a8a63e856
commit
3dd90f0a8b
4 changed files with 123 additions and 0 deletions
|
@ -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
87
src/ec/controller.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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
27
src/ec/ports.rs
Normal 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")
|
||||
}
|
Loading…
Reference in a new issue