Commit 00090d06 authored by Simon Wörner's avatar Simon Wörner

simplified Ports

parent 66e811ba
......@@ -80,50 +80,29 @@ impl Value {
}
}
#[derive(Debug)]
enum PortData {
Sync {
file: File
},
Async {
edge: Edge,
file: RawFd
}
}
#[derive(Debug)]
pub struct Port {
pub number: u8,
pub direction: Direction,
data: PortData
pub direction: Direction
}
impl Port {
pub fn input(number: u8, edge: Edge) -> std::io::Result<Port> {
let port = Port {
number: number,
direction: Direction::In,
data: match edge {
Edge::None => PortData::Sync {
file: Port::open(number, Direction::In)?,
},
_ => PortData::Async {
edge: edge,
file: nix::fcntl::open(format!("/sys/class/gpio/gpio{}/value", number).as_str(), nix::fcntl::O_RDONLY, nix::sys::stat::Mode::empty())?
}
}
};
port.init()?;
Ok(port)
}
#[derive(Debug)]
pub struct SyncPort {
pub port: Port,
file: File
}
#[derive(Debug)]
pub struct AsyncPort {
pub port: Port,
pub edge: Edge,
file: RawFd
}
pub fn output(number: u8) -> std::io::Result<Port> {
impl Port {
pub fn new(number: u8) -> std::io::Result<Port> {
let port = Port {
number: number,
direction: Direction::Out,
data: PortData::Sync {
file: Port::open(number, Direction::Out)?
}
direction: Direction::In
};
port.init()?;
......@@ -133,21 +112,10 @@ impl Port {
fn init(&self) -> std::io::Result<()> {
self.export().ok();
self.set_direction()?;
self.set_edge()?;
Ok(())
}
fn open(number: u8, direction: Direction) -> std::io::Result<File> {
let path = format!("/sys/class/gpio/gpio{}/value", number);
let path = Path::new(path.as_str());
Ok(match direction {
Direction::Out => File::create(path)?,
Direction::In => File::open(path)?,
})
}
pub fn drop(&mut self) {
self.unexport().ok();
}
......@@ -157,70 +125,94 @@ impl Port {
.write_all(value.as_bytes())
}
pub fn read(&mut self) -> std::io::Result<Value> {
match &mut self.data {
&mut PortData::Async{ref edge, file} => Err(Error::new(ErrorKind::Other, "Synchronised read not allowed")),
&mut PortData::Sync{ref mut file} => {
let mut contents = String::new();
fn export(&self) -> std::io::Result<()> {
Port::write_path("/sys/class/gpio/export", self.number.to_string().as_str())
}
fn unexport(&self) -> std::io::Result<()> {
Port::write_path("/sys/class/gpio/unexport", self.number.to_string().as_str())
}
file.seek(SeekFrom::Start(0))?;
file.read_to_string(&mut contents)?;
fn set_direction(&self) -> std::io::Result<()> {
Port::write_path(format!("/sys/class/gpio/gpio{}/direction", self.number).as_str(), self.direction.as_str())
}
}
Value::from_str(contents.as_str())
.ok_or(Error::new(ErrorKind::InvalidData, "Unrecognized GPIO Value"))
}
}
impl SyncPort {
pub fn new(number: u8, direction: Direction) -> std::io::Result<SyncPort> {
Ok(SyncPort {
port: Port::new(number)?,
file: SyncPort::open(number, direction)?
})
}
pub fn poll(&mut self, timeout: Option<u32>) -> std::io::Result<Value> {
match &self.data {
&PortData::Sync{ref file} => Err(Error::new(ErrorKind::Other, "Asynchronous poll not allowed")),
&PortData::Async{ref edge, file} => {
let mut fds = [nix::poll::PollFd::new(file, nix::poll::POLLPRI, nix::poll::EventFlags::empty())];
let mut buffer: [u8; 1] = [0; 1];
fn open(number: u8, direction: Direction) -> std::io::Result<File> {
let path = format!("/sys/class/gpio/gpio{}/value", number);
let path = Path::new(path.as_str());
nix::poll::poll(&mut fds, -1)
.or(Err(Error::new(ErrorKind::Other, "poll failed")))?;
Ok(match direction {
Direction::Out => File::create(path)?,
Direction::In => File::open(path)?,
})
}
nix::unistd::lseek(file, 0, nix::unistd::Whence::SeekSet)
.or(Err(Error::new(ErrorKind::Other, "lseek failed")))?;
pub fn read(&mut self) -> std::io::Result<Value> {
let mut contents = String::new();
nix::unistd::read(file, &mut buffer)
.or(Err(Error::new(ErrorKind::Other, "read failed")))?;
self.file.seek(SeekFrom::Start(0))?;
self.file.read_to_string(&mut contents)?;
match buffer[0] {
48 => Ok(Value::Low), // '0'
49 => Ok(Value::High), // '1'
_ => Err(Error::new(ErrorKind::InvalidData, "Unrecognized GPIO Value"))
}
}
}
Value::from_str(contents.as_str())
.ok_or(Error::new(ErrorKind::InvalidData, "Unrecognized GPIO Value"))
}
pub fn write(&mut self, value: Value) -> std::io::Result<()> {
match &mut self.data {
&mut PortData::Async { ref edge, ref file } => Err(Error::new(ErrorKind::Other, "Synchronised read not allowed")),
&mut PortData::Sync { ref mut file } => file.write_all(value.as_str().as_bytes())
}
self.file.write_all(value.as_str().as_bytes())
}
}
fn export(&self) -> std::io::Result<()> {
Port::write_path("/sys/class/gpio/export", self.number.to_string().as_str())
impl AsyncPort {
pub fn new(number: u8, edge: Edge) -> std::io::Result<AsyncPort> {
let port = AsyncPort {
port: Port::new(number)?,
edge: edge,
file: AsyncPort::open(number)?
};
port.init()?;
Ok(port)
}
fn unexport(&self) -> std::io::Result<()> {
Port::write_path("/sys/class/gpio/unexport", self.number.to_string().as_str())
fn init(&self) -> std::io::Result<()> {
self.set_edge()?;
Ok(())
}
fn set_direction(&self) -> std::io::Result<()> {
Port::write_path(format!("/sys/class/gpio/gpio{}/direction", self.number).as_str(),
self.direction.as_str())
fn open(number: u8) -> std::io::Result<RawFd> {
nix::fcntl::open(format!("/sys/class/gpio/gpio{}/value", number).as_str(), nix::fcntl::O_RDONLY, nix::sys::stat::Mode::empty())
.or(Err(Error::new(ErrorKind::Other, "open failed")))
}
fn set_edge(&self) -> std::io::Result<()> {
match &self.data {
&PortData::Async{ref edge, ref file} =>
Port::write_path(format!("/sys/class/gpio/gpio{}/edge", self.number).as_str(), edge.as_str()),
_ => Ok(())
pub fn poll(&mut self, timeout: Option<i32>) -> std::io::Result<Value> {
let mut fds = [nix::poll::PollFd::new(self.file, nix::poll::POLLPRI, nix::poll::EventFlags::empty())];
let mut buffer: [u8; 1] = [0; 1];
nix::poll::poll(&mut fds, match timeout { None => -1, Some(t) => t})
.or(Err(Error::new(ErrorKind::Other, "poll failed")))?;
nix::unistd::lseek(self.file, 0, nix::unistd::Whence::SeekSet)
.or(Err(Error::new(ErrorKind::Other, "lseek failed")))?;
nix::unistd::read(self.file, &mut buffer)
.or(Err(Error::new(ErrorKind::Other, "read failed")))?;
match buffer[0] {
48 => Ok(Value::Low), // '0'
49 => Ok(Value::High), // '1'
_ => Err(Error::new(ErrorKind::InvalidData, "Unrecognized GPIO Value"))
}
}
fn set_edge(&self) -> std::io::Result<()> {
Port::write_path(format!("/sys/class/gpio/gpio{}/edge", self.port.number).as_str(), self.edge.as_str())
}
}
extern crate kawaii;
use kawaii::gpio::{Port, Direction, Edge, Value};
use kawaii::gpio::{SyncPort, AsyncPort, Direction, Edge, Value};
fn main() {
println!("Hello, world!");
let mut trigger = Port::output(27).expect("Create Trigger GPIO failed");
let mut echo = Port::input(28, Edge::Both).expect("Create Echo GPIO failed");
let mut trigger = SyncPort::new(27, Direction::Out).expect("Create Trigger GPIO failed");
let mut echo = AsyncPort::new(28, Edge::Both).expect("Create Echo GPIO failed");
println!("trigger = {:?}", trigger.read());
trigger.write(Value::High);
trigger.write(Value::High).expect("write failed");
println!("trigger = {:?}", trigger.read());
trigger.write(Value::Low);
trigger.write(Value::Low).expect("write failed");
println!("trigger = {:?}", trigger.read());
println!("echo = {:?}", echo.poll(Some(1000)));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment