@@ -91,7 +91,7 @@ use std::cmp::min;
91
91
use std:: ffi:: CStr ;
92
92
use std:: fs:: { read_dir, File , ReadDir } ;
93
93
use std:: mem;
94
- use std:: os:: unix:: io:: { AsRawFd , FromRawFd } ;
94
+ use std:: os:: unix:: io:: { RawFd , AsRawFd , FromRawFd } ;
95
95
use std:: path:: { Path , PathBuf } ;
96
96
use std:: ptr;
97
97
use std:: slice;
@@ -181,7 +181,7 @@ impl Iterator for ChipIterator {
181
181
/// Iterate over all GPIO chips currently present on this system
182
182
pub fn chips ( ) -> Result < ChipIterator > {
183
183
Ok ( ChipIterator {
184
- readdir : read_dir ( "/dev" ) . chain_err ( || "unabled to rea /dev directory" ) ?,
184
+ readdir : read_dir ( "/dev" ) . chain_err ( || "unabled to read /dev directory" ) ?,
185
185
} )
186
186
}
187
187
@@ -518,11 +518,12 @@ impl Line {
518
518
} )
519
519
}
520
520
521
- /// Get a blocking iterator over events (state changes) for this Line
521
+ /// Get an event handle that can be used as a blocking iterator over
522
+ /// the events (state changes) for this Line
522
523
///
523
- /// This iterator blocks while there is not another event available
524
- /// from the kernel for this line matching the subscription criteria
525
- /// specified in the `event_flags`. The line will be configured
524
+ /// When used as an iterator, it blocks while there is not another event
525
+ /// available from the kernel for this line matching the subscription
526
+ /// criteria specified in the `event_flags`. The line will be configured
526
527
/// with the specified `handle_flags` and `consumer` label.
527
528
///
528
529
/// Note that as compared with the sysfs interface, the character
@@ -559,7 +560,7 @@ impl Line {
559
560
handle_flags : LineRequestFlags ,
560
561
event_flags : EventRequestFlags ,
561
562
consumer : & str ,
562
- ) -> Result < LineEventIterator > {
563
+ ) -> Result < LineEventHandle > {
563
564
let mut request = ffi:: gpioevent_request {
564
565
lineoffset : self . offset ,
565
566
handleflags : handle_flags. bits ( ) ,
@@ -580,7 +581,10 @@ impl Line {
580
581
. chain_err ( || "lineevent ioctl failed" ) ?
581
582
} ;
582
583
583
- Ok ( LineEventIterator {
584
+ Ok ( LineEventHandle {
585
+ line : self . clone ( ) . refresh ( ) ?, // TODO: revisit
586
+ handle_flags,
587
+ event_flags,
584
588
file : unsafe { File :: from_raw_fd ( request. fd ) } ,
585
589
} )
586
590
}
@@ -590,7 +594,7 @@ impl Line {
590
594
///
591
595
/// In order for userspace to read/write the value of a GPIO
592
596
/// it must be requested from the chip using [`Line::request`].
593
- /// On success, the kernel creates and anonymous file descriptor
597
+ /// On success, the kernel creates an anonymous file descriptor
594
598
/// for interacting with the requested line. This structure
595
599
/// is the go-between for callers and that file descriptor.
596
600
///
@@ -647,6 +651,13 @@ impl LineHandle {
647
651
}
648
652
}
649
653
654
+ impl AsRawFd for LineHandle {
655
+ /// Gets the raw file descriptor for the LineHandle.
656
+ fn as_raw_fd ( & self ) -> RawFd {
657
+ self . file . as_raw_fd ( )
658
+ }
659
+ }
660
+
650
661
/// Did the Line rise (go active) or fall (go inactive)?
651
662
///
652
663
/// Maps to kernel [`GPIOEVENT_EVENT_*`] definitions.
@@ -699,13 +710,74 @@ impl LineEvent {
699
710
}
700
711
}
701
712
702
- /// Blocking iterator over events for a given line
713
+ /// Handle for retrieving events from the kernel for a line
714
+ ///
715
+ /// In order for userspace to retrieve incoming events on a GPIO,
716
+ /// an event handle must be requested from the chip using
717
+ /// [`Line::events`].
718
+ /// On success, the kernel creates an anonymous file descriptor
719
+ /// for reading events. This structure is the go-between for callers
720
+ /// and that file descriptor.
721
+ ///
722
+ /// [`Line::events`]: struct.Line.html#method.events
703
723
#[ derive( Debug ) ]
704
- pub struct LineEventIterator {
724
+ pub struct LineEventHandle {
725
+ line : Line ,
726
+ handle_flags : LineRequestFlags ,
727
+ event_flags : EventRequestFlags ,
705
728
file : File ,
706
729
}
707
730
708
- impl Iterator for LineEventIterator {
731
+ impl LineEventHandle {
732
+ /// Retrieve the next event from the kernel for this line
733
+ ///
734
+ /// This blocks while there is not another event available from the
735
+ /// kernel for the line which matches the subscription criteria
736
+ /// specified in the `event_flags` when the handle was created.
737
+ pub fn get_event ( & self ) -> Result < LineEvent > {
738
+ let mut data: ffi:: gpioevent_data = unsafe { mem:: zeroed ( ) } ;
739
+ let mut data_as_buf = unsafe {
740
+ slice:: from_raw_parts_mut (
741
+ & mut data as * mut ffi:: gpioevent_data as * mut u8 ,
742
+ mem:: size_of :: < ffi:: gpioevent_data > ( ) ,
743
+ )
744
+ } ;
745
+ let bytes_read = nix:: unistd:: read ( self . file . as_raw_fd ( ) , & mut data_as_buf) ?;
746
+
747
+ if bytes_read != mem:: size_of :: < ffi:: gpioevent_data > ( ) {
748
+ let e = nix:: Error :: Sys ( nix:: errno:: Errno :: EIO ) ;
749
+ Err ( e. into ( ) )
750
+ } else {
751
+ Ok ( LineEvent ( data) )
752
+ }
753
+ }
754
+
755
+ /// Request the current state of this Line from the kernel
756
+ ///
757
+ /// This value should be 0 or 1 which a "1" representing that
758
+ /// the line is active. Usually this means that the line is
759
+ /// at logic-level high but it could mean the opposite if the
760
+ /// line has been marked as being ACTIVE_LOW.
761
+ pub fn get_value ( & self ) -> Result < u8 > {
762
+ let mut data: ffi:: gpiohandle_data = unsafe { mem:: zeroed ( ) } ;
763
+ let _ = unsafe { ffi:: gpiohandle_get_line_values_ioctl ( self . file . as_raw_fd ( ) , & mut data) ? } ;
764
+ Ok ( data. values [ 0 ] )
765
+ }
766
+
767
+ /// Get the Line information associated with this handle.
768
+ pub fn line ( & self ) -> & Line {
769
+ & self . line
770
+ }
771
+ }
772
+
773
+ impl AsRawFd for LineEventHandle {
774
+ /// Gets the raw file descriptor for the LineEventHandle.
775
+ fn as_raw_fd ( & self ) -> RawFd {
776
+ self . file . as_raw_fd ( )
777
+ }
778
+ }
779
+
780
+ impl Iterator for LineEventHandle {
709
781
type Item = Result < LineEvent > ;
710
782
711
783
fn next ( & mut self ) -> Option < Result < LineEvent > > {
0 commit comments