Commit 66e811ba authored by Simon Wörner's avatar Simon Wörner

splitted input / output port data, added polling

parent 8ac542d4
Cargo.lock
target/
**/*.rs.bk
*.iml
\ No newline at end of file
[root]
name = "kawaii"
version = "0.1.0"
......@@ -4,3 +4,4 @@ version = "0.1.0"
authors = ["Simon Wörner <git@simon-woerner.de>"]
[dependencies]
nix = "0.8.1"
\ No newline at end of file
extern crate std;
extern crate nix;
use std::io::prelude::*;
use std::io::{Error, ErrorKind, SeekFrom};
use std::fs::File;
use std::path::Path;
use std::os::unix::io::RawFd;
#[derive(Debug)]
pub enum Direction {
Out,
......@@ -76,36 +80,74 @@ 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,
pub edge: Edge,
file: File,
data: PortData
}
impl Port {
pub fn new(number: u8, direction: Direction, edge: Edge) -> std::io::Result<Port> {
let path = format!("/sys/class/gpio/gpio{}/value", number);
let path = Path::new(path.as_str());
let file = match direction {
Direction::Out => File::create(path)?,
Direction::In => File::open(path)?,
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)
}
pub fn output(number: u8) -> std::io::Result<Port> {
let port = Port {
number: number,
direction: direction,
edge: edge,
file: file,
direction: Direction::Out,
data: PortData::Sync {
file: Port::open(number, Direction::Out)?
}
};
port.export().ok();
port.set_direction()?;
port.set_edge()?;
port.init()?;
Ok(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();
}
......@@ -116,15 +158,50 @@ impl Port {
}
pub fn read(&mut self) -> std::io::Result<Value> {
let mut contents = String::new();
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();
file.seek(SeekFrom::Start(0))?;
file.read_to_string(&mut contents)?;
Value::from_str(contents.as_str())
.ok_or(Error::new(ErrorKind::InvalidData, "Unrecognized GPIO Value"))
}
}
}
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];
nix::poll::poll(&mut fds, -1)
.or(Err(Error::new(ErrorKind::Other, "poll failed")))?;
nix::unistd::lseek(file, 0, nix::unistd::Whence::SeekSet)
.or(Err(Error::new(ErrorKind::Other, "lseek failed")))?;
self.file.read_to_string(&mut contents)?;
nix::unistd::read(file, &mut buffer)
.or(Err(Error::new(ErrorKind::Other, "read failed")))?;
Value::from_str(contents.as_str())
.ok_or(std::io::Error::new(std::io::ErrorKind::InvalidData, "Unrecognized GPIO Value"))
match buffer[0] {
48 => Ok(Value::Low), // '0'
49 => Ok(Value::High), // '1'
_ => Err(Error::new(ErrorKind::InvalidData, "Unrecognized GPIO Value"))
}
}
}
}
pub fn write(&mut self, value: Value) -> std::io::Result<()> {
self.file.write_all(value.as_str().as_bytes())
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())
}
}
fn export(&self) -> std::io::Result<()> {
......@@ -140,7 +217,10 @@ impl Port {
}
fn set_edge(&self) -> std::io::Result<()> {
Port::write_path(format!("/sys/class/gpio/gpio{}/edge", self.number).as_str(),
self.edge.as_str())
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(())
}
}
}
......@@ -5,9 +5,8 @@ use kawaii::gpio::{Port, Direction, Edge, Value};
fn main() {
println!("Hello, world!");
let mut trigger =
Port::new(27, Direction::Out, Edge::None).expect("Create Trigger GPIO failed");
let mut echo = Port::new(28, Direction::In, Edge::Both).expect("Create Echo GPIO failed");
let mut trigger = Port::output(27).expect("Create Trigger GPIO failed");
let mut echo = Port::input(28, Edge::Both).expect("Create Echo GPIO failed");
println!("trigger = {:?}", trigger.read());
trigger.write(Value::High);
......
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