/* kbstate.c - detect keyboard states from shell
 * jamesbond 2013
 * originally from: http://stackoverflow.com/questions/3649874/how-to-get-keyboard-state-in-linux
 * License: Public Domain
 */
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>

#define pprint(x) (write(1, x, strlen(x)))
#define BAD_PARM 255

//// globals ////
char key_map[KEY_MAX/8 + 1];    //  Create a byte array the size of the number of keys
char *kbd_device = "/dev/input/by-path/platform-i8042-serio-0-event-kbd"; //default
int key;

//// accepted keys ////
int get_keycode_from_keyname (char *keyname) {
	int key = -1;
	
    if ( strcmp(keyname, "lshift") == 0 )       key = KEY_LEFTSHIFT;
    else if ( strcmp(keyname, "rshift") == 0 )  key = KEY_RIGHTSHIFT;
    else if ( strcmp(keyname, "lalt") == 0 )    key = KEY_LEFTALT;
    else if ( strcmp(keyname, "ralt") == 0 )    key = KEY_RIGHTALT;
    else if ( strcmp(keyname, "lctrl") == 0 )   key = KEY_LEFTCTRL;
    else if ( strcmp(keyname, "rctrl") == 0 )   key = KEY_RIGHTCTRL;
    return key;
}

///////////////// main ////////////////////
int main ( int argc, char *argv[], char *env[] )
{
    if ( argc < 2 ) {
		pprint ("Usage: "); pprint (argv[0]);
		pprint (" key [devpath]\n");
		pprint ("Valid keys are lshift/rshift/lalt/ralt/lctrl/rctrl\n");
		return BAD_PARM;
	}
	
    memset(key_map, 0, sizeof(key_map));    //  Initate the array to zeros
    key = get_keycode_from_keyname (argv[1]);
    if (key == -1) {
		pprint ("Invalid key "); pprint (argv[1]); pprint ("\n");
		return BAD_PARM;
	}
    
    if (argc == 3) kbd_device = argv[2];
    int kbdfd = open (kbd_device, O_RDONLY);
    if (kbdfd == -1) {
		pprint ("Can't open "); pprint (kbd_device); pprint ("\n");
		return BAD_PARM;
	}

    ioctl(kbdfd, EVIOCGKEY(sizeof(key_map)), key_map);    //  Fill the keymap with the current keyboard state
    close (kbdfd);

    int keyb = key_map[key/8];  //  The key we want (and the seven others arround it)
    int mask = 1 << (key % 8);  //  Put a one in the same column as out key state will be in;
    return !(keyb & mask);  	//  Returns true if pressed otherwise false
}
