blob: c969af78238374110bfdb5536b4cab771d977c15 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
// SPDX-FileCopyrightText: 2022 Linaro Ltd.
// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
mod common;
mod info_event {
use libc::EINVAL;
use std::{
sync::{
mpsc::{self, Receiver, Sender},
Arc, Mutex,
},
thread,
time::Duration,
};
use gpiosim_sys::Sim;
use libgpiod::{
chip::Chip,
line::{self, Direction, InfoChangeKind, Offset},
request, Error as ChipError, OperationType,
};
fn request_reconfigure_line(chip: Arc<Mutex<Chip>>, tx: Sender<()>, rx: Receiver<()>) {
thread::spawn(move || {
let mut lconfig1 = line::Config::new().unwrap();
let lsettings = line::Settings::new().unwrap();
lconfig1.add_line_settings(&[7], lsettings).unwrap();
let rconfig = request::Config::new().unwrap();
let mut request = chip
.lock()
.unwrap()
.request_lines(Some(&rconfig), &lconfig1)
.unwrap();
// Signal the parent to continue
tx.send(()).expect("Could not send signal on channel");
// Wait for parent to signal
rx.recv().expect("Could not receive from channel");
let mut lconfig2 = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_direction(Direction::Output).unwrap();
lconfig2.add_line_settings(&[7], lsettings).unwrap();
request.reconfigure_lines(&lconfig2).unwrap();
// Signal the parent to continue
tx.send(()).expect("Could not send signal on channel");
// Wait for parent to signal
rx.recv().expect("Could not receive from channel");
});
}
mod watch {
use super::*;
const NGPIO: usize = 8;
const GPIO: Offset = 7;
#[test]
fn line_info() {
let sim = Sim::new(Some(NGPIO), None, true).unwrap();
let chip = Chip::open(&sim.dev_path()).unwrap();
assert_eq!(
chip.watch_line_info(NGPIO as u32).unwrap_err(),
ChipError::OperationFailed(OperationType::ChipWatchLineInfo, errno::Errno(EINVAL))
);
let info = chip.watch_line_info(GPIO).unwrap();
assert_eq!(info.offset(), GPIO);
// No events available
assert!(!chip
.wait_info_event(Some(Duration::from_millis(100)))
.unwrap());
}
#[test]
fn reconfigure() {
let sim = Sim::new(Some(NGPIO), None, true).unwrap();
let chip = Arc::new(Mutex::new(Chip::open(&sim.dev_path()).unwrap()));
let info = chip.lock().unwrap().watch_line_info(GPIO).unwrap();
assert_eq!(info.direction().unwrap(), Direction::Input);
// Thread synchronizing mechanism
let (tx_main, rx_thread) = mpsc::channel();
let (tx_thread, rx_main) = mpsc::channel();
// Generate events
request_reconfigure_line(chip.clone(), tx_thread, rx_thread);
// Wait for thread to signal
rx_main.recv().expect("Could not receive from channel");
// Line requested event
assert!(chip
.lock()
.unwrap()
.wait_info_event(Some(Duration::from_secs(1)))
.unwrap());
let event = chip.lock().unwrap().read_info_event().unwrap();
let ts_req = event.timestamp();
assert_eq!(event.event_type().unwrap(), InfoChangeKind::LineRequested);
assert_eq!(
event.line_info().unwrap().direction().unwrap(),
Direction::Input
);
// Signal the thread to continue
tx_main.send(()).expect("Could not send signal on channel");
// Wait for thread to signal
rx_main.recv().expect("Could not receive from channel");
// Line changed event
assert!(chip
.lock()
.unwrap()
.wait_info_event(Some(Duration::from_secs(1)))
.unwrap());
let event = chip.lock().unwrap().read_info_event().unwrap();
let ts_rec = event.timestamp();
assert_eq!(
event.event_type().unwrap(),
InfoChangeKind::LineConfigChanged
);
assert_eq!(
event.line_info().unwrap().direction().unwrap(),
Direction::Output
);
// Signal the thread to continue
tx_main.send(()).expect("Could not send signal on channel");
// Line released event
assert!(chip
.lock()
.unwrap()
.wait_info_event(Some(Duration::from_secs(1)))
.unwrap());
let event = chip.lock().unwrap().read_info_event().unwrap();
let ts_rel = event.timestamp();
assert_eq!(event.event_type().unwrap(), InfoChangeKind::LineReleased);
// No events available
assert!(!chip
.lock()
.unwrap()
.wait_info_event(Some(Duration::from_millis(100)))
.unwrap());
// Check timestamps are really monotonic.
assert!(ts_rel > ts_rec);
assert!(ts_rec > ts_req);
}
}
}