Skip to content

Commit 68cec3a

Browse files
committed
Relax "extract_pin_from_path" logic
The logic of extract_pin_from_path is too rigid, expecting GPIOs to only exist at the "/sys/class/gpio" path. The problem with this is that the kernel may actually symlink the directory in "/sys/class/gpio" to a chip or SOC-specific path, and the logic prior to extracting the pin from the path performs a canonicalization, breaking the assumption. So, for example, the following is the output of a gpio on the board I'm working with: root# readlink /var/run/gpio/hwid-0 /sys/class/gpio/gpio122 root# readlink /sys/class/gpio/gpio122 ../../devices/soc0/soc/2000000.aips-bus/20a8000.gpio/gpiochip3/gpio/gpio122 This commit fixes the issue by relaxing the restrictions of extract_pin_from_path to only look for a final file component that looks like "gpioXXXX". Signed-off-by: Nick Stevens <nick@bitcurry.com>
1 parent 6bb6aaa commit 68cec3a

File tree

2 files changed

+21
-19
lines changed

2 files changed

+21
-19
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## [master] - Unreleased
44

5+
### Fixed
6+
7+
- Relaxed path restrictions on `Pin::from_path` to allow for directories
8+
outside of `/sys/class/gpio`, required for some SOCs that symlink outside of
9+
that directory.
10+
511
## [0.5.2] - 2018-03-02
612

713
### Changed

src/lib.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ use tokio_core::reactor::{Handle, PollEvented};
7777
mod error;
7878
pub use error::Error;
7979

80-
const GPIO_PATH_PREFIX: &'static str = "/sys/class/gpio/gpio";
81-
8280
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8381
pub struct Pin {
8482
pin_num: u64,
@@ -177,21 +175,17 @@ impl Pin {
177175
a directory"
178176
.to_owned()));
179177
}
180-
let num = Pin::extract_pin_from_path(&pb.to_str().unwrap_or(""))?;
178+
let num = Pin::extract_pin_from_path(&pb)?;
181179
Ok(Pin::new(num))
182180
}
183181

184182
/// Extract pin number from paths like /sys/class/gpio/gpioXXX
185-
fn extract_pin_from_path(path: &str) -> Result<u64> {
186-
if path.starts_with(GPIO_PATH_PREFIX) {
187-
path.split_at(GPIO_PATH_PREFIX.len()).1.parse::<u64>().or(
188-
Err(
189-
Error::InvalidPath(format!("{:?}", path)),
190-
),
191-
)
192-
} else {
193-
Err(Error::InvalidPath(format!("{:?}", path)))
194-
}
183+
fn extract_pin_from_path<P: AsRef<Path>>(path: P) -> Result<u64> {
184+
path.as_ref()
185+
.file_name()
186+
.and_then(|filename| filename.to_str())
187+
.and_then(|filename_str| filename_str.trim_left_matches("gpio").parse::<u64>().ok())
188+
.ok_or(Error::InvalidPath(format!("{:?}", path.as_ref())))
195189
}
196190

197191
/// Get the pin number
@@ -483,14 +477,16 @@ impl Pin {
483477

484478
#[test]
485479
fn extract_pin_fom_path_test() {
486-
let tok = Pin::extract_pin_from_path(&"/sys/class/gpio/gpio951");
487-
assert_eq!(951, tok.unwrap());
488-
let err1 = Pin::extract_pin_from_path(&"/sys/is/error/gpio/gpio111");
480+
let tok1 = Pin::extract_pin_from_path(&"/sys/class/gpio/gpio951");
481+
assert_eq!(951, tok1.unwrap());
482+
let tok2 = Pin::extract_pin_from_path(&"/sys/CLASS/gpio/gpio951/");
483+
assert_eq!(951, tok2.unwrap());
484+
let tok3 = Pin::extract_pin_from_path(&"../../devices/soc0/gpiochip3/gpio/gpio124");
485+
assert_eq!(124, tok3.unwrap());
486+
let err1 = Pin::extract_pin_from_path(&"/sys/CLASS/gpio/gpio");
489487
assert_eq!(true, err1.is_err());
490-
let err2 = Pin::extract_pin_from_path(&"/sys/CLASS/gpio/gpio");
488+
let err2 = Pin::extract_pin_from_path(&"/sys/class/gpio/gpioSDS");
491489
assert_eq!(true, err2.is_err());
492-
let err3 = Pin::extract_pin_from_path(&"/sys/class/gpio/gpioSDS");
493-
assert_eq!(true, err3.is_err());
494490
}
495491

496492
#[derive(Debug)]

0 commit comments

Comments
 (0)