diff options
Diffstat (limited to 'drivers/char/keyboard.c')
| -rw-r--r-- | drivers/char/keyboard.c | 103 | 
1 files changed, 45 insertions, 58 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index cb8d691576d..1b094509b1d 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -41,7 +41,6 @@  #include <linux/input.h>  #include <linux/reboot.h> -static void kbd_disconnect(struct input_handle *handle);  extern void ctrl_alt_del(void);  /* @@ -110,7 +109,7 @@ struct kbd_struct kbd_table[MAX_NR_CONSOLES];  static struct kbd_struct *kbd = kbd_table;  struct vt_spawn_console vt_spawn_con = { -	.lock = SPIN_LOCK_UNLOCKED, +	.lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock),  	.pid  = NULL,  	.sig  = 0,  }; @@ -159,65 +158,41 @@ static int sysrq_alt_use;  static int sysrq_alt;  /* - * Translation of scancodes to keycodes. We set them on only the first attached - * keyboard - for per-keyboard setting, /dev/input/event is more useful. + * Translation of scancodes to keycodes. We set them on only the first + * keyboard in the list that accepts the scancode and keycode. + * Explanation for not choosing the first attached keyboard anymore: + *  USB keyboards for example have two event devices: one for all "normal" + *  keys and one for extra function keys (like "volume up", "make coffee", + *  etc.). So this means that scancodes for the extra function keys won't + *  be valid for the first event device, but will be for the second.   */  int getkeycode(unsigned int scancode)  { -	struct list_head *node; -	struct input_dev *dev = NULL; +	struct input_handle *handle; +	int keycode; +	int error = -ENODEV; -	list_for_each(node, &kbd_handler.h_list) { -		struct input_handle *handle = to_handle_h(node); -		if (handle->dev->keycodesize) { -			dev = handle->dev; -			break; -		} +	list_for_each_entry(handle, &kbd_handler.h_list, h_node) { +		error = handle->dev->getkeycode(handle->dev, scancode, &keycode); +		if (!error) +			return keycode;  	} -	if (!dev) -		return -ENODEV; - -	if (scancode >= dev->keycodemax) -		return -EINVAL; - -	return INPUT_KEYCODE(dev, scancode); +	return error;  }  int setkeycode(unsigned int scancode, unsigned int keycode)  { -	struct list_head *node; -	struct input_dev *dev = NULL; -	unsigned int i, oldkey; +	struct input_handle *handle; +	int error = -ENODEV; -	list_for_each(node, &kbd_handler.h_list) { -		struct input_handle *handle = to_handle_h(node); -		if (handle->dev->keycodesize) { -			dev = handle->dev; +	list_for_each_entry(handle, &kbd_handler.h_list, h_node) { +		error = handle->dev->setkeycode(handle->dev, scancode, keycode); +		if (!error)  			break; -		}  	} -	if (!dev) -		return -ENODEV; - -	if (scancode >= dev->keycodemax) -		return -EINVAL; -	if (keycode < 0 || keycode > KEY_MAX) -		return -EINVAL; -	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) -		return -EINVAL; - -	oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); - -	clear_bit(oldkey, dev->keybit); -	set_bit(keycode, dev->keybit); - -	for (i = 0; i < dev->keycodemax; i++) -		if (INPUT_KEYCODE(dev,i) == oldkey) -			set_bit(oldkey, dev->keybit); - -	return 0; +	return error;  }  /* @@ -225,10 +200,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode)   */  static void kd_nosound(unsigned long ignored)  { -	struct list_head *node; +	struct input_handle *handle; -	list_for_each(node, &kbd_handler.h_list) { -		struct input_handle *handle = to_handle_h(node); +	list_for_each_entry(handle, &kbd_handler.h_list, h_node) {  		if (test_bit(EV_SND, handle->dev->evbit)) {  			if (test_bit(SND_TONE, handle->dev->sndbit))  				input_inject_event(handle, EV_SND, SND_TONE, 0); @@ -1161,7 +1135,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)  	if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)  		if (emulate_raw(vc, keycode, !down << 7)) -			if (keycode < BTN_MISC) +			if (keycode < BTN_MISC && printk_ratelimit())  				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);  #ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */ @@ -1285,11 +1259,11 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,   * likes it, it can open it and get events from it. In this (kbd_connect)   * function, we should decide which VT to bind that keyboard to initially.   */ -static struct input_handle *kbd_connect(struct input_handler *handler, -					struct input_dev *dev, -					const struct input_device_id *id) +static int kbd_connect(struct input_handler *handler, struct input_dev *dev, +			const struct input_device_id *id)  {  	struct input_handle *handle; +	int error;  	int i;  	for (i = KEY_RESERVED; i < BTN_MISC; i++) @@ -1297,24 +1271,37 @@ static struct input_handle *kbd_connect(struct input_handler *handler,  			break;  	if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) -		return NULL; +		return -ENODEV;  	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);  	if (!handle) -		return NULL; +		return -ENOMEM;  	handle->dev = dev;  	handle->handler = handler;  	handle->name = "kbd"; -	input_open_device(handle); +	error = input_register_handle(handle); +	if (error) +		goto err_free_handle; + +	error = input_open_device(handle); +	if (error) +		goto err_unregister_handle; + +	return 0; -	return handle; + err_unregister_handle: +	input_unregister_handle(handle); + err_free_handle: +	kfree(handle); +	return error;  }  static void kbd_disconnect(struct input_handle *handle)  {  	input_close_device(handle); +	input_unregister_handle(handle);  	kfree(handle);  }  | 
