[CentOS] program to monitor USB keys

Tue Sep 18 17:41:32 UTC 2007
Jerry Geis <geisj at pagestation.com>

I wrote a small program to monitor keyboards found on /dev/input/event*
It works great but I always get EAGAIN from my read() function. google 
says this is normal
when open() is used and O_NONBLOCK mode.

I know this is slightly offtopic but I was wondering if the centos gurus 
that also
program know anything about this. My goal was to not be eating CPU cycles
with a small program that just monitors key presses. With EAGAIN always 
coming in
the process though small keeps waking up.

Or perhaps there is another way to do this that I am not aware of.

Thanks for any tips.

Jerry

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <linux/input.h>

#include "smsignal.h"

struct _msgnet_keycode
	{
	int keycode_value;
	char *keycode_str;
	int send_to_server;		// .X will also send to server example: .4 says function 4
	};

struct _msgnet_keycode msgnet_keycode[] =
	{
	{96, "KP_ENTER", 1},		// Keypad Enter			Enter MUST be the first entry
	{28, "KP_ENTER", 1},		// Keypad Enter USB

	{14, "KP_BackSpace", 1},	// Keypad BS
	{55, "KP_Multiply", 1},		// Keypad *
	{98, "KP_Divide", 1},		// Keypad /
	{78, "KP_Plus", 1},		// Keypad +
	{74, "KP_Minus", 1},		// Keypad -

	{83, "KP_Period", 0},		// Keypad .
	{73, "KP_9", 0},		// Keypad 9
	{72, "KP_8", 0},		// Keypad 8
	{71, "KP_7", 0},		// Keypad 7
	{77, "KP_6", 0},		// Keypad 6
	{76, "KP_5", 0},		// Keypad 5
	{75, "KP_4", 0},		// Keypad 4
	{81, "KP_3", 0},		// Keypad 3
	{80, "KP_2", 0},		// Keypad 2
	{79, "KP_1", 0},		// Keypad 1
	{82, "KP_0", 0},		// Keypad 0

	{0, NULL}
	};

static int key_debug = 0;
static int key_timeout = 0;					/* incomplete command found so add KP_Enter and submit key presses */
static char keypad_buffer[200] = "";

#define FALSE					(0)
#define TRUE					(1)

/************************************************************
** int main(int argc, char *argv[])
**
************************************************************/
int main(int argc, char *argv[])
{
int i;
int fd;
int bytes_read;
int keycode;
int done = FALSE;
int any_keyboards;

char *ptr;
char *ptr_comma;


	#define MAX_KEY_WATCH (10)

	int fd[MAX_KEY_WATCH];
	char input_name[200];
		
	while(1)
		{
		done = FALSE;
		any_keyboards = FALSE;

		/* open all /dev/input/event devices */
		for(i = 0; i < MAX_KEY_WATCH; i++)
			{
			sprintf(input_name, "/dev/input/event%d", i);
			fd[i] = open(input_name, O_RDONLY | O_NONBLOCK);
				
			if(fd[i] >= 0)
				{
				ioctl(fd[i], EVIOCGNAME (sizeof (input_name)), input_name);
				if(strstr(input_name, "Keyboard")
					|| strstr(input_name, "1241:1203"))				// Belkin keyboard
					{
					printf("Reading from (%d) %s\n", i, input_name);
					any_keyboards = TRUE;
					}
				else
					{
					close(fd[i]);
					fd[i] = -1;
					}
				}
			}

		if(any_keyboards == FALSE)
			{
			/* no keyboards found so sleep and try again */
			sleep(10);
			}
	
		while(any_keyboards && done == FALSE)
			{
			int bytes_read;
			struct input_event event_keys[64];
	
			for(i = 0; i < MAX_KEY_WATCH; i++)
				{
				if(fd[i] >= 0)
					{
					bytes_read = read(fd[i], event_keys, sizeof(event_keys));
					if(bytes_read > 0)
						{
						/* there is a down event */
						/* there is a UP event */
						/* there is a UP event */
						//printf("D %d %d %d\n", event_keys[0].type, event_keys[0].value, event_keys[0].code);
						//printf("U %d %d %d\n", event_keys[1].type, event_keys[1].value, event_keys[1].code);
	
						if(event_keys[0].type == 1
							&& event_keys[0].value == 1)
							{
							keycode = event_keys[0].code;
	
							for(find_key = 0; msgnet_keycode[find_key].keycode_str; find_key++)
								{
								if(msgnet_keycode[find_key].keycode_value == keycode)
									{
									KeyLog(find_key);
									break;
									}
								}
							}
						}
					else if(bytes_read < 0)
						{
						if(errno == EAGAIN)	
							{
							/* EAGAIN is common on keyboard inputs */
							/* but it HAPPENS ALOT */
							}
						else
							{
							printf("Disconnect read=%d i=%d errno=%d\n", bytes_read, i, errno);
							sleep(2);
							done = TRUE;
							break;
							}
						}
	
					if(key_timeout)
						{
						KeyLog(0);				/* KP_Enter */
						}
					}
				}
			}
	
		for(i = 0; i < MAX_KEY_WATCH; i++)
			{
			if(fd[0] >= 0)
				{
				close(fd[i]);
				fd[0]= -1;
				}
			}
		}
	

return(0);
}