From patchwork Sat Jul 31 09:19:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 116169 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o6V9JusN000993 for ; Sat, 31 Jul 2010 09:19:56 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752713Ab0GaJTq (ORCPT ); Sat, 31 Jul 2010 05:19:46 -0400 Received: from mail-pw0-f46.google.com ([209.85.160.46]:37565 "EHLO mail-pw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752146Ab0GaJTm (ORCPT ); Sat, 31 Jul 2010 05:19:42 -0400 Received: by pwi5 with SMTP id 5so829182pwi.19 for ; Sat, 31 Jul 2010 02:19:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:mime-version:content-type:content-disposition:user-agent; bh=+PfLuwOOmS0//KZsPCmM3ZiPJk9gBNG/97YtBaNiAyM=; b=dckUR2qDYPAaDpbyCdP0xwKVFEDnmZzeU2EykKxlrHWHy2AGJIDIMjnFrUPOaZ5Uio OY4yuC4U9QnpuIE8QTGkXjQw26zXcjlUgzZtpeBq7wD0hM5m6fuvCNRLKwjhJPS4S7Qd Wvnh8hJmgK+1wvGTBcu9HGnyIMLpkzI7BnuX0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; b=sTmpiSbSLXRTh84Fm1MT6GFGY2Uph9aK9Qx8riSp78IRiXTTr625uygvlphGyeh/8R F6yWFBwHn5YN5wKF8WnQS4aDthDHZAe9t+rFCV1JheSRScn4lY6Ek9CGs7RBo33mKY/+ i/PCz7fIFiQhVnfah5gBPituQ2IOVPB9956fs= Received: by 10.142.148.2 with SMTP id v2mr2768340wfd.205.1280567981943; Sat, 31 Jul 2010 02:19:41 -0700 (PDT) Received: from mailhub.coreip.homeip.net (c-24-6-153-206.hsd1.ca.comcast.net [24.6.153.206]) by mx.google.com with ESMTPS id v38sm3915028wfh.0.2010.07.31.02.19.39 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 31 Jul 2010 02:19:40 -0700 (PDT) Date: Sat, 31 Jul 2010 02:19:36 -0700 From: Dmitry Torokhov To: Mauro Carvalho Chehab Cc: Linux Input , linux-media@vger.kernel.org, Jarod Wilson , Maxim Levitsky , David =?iso-8859-1?Q?H=E4rdeman?= Subject: Handling of large keycodes Message-ID: <20100731091936.GA22253@core.coreip.homeip.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-12-10) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sat, 31 Jul 2010 09:19:57 +0000 (UTC) diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 54109dc..4dd9fb0 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier); */ struct getset_keycode_data { - unsigned int scancode; - unsigned int keycode; + struct keymap_entry ke; int error; }; @@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data) { struct getset_keycode_data *d = data; - d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode); + d->error = input_get_keycode(handle->dev, &d->ke); return d->error == 0; /* stop as soon as we successfully get one */ } int getkeycode(unsigned int scancode) { - struct getset_keycode_data d = { scancode, 0, -ENODEV }; + struct getset_keycode_data d = { + .ke = { + .by_index = false, + .len = sizeof(scancode), + .keycode = 0, + }, + .error = -ENODEV, + }; + + memcpy(d.ke.scancode, &scancode, sizeof(scancode)); input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); - return d.error ?: d.keycode; + return d.error ?: d.ke.keycode; } static int setkeycode_helper(struct input_handle *handle, void *data) { struct getset_keycode_data *d = data; - d->error = input_set_keycode(handle->dev, d->scancode, d->keycode); + d->error = input_set_keycode(handle->dev, &d->ke); return d->error == 0; /* stop as soon as we successfully set one */ } int setkeycode(unsigned int scancode, unsigned int keycode) { - struct getset_keycode_data d = { scancode, keycode, -ENODEV }; + struct getset_keycode_data d = { + .ke = { + .by_index = false, + .len = sizeof(scancode), + .keycode = keycode, + }, + .error = -ENODEV, + }; + + memcpy(d.ke.scancode, &scancode, sizeof(scancode)); input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 783cdd3..9c7a97b 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev, } #undef OLD_KEY_MAX +static int evdev_handle_get_keycode(struct input_dev *dev, + void __user *p, size_t size) +{ + struct keymap_entry ke; + int error; + + memset(&ke, 0, sizeof(ke)); + + if (size == sizeof(unsigned int[2])) { + /* legacy case */ + int __user *ip = (int __user *)p; + + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; + + ke.len = sizeof(unsigned int); + ke.by_index = false; + + error = input_get_keycode(dev, &ke); + if (error) + return error; + + if (put_user(ke.keycode, ip + 1)) + return -EFAULT; + + } else { + size = min(size, sizeof(ke)); + + if (copy_from_user(&ke, p, size)) + return -EFAULT; + + error = input_get_keycode(dev, &ke); + if (error) + return error; + + if (copy_to_user(p, &ke, size)) + return -EFAULT; + } + return 0; +} + +static int evdev_handle_set_keycode(struct input_dev *dev, + void __user *p, size_t size) +{ + struct keymap_entry ke; + + memset(&ke, 0, sizeof(ke)); + + if (size == sizeof(unsigned int[2])) { + /* legacy case */ + int __user *ip = (int __user *)p; + + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; + + if (get_user(ke.keycode, ip + 1)) + return -EFAULT; + + ke.len = sizeof(unsigned int); + ke.by_index = false; + + } else { + size = min(size, sizeof(ke)); + + if (copy_from_user(&ke, p, size)) + return -EFAULT; + + if (ke.len > sizeof(ke.scancode)) + return -EINVAL; + } + + return input_set_keycode(dev, &ke); +} + static long evdev_do_ioctl(struct file *file, unsigned int cmd, void __user *p, int compat_mode) { @@ -543,8 +617,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct input_absinfo abs; struct ff_effect effect; int __user *ip = (int __user *)p; - struct keycode_table_entry kt, *kt_p = p; - char scancode[16]; unsigned int i, t, u, v; unsigned int size; int error; @@ -582,62 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return 0; - case EVIOCGKEYCODE: - if (get_user(t, ip)) - return -EFAULT; - - error = input_get_keycode(dev, t, &v); - if (error) - return error; - - if (put_user(v, ip + 1)) - return -EFAULT; - - return 0; - - case EVIOCSKEYCODE: - if (get_user(t, ip) || get_user(v, ip + 1)) - return -EFAULT; - - return input_set_keycode(dev, t, v); - - case EVIOCGKEYCODEBIG: - if (copy_from_user(&kt, kt_p, sizeof(kt))) - return -EFAULT; - - if (kt.len > sizeof(scancode)) - return -EINVAL; - - kt.scancode = scancode; - - error = input_get_keycode_big(dev, &kt); - if (error) - return error; - - if (copy_to_user(kt_p, &kt, sizeof(kt))) - return -EFAULT; - - /* FIXME: probably need some compat32 code */ - if (copy_to_user(kt_p->scancode, kt.scancode, kt.len)) - return -EFAULT; - - return 0; - - case EVIOCSKEYCODEBIG: - if (copy_from_user(&kt, kt_p, sizeof(kt))) - return -EFAULT; - - if (kt.len > sizeof(scancode)) - return -EINVAL; - - kt.scancode = scancode; - - /* FIXME: probably need some compat32 code */ - if (copy_from_user(kt.scancode, kt_p->scancode, kt.len)) - return -EFAULT; - - return input_set_keycode_big(dev, &kt); - case EVIOCRMFF: return input_ff_erase(dev, (int)(unsigned long) p, file); @@ -659,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, /* Now check variable-length commands */ #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) - switch (EVIOC_MASK_SIZE(cmd)) { case EVIOCGKEY(0): @@ -693,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return -EFAULT; return error; + + case EVIOC_MASK_SIZE(EVIOCGKEYCODE): + return evdev_handle_get_keycode(dev, p, size); + + case EVIOC_MASK_SIZE(EVIOCSKEYCODE): + return evdev_handle_set_keycode(dev, p, size); } /* Multi-number variable-length handlers */ diff --git a/drivers/input/input.c b/drivers/input/input.c index bbb95c1..4408913 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -634,131 +634,141 @@ static void input_disconnect_device(struct input_dev *dev) spin_unlock_irq(&dev->event_lock); } -/* - * Those routines handle the default case where no [gs]etkeycode() is - * defined. In this case, an array indexed by the scancode is used. +/** + * input_scancode_to_scalar() - converts scancode in &struct keymap_entry + * @ke: keymap entry containing scancode to be converted. + * @scancode: pointer to the location where converted scancode should + * be stored. + * + * This function is used to convert scancode stored in &struct keymap_entry + * into scalar form understood by legacy keymap handling methods. These + * methods expect scancodes to be represented as 'unsigned int'. */ - -static int input_fetch_keycode(struct input_dev *dev, int scancode) +int input_scancode_to_scalar(const struct keymap_entry *ke, + unsigned int *scancode) { - switch (dev->keycodesize) { - case 1: - return ((u8 *)dev->keycode)[scancode]; + switch (ke->len) { + case 1: + *scancode = *((u8 *)ke->scancode); + break; - case 2: - return ((u16 *)dev->keycode)[scancode]; + case 2: + *scancode = *((u16 *)ke->scancode); + break; + + case 4: + *scancode = *((u32 *)ke->scancode); + break; - default: - return ((u32 *)dev->keycode)[scancode]; + default: + return -EINVAL; } + + return 0; } +EXPORT_SYMBOL(input_scancode_to_scalar); /* - * Supports only 8, 16 and 32 bit scancodes. It wouldn't be that - * hard to write some machine-endian logic to support 24 bit scancodes, - * but it seemed overkill. It should also be noticed that, since there - * are, in general, less than 256 scancodes sparsed into the scancode - * space, even with 16 bits, the codespace is sparsed, with leads into - * memory and code ineficiency, when retrieving the entire scancode - * space. - * So, it is highly recommended to implement getkeycodebig/setkeycodebig - * instead of using a normal table approach, when more than 8 bits is - * needed for the scancode. + * Those routines handle the default case where no [gs]etkeycode() is + * defined. In this case, an array indexed by the scancode is used. */ -static int input_fetch_scancode(struct keycode_table_entry *kt_entry, - u32 *scancode) + +static unsigned int input_fetch_keycode(struct input_dev *dev, + unsigned int index) { - switch (kt_entry->len) { + switch (dev->keycodesize) { case 1: - *scancode = *((u8 *)kt_entry->scancode); - break; + return ((u8 *)dev->keycode)[index]; + case 2: - *scancode = *((u16 *)kt_entry->scancode); - break; - case 4: - *scancode = *((u32 *)kt_entry->scancode); - break; + return ((u16 *)dev->keycode)[index]; + default: - return -EINVAL; + return ((u32 *)dev->keycode)[index]; } - return 0; } - -static int input_default_getkeycode_from_index(struct input_dev *dev, - struct keycode_table_entry *kt_entry) +static int input_default_getkeycode(struct input_dev *dev, + struct keymap_entry *ke) { - u32 scancode = kt_entry->index; + unsigned int index; + int error; if (!dev->keycodesize) return -EINVAL; - if (scancode >= dev->keycodemax) + if (ke->by_index) + index = ke->index; + else { + error = input_scancode_to_scalar(ke, &index); + if (error) + return error; + } + + if (index >= dev->keycodemax) return -EINVAL; - kt_entry->keycode = input_fetch_keycode(dev, scancode); - memcpy(kt_entry->scancode, &scancode, 4); + ke->keycode = input_fetch_keycode(dev, index); + ke->index = index; + ke->len = sizeof(index); + memcpy(ke->scancode, &index, sizeof(index)); return 0; } -static int input_default_getkeycode_from_scancode(struct input_dev *dev, - struct keycode_table_entry *kt_entry) -{ - if (input_fetch_scancode(kt_entry, &kt_entry->index)) - return -EINVAL; - - return input_default_getkeycode_from_index(dev, kt_entry); -} - - static int input_default_setkeycode(struct input_dev *dev, - struct keycode_table_entry *kt_entry) + const struct keymap_entry *ke, + unsigned int *old_keycode) { - u32 old_keycode; + unsigned int index; + int error; int i; - u32 scancode; - if (input_fetch_scancode(kt_entry, &scancode)) + if (!dev->keycodesize) return -EINVAL; - if (scancode >= dev->keycodemax) - return -EINVAL; + if (ke->by_index) { + index = ke->index; + } else { + error = input_scancode_to_scalar(ke, &index); + if (error) + return error; + } - if (!dev->keycodesize) + if (index >= dev->keycodemax) return -EINVAL; if (dev->keycodesize < sizeof(dev->keycode) && - (kt_entry->keycode >> (dev->keycodesize * 8))) + (ke->keycode >> (dev->keycodesize * 8))) return -EINVAL; switch (dev->keycodesize) { case 1: { u8 *k = (u8 *)dev->keycode; - old_keycode = k[scancode]; - k[scancode] = kt_entry->keycode; + *old_keycode = k[index]; + k[index] = ke->keycode; break; } case 2: { u16 *k = (u16 *)dev->keycode; - old_keycode = k[scancode]; - k[scancode] = kt_entry->keycode; + *old_keycode = k[index]; + k[index] = ke->keycode; break; } default: { u32 *k = (u32 *)dev->keycode; - old_keycode = k[scancode]; - k[scancode] = kt_entry->keycode; + *old_keycode = k[index]; + k[index] = ke->keycode; break; } } - __clear_bit(old_keycode, dev->keybit); - __set_bit(kt_entry->keycode, dev->keybit); + __clear_bit(*old_keycode, dev->keybit); + __set_bit(ke->keycode, dev->keybit); for (i = 0; i < dev->keycodemax; i++) { - if (input_fetch_keycode(dev, i) == old_keycode) { - __set_bit(old_keycode, dev->keybit); + if (input_fetch_keycode(dev, i) == *old_keycode) { + __set_bit(*old_keycode, dev->keybit); break; /* Setting the bit twice is useless, so break */ } } @@ -767,215 +777,90 @@ static int input_default_setkeycode(struct input_dev *dev, } /** - * input_get_keycode_big - retrieve keycode currently mapped to a given scancode + * input_get_keycode - retrieve keycode currently mapped to a given scancode * @dev: input device which keymap is being queried - * @kt_entry: keytable entry + * @ke: keymap entry * * This function should be called by anyone interested in retrieving current * keymap. Presently evdev handlers use it. */ -int input_get_keycode_big(struct input_dev *dev, - struct keycode_table_entry *kt_entry) -{ - if (dev->getkeycode) { - u32 scancode = kt_entry->index; - - /* - * Support for legacy drivers, that don't implement the new - * ioctls - */ - memcpy(kt_entry->scancode, &scancode, 4); - return dev->getkeycode(dev, scancode, - &kt_entry->keycode); - } else - return dev->getkeycodebig_from_index(dev, kt_entry); -} -EXPORT_SYMBOL(input_get_keycode_big); - -/** - * input_set_keycode_big - attribute a keycode to a given scancode - * @dev: input device which keymap is being queried - * @kt_entry: keytable entry - * - * This function should be called by anyone needing to update current - * keymap. Presently keyboard and evdev handlers use it. - */ -int input_set_keycode_big(struct input_dev *dev, - struct keycode_table_entry *kt_entry) +int input_get_keycode(struct input_dev *dev, struct keymap_entry *ke) { unsigned long flags; - int old_keycode; - int retval = -EINVAL; - u32 uninitialized_var(scancode); - - if (kt_entry->keycode < 0 || kt_entry->keycode > KEY_MAX) - return -EINVAL; + int retval; spin_lock_irqsave(&dev->event_lock, flags); - /* - * We need to know the old scancode, in order to generate a - * keyup effect, if the set operation happens successfully - */ if (dev->getkeycode) { /* * Support for legacy drivers, that don't implement the new * ioctls */ - if (!dev->setkeycode) - goto out; - - retval = input_fetch_scancode(kt_entry, &scancode); - if (retval) - goto out; + u32 scancode = ke->index; - retval = dev->getkeycode(dev, scancode, - &old_keycode); + memcpy(ke->scancode, &scancode, sizeof(scancode)); + ke->len = sizeof(scancode); + retval = dev->getkeycode(dev, scancode, &ke->keycode); } else { - int new_keycode = kt_entry->keycode; - - retval = dev->getkeycodebig_from_scancode(dev, kt_entry); - old_keycode = kt_entry->keycode; - kt_entry->keycode = new_keycode; + retval = dev->getkeycode_new(dev, ke); } - if (retval) - goto out; - - if (dev->getkeycode) - retval = dev->setkeycode(dev, scancode, - kt_entry->keycode); - else - retval = dev->setkeycodebig(dev, kt_entry); - if (retval) - goto out; - - /* - * Simulate keyup event if keycode is not present - * in the keymap anymore - */ - if (test_bit(EV_KEY, dev->evbit) && - !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && - __test_and_clear_bit(old_keycode, dev->key)) { - - input_pass_event(dev, EV_KEY, old_keycode, 0); - if (dev->sync) - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - } - - out: spin_unlock_irqrestore(&dev->event_lock, flags); - return retval; } -EXPORT_SYMBOL(input_set_keycode_big); - -/** - * input_get_keycode - retrieve keycode currently mapped to a given scancode - * @dev: input device which keymap is being queried - * @scancode: scancode (or its equivalent for device in question) for which - * keycode is needed - * @keycode: result - * - * This function should be called by anyone interested in retrieving current - * keymap. Presently keyboard and evdev handlers use it. - */ -int input_get_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) -{ - unsigned long flags; - - if (dev->getkeycode) { - /* - * Use the legacy calls - */ - return dev->getkeycode(dev, scancode, keycode); - } else { - int retval; - struct keycode_table_entry kt_entry; - - /* - * Userspace is using a legacy call with a driver ported - * to the new way. This is a bad idea with long sparsed - * tables, since lots of the retrieved values will be in - * blank. Also, it makes sense only if the table size is - * lower than 2^32. - */ - memset(&kt_entry, 0, sizeof(kt_entry)); - kt_entry.len = 4; - kt_entry.index = scancode; - kt_entry.scancode = (char *)&scancode; - - spin_lock_irqsave(&dev->event_lock, flags); - retval = dev->getkeycodebig_from_index(dev, &kt_entry); - spin_unlock_irqrestore(&dev->event_lock, flags); - - *keycode = kt_entry.keycode; - return retval; - } -} EXPORT_SYMBOL(input_get_keycode); /** - * input_get_keycode - assign new keycode to a given scancode - * @dev: input device which keymap is being updated - * @scancode: scancode (or its equivalent for device in question) - * @keycode: new keycode to be assigned to the scancode + * input_set_keycode - attribute a keycode to a given scancode + * @dev: input device which keymap is being queried + * @ke: keymap entry + * @old_keycode: keycode previously assigned to the scancode * * This function should be called by anyone needing to update current * keymap. Presently keyboard and evdev handlers use it. */ -int input_set_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode) +int input_set_keycode(struct input_dev *dev, const struct keymap_entry *ke) { unsigned long flags; unsigned int old_keycode; int retval; - if (keycode > KEY_MAX) + if (ke->keycode > KEY_MAX) return -EINVAL; spin_lock_irqsave(&dev->event_lock, flags); - if (dev->getkeycode) { + if (dev->setkeycode) { /* - * Use the legacy calls + * Support for legacy drivers, that don't implement the new + * ioctls */ - retval = dev->getkeycode(dev, scancode, &old_keycode); - if (retval) - goto out; + unsigned int scancode; - retval = dev->setkeycode(dev, scancode, keycode); + retval = input_scancode_to_scalar(ke, &scancode); if (retval) goto out; - } else { - struct keycode_table_entry kt_entry; /* - * Userspace is using a legacy call with a driver ported - * to the new way. This is a bad idea with long sparsed - * tables, since lots of the retrieved values will be in - * blank. Also, it makes sense only if the table size is - * lower than 2^32. + * We need to know the old scancode, in order to generate a + * keyup effect, if the set operation happens successfully */ - memset(&kt_entry, 0, sizeof(kt_entry)); - kt_entry.len = 4; - kt_entry.scancode = (char *)&scancode; - - retval = dev->getkeycodebig_from_scancode(dev, &kt_entry); - if (retval) + if (!dev->getkeycode) { + retval = -EINVAL; goto out; + } - old_keycode = kt_entry.keycode; - kt_entry.keycode = keycode; - - retval = dev->setkeycodebig(dev, &kt_entry); + retval = dev->getkeycode(dev, scancode, &old_keycode); if (retval) goto out; + + retval = dev->setkeycode(dev, scancode, ke->keycode); + } else { + retval = dev->setkeycode_new(dev, ke, &old_keycode); } - /* Make sure KEY_RESERVED did not get enabled. */ - __clear_bit(KEY_RESERVED, dev->keybit); + if (retval) + goto out; /* * Simulate keyup event if keycode is not present @@ -1960,17 +1845,11 @@ int input_register_device(struct input_dev *dev) dev->rep[REP_PERIOD] = 33; } - if (!dev->getkeycode) { - if (!dev->getkeycodebig_from_index) - dev->getkeycodebig_from_index = input_default_getkeycode_from_index; - if (!dev->getkeycodebig_from_scancode) - dev->getkeycodebig_from_scancode = input_default_getkeycode_from_scancode; - } + if (!dev->getkeycode && !dev->getkeycode_new) + dev->getkeycode_new = input_default_getkeycode; - if (!dev->setkeycode) { - if (!dev->setkeycodebig) - dev->setkeycodebig = input_default_setkeycode; - } + if (!dev->setkeycode && !dev->setkeycode_new) + dev->setkeycode_new = input_default_setkeycode; dev_set_name(&dev->dev, "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); diff --git a/include/linux/input.h b/include/linux/input.h index 8d6de8c..e090169 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -56,22 +56,35 @@ struct input_absinfo { __s32 resolution; }; -struct keycode_table_entry { - __u32 keycode; /* e.g. KEY_A */ - __u32 index; /* Index for the given scan/key table, on EVIOCGKEYCODEBIG */ - __u32 len; /* Length of the scancode */ - __u32 reserved[2]; /* Reserved for future usage */ - char *scancode; /* scancode, in machine-endian */ +/** + * struct keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls + * @scancode: scancode represented in machine-endian form. + * @len: length of the scancode that resides in @scancode buffer. + * @index: index in the keymap, may be used instead of scancode + * @by_index: boolean value indicating that kernel should perform + * lookup in keymap by @index instead of @scancode + * @keycode: key code assigned to this scancode + * + * The structure is used to retrieve and modify keymap data. Users have + * of performing lookup either by @scancode itself or by @index in + * keymap entry. EVIOCGKEYCODE will also return scancode or index + * (depending on which element was used to perform lookup). + */ +struct keymap_entry { + __u8 len; + __u8 by_index; + __u16 index; + __u32 keycode; + __u8 scancode[32]; }; #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ #define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ #define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */ -#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */ -#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */ -#define EVIOCGKEYCODEBIG _IOR('E', 0x04, struct keycode_table_entry) /* get keycode */ -#define EVIOCSKEYCODEBIG _IOW('E', 0x04, struct keycode_table_entry) /* set keycode */ + +#define EVIOCGKEYCODE _IOR('E', 0x04, struct keymap_entry) /* get keycode */ +#define EVIOCSKEYCODE _IOW('E', 0x04, struct keymap_entry) /* set keycode */ #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ @@ -1098,22 +1111,13 @@ struct input_mt_slot { * @keycodemax: size of keycode table * @keycodesize: size of elements in keycode table * @keycode: map of scancodes to keycodes for this device - * @setkeycode: optional legacy method to alter current keymap, used to - * implement sparse keymaps. Shouldn't be used in new drivers * @getkeycode: optional legacy method to retrieve current keymap. - * Shouldn't be used on new drivers. - * @setkeycodebig: optional method to alter current keymap, used to implement + * @setkeycode: optional method to alter current keymap, used to implement * sparse keymaps. If not supplied default mechanism will be used. * The method is being called while holding event_lock and thus must * not sleep - * @getkeycodebig_from_index: optional method to retrieve current keymap from - * an array index. If not supplied default mechanism will be used. - * The method is being called while holding event_lock and thus must - * not sleep - * @getkeycodebig_from_scancode: optional method to retrieve current keymap - * from an scancode. If not supplied default mechanism will be used. - * The method is being called while holding event_lock and thus must - * not sleep + * @getkeycode_new: transition method + * @setkeycode_new: transition method * @ff: force feedback structure associated with the device if device * supports force feedback effects * @repeat_key: stores key code of the last key pressed; used to implement @@ -1187,16 +1191,15 @@ struct input_dev { unsigned int keycodemax; unsigned int keycodesize; void *keycode; + int (*setkeycode)(struct input_dev *dev, unsigned int scancode, unsigned int keycode); int (*getkeycode)(struct input_dev *dev, unsigned int scancode, unsigned int *keycode); - int (*setkeycodebig)(struct input_dev *dev, - struct keycode_table_entry *kt_entry); - int (*getkeycodebig_from_index)(struct input_dev *dev, - struct keycode_table_entry *kt_entry); - int (*getkeycodebig_from_scancode)(struct input_dev *dev, - struct keycode_table_entry *kt_entry); + int (*setkeycode_new)(struct input_dev *dev, + const struct keymap_entry *ke, + unsigned int *old_keycode); + int (*getkeycode_new)(struct input_dev *dev, struct keymap_entry *ke); struct ff_device *ff; @@ -1503,14 +1506,11 @@ INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz) INPUT_GENERATE_ABS_ACCESSORS(flat, flat) INPUT_GENERATE_ABS_ACCESSORS(res, resolution) -int input_get_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode); -int input_set_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode); -int input_get_keycode_big(struct input_dev *dev, - struct keycode_table_entry *kt_entry); -int input_set_keycode_big(struct input_dev *dev, - struct keycode_table_entry *kt_entry); +int input_scancode_to_scalar(const struct keymap_entry *ke, + unsigned int *scancode); + +int input_get_keycode(struct input_dev *dev, struct keymap_entry *ke); +int input_set_keycode(struct input_dev *dev, const struct keymap_entry *ke); extern struct class input_class;