diff options
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 113 | 
1 files changed, 58 insertions, 55 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e3f7fc6f956..68f09a86843 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -534,76 +534,73 @@ 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) +static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)  { -	struct input_keymap_entry ke; +	struct input_keymap_entry ke = { +		.len	= sizeof(unsigned int), +		.flags	= 0, +	}; +	int __user *ip = (int __user *)p;  	int error; -	memset(&ke, 0, sizeof(ke)); - -	if (size == sizeof(unsigned int[2])) { -		/* legacy case */ -		int __user *ip = (int __user *)p; +	/* legacy case */ +	if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) +		return -EFAULT; -		if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) -			return -EFAULT; +	error = input_get_keycode(dev, &ke); +	if (error) +		return error; -		ke.len = sizeof(unsigned int); -		ke.flags = 0; +	if (put_user(ke.keycode, ip + 1)) +		return -EFAULT; -		error = input_get_keycode(dev, &ke); -		if (error) -			return error; +	return 0; +} -		if (put_user(ke.keycode, ip + 1)) -			return -EFAULT; +static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) +{ +	struct input_keymap_entry ke; +	int error; -	} else { -		size = min(size, sizeof(ke)); +	if (copy_from_user(&ke, p, sizeof(ke))) +		return -EFAULT; -		if (copy_from_user(&ke, p, size)) -			return -EFAULT; +	error = input_get_keycode(dev, &ke); +	if (error) +		return error; -		error = input_get_keycode(dev, &ke); -		if (error) -			return error; +	if (copy_to_user(p, &ke, sizeof(ke))) +		return -EFAULT; -		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) +static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)  { -	struct input_keymap_entry ke; - -	memset(&ke, 0, sizeof(ke)); +	struct input_keymap_entry ke = { +		.len	= sizeof(unsigned int), +		.flags	= 0, +	}; +	int __user *ip = (int __user *)p; -	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 (copy_from_user(ke.scancode, p, sizeof(unsigned int))) -			return -EFAULT; +	if (get_user(ke.keycode, ip + 1)) +		return -EFAULT; -		if (get_user(ke.keycode, ip + 1)) -			return -EFAULT; +	return input_set_keycode(dev, &ke); +} -		ke.len = sizeof(unsigned int); -		ke.flags = 0; +static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) +{ +	struct input_keymap_entry ke; -	} else { -		size = min(size, sizeof(ke)); +	if (copy_from_user(&ke, p, sizeof(ke))) +		return -EFAULT; -		if (copy_from_user(&ke, p, size)) -			return -EFAULT; - -		if (ke.len > sizeof(ke.scancode)) -			return -EINVAL; -	} +	if (ke.len > sizeof(ke.scancode)) +		return -EINVAL;  	return input_set_keycode(dev, &ke);  } @@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,  			return evdev_grab(evdev, client);  		else  			return evdev_ungrab(evdev, client); + +	case EVIOCGKEYCODE: +		return evdev_handle_get_keycode(dev, p); + +	case EVIOCSKEYCODE: +		return evdev_handle_set_keycode(dev, p); + +	case EVIOCGKEYCODE_V2: +		return evdev_handle_get_keycode_v2(dev, p); + +	case EVIOCSKEYCODE_V2: +		return evdev_handle_set_keycode_v2(dev, p);  	}  	size = _IOC_SIZE(cmd); @@ -708,12 +717,6 @@ 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 */  |