Add KDGETKEYSRL and KDSETKEYSRL to the console to control the soft release key mask in input_dev. Signed-off-by: Giel de Nijs --- Index: linux-2.6.21.1/drivers/char/vt_ioctl.c =================================================================== --- linux-2.6.21.1.orig/drivers/char/vt_ioctl.c 2007-05-10 19:19:32.000000000 +0200 +++ linux-2.6.21.1/drivers/char/vt_ioctl.c 2007-05-11 19:21:52.000000000 +0200 @@ -181,6 +181,29 @@ return kc; } +static int +do_kbkeysrl_ioctl(int cmd, struct kbkeysrl __user *user_kbks, int perm) +{ + struct kbkeysrl tmp; + int srl = 0; + + if (copy_from_user(&tmp, user_kbks, sizeof(struct kbkeysrl))) + return -EFAULT; + switch (cmd) { + case KDGETKEYSRL: + srl = getkeysrl(tmp.scancode); + if (srl >= 0) + srl = put_user(srl, &user_kbks->srl); + break; + case KDSETKEYSRL: + if (!perm) + return -EPERM; + srl = setkeysrl(tmp.scancode, tmp.srl); + break; + } + return srl; +} + static inline int do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) { @@ -571,6 +594,12 @@ perm=0; return do_kbkeycode_ioctl(cmd, up, perm); + case KDGETKEYSRL: + case KDSETKEYSRL: + if(!capable(CAP_SYS_TTY_CONFIG)) + perm=0; + return do_kbkeysrl_ioctl(cmd, up, perm); + case KDGKBENT: case KDSKBENT: return do_kdsk_ioctl(cmd, up, perm, kbd); Index: linux-2.6.21.1/include/linux/kbd_kern.h =================================================================== --- linux-2.6.21.1.orig/include/linux/kbd_kern.h 2007-05-10 19:20:18.000000000 +0200 +++ linux-2.6.21.1/include/linux/kbd_kern.h 2007-05-10 19:25:59.000000000 +0200 @@ -143,6 +143,8 @@ int getkeycode(unsigned int scancode); int setkeycode(unsigned int scancode, unsigned int keycode); +int getkeysrl(unsigned int scancode); +int setkeysrl(unsigned int scancode, int srl); void compute_shiftstate(void); /* defkeymap.c */ Index: linux-2.6.21.1/include/linux/kd.h =================================================================== --- linux-2.6.21.1.orig/include/linux/kd.h 2007-05-10 19:20:27.000000000 +0200 +++ linux-2.6.21.1/include/linux/kd.h 2007-05-10 19:38:52.000000000 +0200 @@ -144,6 +144,13 @@ #define KDFONTOP 0x4B72 /* font operations */ +struct kbkeysrl { + unsigned int scancode; + int srl; +}; +#define KDGETKEYSRL 0x4B82 /* read kernel soft release key table entry */ +#define KDSETKEYSRL 0x4B83 /* write kernel soft release key table entry */ + struct console_font_op { unsigned int op; /* operation code KD_FONT_OP_* */ unsigned int flags; /* KD_FONT_FLAG_* */ Index: linux-2.6.21.1/drivers/char/keyboard.c =================================================================== --- linux-2.6.21.1.orig/drivers/char/keyboard.c 2007-05-10 19:19:39.000000000 +0200 +++ linux-2.6.21.1/drivers/char/keyboard.c 2007-05-10 19:39:46.000000000 +0200 @@ -162,7 +162,7 @@ * Translation of scancodes to keycodes. We set them on only the first attached * keyboard - for per-keyboard setting, /dev/input/event is more useful. */ -int getkeycode(unsigned int scancode) +struct input_dev *find_first_keyboard(void) { struct list_head *node; struct input_dev *dev = NULL; @@ -175,6 +175,13 @@ } } + return dev; +} + +int getkeycode(unsigned int scancode) +{ + struct input_dev *dev = find_first_keyboard(); + if (!dev) return -ENODEV; @@ -186,18 +193,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode) { - struct list_head *node; - struct input_dev *dev = NULL; + struct input_dev *dev = find_first_keyboard(); unsigned int i, oldkey; - list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - if (handle->dev->keycodesize) { - dev = handle->dev; - break; - } - } - if (!dev) return -ENODEV; @@ -221,6 +219,48 @@ } /* + * Read/write the soft release bit for scancodes of a keyboard. The soft release + * bit is used to mark keys that don't generate a hardware release event. + * Here, we only handle the first attached keyboard. + */ +int getkeysrl(unsigned int scancode) +{ + struct input_dev *dev = find_first_keyboard(); + + if (!dev) + return -ENODEV; + + if (scancode >= dev->keycodemax) + return -EINVAL; + + if (!dev->keysrlmask) /* driver doesn't support soft release */ + return -EINVAL; + + return !! test_bit(scancode, dev->keysrlmask); +} + +int setkeysrl(unsigned int scancode, int srl) +{ + struct input_dev *dev = find_first_keyboard(); + + if (!dev) + return -ENODEV; + + if (scancode >= dev->keycodemax) + return -EINVAL; + + if (!dev->keysrlmask) /* driver doesn't support soft release */ + return -EINVAL; + + if (srl) + set_bit(scancode, dev->keysrlmask); + else + clear_bit(scancode, dev->keysrlmask); + + return 0; +} + +/* * Making beeps and bells. */ static void kd_nosound(unsigned long ignored) Index: linux-2.6.21.1/include/linux/compat_ioctl.h =================================================================== --- linux-2.6.21.1.orig/include/linux/compat_ioctl.h 2007-05-10 20:28:43.000000000 +0200 +++ linux-2.6.21.1/include/linux/compat_ioctl.h 2007-05-10 20:30:08.000000000 +0200 @@ -172,6 +172,8 @@ ULONG_IOCTL(KDSIGACCEPT) COMPATIBLE_IOCTL(KDGETKEYCODE) COMPATIBLE_IOCTL(KDSETKEYCODE) +COMPATIBLE_IOCTL(KDGETKEYSRL) +COMPATIBLE_IOCTL(KDSETKEYSRL) ULONG_IOCTL(KIOCSOUND) ULONG_IOCTL(KDMKTONE) COMPATIBLE_IOCTL(KDGKBTYPE) -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/