Commit 87b2c140 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Shorten the keycode handling code in keyboard.c and evdev.c.

Recompute keybit when keycode table changes.
Stricter checks on input keycode/scancode values.
parent c906c90c
...@@ -131,39 +131,44 @@ static struct ledptr { ...@@ -131,39 +131,44 @@ static struct ledptr {
int getkeycode(unsigned int scancode) int getkeycode(unsigned int scancode)
{ {
struct input_handle *handle; struct input_handle *handle;
unsigned int keycode; struct input_dev *dev = NULL;
for (handle = kbd_handler.handle; handle; handle = handle->hnext) for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (handle->dev->keycodesize) break; if (handle->dev->keycodesize) { dev = handle->dev; break; }
if (!handle->dev->keycodesize) if (!dev)
return -ENODEV; return -ENODEV;
switch (handle->dev->keycodesize) { if (scancode < 0 || scancode >= dev->keycodemax)
case 1: keycode = *(u8*)(handle->dev->keycode + scancode); break; return -EINVAL;
case 2: keycode = *(u16*)(handle->dev->keycode + scancode * 2); break;
case 4: keycode = *(u32*)(handle->dev->keycode + scancode * 4); break;
default: return -EINVAL;
}
return keycode; return INPUT_KEYCODE(dev, scancode);
} }
int setkeycode(unsigned int scancode, unsigned int keycode) int setkeycode(unsigned int scancode, unsigned int keycode)
{ {
struct input_handle *handle; struct input_handle *handle;
struct input_dev *dev = NULL;
int i, oldkey;
for (handle = kbd_handler.handle; handle; handle = handle->hnext) for (handle = kbd_handler.handle; handle; handle = handle->hnext)
if (handle->dev->keycodesize) break; if (handle->dev->keycodesize) { dev = handle->dev; break; }
if (!handle->dev->keycodesize) if (!dev)
return -ENODEV; return -ENODEV;
switch (handle->dev->keycodesize) { if (scancode < 0 || scancode >= dev->keycodemax)
case 1: *(u8*)(handle->dev->keycode + scancode) = keycode; break; return -EINVAL;
case 2: *(u16*)(handle->dev->keycode + scancode * 2) = keycode; break;
case 4: *(u32*)(handle->dev->keycode + scancode * 4) = keycode; break; oldkey = INPUT_KEYCODE(dev, scancode);
} INPUT_KEYCODE(dev, scancode) = keycode;
for (i = 0; i < dev->keycodemax; i++)
if(INPUT_KEYCODE(dev, scancode) == oldkey)
break;
if (i == dev->keycodemax)
clear_bit(oldkey, dev->keybit);
set_bit(keycode, dev->keybit);
return 0; return 0;
} }
......
...@@ -234,7 +234,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -234,7 +234,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct evdev *evdev = list->evdev; struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev; struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs; struct input_absinfo abs;
int t, u; int i, t, u;
if (!evdev->exist) return -ENODEV; if (!evdev->exist) return -ENODEV;
...@@ -258,26 +258,21 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -258,26 +258,21 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EVIOCGKEYCODE: case EVIOCGKEYCODE:
if (get_user(t, ((int *) arg) + 0)) return -EFAULT; if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
if (t < 0 || t > dev->keycodemax) return -EINVAL; if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
switch (dev->keycodesize) { if (put_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
case 1: u = *(u8*)(dev->keycode + t); break;
case 2: u = *(u16*)(dev->keycode + t * 2); break;
case 4: u = *(u32*)(dev->keycode + t * 4); break;
default: return -EINVAL;
}
if (put_user(u, ((int *) arg) + 1)) return -EFAULT;
return 0; return 0;
case EVIOCSKEYCODE: case EVIOCSKEYCODE:
if (get_user(t, ((int *) arg) + 0)) return -EFAULT; if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
if (t < 0 || t > dev->keycodemax) return -EINVAL; if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
if (get_user(u, ((int *) arg) + 1)) return -EFAULT; u = INPUT_KEYCODE(dev, t);
switch (dev->keycodesize) { if (get_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
case 1: *(u8*)(dev->keycode + t) = u; break;
case 2: *(u16*)(dev->keycode + t * 2) = u; break; for (i = 0; i < dev->keycodemax; i++)
case 4: *(u32*)(dev->keycode + t * 4) = u; break; if(INPUT_KEYCODE(dev, t) == u) break;
default: return -EINVAL; if (i == dev->keycodemax) clear_bit(u, dev->keybit);
} set_bit(INPUT_KEYCODE(dev, t), dev->keybit);
return 0; return 0;
case EVIOCSFF: case EVIOCSFF:
......
...@@ -757,6 +757,9 @@ struct ff_effect { ...@@ -757,6 +757,9 @@ struct ff_effect {
#define BIT(x) (1UL<<((x)%BITS_PER_LONG)) #define BIT(x) (1UL<<((x)%BITS_PER_LONG))
#define LONG(x) ((x)/BITS_PER_LONG) #define LONG(x) ((x)/BITS_PER_LONG)
#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
struct input_dev { struct input_dev {
void *private; void *private;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment