This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/v4l-utils.git tree:
Subject: Improve it to better support IR Author: Mauro Carvalho Chehab <mche...@redhat.com> Date: Thu Mar 11 19:27:06 2010 -0300 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 <mche...@redhat.com> utils/keytable/keytable.c | 393 ++++++++++++++++++++++++++++++++++----------- 1 files changed, 302 insertions(+), 91 deletions(-) --- http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=c0f920e3c2eb81a326d2a69e3ee2887214e1688b diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c index b94ee77..5f7dbd4 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 <mche...@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; } - _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits