aboutsummaryrefslogtreecommitdiff
path: root/src/input33.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input33.c')
-rw-r--r--src/input33.c232
1 files changed, 232 insertions, 0 deletions
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 <linux/input-event-codes.h>
+#include <linux/input.h>
+
+#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 );
+}
+