aboutsummaryrefslogtreecommitdiffstats
path: root/input-kbd.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2004-04-21 11:55:44 +0000
committerkraxel <kraxel>2004-04-21 11:55:44 +0000
commitc4d7dacb41039e087d20b8889a4d13bd4c9928f2 (patch)
tree0aef1f53f2e8cd55c4db8915d9d9a1265dd97adc /input-kbd.c
downloadinput-c4d7dacb41039e087d20b8889a4d13bd4c9928f2.tar.gz
Initial revision
Diffstat (limited to 'input-kbd.c')
-rw-r--r--input-kbd.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/input-kbd.c b/input-kbd.c
new file mode 100644
index 0000000..fbe3f27
--- /dev/null
+++ b/input-kbd.c
@@ -0,0 +1,260 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/select.h>
+
+#include "input.h"
+
+struct kbd_entry {
+ int scancode;
+ int keycode;
+};
+
+struct kbd_map {
+ struct kbd_entry *map;
+ int keys;
+ int size;
+ int alloc;
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct kbd_map* kbd_map_read(int fd)
+{
+ struct kbd_entry entry;
+ struct kbd_map *map;
+ int rc;
+
+ map = malloc(sizeof(*map));
+ memset(map,0,sizeof(*map));
+ for (map->size = 0; map->size < 65536; map->size++) {
+ entry.scancode = map->size;
+ entry.keycode = KEY_RESERVED;
+ rc = ioctl(fd, EVIOCGKEYCODE, &entry);
+ if (rc < 0) {
+ map->size--;
+ break;
+ }
+ if (map->size >= map->alloc) {
+ map->alloc += 64;
+ map->map = realloc(map->map, map->alloc * sizeof(entry));
+ }
+ map->map[map->size] = entry;
+
+ if (KEY_RESERVED != entry.keycode)
+ map->keys++;
+ }
+ if (map->keys) {
+ fprintf(stderr,"map: %d keys, size: %d/%d\n",
+ map->keys, map->size, map->alloc);
+ return map;
+ } else {
+ free(map);
+ return NULL;
+ }
+}
+
+static int kbd_map_write(int fh, struct kbd_map *map)
+{
+ int i,rc;
+
+ for (i = 0; i < map->size; i++) {
+ rc = ioctl(fh, EVIOCSKEYCODE, &map->map[i]);
+ if (0 != rc) {
+ fprintf(stderr,"ioctl EVIOCSKEYCODE(%d,%d): %s\n",
+ map->map[i].scancode,map->map[i].keycode,
+ strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void kbd_key_print(FILE *fp, int scancode, int keycode)
+{
+ fprintf(fp, "0x%04x = %3d # %s\n",
+ scancode, keycode, key_name(keycode));
+}
+
+static void kbd_map_print(FILE *fp, struct kbd_map *map, int complete)
+{
+ int i;
+
+ for (i = 0; i < map->size; i++) {
+ if (!complete && KEY_RESERVED == map->map[i].keycode)
+ continue;
+ kbd_key_print(fp,map->map[i].scancode,map->map[i].keycode);
+ }
+}
+
+static int kbd_map_parse(FILE *fp, struct kbd_map *map)
+{
+ struct kbd_entry entry;
+ char line[80],scancode[80],keycode[80];
+ int i;
+
+ while (NULL != fgets(line,sizeof(line),fp)) {
+ if (2 != sscanf(line," %80s = %80s", scancode, keycode)) {
+ fprintf(stderr,"parse error: %s",line);
+ return -1;
+ }
+
+ /* parse scancode */
+ if (0 == strncasecmp(scancode,"0x",2)) {
+ entry.scancode = strtol(scancode, NULL, 16);
+ } else {
+ entry.scancode = strtol(scancode, NULL, 10);
+ }
+ if (entry.scancode < 0 ||
+ entry.scancode >= map->size) {
+ fprintf(stderr,"scancode %d out of range (0-%d)\n",
+ entry.scancode,map->size);
+ return -1;
+ }
+
+ /* parse keycode */
+ for (i = 0; i < KEY_MAX; i++) {
+ if (!KEY_NAME[i])
+ continue;
+ if (0 == strcmp(keycode,KEY_NAME[i]))
+ break;
+ }
+ if (i == KEY_MAX)
+ entry.keycode = atoi(keycode);
+ else
+ entry.keycode = i;
+
+ fprintf(stderr,"set: ");
+ kbd_key_print(stderr,entry.scancode,entry.keycode);
+ map->map[entry.scancode] = entry;
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static void kbd_print_bits(int fd)
+{
+ BITFIELD bits[KEY_MAX/sizeof(BITFIELD)];
+ int rc,bit;
+
+ rc = ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(bits)),bits);
+ if (rc < 0)
+ return;
+ for (bit = 0; bit < rc*8 && bit < KEY_MAX; bit++) {
+ if (!test_bit(bit,bits))
+ continue;
+ if (KEY_NAME[bit]) {
+ fprintf(stderr,"bits: %s\n", KEY_NAME[bit]);
+ } else {
+ fprintf(stderr,"bits: unknown [%d]\n", bit);
+ }
+ }
+}
+
+static void show_kbd(int nr)
+{
+ struct kbd_map *map;
+ int fd;
+
+ fd = device_open(nr,1);
+ if (-1 == fd)
+ return;
+ device_info(fd);
+
+ map = kbd_map_read(fd);
+ if (NULL != map) {
+ kbd_map_print(stdout,map,0);
+ } else {
+ kbd_print_bits(fd);
+ }
+
+ close(fd);
+}
+
+static int set_kbd(int nr, char *mapfile)
+{
+ struct kbd_map *map;
+ FILE *fp;
+ int fd;
+
+ fd = device_open(nr,1);
+ if (-1 == fd)
+ return -1;
+
+ map = kbd_map_read(fd);
+ if (NULL == map) {
+ fprintf(stderr,"device has no map\n");
+ close(fd);
+ return -1;
+ }
+
+ if (0 == strcmp(mapfile,"-"))
+ fp = stdin;
+ else {
+ fp = fopen(mapfile,"r");
+ if (NULL == fp) {
+ fprintf(stderr,"open %s: %s\n",mapfile,strerror(errno));
+ close(fd);
+ return -1;
+ }
+ }
+
+ if (0 != kbd_map_parse(fp,map) ||
+ 0 != kbd_map_write(fd,map)) {
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static int usage(char *prog, int error)
+{
+ fprintf(error ? stderr : stdout,
+ "usage: %s [ -f file ] devnr\n",
+ prog);
+ exit(error);
+}
+
+int main(int argc, char *argv[])
+{
+ int c,devnr;
+ char *mapfile = NULL;
+
+ for (;;) {
+ if (-1 == (c = getopt(argc, argv, "hf:")))
+ break;
+ switch (c) {
+ case 'f':
+ mapfile = optarg;
+ break;
+ case 'h':
+ usage(argv[0],0);
+ default:
+ usage(argv[0],1);
+ }
+ }
+
+ if (optind == argc)
+ usage(argv[0],1);
+
+ devnr = atoi(argv[optind]);
+ if (mapfile) {
+ set_kbd(devnr,mapfile);
+ } else {
+ show_kbd(devnr);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */