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); }
On Tue, Sep 18, 2007 at 01:41:32PM -0400, Jerry Geis alleged:
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.
Correct. EAGAIN is how you distinguish between a "real" error, and a normal nonblocking return.
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.
Typically, one opens the file or files and passes the file descriptors to select(2) or poll(2) to determine when they are ready for reading or writing. select(2) and poll(2) can do a neat idle for you.