// Copyright (c) 2018 The rust-gpio-cdev Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `gpio-cdev` crate provides access to the [GPIO character device
//! ABI](https://www.kernel.org/doc/Documentation/ABI/testing/gpio-cdev).  This API,
//! stabilized with Linux v4.4, deprecates the legacy sysfs interface to GPIOs that is
//! planned to be removed from the upstream kernel after
//! year 2020 (which is coming up quickly).
//!
//! This crate attempts to wrap this interface in a moderately direction fashion
//! while retaining safety and using Rust idioms (where doing so could be mapped
//! to the underlying abstraction without significant overhead or loss of
//! functionality).
//!
//! For additional context for why the kernel is moving from the sysfs API to the
//! character device API, please see the main [README on Github].
//!
//! # Examples
//!
//! The following example reads the state of a GPIO line/pin and writes the matching
//! state to another line/pin.
//!
//! ```no_run
//! use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags, EventType};
//!
//! // Lines are offset within gpiochip0; see docs for more info on chips/lines
//! fn mirror_gpio(inputline: u32, outputline: u32) -> Result<(), gpio_cdev::Error> {
//!     let mut chip = Chip::new("/dev/gpiochip0")?;
//!     let input = chip.get_line(inputline)?;
//!     let output = chip.get_line(outputline)?;
//!     let output_handle = output.request(LineRequestFlags::OUTPUT, 0, "mirror-gpio")?;
//!     for event in input.events(
//!         LineRequestFlags::INPUT,
//!         EventRequestFlags::BOTH_EDGES,
//!         "mirror-gpio",
//!     )? {
//!         let evt = event?;
//!         println!("{:?}", evt);
//!         match evt.event_type() {
//!             EventType::RisingEdge => {
//!                 output_handle.set_value(1)?;
//!             }
//!             EventType::FallingEdge => {
//!                 output_handle.set_value(0)?;
//!             }
//!         }
//!     }
//!
//!     Ok(())
//! }
//!
//! # fn main() -> Result<(), gpio_cdev::Error> {
//! #     mirror_gpio(0, 1)
//! # }
//! ```
//!
//! To get the state of a GPIO Line on a given chip:
//!
//! ```no_run
//! use gpio_cdev::{Chip, LineRequestFlags};
//!
//! # fn main() -> Result<(), gpio_cdev::Error> {
//! // Read the state of GPIO4 on a raspberry pi.  /dev/gpiochip0
//! // maps to the driver for the SoC (builtin) GPIO controller.
//! // The LineHandle returned by request must be assigned to a
//! // variable (in this case the variable handle) to ensure that
//! // the corresponding file descriptor is not closed.
//! let mut chip = Chip::new("/dev/gpiochip0")?;
//! let handle = chip
//!     .get_line(4)?
//!     .request(LineRequestFlags::INPUT, 0, "read-input")?;
//! for _ in 1..4 {
//!     println!("Value: {:?}", handle.get_value()?);
//! }
//! # Ok(()) }
//! ```
//!
//! [README on Github]: https://github.com/rust-embedded/rust-gpio-cdev

#![cfg_attr(docsrs, feature(doc_cfg))]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate nix;

use std::cmp::min;
use std::ffi::CStr;
use std::fs::{read_dir, File, ReadDir};
use std::io::Read;
use std::mem;
use std::ops::Index;
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
use std::path::{Path, PathBuf};
use std::ptr;
use std::slice;
use std::sync::Arc;

#[cfg(feature = "async-tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "async-tokio")))]
mod async_tokio;
pub mod errors; // pub portion is deprecated
mod ffi;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IoctlKind {
    ChipInfo,
    LineInfo,
    LineHandle,
    LineEvent,
    GetLine,
    SetLine,
}

#[cfg(feature = "async-tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "async-tokio")))]
pub use crate::async_tokio::AsyncLineEventHandle;
pub use errors::*;

unsafe fn rstr_lcpy(dst: *mut libc::c_char, src: &str, length: usize) {
    let copylen = min(src.len() + 1, length);
    ptr::copy_nonoverlapping(src.as_bytes().as_ptr().cast(), dst, copylen - 1);
    slice::from_raw_parts_mut(dst, length)[copylen - 1] = 0;
}

#[derive(Debug)]
struct InnerChip {
    pub path: PathBuf,
    pub file: File,
    pub name: String,
    pub label: String,
    pub lines: u32,
}

/// A GPIO Chip maps to the actual device driver instance in hardware that
/// one interacts with to interact with individual GPIOs.  Often these chips
/// map to IP chunks on an SoC but could also be enumerated within the kernel
/// via something like a PCI or USB bus.
///
/// The Linux kernel itself enumerates GPIO character devices at two paths:
/// 1. `/dev/gpiochipN`
/// 2. `/sys/bus/gpiochipN`
///
/// It is best not to assume that a device will always be enumerated in the
/// same order (especially if it is connected via a bus).  In order to reliably
/// find the correct chip, there are a few approaches that one could reasonably
/// take:
///
/// 1. Create a udev rule that will match attributes of the device and
///    setup a symlink to the device.
/// 2. Iterate over all available chips using the [`chips()`] call to find the
///    device with matching criteria.
/// 3. For simple cases, just using the enumerated path is fine (demo work).  This
///    is discouraged for production.
///
/// [`chips()`]: fn.chips.html
#[derive(Debug)]
pub struct Chip {
    inner: Arc<InnerChip>,
}

/// Iterator over chips
#[derive(Debug)]
pub struct ChipIterator {
    readdir: ReadDir,
}

impl Iterator for ChipIterator {
    type Item = Result<Chip>;

    fn next(&mut self) -> Option<Result<Chip>> {
        for entry in &mut self.readdir {
            match entry {
                Ok(entry) => {
                    if entry
                        .path()
                        .as_path()
                        .to_string_lossy()
                        .contains("gpiochip")
                    {
                        return Some(Chip::new(entry.path()));
                    }
                }
                Err(e) => {
                    return Some(Err(e.into()));
                }
            }
        }

        None
    }
}

/// Iterate over all GPIO chips currently present on this system
pub fn chips() -> Result<ChipIterator> {
    Ok(ChipIterator {
        readdir: read_dir("/dev")?,
    })
}

impl Chip {
    /// Open the GPIO Chip at the provided path (e.g. `/dev/gpiochip<N>`)
    pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
        let f = File::open(path.as_ref())?;
        let mut info: ffi::gpiochip_info = unsafe { mem::zeroed() };
        ffi::gpio_get_chipinfo_ioctl(f.as_raw_fd(), &mut info)?;

        Ok(Self {
            inner: Arc::new(InnerChip {
                file: f,
                path: path.as_ref().to_path_buf(),
                name: unsafe {
                    CStr::from_ptr(info.name.as_ptr())
                        .to_string_lossy()
                        .into_owned()
                },
                label: unsafe {
                    CStr::from_ptr(info.label.as_ptr())
                        .to_string_lossy()
                        .into_owned()
                },
                lines: info.lines,
            }),
        })
    }

    /// Get the fs path of this character device (e.g. `/dev/gpiochipN`)
    pub fn path(&self) -> &Path {
        self.inner.path.as_path()
    }

    /// The name of the device driving this GPIO chip in the kernel
    pub fn name(&self) -> &str {
        self.inner.name.as_str()
    }

    /// A functional name for this GPIO chip, such as a product number.  Might
    /// be an empty string.
    ///
    /// As an example, the SoC GPIO chip on a Raspberry Pi is "pinctrl-bcm2835"
    pub fn label(&self) -> &str {
        self.inner.label.as_str()
    }

    /// The number of lines/pins indexable through this chip
    ///
    /// Not all of these may be usable depending on how the hardware is
    /// configured/muxed.
    pub fn num_lines(&self) -> u32 {
        self.inner.lines
    }

    /// Get a handle to the GPIO line at a given offset
    ///
    /// The actual physical line corresponding to a given offset
    /// is completely dependent on how the driver/hardware for
    /// the chip works as well as the associated board layout.
    ///
    /// For a device like the NXP i.mx6 SoC GPIO controller there
    /// are several banks of GPIOs with each bank containing 32
    /// GPIOs.  For this hardware and driver something like
    /// `GPIO2_5` would map to offset 37.
    pub fn get_line(&mut self, offset: u32) -> Result<Line> {
        Line::new(self.inner.clone(), offset)
    }

    /// Get a handle to multiple GPIO line at a given offsets
    ///
    /// The group of lines can be manipulated simultaneously.
    pub fn get_lines(&mut self, offsets: &[u32]) -> Result<Lines> {
        Lines::new(self.inner.clone(), offsets)
    }

    /// Get a handle to all the GPIO lines on the chip
    ///
    /// The group of lines can be manipulated simultaneously.
    pub fn get_all_lines(&mut self) -> Result<Lines> {
        let offsets: Vec<u32> = (0..self.num_lines()).collect();
        self.get_lines(&offsets)
    }

    /// Get an interator over all lines that can be potentially access for this
    /// chip.
    pub fn lines(&self) -> LineIterator {
        LineIterator {
            chip: self.inner.clone(),
            idx: 0,
        }
    }
}

/// Iterator over GPIO Lines for a given chip.
#[derive(Debug)]
pub struct LineIterator {
    chip: Arc<InnerChip>,
    idx: u32,
}

impl Iterator for LineIterator {
    type Item = Line;

    fn next(&mut self) -> Option<Line> {
        if self.idx < self.chip.lines {
            let idx = self.idx;
            self.idx += 1;
            // Since we checked the index, we know this will be Ok
            Some(Line::new(self.chip.clone(), idx).unwrap())
        } else {
            None
        }
    }
}

/// Access to a specific GPIO Line
///
/// GPIO Lines must be obtained through a parent [`Chip`] and
/// represent an actual GPIO pin/line accessible via that chip.
/// Not all accessible lines for a given chip may actually
/// map to hardware depending on how the board is setup
/// in the kernel.
///
#[derive(Debug, Clone)]
pub struct Line {
    chip: Arc<InnerChip>,
    offset: u32,
}

/// Information about a specific GPIO Line
///
/// Wraps kernel [`struct gpioline_info`].
///
/// [`struct gpioline_info`]: https://elixir.bootlin.com/linux/v4.9.127/source/include/uapi/linux/gpio.h#L36
#[derive(Debug)]
pub struct LineInfo {
    line: Line,
    flags: LineFlags,
    name: Option<String>,
    consumer: Option<String>,
}

bitflags! {
    /// Line Request Flags
    ///
    /// Maps to kernel [`GPIOHANDLE_REQUEST_*`] flags.
    ///
    /// [`GPIOHANDLE_REQUEST_*`]: https://elixir.bootlin.com/linux/v4.9.127/source/include/uapi/linux/gpio.h#L58
    #[derive(Debug, Clone)]
    pub struct LineRequestFlags: u32 {
        const INPUT = (1 << 0);
        const OUTPUT = (1 << 1);
        const ACTIVE_LOW = (1 << 2);
        const OPEN_DRAIN = (1 << 3);
        const OPEN_SOURCE = (1 << 4);
    }
}

bitflags! {
    /// Event request flags
    ///
    /// Maps to kernel [`GPIOEVENT_REQEST_*`] flags.
    ///
    /// [`GPIOEVENT_REQUEST_*`]: https://elixir.bootlin.com/linux/v4.9.127/source/include/uapi/linux/gpio.h#L109
    pub struct EventRequestFlags: u32 {
        const RISING_EDGE = (1 << 0);
        const FALLING_EDGE = (1 << 1);
        const BOTH_EDGES = Self::RISING_EDGE.bits() | Self::FALLING_EDGE.bits();
    }
}

bitflags! {
    /// Informational Flags
    ///
    /// Maps to kernel [`GPIOLINE_FLAG_*`] flags.
    ///
    /// [`GPIOLINE_FLAG_*`]: https://elixir.bootlin.com/linux/v4.9.127/source/include/uapi/linux/gpio.h#L29
    #[derive(Debug)]
    pub struct LineFlags: u32 {
        const KERNEL = (1 << 0);
        const IS_OUT = (1 << 1);
        const ACTIVE_LOW = (1 << 2);
        const OPEN_DRAIN = (1 << 3);
        const OPEN_SOURCE = (1 << 4);
    }
}

/// In or Out
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LineDirection {
    In,
    Out,
}

unsafe fn cstrbuf_to_string(buf: &[libc::c_char]) -> Option<String> {
    if buf[0] == 0 {
        None
    } else {
        Some(CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned())
    }
}

impl Line {
    fn new(chip: Arc<InnerChip>, offset: u32) -> Result<Self> {
        if offset >= chip.lines {
            return Err(offset_err(offset));
        }
        Ok(Self { chip, offset })
    }

    /// Get info about the line from the kernel.
    pub fn info(&self) -> Result<LineInfo> {
        let mut line_info = ffi::gpioline_info {
            line_offset: self.offset,
            flags: 0,
            name: [0; 32],
            consumer: [0; 32],
        };
        ffi::gpio_get_lineinfo_ioctl(self.chip.file.as_raw_fd(), &mut line_info)?;

        Ok(LineInfo {
            line: self.clone(),
            flags: LineFlags::from_bits_truncate(line_info.flags),
            name: unsafe { cstrbuf_to_string(&line_info.name[..]) },
            consumer: unsafe { cstrbuf_to_string(&line_info.consumer[..]) },
        })
    }

    /// Offset of this line within its parent chip
    pub fn offset(&self) -> u32 {
        self.offset
    }

    /// Get a handle to this chip's parent
    pub fn chip(&self) -> Chip {
        Chip {
            inner: self.chip.clone(),
        }
    }

    /// Request access to interact with this line from the kernel
    ///
    /// This is similar to the "export" operation present in the sysfs
    /// API with the key difference that we are also able to configure
    /// the GPIO with `flags` to specify how the line will be used
    /// at the time of request.
    ///
    /// For an output, the `default` parameter specifies the value
    /// the line should have when it is configured as an output.  The
    /// `consumer` string should describe the process consuming the
    /// line (this will be truncated to 31 characters if too long).
    ///
    /// # Errors
    ///
    /// The main source of errors here is if the kernel returns an
    /// error to the ioctl performing the request here.  This will
    /// result in an [`Error`] being returned with [`ErrorKind::Ioctl`].
    ///
    /// One possible cause for an error here would be if the line is
    /// already in use.  One can check for this prior to making the
    /// request using [`is_kernel`].
    ///
    /// [`Error`]: errors/struct.Error.html
    /// [`ErrorKind::Ioctl`]: errors/enum.ErrorKind.html#variant.Ioctl
    /// [`is_kernel`]: struct.Line.html#method.is_kernel
    pub fn request(
        &self,
        flags: LineRequestFlags,
        default: u8,
        consumer: &str,
    ) -> Result<LineHandle> {
        // prepare the request; the kernel consumes some of these values and will
        // set the fd for us.
        let mut request = ffi::gpiohandle_request {
            lineoffsets: unsafe { mem::zeroed() },
            flags: flags.bits(),
            default_values: unsafe { mem::zeroed() },
            consumer_label: unsafe { mem::zeroed() },
            lines: 1,
            fd: 0,
        };
        request.lineoffsets[0] = self.offset;
        request.default_values[0] = default;
        unsafe {
            rstr_lcpy(
                request.consumer_label[..].as_mut_ptr(),
                consumer,
                request.consumer_label.len(),
            );
        }
        ffi::gpio_get_linehandle_ioctl(self.chip.file.as_raw_fd(), &mut request)?;
        Ok(LineHandle {
            line: self.clone(),
            flags,
            file: unsafe { File::from_raw_fd(request.fd) },
        })
    }

    /// Get an event handle that can be used as a blocking iterator over
    /// the events (state changes) for this Line
    ///
    /// When used as an iterator, it blocks while there is not another event
    /// available from the kernel for this line matching the subscription
    /// criteria specified in the `event_flags`.  The line will be configured
    /// with the specified `handle_flags` and `consumer` label.
    ///
    /// Note that as compared with the sysfs interface, the character
    /// device interface maintains a queue of events in the kernel so
    /// events may happen (e.g. a line changing state faster than can
    /// be picked up in userspace in real-time).  These events will be
    /// returned on the iterator in order with the event containing the
    /// associated timestamp attached with high precision within the
    /// kernel (from an ISR for most drivers).
    ///
    /// # Example
    ///
    /// ```no_run
    /// # fn main() -> Result<(), gpio_cdev::Error> {
    /// use gpio_cdev::{Chip, LineRequestFlags, EventRequestFlags};
    /// use std::io;
    ///
    /// let mut chip = Chip::new("/dev/gpiochip0")?;
    /// let input = chip.get_line(0)?;
    ///
    /// // Show all state changes for this line forever
    /// for event in input.events(
    ///     LineRequestFlags::INPUT,
    ///     EventRequestFlags::BOTH_EDGES,
    ///     "rust-gpio"
    /// )? {
    ///     println!("{:?}", event?);
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn events(
        &self,
        handle_flags: LineRequestFlags,
        event_flags: EventRequestFlags,
        consumer: &str,
    ) -> Result<LineEventHandle> {
        let mut request = ffi::gpioevent_request {
            lineoffset: self.offset,
            handleflags: handle_flags.bits(),
            eventflags: event_flags.bits(),
            consumer_label: unsafe { mem::zeroed() },
            fd: 0,
        };

        unsafe {
            rstr_lcpy(
                request.consumer_label[..].as_mut_ptr(),
                consumer,
                request.consumer_label.len(),
            );
        }
        ffi::gpio_get_lineevent_ioctl(self.chip.file.as_raw_fd(), &mut request)?;

        Ok(LineEventHandle {
            line: self.clone(),
            file: unsafe { File::from_raw_fd(request.fd) },
        })
    }

    #[cfg(feature = "async-tokio")]
    #[cfg_attr(docsrs, doc(cfg(feature = "async-tokio")))]
    pub fn async_events(
        &self,
        handle_flags: LineRequestFlags,
        event_flags: EventRequestFlags,
        consumer: &str,
    ) -> Result<AsyncLineEventHandle> {
        let events = self.events(handle_flags, event_flags, consumer)?;
        AsyncLineEventHandle::new(events)
    }
}

impl LineInfo {
    /// Get a handle to the line that this info represents
    pub fn line(&self) -> &Line {
        &self.line
    }

    /// Name assigned to this chip if assigned
    pub fn name(&self) -> Option<&str> {
        self.name.as_deref()
    }

    /// The name of this GPIO line, such as the output pin of the line on the
    /// chip, a rail or a pin header name on a board, as specified by the gpio
    /// chip.
    pub fn consumer(&self) -> Option<&str> {
        self.consumer.as_deref()
    }

    /// Get the direction of this GPIO if configured
    ///
    /// Lines are considered to be inputs if not explicitly
    /// marked as outputs in the line info flags by the kernel.
    pub fn direction(&self) -> LineDirection {
        if self.flags.contains(LineFlags::IS_OUT) {
            LineDirection::Out
        } else {
            LineDirection::In
        }
    }

    /// True if the any flags for the device are set (input or output)
    pub fn is_used(&self) -> bool {
        !self.flags.is_empty()
    }

    /// True if this line is being used by something else in the kernel
    ///
    /// If another driver or subsystem in the kernel is using the line
    /// then it cannot be used via the cdev interface. See [relevant kernel code].
    ///
    /// [relevant kernel code]: https://elixir.bootlin.com/linux/v4.9.127/source/drivers/gpio/gpiolib.c#L938
    pub fn is_kernel(&self) -> bool {
        self.flags.contains(LineFlags::KERNEL)
    }

    /// True if this line is marked as active low in the kernel
    pub fn is_active_low(&self) -> bool {
        self.flags.contains(LineFlags::ACTIVE_LOW)
    }

    /// True if this line is marked as open drain in the kernel
    pub fn is_open_drain(&self) -> bool {
        self.flags.contains(LineFlags::OPEN_DRAIN)
    }

    /// True if this line is marked as open source in the kernel
    pub fn is_open_source(&self) -> bool {
        self.flags.contains(LineFlags::OPEN_SOURCE)
    }
}

/// Handle for interacting with a "requested" line
///
/// In order for userspace to read/write the value of a GPIO
/// it must be requested from the chip using [`Line::request`].
/// On success, the kernel creates an anonymous file descriptor
/// for interacting with the requested line.  This structure
/// is the go-between for callers and that file descriptor.
///
/// [`Line::request`]: struct.Line.html#method.request
#[derive(Debug)]
pub struct LineHandle {
    line: Line,
    flags: LineRequestFlags,
    file: File,
}

impl LineHandle {
    /// Request the current state of this Line from the kernel
    ///
    /// This call is expected to succeed for both input and output
    /// lines.  It should be noted, however, that some drivers may
    /// not be able to give any useful information when the value
    /// is requested for an output line.
    ///
    /// This value should be 0 or 1 which a "1" representing that
    /// the line is active.  Usually this means that the line is
    /// at logic-level high but it could mean the opposite if the
    /// line has been marked as being `ACTIVE_LOW`.
    pub fn get_value(&self) -> Result<u8> {
        let mut data: ffi::gpiohandle_data = unsafe { mem::zeroed() };
        ffi::gpiohandle_get_line_values_ioctl(self.file.as_raw_fd(), &mut data)?;
        Ok(data.values[0])
    }

    /// Request that the line be driven to the specified value
    ///
    /// The value should be 0 or 1 with 1 representing a request
    /// to make the line "active".  Usually "active" means
    /// logic level high unless the line has been marked as `ACTIVE_LOW`.
    ///
    /// Calling `set_value` on a line that is not an output will
    /// likely result in an error (from the kernel).
    pub fn set_value(&self, value: u8) -> Result<()> {
        let mut data: ffi::gpiohandle_data = unsafe { mem::zeroed() };
        data.values[0] = value;
        ffi::gpiohandle_set_line_values_ioctl(self.file.as_raw_fd(), &mut data)?;
        Ok(())
    }

    /// Get the Line information associated with this handle.
    pub fn line(&self) -> &Line {
        &self.line
    }

    /// Get the flags with which this handle was created
    pub fn flags(&self) -> LineRequestFlags {
        self.flags.clone()
    }
}

impl AsRawFd for LineHandle {
    /// Gets the raw file descriptor for the `LineHandle`.
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

/// A collection of lines that can be accesses simultaneously
///
/// This is a collection of lines, all from the same GPIO chip that can
/// all be accessed simultaneously
#[derive(Debug)]
pub struct Lines {
    lines: Vec<Line>,
}

impl Lines {
    fn new(chip: Arc<InnerChip>, offsets: &[u32]) -> Result<Self> {
        let res: Result<Vec<Line>> = offsets
            .iter()
            .map(|off| Line::new(chip.clone(), *off))
            .collect();
        let lines = res?;
        Ok(Self { lines })
    }

    /// Get a handle to the parent chip for the lines
    pub fn chip(&self) -> Chip {
        self.lines[0].chip()
    }

    /// Get the number of lines in the collection
    pub fn is_empty(&self) -> bool {
        self.lines.is_empty()
    }

    /// Get the number of lines in the collection
    pub fn len(&self) -> usize {
        self.lines.len()
    }

    /// Request access to interact with these lines from the kernel
    ///
    /// This is similar to the "export" operation present in the sysfs
    /// API with the key difference that we are also able to configure
    /// the GPIO with `flags` to specify how the line will be used
    /// at the time of request.
    ///
    /// For an output, the `default` parameter specifies the value
    /// each line should have when it is configured as an output.  The
    /// `consumer` string should describe the process consuming the
    /// line (this will be truncated to 31 characters if too long).
    ///
    /// # Errors
    ///
    /// The main source of errors here is if the kernel returns an
    /// error to the ioctl performing the request here.  This will
    /// result in an [`Error`] being returned with [`ErrorKind::Ioctl`].
    ///
    /// One possible cause for an error here would be if the lines are
    /// already in use.  One can check for this prior to making the
    /// request using [`is_kernel`].
    ///
    /// [`Error`]: errors/struct.Error.html
    /// [`ErrorKind::Ioctl`]: errors/enum.ErrorKind.html#variant.Ioctl
    /// [`is_kernel`]: struct.Line.html#method.is_kernel
    pub fn request(
        &self,
        flags: LineRequestFlags,
        default: &[u8],
        consumer: &str,
    ) -> Result<MultiLineHandle> {
        let n = self.lines.len();
        if default.len() != n {
            return Err(invalid_err(n, default.len()));
        }
        // prepare the request; the kernel consumes some of these values and will
        // set the fd for us.
        let mut request = ffi::gpiohandle_request {
            lineoffsets: unsafe { mem::zeroed() },
            flags: flags.bits(),
            default_values: unsafe { mem::zeroed() },
            consumer_label: unsafe { mem::zeroed() },
            lines: n as u32,
            fd: 0,
        };
        #[allow(clippy::needless_range_loop)] // clippy does not understand this loop correctly
        for i in 0..n {
            request.lineoffsets[i] = self.lines[i].offset();
            request.default_values[i] = default[i];
        }
        unsafe {
            rstr_lcpy(
                request.consumer_label[..].as_mut_ptr(),
                consumer,
                request.consumer_label.len(),
            );
        }
        ffi::gpio_get_linehandle_ioctl(self.lines[0].chip().inner.file.as_raw_fd(), &mut request)?;
        let lines = self.lines.clone();
        Ok(MultiLineHandle {
            lines: Self { lines },
            file: unsafe { File::from_raw_fd(request.fd) },
        })
    }
}

impl Index<usize> for Lines {
    type Output = Line;

    fn index(&self, i: usize) -> &Line {
        &self.lines[i]
    }
}

/// Handle for interacting with a "requested" line
///
/// In order for userspace to read/write the value of a GPIO
/// it must be requested from the chip using [`Line::request`].
/// On success, the kernel creates an anonymous file descriptor
/// for interacting with the requested line.  This structure
/// is the go-between for callers and that file descriptor.
///
/// [`Line::request`]: struct.Line.html#method.request
#[derive(Debug)]
pub struct MultiLineHandle {
    lines: Lines,
    file: File,
}

impl MultiLineHandle {
    /// Request the current state of this Line from the kernel
    ///
    /// This call is expected to succeed for both input and output
    /// lines.  It should be noted, however, that some drivers may
    /// not be able to give any useful information when the value
    /// is requested for an output line.
    ///
    /// This value should be 0 or 1 which a "1" representing that
    /// the line is active.  Usually this means that the line is
    /// at logic-level high but it could mean the opposite if the
    /// line has been marked as being `ACTIVE_LOW`.
    pub fn get_values(&self) -> Result<Vec<u8>> {
        let mut data: ffi::gpiohandle_data = unsafe { mem::zeroed() };
        ffi::gpiohandle_get_line_values_ioctl(self.file.as_raw_fd(), &mut data)?;
        let n = self.num_lines();
        let values: Vec<u8> = (0..n).map(|i| data.values[i]).collect();
        Ok(values)
    }

    /// Request that the line be driven to the specified value
    ///
    /// The value should be 0 or 1 with 1 representing a request
    /// to make the line "active".  Usually "active" means
    /// logic level high unless the line has been marked as `ACTIVE_LOW`.
    ///
    /// Calling `set_value` on a line that is not an output will
    /// likely result in an error (from the kernel).
    pub fn set_values(&self, values: &[u8]) -> Result<()> {
        let n = self.num_lines();
        if values.len() != n {
            return Err(invalid_err(n, values.len()));
        }
        let mut data: ffi::gpiohandle_data = unsafe { mem::zeroed() };
        data.values[..n].clone_from_slice(&values[..n]);
        ffi::gpiohandle_set_line_values_ioctl(self.file.as_raw_fd(), &mut data)?;
        Ok(())
    }

    /// Get the number of lines associated with this handle
    pub fn num_lines(&self) -> usize {
        self.lines.len()
    }

    /// Get the Line information associated with this handle.
    pub fn lines(&self) -> &Lines {
        &self.lines
    }
}

impl AsRawFd for MultiLineHandle {
    /// Gets the raw file descriptor for the `LineHandle`.
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

/// Did the Line rise (go active) or fall (go inactive)?
///
/// Maps to kernel [`GPIOEVENT_EVENT_*`] definitions.
///
/// [`GPIOEVENT_EVENT_*`]: https://elixir.bootlin.com/linux/v4.9.127/source/include/uapi/linux/gpio.h#L136
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EventType {
    RisingEdge,
    FallingEdge,
}

/// Information about a change to the state of a Line
///
/// Wraps kernel [`struct gpioevent_data`].
///
/// [`struct gpioevent_data`]: https://elixir.bootlin.com/linux/v4.9.127/source/include/uapi/linux/gpio.h#L142
pub struct LineEvent(ffi::gpioevent_data);

impl std::fmt::Debug for LineEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "LineEvent {{ timestamp: {:?}, event_type: {:?} }}",
            self.timestamp(),
            self.event_type()
        )
    }
}

impl LineEvent {
    /// Best estimate of event occurrence time, in nanoseconds
    ///
    /// In most cases, the timestamp for the event is captured
    /// in an interrupt handler so it should be very accurate.
    ///
    /// The nanosecond timestamp value should are captured
    /// using the `CLOCK_MONOTONIC` offsets in the kernel and
    /// should be compared against `CLOCK_MONOTONIC` values.
    /// Note that kernel versions prior to 5.7 used
    /// `CLOCK_REALTIME` offsets instead.
    pub fn timestamp(&self) -> u64 {
        self.0.timestamp
    }

    /// Was this a rising or a falling edge?
    pub fn event_type(&self) -> EventType {
        if self.0.id == 0x01 {
            EventType::RisingEdge
        } else {
            EventType::FallingEdge
        }
    }
}

/// Handle for retrieving events from the kernel for a line
///
/// In order for userspace to retrieve incoming events on a GPIO,
/// an event handle must be requested from the chip using
/// [`Line::events`].
/// On success, the kernel creates an anonymous file descriptor
/// for reading events. This structure is the go-between for callers
/// and that file descriptor.
///
/// [`Line::events`]: struct.Line.html#method.events
#[derive(Debug)]
pub struct LineEventHandle {
    line: Line,
    file: File,
}

impl LineEventHandle {
    /// Retrieve the next event from the kernel for this line
    ///
    /// This blocks while there is not another event available from the
    /// kernel for the line which matches the subscription criteria
    /// specified in the `event_flags` when the handle was created.
    pub fn get_event(&mut self) -> Result<LineEvent> {
        match self.read_event() {
            Ok(Some(event)) => Ok(event),
            Ok(None) => Err(event_err(nix::errno::Errno::EIO)),
            Err(e) => Err(e.into()),
        }
    }

    /// Request the current state of this Line from the kernel
    ///
    /// This value should be 0 or 1 which a "1" representing that
    /// the line is active.  Usually this means that the line is
    /// at logic-level high but it could mean the opposite if the
    /// line has been marked as being `ACTIVE_LOW`.
    pub fn get_value(&self) -> Result<u8> {
        let mut data: ffi::gpiohandle_data = unsafe { mem::zeroed() };
        ffi::gpiohandle_get_line_values_ioctl(self.file.as_raw_fd(), &mut data)?;
        Ok(data.values[0])
    }

    /// Get the Line information associated with this handle.
    pub fn line(&self) -> &Line {
        &self.line
    }

    pub fn file(&self) -> &File {
        &self.file
    }

    pub fn file2(&mut self) -> &File {
        &self.file
    }

    /// Helper function which returns the line event if a complete event was read, Ok(None) if not
    /// enough data was read or the error returned by `read()`.
    pub(crate) fn read_event(&mut self) -> std::io::Result<Option<LineEvent>> {
        let mut data: ffi::gpioevent_data = unsafe { mem::zeroed() };
        let data_as_buf = unsafe {
            slice::from_raw_parts_mut(
                (&mut data as *mut ffi::gpioevent_data).cast(),
                mem::size_of::<ffi::gpioevent_data>(),
            )
        };
        let bytes_read = self.file.read(data_as_buf)?;
        if bytes_read == mem::size_of::<ffi::gpioevent_data>() {
            Ok(Some(LineEvent(data)))
        } else {
            Ok(None)
        }
    }
}

impl AsRawFd for LineEventHandle {
    /// Gets the raw file descriptor for the `LineEventHandle`.
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

impl AsFd for LineEventHandle {
    /// Gets the raw file descriptor for the `LineEventHandle`.
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.file.as_fd()
    }
}

impl Iterator for LineEventHandle {
    type Item = Result<LineEvent>;

    fn next(&mut self) -> Option<Result<LineEvent>> {
        match self.read_event() {
            Ok(None) => None,
            Ok(Some(event)) => Some(Ok(event)),
            Err(e) => Some(Err(e.into())),
        }
    }
}
