[BRLTTY] Proof of concept code: Filter keyboard keypresses on Linux
Samuel Thibault
samuel.thibault at ens-lyon.org
Sat Dec 15 11:24:37 EST 2007
Mario Lang, le Sat 15 Dec 2007 17:17:47 +0100, a écrit :
> As usual, I am not the best code designer,
Nobody is :)
> so some starting help for getting this into brltty core would
> be very appreciated? Dave?
>
> P.S.: The following code checks for a specific keyboard.
> We will of course want to do something much more generic here,
> like test for a keyboard that actually has the keys we'd like to watch out for.
> The function has_event() can be used to do this, a call like
> has_event(filedescriptor, EV_KEY, KEY_ESC) will return 1 if the keyboard
> associated with filedescriptor does have an ESC key...
>
> #include <dirent.h>
> #include <fcntl.h>
> #include <linux/input.h>
> #include <linux/uinput.h>
> #include <stdio.h>
> #include <string.h>
> #include <sys/stat.h>
> #include <sys/types.h>
> #include <unistd.h>
>
> static int
> has_event(int fd, unsigned short type, unsigned short code)
> {
> #define MAX(a,b) a>b?a:b
> const unsigned int len = sizeof(unsigned long)*8;
> const unsigned int max = MAX(EV_MAX,
> MAX(KEY_MAX,
> MAX(REL_MAX,
> MAX(ABS_MAX,
> MAX(LED_MAX,
> MAX(SND_MAX, FF_MAX))))));
> unsigned long bits[(max+len-1)/len];
> if (ioctl(fd, EVIOCGBIT(type, max), bits)) {
> return (bits[code/len] >> (code%len)) & 1;
> }
> return 0;
> #undef MAX
> }
>
> static int
> constructKeyboard (char *name, struct input_id *id, unsigned long *keymask)
> {
> int fd;
> if ((fd = open("/dev/input/uinput", O_WRONLY)) > 0) {
> struct uinput_user_dev description;
>
> memset(&description, 0, sizeof(description));
> strncpy(description.name, name, UINPUT_MAX_NAME_SIZE);
> memcpy(&description.id, id, sizeof(description.id));
> if (write(fd, &description, sizeof(description)) == sizeof(description)) {
> int key;
>
> ioctl(fd, UI_SET_EVBIT, EV_KEY);
> ioctl(fd, UI_SET_EVBIT, EV_REP);
>
> for (key=KEY_RESERVED; key<=KEY_MAX; key++) {
> if ((keymask[key/(sizeof(unsigned long)*8)] >> (key%(sizeof(unsigned long)*8)))&1) {
> ioctl(fd, UI_SET_KEYBIT, key);
> }
> }
> if (ioctl(fd, UI_DEV_CREATE) != -1) {
> return fd;
> } else {
> perror("ioctl UI_DEV_CREATE");
> }
> } else {
> perror("write (struct uinput_user_dev)");
> }
> } else {
> perror("open /dev/input/uinput");
> }
> return -1;
> }
>
> int
> main(int argc, char *argv[])
> {
> char root[] = "/dev/input";
> int rootLength = strlen(root);
> int foundKeyboard = 0;
> DIR *directory;
>
> if ((directory = opendir(root))) {
> struct dirent *entry;
>
> while ((entry = readdir(directory))) {
> size_t nameLength = strlen(entry->d_name);
> struct stat status;
> char path[rootLength + 1 + nameLength + 1];
>
> snprintf(path, sizeof(path), "%s/%s", root, entry->d_name);
> if (stat(path, &status) == -1) continue;
> if (S_ISCHR(status.st_mode)) {
> int fd;
>
> if ((fd = open(path, O_RDONLY)) > 0) {
> struct input_id id;
>
> if (ioctl(fd, EVIOCGID, &id) != -1) {
> if (id.bustype == 3 &&
> id.vendor == 0X0430 && id.product == 0X0005 &&
> has_event(fd, EV_KEY, KEY_HELP)) {
> unsigned long keymask[(KEY_MAX+(sizeof(unsigned long)*8)-1)/(sizeof(unsigned long)*8)];
> struct input_event event;
>
> foundKeyboard = 1;
>
> if (ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX), keymask)) {
> int uinput = constructKeyboard("test", &id, keymask);
>
> if (uinput != -1) {
> ioctl(fd, EVIOCGRAB, 1);
> while (read(fd, &event, sizeof(event)) == sizeof(event)) {
> if (event.type == EV_KEY) {
> switch (event.code) {
> case KEY_MUTE:
> printf("MUTE %s\n", event.value ? "press":"release");
> break;
> case KEY_VOLUMEDOWN:
> printf("VOLUMEDOWN %s\n", event.value ? "press":"release");
> break;
> case KEY_VOLUMEUP:
> printf("VOLUMEUP %s\n", event.value ? "press":"release");
> break;
> case KEY_POWER:
> printf("POWER %s\n", event.value ? "press":"release");
> break;
> case KEY_STOP:
> printf("STOP %s\n", event.value ? "press":"release");
> break;
> case KEY_AGAIN:
> printf("AGAIN %s\n", event.value ? "press":"release");
> break;
> case KEY_PROPS:
> printf("PROPS %s\n", event.value ? "press":"release");
> break;;
> case KEY_UNDO:
> printf("UNDO %s\n", event.value ? "press":"release");
> break;;
> default:
> write(uinput, &event, sizeof(event));
> printf("%d = %d\n", event.code, event.value);
> }
> }
> }
>
> ioctl(fd, EVIOCGRAB, 0);
> close(uinput);
> }
> }
> }
> }
> close(fd);
> }
> }
> }
> closedir(directory);
>
> if (!foundKeyboard) {
> printf("No supported USB keyboard found.\n");
> }
> } else {
> fprintf(stderr, "Unable to open %s\n", root);
> }
> return 0;
> }
>
>
> --
> CYa,
> Mario | Debian Developer <URL:http://debian.org/>
> .''`. | Get my public key via finger mlang at db.debian.org
> : :' : | 1024D/7FC1A0854909BCCDBE6C102DDFFC022A6B113E44
> `. `'
> `- <URL:http://delysid.org/> <URL:http://www.staff.tugraz.at/mlang/>
> _______________________________________________
> This message was sent via the BRLTTY mailing list.
> To post a message, send an e-mail to: BRLTTY at mielke.cc
> For general information, go to: http://mielke.cc/mailman/listinfo/brltty
>
--
Samuel
"c'est pas nous qui sommes à la rue, c'est la rue qui est à nous"
More information about the BRLTTY
mailing list