On Tue, May 24, 2011 at 1:30 PM, David Christen <davidchristen@xxxxxxxxx> wrote: > On Tue, May 24, 2011 at 8:22 AM, Dmitry Torokhov > <dmitry.torokhov@xxxxxxxxx> wrote: >> Hi David, >> >> On Mon, May 16, 2011 at 09:54:49PM +0200, David Christen wrote: >>> I have a custom made keyboard with 48 Function keys attached to an embedded >>> PC running on a RISC CPU. With hid module in the kernel the regular part of >>> the keyboard (i.e. all letters, num pad and Fxx keys up to F12) are working >>> perfectly fine. However with the additional keys I don't get any events in >>> /dev/input/event0. This is the same behavior as found on a regular Linux PC >>> and also under Windows. Although the manufacturer of the keyboard confirmed >>> that those keys do send proper HID codes (0x68 to 0x8b for F13 to F48). >>> I don't have any experience in programming on the Kernel level. Could you >>> maybe direct me in how to get the input events of those keys running? >>> >> >> Even though the usage codes are not mapped you should be able to map >> them yourself using EVIOCSKEYCODE ioctl. See udev sources for how to >> adjust keymaps on input devices. >> >> We have F1 through F24 keycode defines, but no F25-F48 (nor do I want to >> add these since userspace would not really know what to do with these, >> they are device-specific); you'll have to pick some standard ones that >> match the functions you want to assign to your extended keys. >> > > Dear Dmitry, > > Thank you for looking into this. > > I'm trying to figure out how to use udev for this. Just to make sure > that my problem was described correctly. My issue is not the mapping > from the scancode to the keycode, but that I don't get any scancode at > all. If I look at the output of usbmon, in particular the rdesc file, > I get > > ==== > Keyboard.0063 ---> Key.KPDot > Keyboard.0064 ---> Key.102nd > Keyboard.0065 ---> Key.Compose > LED.NumLock ---> LED.NumLock > LED.CapsLock ---> LED.CapsLock > LED.ScrollLock ---> LED.ScrollLock > (eof) > ==== > > Looking at the output of my standard Logitech keyboard, this would be > exactly what I would need: > > ==== > Keyboard.0080 ---> Key.VolumeUp > Keyboard.0081 ---> Key.VolumeDown > Keyboard.0082 ---> Key.Unknown > Keyboard.0083 ---> Key.Unknown > Keyboard.0084 ---> Key.Unknown > Keyboard.0085 ---> Key.KPComma > Keyboard.0086 ---> Key.Unknown > Keyboard.0087 ---> Key.RO > Keyboard.0088 ---> Key.Katakana/Hiragana > Keyboard.0089 ---> Key.Yen > Keyboard.008a ---> Key.Henkan > Keyboard.008b ---> Key.Muhenkan > Keyboard.008c ---> Key.KPJpComma > Keyboard.008d ---> Key.Unknown > Keyboard.008e ---> Key.Unknown > Keyboard.008f ---> Key.Unknown > Keyboard.0090 ---> Key.Hangeul > Keyboard.0091 ---> Key.Hanja > (eof) > ==== > > Even better would be to use a keymap without any Key.Unknown in the > range 0x6b - 0x8b. The exact keycode is not relevant to me as long as > they are unique. I translate them immediately to some other codes and > send them to the serial port. > > So is there an easy way to select which keymap should be loaded? Below > is the output when the keyboard is being attached: > > ==== > usb 2-1: new full speed USB device using uhci_hcd and address 9 > usb 2-1: New USB device found, idVendor=03eb, idProduct=2003 > usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 > usb 2-1: Product: USB Foil Keyboard Controller 32 12 885 > usb 2-1: Manufacturer: GESYS > input: GESYS USB Foil Keyboard Controller 32 12 885 as /class/input/input11 > generic-usb 0003:03EB:2003.000C: input,hidraw0: USB HID v1.11 Keyboard > [GESYS USB Foil Keyboard Controller 32 12 885] on > usb-0000:00:06.0-1/input0 > ==== > > as opposed to the logitech keyboard: > > ==== > usb 2-1: new low speed USB device using uhci_hcd and address 10 > usb 2-1: New USB device found, idVendor=046d, idProduct=c30e > usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 > usb 2-1: Product: HID compliant keyboard > usb 2-1: Manufacturer: Logitech > input: Logitech HID compliant keyboard as /class/input/input12 > generic-usb 0003:046D:C30E.000D: input,hidraw0: USB HID v1.10 Keyboard > [Logitech HID compliant keyboard] on usb-0000:00:06.0-1/input0 > input: Logitech HID compliant keyboard as /class/input/input13 > generic-usb 0003:046D:C30E.000E: input,hidraw1: USB HID v1.10 Device > [Logitech HID compliant keyboard] on usb-0000:00:06.0-1/input1 > ==== > > Thank you, > David > Dear Dmitry, I'm starting to feel stupid. I tried a simple code doing some ioctl calls using EVIOCSKEYCODE and EVIOCGKEYCODE. But it does not appear to work. If I run it using ./ioctl-test /dev/input/event0 I get lots of complains about wrong arguments: ==== evdev ioctl: Invalid argument [0]= 125, [1] = 0 evdev ioctl: Invalid argument [0]= 126, [1] = 0 evdev ioctl: Invalid argument [0]= 127, [1] = 0 evdev ioctl: Invalid argument [0]= 128, [1] = 0 evdev ioctl: Invalid argument [0]= 129, [1] = 0 evdev ioctl: Invalid argument Testing changes evdev ioctl: Invalid argument [0]= 49, [1] = 49 evdev ioctl: Invalid argument [0]= 50, [1] = 49 ==== Sorry for bothering you with this but I haven't found a lot of information on this on the web. Best regards, David
#include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <fcntl.h> #include <linux/input.h> #include <linux/serial.h> #include <errno.h> #include <unistd.h> #include <termios.h> #include <string.h> #include <linux/input.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/time.h> #include <sys/stat.h> int main (int argc, char *argv[]) { int i, fd, ret; struct input_event ev[64]; if ((fd = open(argv[1], O_RDWR)) < 0) { perror("Couldn't open input device"); return 1; } int version; if (ioctl(fd, EVIOCGVERSION, &version)) { perror("evdev ioctl"); } /* the EVIOCGVERSION ioctl() returns an int */ /* so we unpack it and display it */ printf("evdev driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff); int codes[2]; for (i=0; i<130; i++) { codes[0] = i; if(ioctl(fd, EVIOCSKEYCODE, codes)) { perror("evdev ioctl"); } printf("[0]= %d, [1] = %d\n", codes[0], codes[1]); } codes[0] = 58; /* M keycap */ codes[1] = 49; /* assign to N */ if(ioctl(fd, EVIOCSKEYCODE, codes)) { perror("evdev ioctl"); } printf("Testing changes\n"); for (i=49; i<60; i++) { codes[0] = i; if(ioctl(fd, EVIOCSKEYCODE, codes)) { perror("evdev ioctl"); } printf("[0]= %d, [1] = %d\n", codes[0], codes[1]); } return 0; }