From 5a54774474f43ae29716751d6415563a59b92c7d Mon Sep 17 00:00:00 2001 From: pk33 Date: Mon, 11 Nov 2024 18:06:18 +0100 Subject: tidying up and basic input --- src/input33.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 src/input33.c (limited to 'src/input33.c') diff --git a/src/input33.c b/src/input33.c new file mode 100644 index 0000000..1ba1ff2 --- /dev/null +++ b/src/input33.c @@ -0,0 +1,232 @@ +#include "fcntl.h" +#include "dirent.h" +#include "stdio.h" +#include "stdlib.h" +#include "unistd.h" +#include "string.h" +#include "sys/stat.h" +#include "sys/kd.h" +#include +#include + +#include "input33.h" +#include "logger33.h" +#include "strings33.h" + + +#define _INPUT_DEVICES_MAX 8 +#define _POLL_EVENTS_MAX 16 + + +Input33 __input = {0}; + + +static int _is_char_device( const struct dirent *f ); +static Boolean _is_keyboard( Size fd ); +static Boolean _is_mouse( Size fd ); +static Size _has_key( Size fd, unsigned int event ); +static Size _has_rel( Size fd, unsigned int event ); +static u64 _has_evbits( Size fd, unsigned int type ); + + +Error input33_init( void ) +{ + Size i, deviceCount; + Boolean hasKeyboard = E33_FALSE; + Boolean hasMouse = E33_FALSE; + struct dirent **evfs; + + deviceCount = scandir( "/dev/input", &evfs, _is_char_device, 0 ); + + if( deviceCount <= 0 ) { + LOGE( "No valid character devices found." ); + return E33_EXIT_FAILURE; + } + + for( i = 0; i < deviceCount; ++i ) + { + Size j; + Size devFd; + char path[ _STRING_MAX ]; + + snprintf( path, _STRING_MAX , "%s%s", "/dev/input/", evfs[i]->d_name ); + free( evfs[i] ); + + devFd = open( path, O_RDONLY | O_NONBLOCK ); + if( devFd == -1 ) { + continue; + } + + if( _is_keyboard( devFd ) ) + { + hasKeyboard = E33_TRUE; + __input.devices[ __input.deviceCount++ ] = devFd; + } + else if( _is_mouse(devFd) ) + { + hasMouse = E33_TRUE; + __input.devices[ __input.deviceCount++ ] = devFd; + ioctl( devFd, EVIOCGRAB, 1 ); + } + else { + close( devFd ); + } + + if( __input.deviceCount == _INPUT_DEVICES_MAX ){ + break; + } + } + + free( evfs ); + + if( (hasKeyboard == E33_TRUE) && (hasMouse == E33_TRUE) ) { + return E33_EXIT_SUCCESS; + } + + return E33_EXIT_FAILURE; +} + +void input33_poll( void ) +{ + u16 i; + + for( i = 0; i < __input.deviceCount; ++i ) + { + Size j; + Size readBytes; + Size eventCount; + struct input_event events[ _POLL_EVENTS_MAX ]; + + __input.relStates[REL_X] = 0; + __input.relStates[REL_Y] = 0; + __input.relStates[REL_WHEEL] = 0; + + readBytes = read( __input.devices[i], events, + sizeof(struct input_event) * _POLL_EVENTS_MAX ); + + if( readBytes == -1 ) { + continue; + } + + eventCount = readBytes / sizeof( struct input_event ); + + for( j = 0; j < eventCount; ++j ) + { + switch( events[j].type ) + { + case EV_KEY: + __input.keyStates[ events[j].code ] = events[j].value; + + if( (events[j].value == _PRESS) || (events[j].value == _REPEAT) ) + { + __input.buffer[__input.tail++] = events[j].code; + __input.tail &= (_KBBUFF_LEN - 1); + + if( __input.tail == __input.head ) + { + ++__input.head; + __input.head &= (_KBBUFF_LEN - 1); + } + } + break; + + case EV_REL: + __input.relStates[ events[j].code ] = events[j].value; + break; + } + } + } + + __input.modFlags = 6; + ioctl( 0, TIOCLINUX, &__input.modFlags ); + ioctl( 0, KDGKBLED, &__input.cnsFlags ); +} + +void input33_term( void ) +{ + Size i; + + for( i = 0; i < __input.deviceCount; ++i ) { + close( __input.devices[i] ); + } +} + + +static u64 _has_evbits( Size fd, unsigned int type ) +{ + u64 kbb; + + if( ioctl( fd, EVIOCGBIT( 0, (int)sizeof(kbb) ), &kbb ) == -1 ) { + return 0; + } + + return (kbb & (1 << type)); +} + +static Size _has_key( Size fd, unsigned int event ) +{ + unsigned char bits[ (KEY_MAX >> 3) + 1 ]; + + if( ioctl( fd, EVIOCGBIT(EV_KEY, (int)sizeof(bits)), &bits ) == -1 ) { + return 0; + } + + return ( (bits[event >> 3] & (1 << (event % 8))) > 0 ); +} + +static Size _has_rel( Size fd, unsigned int event ) +{ + unsigned char bits[ (REL_MAX >> 3) + 1 ]; + + if( ioctl( fd, EVIOCGBIT(EV_REL, (int)sizeof(bits)), &bits ) == -1 ) { + return 0; + } + + return ( (bits[event >> 3] & (1 << (event % 8))) > 0 ); +} + +static Boolean _is_mouse( Size fd ) +{ + if( _has_evbits( fd, EV_KEY ) && + _has_evbits( fd, EV_REL ) ) + { + return( _has_rel( fd, REL_X ) & + _has_rel( fd, REL_Y ) & + _has_key( fd, BTN_LEFT ) & + _has_key( fd, BTN_RIGHT ) & 1 ); + } + + return E33_FALSE; +} + +static Boolean _is_keyboard( Size fd ) +{ + if( _has_evbits( fd, EV_KEY ) ) + { + return( _has_key( fd, KEY_W ) & + _has_key( fd, KEY_SPACE ) & + _has_key( fd, KEY_LEFTSHIFT ) & + _has_key( fd, KEY_I ) & 1 ); + } + + return E33_FALSE; +} + +static int _is_char_device( const struct dirent *f ) +{ + struct stat fstat; + char path[512]; + + if( strncmp( f->d_name, "event", 5 ) ) { + return 0; + } + + snprintf( path, 512, "%s%s", "/dev/input/", f->d_name ); + + if( stat( path, &fstat ) ) { + return 0; + } + + return S_ISCHR( fstat.st_mode ); +} + -- cgit v1.2.3