aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2010-03-11 19:27:06 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-03-11 19:32:19 -0300
commitc0f920e3c2eb81a326d2a69e3ee2887214e1688b (patch)
tree3a75023ef3ea57ee269d9089ae0b78263763f567
parent2df0dfa279ee3b04ab0db0d8bceb831b86708b5a (diff)
Improve it to better support IR
This patch improves the tool by adding the capability to autodetect the IR device, based on sysfs class. It also adds a proper parameter handling to give more flexibility to the tool. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--utils/keytable/keytable.c393
1 files changed, 302 insertions, 91 deletions
diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index b94ee77a..5f7dbd49 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -20,9 +20,187 @@
#include <string.h>
#include <linux/input.h>
#include <sys/ioctl.h>
+#include <dirent.h>
+#include <argp.h>
#include "parse.h"
+struct keytable {
+ int codes[2];
+ struct keytable *next;
+};
+
+static int parse_code(char *string)
+{
+ struct parse_key *p;
+
+ for (p = keynames; p->name != NULL; p++) {
+ if (!strcasecmp(p->name, string))
+ return p->value;
+ }
+ return -1;
+}
+
+const char *argp_program_version = "IR keytable control version 0.1.0";
+const char *argp_program_bug_address = "Mauro Carvalho Chehab <mchehab@redhat.com>";
+
+static const char doc[] = "\nAllows get/set IR keycode/scancode tables\n"
+ "You need to have read permissions on /dev/input for the program to work\n"
+ "\nOn the options bellow, the arguments are:\n"
+ " DEV - the /dev/input/event* device to control\n"
+ " SYSDEV - the ir class as found at /sys/class/irrcv\n"
+ " TABLE - a file wit a set of scancode=keycode value pairs\n"
+ " SCANKEY - a set of scancode1=keycode1,scancode2=keycode2.. value pairs\n";
+
+static const struct argp_option options[] = {
+ {"verbose", 'v', 0, 0, "enables debug messages", 0},
+ {"clear", 'c', 0, 0, "clears the old table", 0},
+ {"sysdev", 's', "SYSDEV", 0, "ir class device to control", 0},
+ {"device", 'd', "DEV", 0, "ir device to control", 0},
+ {"get-table", 'g', 0, 0, "reads the current scancode/keycode table", 0},
+ {"put-table", 'p', "TABLE", 0, "adds/replaces the scancodes to a new scancode/keycode table", 0},
+ {"set-key", 'k', "SCANKEY", 0, "Change scan/key pairs", 0},
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+static const char args_doc[] =
+ "--device [/dev/input/event* device]\n"
+ "--sysdev [ir class (f. ex. irrcv0)]\n"
+ "[for using the irrcv0 sysdev]";
+
+
+static char *devclass = "irrcv0";
+static char *devname = NULL;
+static int read = 0;
+static int clear = 0;
+static int debug = 0;
+
+struct keytable keys = {
+ {0, 0}, NULL
+};
+
+struct keytable *nextkey = &keys;
+
+static error_t parse_keyfile(char *fname)
+{
+ FILE *fin;
+ int value;
+ char *scancode, *keycode, s[2048];
+
+ fin = fopen(fname, "r");
+ if (!fin) {
+ perror("opening keycode file");
+ return errno;
+ }
+
+ while (fgets(s, sizeof(s), fin)) {
+ scancode = strtok(s, "\n\t =:");
+ if (!scancode) {
+ perror ("parsing input file scancode");
+ return EINVAL;
+ }
+ if (!strcasecmp(scancode, "scancode")) {
+ scancode = strtok(NULL,"\n\t =:");
+ if (!scancode) {
+ perror ("parsing input file scancode");
+ return EINVAL;
+ }
+ }
+
+ keycode=strtok(NULL, "\n\t =:(");
+ if (!keycode) {
+ perror("parsing input file keycode");
+ return EINVAL;
+ }
+
+ if (debug)
+ fprintf(stderr, "parsing %s=%s:", scancode, keycode);
+ value=parse_code(keycode);
+ if (debug)
+ fprintf(stderr, "\tvalue=%d\n",value);
+
+ if (value == -1) {
+ value = strtol(keycode, NULL, 0);
+ if (errno)
+ perror("value");
+ }
+
+ nextkey->codes[0] = (unsigned) strtol(scancode, NULL, 0);
+ nextkey->codes[1] = (unsigned) value;
+ nextkey->next = calloc(1, sizeof(keys));
+ if (!nextkey->next)
+ return ENOMEM;
+ nextkey = nextkey->next;
+ }
+ fclose(fin);
+
+ return 0;
+}
+
+static error_t parse_opt (int k, char *arg, struct argp_state *state)
+{
+ char *p;
+ long key;
+
+ switch (k) {
+ case 'v':
+ debug++;
+ break;
+ case 'c':
+ clear++;
+ break;
+ case 'd':
+ devname=arg;
+ break;
+ case 's':
+ devclass=arg;
+ break;
+ case 'g':
+ read++;
+ break;
+ case 'p':
+ return parse_keyfile(arg);
+ case 'k':
+ p = strtok(arg, ":=");
+ do {
+ if (!p)
+ return EINVAL;
+ nextkey->codes[0] = strtol(p, NULL, 0);
+ if (errno)
+ return EINVAL;
+
+ p = strtok(NULL, ",;");
+ if (!p)
+ return EINVAL;
+ key = parse_code(p);
+ if (key == -1) {
+ key = strtol(p, NULL, 0);
+ if (errno)
+ return EINVAL;
+ }
+ nextkey->codes[1] = key;
+
+ nextkey->next = calloc(1, sizeof(keys));
+ if (!nextkey->next)
+ return ENOMEM;
+ nextkey = nextkey->next;
+
+ p = strtok(NULL, ":=");
+ } while (p);
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp argp = {
+ .options = options,
+ .parser = parse_opt,
+ .args_doc = args_doc,
+ .doc = doc,
+};
+
static void prtcode (int *codes)
{
struct parse_key *p;
@@ -40,68 +218,108 @@ static void prtcode (int *codes)
printf("scancode %d = 0x%02x\n", codes[0], codes[1]);
}
-static int parse_code(char *string)
+static char *find_device(void)
{
- struct parse_key *p;
+ DIR *dir;
+ struct dirent *entry;
+ FILE *fp;
+ char dname[256], *event = "event", *name = NULL;
+ char s[256];
+ int found = 0;
+ char *DEV = "/dev/";
- for (p=keynames;p->name!=NULL;p++) {
- if (!strcasecmp(p->name, string)) {
- return p->value;
- }
+ /*
+ * Get event sysfs node
+ */
+ snprintf(dname, sizeof(dname) - 30, "/sys/class/irrcv/%s/input/",
+ devclass);
+ dir = opendir(dname);
+ if (!dir) {
+ perror(dname);
+ return NULL;
}
- return -1;
-}
-
-int main (int argc, char *argv[])
-{
- int fd;
- unsigned int i, j;
- int codes[2];
- if (argc<2 || argc>4) {
- printf ("usage: %s <device> to get table; or\n"
- " %s <device> <scancode> <keycode>\n"
- " %s <device> <keycode_file>\n",*argv,*argv,*argv);
- return -1;
+ entry = readdir(dir);
+ while (entry) {
+ if (!strncmp(entry->d_name, event, strlen(event))) {
+ strcat(dname, entry->d_name);
+ found = 1;
+ break;
+ }
+ entry = readdir(dir);
}
+ closedir(dir);
- if ((fd = open(argv[1], O_RDONLY)) < 0) {
- perror("Couldn't open input device");
- return(-1);
+ if (!found) {
+ fprintf(stderr, "Couldn't find event device. Too old driver?");
+ return NULL;
}
+ if (debug)
+ fprintf(stderr, "Event sysfs node is %s\n", dname);
- if (argc==4) {
- int value;
-
- value=parse_code(argv[3]);
+ strcat(dname, "/uevent");
- if (value==-1) {
- value = strtol(argv[3], NULL, 0);
- if (errno)
- perror("value");
+ fp = fopen (dname, "r");
+ if (!fp) {
+ perror (dname);
+ return NULL;
+ }
+ while (fgets(s, sizeof(s), fp)) {
+ char *p = strtok(s, "=");
+ if (!strcmp(p, "DEVNAME")) {
+ p = strtok(NULL, "\n");
+ if (!p) {
+ fprintf(stderr, "Error on uevent information\n");
+ fclose (fp);
+ return NULL;
+ }
+ name = malloc(strlen(p) + sizeof(DEV) + 1);
+ if (!name) {
+ fprintf(stderr, "No memory\n");
+ fclose (fp);
+ return NULL;
+ }
+ strcpy(name, DEV);
+ strcat(name, p);
+ break;
}
+ }
+ fclose (fp);
- codes [0] = (unsigned) strtol(argv[2], NULL, 0);
- codes [1] = (unsigned) value;
+ if (debug)
+ fprintf(stderr, "input device is %s\n", name);
- if(ioctl(fd, EVIOCSKEYCODE, codes))
- perror ("EVIOCSKEYCODE");
+ return name;
+}
- if(ioctl(fd, EVIOCGKEYCODE, codes)==0)
- prtcode(codes);
- return 0;
- }
+int main (int argc, char *argv[])
+{
+ int fd;
+ unsigned int i, j;
+ int dev_from_class = 0, done = 0;
- if (argc==3) {
- FILE *fin;
- int value;
- char *scancode, *keycode, s[2048];
+ argp_parse (&argp, argc, argv, 0, 0, 0);
- fin=fopen(argv[2],"r");
- if (fin==NULL) {
- perror ("opening keycode file");
+ if (!devname) {
+ devname = find_device();
+ if (!devname)
return -1;
- }
+ dev_from_class++;
+ }
+ if (debug)
+ fprintf(stderr, "Opening %s\n",devname);
+ if ((fd = open(devname, O_RDONLY)) < 0) {
+ perror(devname);
+ return -1;
+ }
+ if (dev_from_class)
+ free(devname);
+
+ /*
+ * First step: clear, if --clear is specified
+ */
+ if (clear) {
+ int codes[2];
/* Clears old table */
for (j = 0; j < 256; j++) {
@@ -111,60 +329,53 @@ int main (int argc, char *argv[])
ioctl(fd, EVIOCSKEYCODE, codes);
}
}
+ done++;
+ }
- while (fgets(s,sizeof(s),fin)) {
- scancode=strtok(s,"\n\t =:");
- if (!scancode) {
- perror ("parsing input file scancode");
- return -1;
- }
- if (!strcasecmp(scancode, "scancode")) {
- scancode = strtok(NULL,"\n\t =:");
- if (!scancode) {
- perror ("parsing input file scancode");
- return -1;
- }
- }
-
- keycode=strtok(NULL,"\n\t =:(");
- if (!keycode) {
- perror ("parsing input file keycode");
- return -1;
- }
+ /*
+ * Second step: stores key tables from file or from commandline
+ */
+ nextkey = &keys;
+ while (nextkey->next) {
+ int value;
+ struct keytable *old;
- // printf ("parsing %s=%s:", scancode, keycode);
- value=parse_code(keycode);
- // printf ("\tvalue=%d\n",value);
+ if (debug)
+ fprintf(stderr, "\t%04x=%04x\n",
+ nextkey->codes[0], nextkey->codes[1]);
- if (value==-1) {
- value = strtol(keycode, NULL, 0);
- if (errno)
- perror("value");
- }
+ if (ioctl(fd, EVIOCSKEYCODE, nextkey->codes)) {
+ fprintf(stderr,
+ "Setting scancode 0x%04x with 0x%04x via ",
+ nextkey->codes[0], nextkey->codes[1]);
+ perror ("EVIOCSKEYCODE");
+ }
+ old = nextkey;
+ nextkey = nextkey->next;
+ if (old != &keys)
+ free(old);
+ done++;
+ }
- codes [0] = (unsigned) strtol(scancode, NULL, 0);
- codes [1] = (unsigned) value;
+ /*
+ * Third step: display current keytable
+ */
+ if (read) {
+ done++;
+ for (j = 0; j < 256; j++) {
+ for (i = 0; i < 256; i++) {
+ int codes[2];
- // printf("\t%04x=%04x\n",codes[0], codes[1]);
- if(ioctl(fd, EVIOCSKEYCODE, codes)) {
- fprintf(stderr, "Setting scancode 0x%04x with 0x%04x via ",codes[0], codes[1]);
- perror ("EVIOCSKEYCODE");
+ codes[0] = (j << 8) | i;
+ if (!ioctl(fd, EVIOCGKEYCODE, codes) && codes[1] != KEY_RESERVED)
+ prtcode(codes);
}
-
- if(ioctl(fd, EVIOCGKEYCODE, codes)==0)
- prtcode(codes);
}
- return 0;
}
- /* Get scancode table */
- for (j = 0; j < 256; j++) {
- for (i = 0; i < 256; i++) {
- codes[0] = (j << 8) | i;
- if (!ioctl(fd, EVIOCGKEYCODE, codes) && codes[1] != KEY_RESERVED)
- prtcode(codes);
- }
+ if (!done) {
+ argp_help(&argp, stderr, ARGP_HELP_SEE, argv[0]);
}
+
return 0;
}
-

Privacy Policy