Skip to content

Commit a33b442

Browse files
committed
unexport: implement unexport* functionality
Also, fix up a few minor things with export (was not respecing export flag previously). Signed-off-by: Paul Osborne <[email protected]>
1 parent 4ecc178 commit a33b442

File tree

8 files changed

+119
-9
lines changed

8 files changed

+119
-9
lines changed

src/commands/gpio_exportall.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ pub fn main(config: &GpioConfig, opts: &GpioExportAllOptions) {
1111
None => config.get_symlink_root(),
1212
};
1313

14-
for pin in config.get_pins() {
14+
// export all pins except those fork which export is set to false
15+
for pin in config.get_pins().iter().filter(|p| p.export) {
1516
if let Err(e) = export::export(pin, Some(symlink_root)) {
1617
println!("Error occurred while exporting pin: {:?}", pin);
1718
println!("{}", e);

src/commands/gpio_read.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (C) 2016, Paul Osborne <[email protected]>
22

3-
use options::{GpioReadOptions};
3+
use options::GpioReadOptions;
44
use config::GpioConfig;
55
use std::process::exit;
66

src/commands/gpio_unexport.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (C) 2016, The gpio-utils Authors
2+
3+
use options::GpioUnexportOptions;
4+
use config::GpioConfig;
5+
use std::process::exit;
6+
use export;
7+
8+
pub fn main(config: &GpioConfig, opts: &GpioUnexportOptions) {
9+
let pin_config = config.get_pin(&opts.pin[..]).unwrap_or_else(|| {
10+
println!("Unable to find config entry for pin '{}'", opts.pin);
11+
exit(1)
12+
});
13+
14+
let symlink_root = match opts.symlink_root {
15+
Some(ref slr) => &slr[..],
16+
None => config.get_symlink_root(),
17+
};
18+
19+
if let Err(e) = export::unexport(pin_config, Some(symlink_root)) {
20+
println!("Error occurred while unexport pin {:?}", pin_config);
21+
println!("{}", e);
22+
exit(1);
23+
}
24+
}

src/commands/gpio_unexportall.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (C) 2016, The gpio-utils Authors
2+
3+
use options::GpioUnexportAllOptions;
4+
use config::GpioConfig;
5+
use std::process::exit;
6+
use export;
7+
8+
pub fn main(config: &GpioConfig, opts: &GpioUnexportAllOptions) {
9+
let symlink_root = match opts.symlink_root {
10+
Some(ref slr) => &slr[..],
11+
None => config.get_symlink_root(),
12+
};
13+
14+
for pin in config.get_pins().iter().filter(|p| p.export) {
15+
if let Err(e) = export::unexport(pin, Some(symlink_root)) {
16+
println!("Error occurred while exporting pin: {:?}", pin);
17+
println!("{}", e);
18+
exit(1);
19+
}
20+
}
21+
}

src/commands/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ pub mod gpio_read;
44
pub mod gpio_export;
55
pub mod gpio_exportall;
66
pub mod gpio_write;
7+
pub mod gpio_unexport;
8+
pub mod gpio_unexportall;

src/export.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,45 @@ use std::io::ErrorKind;
77
use config::PinConfig;
88
use sysfs_gpio;
99

10+
/// Unexport the pin specified in the provided config
11+
///
12+
/// Unexporting a config (in this context) involves a few different
13+
/// actions:
14+
///
15+
/// 1. For each GPIO name/alias, the corresponding symlink is remvoed from
16+
/// `/var/run/gpio/<name>` (or an alternate configured symlink_root).
17+
/// 2. The GPIO pin istself is unexported (vai /sys/class/gpio/unexport)
18+
///
19+
/// If the GPIO was already unexported, this function will continue
20+
/// without an error as the desired end state is achieved.
21+
pub fn unexport(pin_config: &PinConfig,
22+
symlink_root: Option<&str>)
23+
-> Result<(), sysfs_gpio::Error> {
24+
if let Some(symroot) = symlink_root {
25+
// create symlink for each name
26+
for name in &pin_config.names {
27+
let mut dst = path::PathBuf::from(symroot);
28+
dst.push(name);
29+
try!(match fs::remove_file(dst) {
30+
Ok(_) => Ok(()),
31+
Err(ref e) if e.kind() == ErrorKind::NotFound => Ok(()),
32+
Err(e) => Err(e),
33+
});
34+
}
35+
}
36+
37+
// unexport the pin itself. On many boards, it turns out, some pins are
38+
// exported by the kernel itself but we might still be assigning names. In
39+
// those cases we will get an error here. We handle that rather than
40+
// exposing the error up the chain. (EINVAL)
41+
let pin = pin_config.get_pin();
42+
match pin.unexport() {
43+
Ok(_) => Ok(()),
44+
Err(sysfs_gpio::Error::Io(ref e)) if e.kind() == ErrorKind::InvalidInput => Ok(()),
45+
Err(e) => Err(e)
46+
}
47+
}
48+
1049
/// Export the pin specified in the provided config
1150
///
1251
/// Exporting a pin (in this context) involves, a few different

src/main.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,23 @@ fn main() {
8888
.arg(Arg::with_name("pin")
8989
.help("The pin name (or number)")
9090
.index(1)
91-
.required(true)))
91+
.required(true))
92+
.arg(Arg::with_name("symlink-root")
93+
.help("root directory for export symlinks")
94+
.takes_value(true)
95+
.short("r")
96+
.long("symlink-root")
97+
.required(false)))
9298

9399
// gpio unexport-all
94100
.subcommand(SubCommand::with_name("unexport-all")
95101
.about("Unexport all configured, exported GPIOs")
96-
.arg(Arg::with_name("pin")
97-
.help("The pin name (or number)")
98-
.index(1)
99-
.required(true)))
102+
.arg(Arg::with_name("symlink-root")
103+
.help("root directory for export symlinks")
104+
.takes_value(true)
105+
.short("r")
106+
.long("symlink-root")
107+
.required(false)))
100108

101109
// gpio status
102110
.subcommand(SubCommand::with_name("status")
@@ -169,8 +177,21 @@ fn main() {
169177
};
170178
gpio_exportall::main(&cfg, &exportall_options);
171179
}
172-
("unexport", Some(_)) => {}
173-
("unexport-all", Some(_)) => {}
180+
("unexport", Some(m)) => {
181+
let unexport_options = GpioUnexportOptions {
182+
gpio_opts: gpio_options,
183+
pin: String::from(m.value_of("pin").unwrap()),
184+
symlink_root: m.value_of("symlink-root").map(|slr| String::from(slr)),
185+
};
186+
gpio_unexport::main(&cfg, &unexport_options);
187+
}
188+
("unexport-all", Some(m)) => {
189+
let unexportall_options = GpioUnexportAllOptions {
190+
gpio_opts: gpio_options,
191+
symlink_root: m.value_of("symlink-root").map(|slr| String::from(slr)),
192+
};
193+
gpio_unexportall::main(&cfg, &unexportall_options);
194+
}
174195
("status", Some(_)) => {}
175196
_ => {}
176197
}

src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ pub struct GpioExportAllOptions {
4040
#[derive(Debug)]
4141
pub struct GpioUnexportOptions {
4242
pub gpio_opts: GpioOptions,
43+
pub symlink_root: Option<String>,
4344
pub pin: String,
4445
}
4546

4647
#[derive(Debug)]
4748
pub struct GpioUnexportAllOptions {
4849
pub gpio_opts: GpioOptions,
50+
pub symlink_root: Option<String>,
4951
}
5052

5153
#[derive(Debug)]

0 commit comments

Comments
 (0)