1use std::fs::OpenOptions;
21use std::io::prelude::*;
22use std::io::Result;
23use std::io::ErrorKind;
24use std::io::Error;
25use std::path::Path;
26use std::fmt;
27
28use globals::GPIO_PATH;
29
30#[derive(Debug, Clone, Copy, PartialEq)]
31pub enum GPIOMode {
32 Read,
33 Write,
34}
35
36#[derive(Debug, Clone, Copy)]
37pub enum GPIOData {
38 Low = 0,
39 High = 1,
40}
41
42pub struct GPIO {
44 pin: u8,
45 mode: GPIOMode,
46}
47
48impl GPIO {
49 pub fn gpio_number(&self) -> u8 {
51 self.pin
52 }
53
54 pub fn current_mode(&self) -> GPIOMode {
56 self.mode
57 }
58
59 pub fn set_mode(&mut self, mode: GPIOMode) -> Result<&mut Self> {
61 let mut direction = OpenOptions::new()
62 .write(true)
63 .open(format!("{}gpio{}/direction", GPIO_PATH, self.pin))?;
64 match mode {
65 GPIOMode::Read => try!(direction.write_all("in".as_bytes())),
66 GPIOMode::Write => try!(direction.write_all("out".as_bytes())),
67 };
68 self.mode = mode;
69 Ok(self)
70 }
71
72 pub fn new(gpio: u8, mode: GPIOMode) -> Result<Self> {
76 if Path::new(&format!("{}gpio{}/", GPIO_PATH, gpio)).exists() {
77 return Err(Error::new(
78 ErrorKind::AddrInUse,
79 "Error: gpio was already initialized",
80 ));
81 }
82 {
83 let mut export = OpenOptions::new()
84 .write(true)
85 .open(format!("{}export", GPIO_PATH))?;
86 export.write_all(format!("{}", gpio).as_bytes())?;
87 }
88 let mut result = GPIO {
89 pin: gpio,
90 mode: mode,
91 };
92 result.set_mode(mode)?;
93 Ok(result)
94 }
95
96 pub fn value(&self) -> Result<GPIOData> {
99 let mut value = try!(
100 OpenOptions::new()
101 .read(true)
102 .open(format!("{}gpio{}/value", GPIO_PATH, self.pin))
103 );
104 let mut buffer = vec![];
105 try!(value.read_to_end(&mut buffer));
106 match buffer[0] as char {
107 '0' => Ok(GPIOData::Low),
108 '1' => Ok(GPIOData::High),
109 _ => Err(Error::new(
110 ErrorKind::InvalidData,
111 "read value other than 1 or 0",
112 )),
113 }
114 }
115
116 pub fn set(&self, data: GPIOData) -> Result<()> {
119 if self.mode != GPIOMode::Write {
120 return Err(Error::new(
121 ErrorKind::PermissionDenied,
122 "Error: gpio is not in write mode",
123 ));
124 }
125 let buffer = match data {
126 GPIOData::Low => "0",
127 GPIOData::High => "1",
128 };
129 let mut direction = OpenOptions::new()
130 .write(true)
131 .open(format!("{}gpio{}/value", GPIO_PATH, self.pin))?;
132 try!(direction.write_all(buffer.as_bytes()));
133 Ok(())
134 }
135}
136
137impl Drop for GPIO {
139 fn drop(&mut self) {
140 if let Ok(mut unexport) = OpenOptions::new()
141 .write(true)
142 .open(format!("{}unexport", GPIO_PATH))
143 {
144 match unexport.write_all(format!("{}", self.pin).as_bytes()) {
145 Err(why) => panic!("couldn't close gpio {}: {}", self.pin, why),
146 Ok(_) => {}
147 }
148 } else {
149 panic!("file error: {}")
150 }
151 }
152}
153
154impl fmt::Display for GPIOData {
156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 match *self {
158 GPIOData::Low => write!(f, "LOW"),
159 GPIOData::High => write!(f, "HIGH"),
160 }
161 }
162}
163
164impl fmt::Display for GPIOMode {
166 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167 match *self {
168 GPIOMode::Read => write!(f, "Read"),
169 GPIOMode::Write => write!(f, "Write"),
170 }
171 }
172}