]> git.hungrycats.org Git - linux/commitdiff
Shorten the keycode handling code in keyboard.c and evdev.c.
authorVojtech Pavlik <vojtech@suse.cz>
Mon, 26 Aug 2002 13:13:55 +0000 (15:13 +0200)
committerVojtech Pavlik <vojtech@suse.cz>
Mon, 26 Aug 2002 13:13:55 +0000 (15:13 +0200)
Recompute keybit when keycode table changes.
Stricter checks on input keycode/scancode values.

drivers/char/keyboard.c
drivers/input/evdev.c
include/linux/input.h

index d773e736e427f314b7220590c088f53ba7d320db..5a23661357912c05345d9680f2c8448050415979 100644 (file)
@@ -131,39 +131,44 @@ static struct ledptr {
 int getkeycode(unsigned int scancode)
 {
        struct input_handle *handle;
-       unsigned int keycode;
+       struct input_dev *dev = NULL;
 
        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;
 
-       switch (handle->dev->keycodesize) {
-               case 1: keycode = *(u8*)(handle->dev->keycode + scancode); break;
-               case 2: keycode = *(u16*)(handle->dev->keycode + scancode * 2); break;
-               case 4: keycode = *(u32*)(handle->dev->keycode + scancode * 4); break;
-               default: return -EINVAL;
-       }
+       if (scancode < 0 || scancode >= dev->keycodemax)
+               return -EINVAL;
 
-       return keycode;
+       return INPUT_KEYCODE(dev, scancode);
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
        struct input_handle *handle;
+       struct input_dev *dev = NULL;
+       int i, oldkey;
 
        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;
 
-       switch (handle->dev->keycodesize) {
-               case 1: *(u8*)(handle->dev->keycode + scancode) = keycode; break;
-               case 2: *(u16*)(handle->dev->keycode + scancode * 2) = keycode; break;
-               case 4: *(u32*)(handle->dev->keycode + scancode * 4) = keycode; break;
-       }
+       if (scancode < 0 || scancode >= dev->keycodemax)
+               return -EINVAL;
+
+       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;
 }
index c0ee61af624e29741f92bceee579a63a07d15b08..d6e7429020cc94500dcbb6213f5116779c472fd6 100644 (file)
@@ -234,7 +234,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        struct evdev *evdev = list->evdev;
        struct input_dev *dev = evdev->handle.dev;
        struct input_absinfo abs;
-       int t, u;
+       int i, t, u;
 
        if (!evdev->exist) return -ENODEV;
 
@@ -258,26 +258,21 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                case EVIOCGKEYCODE:
                        if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
-                       if (t < 0 || t > dev->keycodemax) return -EINVAL;
-                       switch (dev->keycodesize) {
-                               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;
+                       if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
+                       if (put_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
                        return 0;
 
                case EVIOCSKEYCODE:
                        if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
-                       if (t < 0 || t > dev->keycodemax) return -EINVAL;
-                       if (get_user(u, ((int *) arg) + 1)) return -EFAULT;
-                       switch (dev->keycodesize) {
-                               case 1: *(u8*)(dev->keycode + t) = u; break;
-                               case 2: *(u16*)(dev->keycode + t * 2) = u; break;
-                               case 4: *(u32*)(dev->keycode + t * 4) = u; break;
-                               default: return -EINVAL;
-                       }
+                       if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
+                       u = INPUT_KEYCODE(dev, t);
+                       if (get_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT;
+
+                       for (i = 0; i < dev->keycodemax; i++)
+                               if(INPUT_KEYCODE(dev, t) == u) break;
+                       if (i == dev->keycodemax) clear_bit(u, dev->keybit);
+                       set_bit(INPUT_KEYCODE(dev, t), dev->keybit);
+
                        return 0;
 
                case EVIOCSFF:
index cd2a6856e2a95f68bfa5e00a74c4a27153a3e635..a70952ffb036ee2e902888112be9782462c14af8 100644 (file)
@@ -757,6 +757,9 @@ struct ff_effect {
 #define BIT(x) (1UL<<((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 {
 
        void *private;