Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0fe3cc5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (40 commits)
  Input: psmouse - small formatting changes to better follow coding style
  Input: synaptics - set dimensions as reported by firmware
  Input: elantech - relax signature checks
  Input: elantech - enforce common prefix on messages
  Input: wistron_btns - switch to using kmemdup()
  Input: usbtouchscreen - switch to using kmemdup()
  Input: do not force selecting i8042 on Moorestown
  Input: Documentation/sysrq.txt - update KEY_SYSRQ info
  Input: 88pm860x_onkey - remove invalid irq number assignment
  Input: i8042 - add a PNP entry to the aux device list
  Input: i8042 - add some extra PNP keyboard types
  Input: wm9712 - fix wm97xx_set_gpio() logic
  Input: add keypad driver for keys interfaced to TCA6416
  Input: remove obsolete {corgi,spitz,tosa}kbd.c
  Input: kbtab - do not advertise unsupported events
  Input: kbtab - simplify kbtab_disconnect()
  Input: kbtab - fix incorrect size parameter in usb_buffer_free
  Input: acecad - don't advertise mouse events
  Input: acecad - fix some formatting issues
  Input: acecad - simplify usb_acecad_disconnect()
  ...

Trivial conflict in Documentation/feature-removal-schedule.txt
parents 04afb405 a62f0d27
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -177,13 +177,13 @@ virtual console (ALT+Fn) and then back again should also help.


*  I hit SysRq, but nothing seems to happen, what's wrong?
*  I hit SysRq, but nothing seems to happen, what's wrong?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are some keyboards that send different scancodes for SysRq than the
There are some keyboards that produce a different keycode for SysRq than the
pre-defined 0x54. So if SysRq doesn't work out of the box for a certain
pre-defined value of 99 (see KEY_SYSRQ in include/linux/input.h), or which
keyboard, run 'showkey -s' to find out the proper scancode sequence. Then
don't have a SysRq key at all. In these cases, run 'showkey -s' to find an
use 'setkeycodes <sequence> 84' to define this sequence to the usual SysRq
appropriate scancode sequence, and use 'setkeycodes <sequence> 99' to map
code (84 is decimal for 0x54). It's probably best to put this command in a
this sequence to the usual SysRq code (e.g., 'setkeycodes e05b 99'). It's
boot script. Oh, and by the way, you exit 'showkey' by not typing anything
probably best to put this command in a boot script. Oh, and by the way, you
for ten seconds.
exit 'showkey' by not typing anything for ten seconds.


*  I want to add SysRQ key events to a module, how does it work?
*  I want to add SysRQ key events to a module, how does it work?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+155 −170
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@
 * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
 * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
 */
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/consolemap.h>
#include <linux/consolemap.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sched.h>
@@ -38,7 +40,6 @@
#include <linux/kbd_kern.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/kbd_diacr.h>
#include <linux/vt_kern.h>
#include <linux/vt_kern.h>
#include <linux/sysrq.h>
#include <linux/input.h>
#include <linux/input.h>
#include <linux/reboot.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/notifier.h>
@@ -82,8 +83,7 @@ void compute_shiftstate(void);
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
			    char up_flag);
			    char up_flag);
static k_handler_fn K_HANDLERS;
static k_handler_fn K_HANDLERS;
k_handler_fn *k_handler[16] = { K_HANDLERS };
static k_handler_fn *k_handler[16] = { K_HANDLERS };
EXPORT_SYMBOL_GPL(k_handler);


#define FN_HANDLERS\
#define FN_HANDLERS\
	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
	fn_null,	fn_enter,	fn_show_ptregs,	fn_show_mem,\
@@ -133,7 +133,7 @@ static struct input_handler kbd_handler;
static DEFINE_SPINLOCK(kbd_event_lock);
static DEFINE_SPINLOCK(kbd_event_lock);
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];	/* keyboard key bitmap */
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)];	/* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
static unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
static int dead_key_next;
static bool dead_key_next;
static int npadch = -1;					/* -1 or number assembled on pad */
static int npadch = -1;					/* -1 or number assembled on pad */
static unsigned int diacr;
static unsigned int diacr;
static char rep;					/* flag telling character repeat */
static char rep;					/* flag telling character repeat */
@@ -147,22 +147,6 @@ static struct ledptr {
	unsigned char valid:1;
	unsigned char valid:1;
} ledptrs[3];
} ledptrs[3];


/* Simple translation table for the SysRq keys */

#ifdef CONFIG_MAGIC_SYSRQ
unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
        "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
        "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
        "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
        "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
        "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
        "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
        "\r\000/";                                      /* 0x60 - 0x6f */
static int sysrq_down;
static int sysrq_alt_use;
#endif
static int sysrq_alt;

/*
/*
 * Notifier list for console keyboard events
 * Notifier list for console keyboard events
 */
 */
@@ -469,6 +453,7 @@ static void fn_enter(struct vc_data *vc)
		}
		}
		diacr = 0;
		diacr = 0;
	}
	}

	put_queue(vc, 13);
	put_queue(vc, 13);
	if (vc_kbd_mode(kbd, VC_CRLF))
	if (vc_kbd_mode(kbd, VC_CRLF))
		put_queue(vc, 10);
		put_queue(vc, 10);
@@ -478,6 +463,7 @@ static void fn_caps_toggle(struct vc_data *vc)
{
{
	if (rep)
	if (rep)
		return;
		return;

	chg_vc_kbd_led(kbd, VC_CAPSLOCK);
	chg_vc_kbd_led(kbd, VC_CAPSLOCK);
}
}


@@ -485,12 +471,14 @@ static void fn_caps_on(struct vc_data *vc)
{
{
	if (rep)
	if (rep)
		return;
		return;

	set_vc_kbd_led(kbd, VC_CAPSLOCK);
	set_vc_kbd_led(kbd, VC_CAPSLOCK);
}
}


static void fn_show_ptregs(struct vc_data *vc)
static void fn_show_ptregs(struct vc_data *vc)
{
{
	struct pt_regs *regs = get_irq_regs();
	struct pt_regs *regs = get_irq_regs();

	if (regs)
	if (regs)
		show_regs(regs);
		show_regs(regs);
}
}
@@ -610,7 +598,7 @@ static void fn_boot_it(struct vc_data *vc)


static void fn_compose(struct vc_data *vc)
static void fn_compose(struct vc_data *vc)
{
{
	dead_key_next = 1;
	dead_key_next = true;
}
}


static void fn_spawn_con(struct vc_data *vc)
static void fn_spawn_con(struct vc_data *vc)
@@ -657,7 +645,7 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)


static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag)
{
{
	printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n");
	pr_err("k_lowercase was called - impossible\n");
}
}


static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
@@ -669,7 +657,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
		value = handle_diacr(vc, value);
		value = handle_diacr(vc, value);


	if (dead_key_next) {
	if (dead_key_next) {
		dead_key_next = 0;
		dead_key_next = false;
		diacr = value;
		diacr = value;
		return;
		return;
	}
	}
@@ -691,6 +679,7 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
{
{
	if (up_flag)
	if (up_flag)
		return;
		return;

	diacr = (diacr ? handle_diacr(vc, value) : value);
	diacr = (diacr ? handle_diacr(vc, value) : value);
}
}


@@ -710,29 +699,28 @@ static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
static void k_dead(struct vc_data *vc, unsigned char value, char up_flag)
{
{
	static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
	static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
	value = ret_diacr[value];

	k_deadunicode(vc, value, up_flag);
	k_deadunicode(vc, ret_diacr[value], up_flag);
}
}


static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
static void k_cons(struct vc_data *vc, unsigned char value, char up_flag)
{
{
	if (up_flag)
	if (up_flag)
		return;
		return;

	set_console(value);
	set_console(value);
}
}


static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
{
{
	unsigned v;

	if (up_flag)
	if (up_flag)
		return;
		return;
	v = value;

	if (v < ARRAY_SIZE(func_table)) {
	if ((unsigned)value < ARRAY_SIZE(func_table)) {
		if (func_table[value])
		if (func_table[value])
			puts_queue(vc, func_table[value]);
			puts_queue(vc, func_table[value]);
	} else
	} else
		printk(KERN_ERR "k_fn called with value=%d\n", value);
		pr_err("k_fn called with value=%d\n", value);
}
}


static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)
@@ -741,6 +729,7 @@ static void k_cur(struct vc_data *vc, unsigned char value, char up_flag)


	if (up_flag)
	if (up_flag)
		return;
		return;

	applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
	applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
}
}


@@ -758,7 +747,8 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
		return;
		return;
	}
	}


	if (!vc_kbd_led(kbd, VC_NUMLOCK))
	if (!vc_kbd_led(kbd, VC_NUMLOCK)) {

		switch (value) {
		switch (value) {
		case KVAL(K_PCOMMA):
		case KVAL(K_PCOMMA):
		case KVAL(K_PDOT):
		case KVAL(K_PDOT):
@@ -795,6 +785,7 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
			applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
			applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC));
			return;
			return;
		}
		}
	}


	put_queue(vc, pad_chars[value]);
	put_queue(vc, pad_chars[value]);
	if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
	if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
@@ -880,6 +871,7 @@ static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)
{
{
	if (up_flag || rep)
	if (up_flag || rep)
		return;
		return;

	chg_vc_kbd_lock(kbd, value);
	chg_vc_kbd_lock(kbd, value);
}
}


@@ -888,6 +880,7 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag)
	k_shift(vc, value, up_flag);
	k_shift(vc, value, up_flag);
	if (up_flag || rep)
	if (up_flag || rep)
		return;
		return;

	chg_vc_kbd_slock(kbd, value);
	chg_vc_kbd_slock(kbd, value);
	/* try to make Alt, oops, AltGr and such work */
	/* try to make Alt, oops, AltGr and such work */
	if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
	if (!key_maps[kbd->lockstate ^ kbd->slockstate]) {
@@ -930,7 +923,7 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)


	if (kbd->kbdmode != VC_UNICODE) {
	if (kbd->kbdmode != VC_UNICODE) {
		if (!up_flag)
		if (!up_flag)
			printk("keyboard mode must be unicode for braille patterns\n");
			pr_warning("keyboard mode must be unicode for braille patterns\n");
		return;
		return;
	}
	}


@@ -942,8 +935,11 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
	if (value > 8)
	if (value > 8)
		return;
		return;


	if (up_flag) {
	if (!up_flag) {
		if (brl_timeout) {
		pressed |= 1 << (value - 1);
		if (!brl_timeout)
			committing = pressed;
	} else if (brl_timeout) {
		if (!committing ||
		if (!committing ||
		    time_after(jiffies,
		    time_after(jiffies,
			       releasestart + msecs_to_jiffies(brl_timeout))) {
			       releasestart + msecs_to_jiffies(brl_timeout))) {
@@ -951,12 +947,10 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
			releasestart = jiffies;
			releasestart = jiffies;
		}
		}
		pressed &= ~(1 << (value - 1));
		pressed &= ~(1 << (value - 1));
			if (!pressed) {
		if (!pressed && committing) {
				if (committing) {
			k_brlcommit(vc, committing, 0);
			k_brlcommit(vc, committing, 0);
			committing = 0;
			committing = 0;
		}
		}
			}
	} else {
	} else {
		if (committing) {
		if (committing) {
			k_brlcommit(vc, committing, 0);
			k_brlcommit(vc, committing, 0);
@@ -964,11 +958,6 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
		}
		}
		pressed &= ~(1 << (value - 1));
		pressed &= ~(1 << (value - 1));
	}
	}
	} else {
		pressed |= 1 << (value - 1);
		if (!brl_timeout)
			committing = pressed;
	}
}
}


/*
/*
@@ -988,6 +977,7 @@ void setledstate(struct kbd_struct *kbd, unsigned int led)
		kbd->ledmode = LED_SHOW_IOCTL;
		kbd->ledmode = LED_SHOW_IOCTL;
	} else
	} else
		kbd->ledmode = LED_SHOW_FLAGS;
		kbd->ledmode = LED_SHOW_FLAGS;

	set_leds();
	set_leds();
}
}


@@ -1075,7 +1065,7 @@ static const unsigned short x86_keycodes[256] =
	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };


#ifdef CONFIG_SPARC
#ifdef CONFIG_SPARC
static int sparc_l1_a_state = 0;
static int sparc_l1_a_state;
extern void sun_do_break(void);
extern void sun_do_break(void);
#endif
#endif


@@ -1085,6 +1075,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
	int code;
	int code;


	switch (keycode) {
	switch (keycode) {

	case KEY_PAUSE:
	case KEY_PAUSE:
		put_queue(vc, 0xe1);
		put_queue(vc, 0xe1);
		put_queue(vc, 0x1d | up_flag);
		put_queue(vc, 0x1d | up_flag);
@@ -1108,7 +1099,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
		 * pressing PrtSc/SysRq alone, but simply 0x54
		 * pressing PrtSc/SysRq alone, but simply 0x54
		 * when pressing Alt+PrtSc/SysRq.
		 * when pressing Alt+PrtSc/SysRq.
		 */
		 */
			if (sysrq_alt) {
		if (test_bit(KEY_LEFTALT, key_down) ||
		    test_bit(KEY_RIGHTALT, key_down)) {
			put_queue(vc, 0x54 | up_flag);
			put_queue(vc, 0x54 | up_flag);
		} else {
		} else {
			put_queue(vc, 0xe0);
			put_queue(vc, 0xe0);
@@ -1153,6 +1145,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
static void kbd_rawcode(unsigned char data)
static void kbd_rawcode(unsigned char data)
{
{
	struct vc_data *vc = vc_cons[fg_console].d;
	struct vc_data *vc = vc_cons[fg_console].d;

	kbd = kbd_table + vc->vc_num;
	kbd = kbd_table + vc->vc_num;
	if (kbd->kbdmode == VC_RAW)
	if (kbd->kbdmode == VC_RAW)
		put_queue(vc, data);
		put_queue(vc, data);
@@ -1162,10 +1155,12 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
{
{
	struct vc_data *vc = vc_cons[fg_console].d;
	struct vc_data *vc = vc_cons[fg_console].d;
	unsigned short keysym, *key_map;
	unsigned short keysym, *key_map;
	unsigned char type, raw_mode;
	unsigned char type;
	bool raw_mode;
	struct tty_struct *tty;
	struct tty_struct *tty;
	int shift_final;
	int shift_final;
	struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
	struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down };
	int rc;


	tty = vc->vc_tty;
	tty = vc->vc_tty;


@@ -1176,8 +1171,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)


	kbd = kbd_table + vc->vc_num;
	kbd = kbd_table + vc->vc_num;


	if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
		sysrq_alt = down ? keycode : 0;
#ifdef CONFIG_SPARC
#ifdef CONFIG_SPARC
	if (keycode == KEY_STOP)
	if (keycode == KEY_STOP)
		sparc_l1_a_state = down;
		sparc_l1_a_state = down;
@@ -1185,29 +1178,16 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)


	rep = (down == 2);
	rep = (down == 2);


	if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
	raw_mode = (kbd->kbdmode == VC_RAW);
	if (raw_mode && !hw_raw)
		if (emulate_raw(vc, keycode, !down << 7))
		if (emulate_raw(vc, keycode, !down << 7))
			if (keycode < BTN_MISC && printk_ratelimit())
			if (keycode < BTN_MISC && printk_ratelimit())
				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
				pr_warning("can't emulate rawmode for keycode %d\n",
					   keycode);


#ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
	if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
		if (!sysrq_down) {
			sysrq_down = down;
			sysrq_alt_use = sysrq_alt;
		}
		return;
	}
	if (sysrq_down && !down && keycode == sysrq_alt_use)
		sysrq_down = 0;
	if (sysrq_down && down && !rep) {
		handle_sysrq(kbd_sysrq_xlate[keycode], tty);
		return;
	}
#endif
#ifdef CONFIG_SPARC
#ifdef CONFIG_SPARC
	if (keycode == KEY_A && sparc_l1_a_state) {
	if (keycode == KEY_A && sparc_l1_a_state) {
		sparc_l1_a_state = 0;
		sparc_l1_a_state = false;
		sun_do_break();
		sun_do_break();
	}
	}
#endif
#endif
@@ -1229,7 +1209,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
			put_queue(vc, (keycode >> 7) | 0x80);
			put_queue(vc, (keycode >> 7) | 0x80);
			put_queue(vc, keycode | 0x80);
			put_queue(vc, keycode | 0x80);
		}
		}
		raw_mode = 1;
		raw_mode = true;
	}
	}


	if (down)
	if (down)
@@ -1252,27 +1232,30 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
	param.ledstate = kbd->ledflagstate;
	param.ledstate = kbd->ledflagstate;
	key_map = key_maps[shift_final];
	key_map = key_maps[shift_final];


	if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
		atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, &param);
					KBD_KEYCODE, &param);
	if (rc == NOTIFY_STOP || !key_map) {
		atomic_notifier_call_chain(&keyboard_notifier_list,
					   KBD_UNBOUND_KEYCODE, &param);
		compute_shiftstate();
		compute_shiftstate();
		kbd->slockstate = 0;
		kbd->slockstate = 0;
		return;
		return;
	}
	}


	if (keycode >= NR_KEYS)
	if (keycode < NR_KEYS)
		if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
		keysym = key_map[keycode];
	else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
		keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
		keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1));
	else
	else
		return;
		return;
	else
		keysym = key_map[keycode];


	type = KTYP(keysym);
	type = KTYP(keysym);


	if (type < 0xf0) {
	if (type < 0xf0) {
		param.value = keysym;
		param.value = keysym;
		if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, &param) == NOTIFY_STOP)
		rc = atomic_notifier_call_chain(&keyboard_notifier_list,
			return;
						KBD_UNICODE, &param);
		if (rc != NOTIFY_STOP)
			if (down && !raw_mode)
			if (down && !raw_mode)
				to_utf8(vc, keysym);
				to_utf8(vc, keysym);
		return;
		return;
@@ -1288,9 +1271,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
				keysym = key_map[keycode];
				keysym = key_map[keycode];
		}
		}
	}
	}
	param.value = keysym;


	if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, &param) == NOTIFY_STOP)
	param.value = keysym;
	rc = atomic_notifier_call_chain(&keyboard_notifier_list,
					KBD_KEYSYM, &param);
	if (rc == NOTIFY_STOP)
		return;
		return;


	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
+213 −30
Original line number Original line Diff line number Diff line
/* -*- linux-c -*-
/*
 *
 *	$Id: sysrq.c,v 1.15 1998/08/23 14:56:41 mj Exp $
 *
 *	Linux Magic System Request Key Hacks
 *	Linux Magic System Request Key Hacks
 *
 *
 *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
 *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
@@ -10,8 +7,13 @@
 *	(c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
 *	(c) 2000 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
 *	overhauled to use key registration
 *	overhauled to use key registration
 *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
 *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
 *
 *	Copyright (c) 2010 Dmitry Torokhov
 *	Input handler conversion
 */
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/mm.h>
@@ -39,33 +41,34 @@
#include <linux/hrtimer.h>
#include <linux/hrtimer.h>
#include <linux/oom.h>
#include <linux/oom.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/input.h>


#include <asm/ptrace.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
#include <asm/irq_regs.h>


/* Whether we react on sysrq keys or just ignore them */
/* Whether we react on sysrq keys or just ignore them */
int __read_mostly __sysrq_enabled = 1;
static int __read_mostly sysrq_enabled = 1;

static bool __read_mostly sysrq_always_enabled;
static int __read_mostly sysrq_always_enabled;


int sysrq_on(void)
static bool sysrq_on(void)
{
{
	return __sysrq_enabled || sysrq_always_enabled;
	return sysrq_enabled || sysrq_always_enabled;
}
}


/*
/*
 * A value of 1 means 'all', other nonzero values are an op mask:
 * A value of 1 means 'all', other nonzero values are an op mask:
 */
 */
static inline int sysrq_on_mask(int mask)
static bool sysrq_on_mask(int mask)
{
{
	return sysrq_always_enabled || __sysrq_enabled == 1 ||
	return sysrq_always_enabled ||
						(__sysrq_enabled & mask);
	       sysrq_enabled == 1 ||
	       (sysrq_enabled & mask);
}
}


static int __init sysrq_always_enabled_setup(char *str)
static int __init sysrq_always_enabled_setup(char *str)
{
{
	sysrq_always_enabled = 1;
	sysrq_always_enabled = true;
	printk(KERN_INFO "debug: sysrq always enabled.\n");
	pr_info("sysrq always enabled.\n");


	return 1;
	return 1;
}
}
@@ -76,6 +79,7 @@ __setup("sysrq_always_enabled", sysrq_always_enabled_setup);
static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
{
{
	int i;
	int i;

	i = key - '0';
	i = key - '0';
	console_loglevel = 7;
	console_loglevel = 7;
	printk("Loglevel set to %d\n", i);
	printk("Loglevel set to %d\n", i);
@@ -101,7 +105,7 @@ static struct sysrq_key_op sysrq_SAK_op = {
	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
};
};
#else
#else
#define sysrq_SAK_op (*(struct sysrq_key_op *)0)
#define sysrq_SAK_op (*(struct sysrq_key_op *)NULL)
#endif
#endif


#ifdef CONFIG_VT
#ifdef CONFIG_VT
@@ -119,7 +123,7 @@ static struct sysrq_key_op sysrq_unraw_op = {
	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
	.enable_mask	= SYSRQ_ENABLE_KEYBOARD,
};
};
#else
#else
#define sysrq_unraw_op (*(struct sysrq_key_op *)0)
#define sysrq_unraw_op (*(struct sysrq_key_op *)NULL)
#endif /* CONFIG_VT */
#endif /* CONFIG_VT */


static void sysrq_handle_crash(int key, struct tty_struct *tty)
static void sysrq_handle_crash(int key, struct tty_struct *tty)
@@ -195,7 +199,7 @@ static struct sysrq_key_op sysrq_showlocks_op = {
	.action_msg	= "Show Locks Held",
	.action_msg	= "Show Locks Held",
};
};
#else
#else
#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
#define sysrq_showlocks_op (*(struct sysrq_key_op *)NULL)
#endif
#endif


#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
@@ -298,7 +302,7 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = {
	.enable_mask	= SYSRQ_ENABLE_DUMP,
	.enable_mask	= SYSRQ_ENABLE_DUMP,
};
};
#else
#else
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)0)
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL)
#endif
#endif


static void sysrq_handle_showmem(int key, struct tty_struct *tty)
static void sysrq_handle_showmem(int key, struct tty_struct *tty)
@@ -477,6 +481,7 @@ struct sysrq_key_op *__sysrq_get_key_op(int key)
	i = sysrq_key_table_key2index(key);
	i = sysrq_key_table_key2index(key);
	if (i != -1)
	if (i != -1)
	        op_p = sysrq_key_table[i];
	        op_p = sysrq_key_table[i];

        return op_p;
        return op_p;
}
}


@@ -488,11 +493,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
                sysrq_key_table[i] = op_p;
                sysrq_key_table[i] = op_p;
}
}


/*
static void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
 * This is the non-locking version of handle_sysrq.  It must/can only be called
 * by sysrq key handlers, as they are inside of the lock
 */
void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
{
{
	struct sysrq_key_op *op_p;
	struct sysrq_key_op *op_p;
	int orig_log_level;
	int orig_log_level;
@@ -544,10 +545,6 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
	spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
	spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
}
}


/*
 * This function is called by the keyboard handler when SysRq is pressed
 * and any other keycode arrives.
 */
void handle_sysrq(int key, struct tty_struct *tty)
void handle_sysrq(int key, struct tty_struct *tty)
{
{
	if (sysrq_on())
	if (sysrq_on())
@@ -555,10 +552,177 @@ void handle_sysrq(int key, struct tty_struct *tty)
}
}
EXPORT_SYMBOL(handle_sysrq);
EXPORT_SYMBOL(handle_sysrq);


#ifdef CONFIG_INPUT

/* Simple translation table for the SysRq keys */
static const unsigned char sysrq_xlate[KEY_MAX + 1] =
        "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
        "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
        "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
        "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
        "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
        "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
        "\r\000/";                                      /* 0x60 - 0x6f */

static bool sysrq_down;
static int sysrq_alt_use;
static int sysrq_alt;

static bool sysrq_filter(struct input_handle *handle, unsigned int type,
		         unsigned int code, int value)
{
	if (type != EV_KEY)
		goto out;

	switch (code) {

	case KEY_LEFTALT:
	case KEY_RIGHTALT:
		if (value)
			sysrq_alt = code;
		else if (sysrq_down && code == sysrq_alt_use)
			sysrq_down = false;
		break;

	case KEY_SYSRQ:
		if (value == 1 && sysrq_alt) {
			sysrq_down = true;
			sysrq_alt_use = sysrq_alt;
		}
		break;

	default:
		if (sysrq_down && value && value != 2)
			__handle_sysrq(sysrq_xlate[code], NULL, 1);
		break;
	}

out:
	return sysrq_down;
}

static int sysrq_connect(struct input_handler *handler,
			 struct input_dev *dev,
			 const struct input_device_id *id)
{
	struct input_handle *handle;
	int error;

	sysrq_down = false;
	sysrq_alt = 0;

	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
	if (!handle)
		return -ENOMEM;

	handle->dev = dev;
	handle->handler = handler;
	handle->name = "sysrq";

	error = input_register_handle(handle);
	if (error) {
		pr_err("Failed to register input sysrq handler, error %d\n",
			error);
		goto err_free;
	}

	error = input_open_device(handle);
	if (error) {
		pr_err("Failed to open input device, error %d\n", error);
		goto err_unregister;
	}

	return 0;

 err_unregister:
	input_unregister_handle(handle);
 err_free:
	kfree(handle);
	return error;
}

static void sysrq_disconnect(struct input_handle *handle)
{
	input_close_device(handle);
	input_unregister_handle(handle);
	kfree(handle);
}

/*
 * We are matching on KEY_LEFTALT insteard of KEY_SYSRQ because not all
 * keyboards have SysRq ikey predefined and so user may add it to keymap
 * later, but we expect all such keyboards to have left alt.
 */
static const struct input_device_id sysrq_ids[] = {
	{
		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
				INPUT_DEVICE_ID_MATCH_KEYBIT,
		.evbit = { BIT_MASK(EV_KEY) },
		.keybit = { BIT_MASK(KEY_LEFTALT) },
	},
	{ },
};

static struct input_handler sysrq_handler = {
	.filter		= sysrq_filter,
	.connect	= sysrq_connect,
	.disconnect	= sysrq_disconnect,
	.name		= "sysrq",
	.id_table	= sysrq_ids,
};

static bool sysrq_handler_registered;

static inline void sysrq_register_handler(void)
{
	int error;

	error = input_register_handler(&sysrq_handler);
	if (error)
		pr_err("Failed to register input handler, error %d", error);
	else
		sysrq_handler_registered = true;
}

static inline void sysrq_unregister_handler(void)
{
	if (sysrq_handler_registered) {
		input_unregister_handler(&sysrq_handler);
		sysrq_handler_registered = false;
	}
}

#else

static inline void sysrq_register_handler(void)
{
}

static inline void sysrq_unregister_handler(void)
{
}

#endif /* CONFIG_INPUT */

int sysrq_toggle_support(int enable_mask)
{
	bool was_enabled = sysrq_on();

	sysrq_enabled = enable_mask;

	if (was_enabled != sysrq_on()) {
		if (sysrq_on())
			sysrq_register_handler();
		else
			sysrq_unregister_handler();
	}

	return 0;
}

static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
                                struct sysrq_key_op *remove_op_p)
                                struct sysrq_key_op *remove_op_p)
{
{

	int retval;
	int retval;
	unsigned long flags;
	unsigned long flags;


@@ -599,6 +763,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
			return -EFAULT;
			return -EFAULT;
		__handle_sysrq(c, NULL, 0);
		__handle_sysrq(c, NULL, 0);
	}
	}

	return count;
	return count;
}
}


@@ -606,10 +771,28 @@ static const struct file_operations proc_sysrq_trigger_operations = {
	.write		= write_sysrq_trigger,
	.write		= write_sysrq_trigger,
};
};


static void sysrq_init_procfs(void)
{
	if (!proc_create("sysrq-trigger", S_IWUSR, NULL,
			 &proc_sysrq_trigger_operations))
		pr_err("Failed to register proc interface\n");
}

#else

static inline void sysrq_init_procfs(void)
{
}

#endif /* CONFIG_PROC_FS */

static int __init sysrq_init(void)
static int __init sysrq_init(void)
{
{
	proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
	sysrq_init_procfs();

	if (sysrq_on())
		sysrq_register_handler();

	return 0;
	return 0;
}
}
module_init(sysrq_init);
module_init(sysrq_init);
#endif
+17 −1
Original line number Original line Diff line number Diff line
@@ -73,7 +73,7 @@ config KEYBOARD_ATKBD
	default y
	default y
	select SERIO
	select SERIO
	select SERIO_LIBPS2
	select SERIO_LIBPS2
	select SERIO_I8042 if X86
	select SERIO_I8042 if X86 && !X86_MRST
	select SERIO_GSCPS2 if GSC
	select SERIO_GSCPS2 if GSC
	help
	help
	  Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
	  Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
@@ -179,6 +179,22 @@ config KEYBOARD_GPIO
	  To compile this driver as a module, choose M here: the
	  To compile this driver as a module, choose M here: the
	  module will be called gpio_keys.
	  module will be called gpio_keys.


config KEYBOARD_TCA6416
	tristate "TCA6416 Keypad Support"
	depends on I2C
	help
	  This driver implements basic keypad functionality
	  for keys connected through TCA6416 IO expander

	  Say Y here if your device has keys connected to
	  TCA6416 IO expander. Your board-specific setup logic
	  must also provide pin-mask details(of which TCA6416 pins
	  are used for keypad).

	  If enabled the complete TCA6416 device will be managed through
	  this driver.


config KEYBOARD_MATRIX
config KEYBOARD_MATRIX
	tristate "GPIO driven matrix keypad support"
	tristate "GPIO driven matrix keypad support"
	depends on GENERIC_GPIO
	depends on GENERIC_GPIO
+1 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_DAVINCI)		+= davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_DAVINCI)		+= davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_EP93XX)		+= ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_EP93XX)		+= ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
obj-$(CONFIG_KEYBOARD_TCA6416)		+= tca6416-keypad.o
obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
obj-$(CONFIG_KEYBOARD_IMX)		+= imx_keypad.o
obj-$(CONFIG_KEYBOARD_IMX)		+= imx_keypad.o
Loading