Last active
September 9, 2019 09:33
-
-
Save mvduin/578509d458da8948ae3a14a81dc639e4 to your computer and use it in GitHub Desktop.
sysfs gpio event example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <stdio.h> | |
#include <stdarg.h> | |
#include <stdlib.h> | |
[[ noreturn ]] | |
inline void die( char const *fmt, ... ) | |
{ | |
va_list ap; | |
va_start( ap, fmt ); | |
vfprintf( stderr, fmt, ap ); | |
va_end( ap ); | |
exit( EXIT_FAILURE ); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "sysfs-gpio.h" | |
int main() | |
{ | |
GpIn in { "/sys/class/gpio/gpio60", GpIn::Edge::BOTH }; | |
bool value = in; | |
for(;;) { | |
printf( "%d\n", value ); | |
do in.wait(); while( value == in ); | |
value = ! value; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "die.h" | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <poll.h> | |
#include <assert.h> | |
#include <stdlib.h> | |
#include <string.h> | |
struct Gpio { | |
protected: | |
int fd = -1; | |
int pathfd = -1; | |
char *path = NULL; | |
Gpio( char const *dir, bool output ) | |
{ | |
assert( dir != NULL ); | |
path = strdup( dir ); | |
if( path == NULL ) | |
die( "strdup: %m\n" ); | |
pathfd = open( path, O_PATH | O_CLOEXEC ); | |
if( pathfd < 0 ) | |
die( "open %s: %m\n", path ); | |
fd = open_attribute( "value", output ); | |
} | |
int open_attribute( char const *attr, bool write ) const | |
{ | |
int flags = (write ? O_RDWR : O_RDONLY) | O_CLOEXEC; | |
int afd = openat( pathfd, attr, flags ); | |
if( afd < 0 ) | |
die( "open %s/%s: %m\n", path, attr ); | |
return afd; | |
} | |
char read_attribute( char const *attr ) const | |
{ | |
int afd = open_attribute( attr, false ); | |
char c = 0; | |
if( read( afd, &c, 1 ) < 0 ) | |
die( "read %s/%s: %m\n", path, attr ); | |
close( afd ); | |
return c; | |
} | |
void write_attribute( char const *attr, char const *value ) | |
{ | |
int afd = open_attribute( attr, true ); | |
if( write( afd, value, strlen( value ) ) < 0 ) | |
die( "write %s/%s: %m\n", path, attr ); | |
close( afd ); | |
} | |
public: | |
Gpio() = delete; | |
Gpio( Gpio const & ) = delete; | |
~Gpio() | |
{ | |
if( fd >= 0 ) | |
close( fd ); | |
if( pathfd >= 0 ) | |
close( pathfd ); | |
free( path ); | |
} | |
bool active_low() const | |
{ | |
return read_attribute( "active_low" ) != '0'; | |
} | |
operator bool () const | |
{ | |
char c; | |
ssize_t res = pread( fd, &c, 1, 0 ); | |
if( res < 0 ) | |
die( "pread %s/value: %m\n", path ); | |
if( res == 0 ) | |
die( "pread %s/value: no data\n", path ); | |
return c != '0'; | |
} | |
}; | |
struct GpIn : Gpio { | |
enum Edge { NONE, RISING, FALLING, BOTH }; | |
GpIn( const char *dir, Edge event_edge ) : Gpio{ dir, false } | |
{ | |
if( read_attribute( "direction" ) != 'i' ) | |
write_attribute( "direction", "in" ); | |
static char const *const edge_names[] | |
= { "none", "rising", "falling", "both" }; | |
write_attribute( "edge", edge_names[ event_edge ] ); | |
} | |
// wait for edge event | |
void wait() | |
{ | |
struct pollfd pfd = { fd, POLLPRI, 0 }; | |
if( poll( &pfd, 1, -1 ) < 0 ) | |
die( "poll %s: %m\n", path ); | |
} | |
}; | |
struct GpOut : Gpio { | |
GpOut( const char *dir, bool init ) : Gpio{ dir, true } | |
{ | |
if( read_attribute( "direction" ) != 'i' ) { | |
*this = init; | |
return; | |
} | |
write_attribute( "edge", "none" ); | |
if( active_low() ) | |
init = ! init; | |
write_attribute( "direction", init ? "high" : "low" ); | |
} | |
bool operator = ( bool value ) | |
{ | |
char c = '0' + value; | |
ssize_t res = pwrite( fd, &c, 1, 0 ); | |
if( res < 0 ) | |
die( "pwrite %s/value: %m\n", path ); | |
return value; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment