2016-04-26 11:47:09 +03:00
/*
* gpio - hammer - example swiss army knife to shake GPIO lines on a system
*
* Copyright ( C ) 2016 Linus Walleij
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*
* Usage :
* gpio - hammer - n < device - name > - o < offset1 > - o < offset2 >
*/
# include <unistd.h>
# include <stdlib.h>
# include <stdbool.h>
# include <stdio.h>
# include <dirent.h>
# include <errno.h>
# include <string.h>
# include <poll.h>
# include <fcntl.h>
# include <getopt.h>
# include <sys/ioctl.h>
# include <linux/gpio.h>
2016-10-14 05:48:26 +03:00
# include "gpio-utils.h"
2016-04-26 11:47:09 +03:00
int hammer_device ( const char * device_name , unsigned int * lines , int nlines ,
unsigned int loops )
{
struct gpiohandle_data data ;
char swirr [ ] = " - \\ |/ " ;
int fd ;
int ret ;
int i , j ;
unsigned int iteration = 0 ;
2016-10-14 05:48:26 +03:00
memset ( & data . values , 0 , sizeof ( data . values ) ) ;
ret = gpiotools_request_linehandle ( device_name , lines , nlines ,
GPIOHANDLE_REQUEST_OUTPUT , & data ,
2017-01-26 00:01:44 +03:00
" gpio-hammer " ) ;
2016-04-26 11:47:09 +03:00
if ( ret < 0 )
2016-10-14 05:48:26 +03:00
goto exit_error ;
else
fd = ret ;
2016-04-26 11:47:09 +03:00
2016-10-14 05:48:26 +03:00
ret = gpiotools_get_values ( fd , & data ) ;
if ( ret < 0 )
2016-04-26 11:47:09 +03:00
goto exit_close_error ;
fprintf ( stdout , " Hammer lines [ " ) ;
for ( i = 0 ; i < nlines ; i + + ) {
fprintf ( stdout , " %d " , lines [ i ] ) ;
if ( i ! = ( nlines - 1 ) )
fprintf ( stdout , " , " ) ;
}
fprintf ( stdout , " ] on %s, initial states: [ " , device_name ) ;
for ( i = 0 ; i < nlines ; i + + ) {
fprintf ( stdout , " %d " , data . values [ i ] ) ;
if ( i ! = ( nlines - 1 ) )
fprintf ( stdout , " , " ) ;
}
fprintf ( stdout , " ] \n " ) ;
/* Hammertime! */
j = 0 ;
while ( 1 ) {
/* Invert all lines so we blink */
for ( i = 0 ; i < nlines ; i + + )
data . values [ i ] = ! data . values [ i ] ;
2016-10-14 05:48:26 +03:00
ret = gpiotools_set_values ( fd , & data ) ;
if ( ret < 0 )
2016-04-26 11:47:09 +03:00
goto exit_close_error ;
2016-10-14 05:48:26 +03:00
2016-04-26 11:47:09 +03:00
/* Re-read values to get status */
2016-10-14 05:48:26 +03:00
ret = gpiotools_get_values ( fd , & data ) ;
if ( ret < 0 )
2016-04-26 11:47:09 +03:00
goto exit_close_error ;
fprintf ( stdout , " [%c] " , swirr [ j ] ) ;
j + + ;
if ( j = = sizeof ( swirr ) - 1 )
j = 0 ;
fprintf ( stdout , " [ " ) ;
for ( i = 0 ; i < nlines ; i + + ) {
fprintf ( stdout , " %d: %d " , lines [ i ] , data . values [ i ] ) ;
if ( i ! = ( nlines - 1 ) )
fprintf ( stdout , " , " ) ;
}
fprintf ( stdout , " ] \r " ) ;
fflush ( stdout ) ;
sleep ( 1 ) ;
iteration + + ;
if ( loops & & iteration = = loops )
break ;
}
fprintf ( stdout , " \n " ) ;
ret = 0 ;
exit_close_error :
2016-10-14 05:48:26 +03:00
gpiotools_release_linehandle ( fd ) ;
exit_error :
2016-04-26 11:47:09 +03:00
return ret ;
}
void print_usage ( void )
{
fprintf ( stderr , " Usage: gpio-hammer [options]... \n "
" Hammer GPIO lines, 0->1->0->1... \n "
" -n <name> Hammer GPIOs on a named device (must be stated) \n "
" -o <n> Offset[s] to hammer, at least one, several can be stated \n "
" [-c <n>] Do <n> loops (optional, infinite loop if not stated) \n "
" -? This helptext \n "
" \n "
" Example: \n "
" gpio-hammer -n gpiochip0 -o 4 \n "
) ;
}
int main ( int argc , char * * argv )
{
const char * device_name = NULL ;
unsigned int lines [ GPIOHANDLES_MAX ] ;
unsigned int loops = 0 ;
int nlines ;
int c ;
int i ;
i = 0 ;
while ( ( c = getopt ( argc , argv , " c:n:o:? " ) ) ! = - 1 ) {
switch ( c ) {
case ' c ' :
loops = strtoul ( optarg , NULL , 10 ) ;
break ;
case ' n ' :
device_name = optarg ;
break ;
case ' o ' :
lines [ i ] = strtoul ( optarg , NULL , 10 ) ;
i + + ;
break ;
case ' ? ' :
print_usage ( ) ;
return - 1 ;
}
}
nlines = i ;
if ( ! device_name | | ! nlines ) {
print_usage ( ) ;
return - 1 ;
}
return hammer_device ( device_name , lines , nlines , loops ) ;
}