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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = ["embedded-io/std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# logging
|
# logging
|
||||||
log = "0.4"
|
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 raw_io;
|
||||||
pub mod led;
|
pub mod led;
|
||||||
|
mod controller;
|
||||||
|
mod ports;
|
||||||
|
pub use controller::EmbeddedController;
|
||||||
|
|
||||||
use std::io::Error;
|
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