2021-08-27 09:09:32 -07:00
# include <errno.h>
2021-08-26 10:26:53 -07:00
# include <fcntl.h>
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <unistd.h>
2021-08-27 09:09:32 -07:00
2021-08-26 10:26:53 -07:00
# include <linux/input.h>
2021-08-27 09:09:32 -07:00
# include <sys/epoll.h>
# define MAX_EVENTS 16
# define CONTENT_BUFFER_SIZE 32
static char * KEYBOARD = " k " ;
static char * MOUSE = " m " ;
2021-08-26 10:26:53 -07:00
2021-08-27 09:09:32 -07:00
int dump_event ( struct timespec * start , int fd , char * type ) ;
int event_content_keyboard ( char * buffer , int buffer_size , struct input_event * event ) ;
int event_content_mouse ( char * buffer , int buffer_size , struct input_event * event ) ;
int stream_events ( char * mouse_path , char * keyboard_path ) ;
2021-08-26 10:26:53 -07:00
static inline void timespec_diff ( struct timespec * a , struct timespec * b , struct timespec * result ) {
result - > tv_sec = a - > tv_sec - b - > tv_sec ;
result - > tv_nsec = a - > tv_nsec - b - > tv_nsec ;
if ( result - > tv_nsec < 0 ) {
- - result - > tv_sec ;
result - > tv_nsec + = 1000000000L ;
}
}
2021-08-27 09:09:32 -07:00
int dump_event ( struct timespec * start , int fd , char * type ) {
struct input_event event ;
2021-08-26 10:26:53 -07:00
struct timespec now ;
struct timespec diff ;
2021-08-27 09:09:32 -07:00
char content_buffer [ CONTENT_BUFFER_SIZE ] ;
int result = read ( fd , & event , sizeof ( struct input_event ) ) ;
if ( result < 0 ) {
fprintf ( stderr , " Failed to read an event: %d " , errno ) ;
return 1 ;
}
2021-08-26 10:26:53 -07:00
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
timespec_diff ( & now , start , & diff ) ;
2021-08-27 09:09:32 -07:00
if ( type = = MOUSE ) {
if ( event_content_mouse ( content_buffer , CONTENT_BUFFER_SIZE , & event ) ) {
return 1 ;
}
} else if ( type = = KEYBOARD ) {
2021-08-27 09:33:08 -07:00
// Ignore all but EV_KEY events on keyboard, they have no useful content.
if ( event . type ! = EV_KEY ) {
2021-08-27 09:09:32 -07:00
return 0 ;
}
if ( event_content_keyboard ( content_buffer , CONTENT_BUFFER_SIZE , & event ) ) {
return 1 ;
}
} else {
fprintf ( stderr , " Unknown event type. \n " ) ;
return 1 ;
}
2021-08-27 11:44:14 -07:00
printf ( " %ld %ld,%s,%s \n " ,
2021-08-27 09:09:32 -07:00
diff . tv_sec ,
diff . tv_nsec ,
type ,
content_buffer ) ;
2021-08-27 10:10:53 -07:00
fflush ( stdout ) ;
2021-08-27 09:09:32 -07:00
return 0 ;
}
int event_content_keyboard ( char * buffer , int buffer_size , struct input_event * event ) {
2021-08-27 09:33:08 -07:00
sprintf ( buffer , " %d,%d,%d " ,
event - > type ,
event - > code ,
event - > value ) ;
2021-08-27 09:09:32 -07:00
return 0 ;
}
int event_content_mouse ( char * buffer , int buffer_size , struct input_event * event ) {
unsigned char button , bLeft , bMiddle , bRight ;
unsigned char * ptr = ( unsigned char * ) event ;
int i ;
char x , y ;
2021-08-26 10:26:53 -07:00
button = ptr [ 0 ] ;
bLeft = button & 0x1 ;
bMiddle = ( button & 0x4 ) > 0 ;
bRight = ( button & 0x2 ) > 0 ;
2021-08-27 09:09:32 -07:00
x = ( char ) ptr [ 1 ] ;
y = ( char ) ptr [ 2 ] ;
int chars = sprintf ( buffer , " l%d,m%d,r%d,x%d,y%d " ,
2021-08-26 10:26:53 -07:00
bLeft , bMiddle , bRight , x , y ) ;
2021-08-27 09:09:32 -07:00
return chars < 0 ;
2021-08-26 10:26:53 -07:00
}
2021-08-27 09:09:32 -07:00
2021-08-26 10:26:53 -07:00
int main ( int argc , char * argv [ ] ) {
if ( argc < 2 ) {
fprintf ( stderr , " You must specify a mouse input to track like /dev/input/mouse1. " ) ;
exit ( EXIT_FAILURE ) ;
}
2021-08-27 09:09:32 -07:00
if ( argc < 3 ) {
fprintf ( stderr , " You must specify a keyboard input to track like /dev/input/event3. If you're not sure which to use read through /proc/bus/input/devices and look for 'Handlers=eventX' " ) ;
exit ( EXIT_FAILURE ) ;
}
int result = stream_events ( argv [ 1 ] , argv [ 2 ] ) ;
2021-08-26 10:26:53 -07:00
exit ( result ) ;
}
2021-08-27 09:09:32 -07:00
int stream_events ( char * mouse_path , char * keyboard_path ) {
int keyboard_fd , mouse_fd ;
2021-08-26 10:26:53 -07:00
struct timespec start ;
2021-08-27 09:09:32 -07:00
struct epoll_event event , events [ MAX_EVENTS ] ;
int running = 1 ;
int epoll_fd = epoll_create1 ( 0 ) ;
if ( epoll_fd < 0 ) {
fprintf ( stderr , " Failed to initialize epoll fd: %d " , errno ) ;
return 1 ;
}
if ( ( mouse_fd = open ( mouse_path , O_RDONLY ) ) = = - 1 ) {
fprintf ( stderr , " Failed to open %s. Are you running as root? \n " , mouse_path ) ;
2021-08-26 10:26:53 -07:00
return 1 ;
}
else {
2021-08-27 09:09:32 -07:00
fprintf ( stderr , " %s open OK \n " , mouse_path ) ;
2021-08-26 10:26:53 -07:00
}
2021-08-27 09:09:32 -07:00
if ( ( keyboard_fd = open ( keyboard_path , O_RDONLY ) ) = = - 1 ) {
fprintf ( stderr , " Failed to open %s. Are you running as root? \n " , keyboard_path ) ;
return 1 ;
}
else {
fprintf ( stderr , " %s open OK \n " , keyboard_path ) ;
}
event . events = EPOLLIN ;
event . data . fd = keyboard_fd ;
if ( epoll_ctl ( epoll_fd , EPOLL_CTL_ADD , keyboard_fd , & event ) ) {
fprintf ( stderr , " Failed to add keyboard file descriptor \n " ) ;
close ( epoll_fd ) ;
return 1 ;
}
event . data . fd = mouse_fd ;
if ( epoll_ctl ( epoll_fd , EPOLL_CTL_ADD , mouse_fd , & event ) ) {
fprintf ( stderr , " Failed to add mouse file descriptor \n " ) ;
close ( epoll_fd ) ;
return 1 ;
}
fprintf ( stderr , " Waiting for events \n " ) ;
2021-08-26 10:26:53 -07:00
clock_gettime ( CLOCK_MONOTONIC , & start ) ;
2021-08-27 09:09:32 -07:00
while ( running ) {
int event_count = epoll_wait ( epoll_fd , events , MAX_EVENTS , - 1 ) ;
char * type ;
for ( int i = 0 ; i < event_count ; i + + ) {
if ( events [ i ] . data . fd = = keyboard_fd ) {
type = KEYBOARD ;
} else if ( events [ i ] . data . fd = = mouse_fd ) {
type = MOUSE ;
} else {
fprintf ( stderr , " Unknown fd " ) ;
return 1 ;
}
if ( dump_event ( & start , events [ i ] . data . fd , type ) ) {
return 1 ;
}
}
2021-08-26 10:26:53 -07:00
}
}