diff options
| -rw-r--r-- | drivers/char/keyboard.c | 118 | ||||
| -rw-r--r-- | include/linux/input.h | 9 | ||||
| -rw-r--r-- | include/linux/kbd_kern.h | 2 | ||||
| -rw-r--r-- | include/linux/keyboard.h | 13 |
4 files changed, 125 insertions, 17 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 8b603b2d1c42..935670a3cd98 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
| @@ -74,7 +74,7 @@ void compute_shiftstate(void); | |||
| 74 | k_self, k_fn, k_spec, k_pad,\ | 74 | k_self, k_fn, k_spec, k_pad,\ |
| 75 | k_dead, k_cons, k_cur, k_shift,\ | 75 | k_dead, k_cons, k_cur, k_shift,\ |
| 76 | k_meta, k_ascii, k_lock, k_lowercase,\ | 76 | k_meta, k_ascii, k_lock, k_lowercase,\ |
| 77 | k_slock, k_dead2, k_ignore, k_ignore | 77 | k_slock, k_dead2, k_brl, k_ignore |
| 78 | 78 | ||
| 79 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, | 79 | typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, |
| 80 | char up_flag, struct pt_regs *regs); | 80 | char up_flag, struct pt_regs *regs); |
| @@ -100,7 +100,7 @@ static fn_handler_fn *fn_handler[] = { FN_HANDLERS }; | |||
| 100 | const int max_vals[] = { | 100 | const int max_vals[] = { |
| 101 | 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, | 101 | 255, ARRAY_SIZE(func_table) - 1, ARRAY_SIZE(fn_handler) - 1, NR_PAD - 1, |
| 102 | NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, | 102 | NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, |
| 103 | 255, NR_LOCK - 1, 255 | 103 | 255, NR_LOCK - 1, 255, NR_BRL - 1 |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | const int NR_TYPES = ARRAY_SIZE(max_vals); | 106 | const int NR_TYPES = ARRAY_SIZE(max_vals); |
| @@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */ | |||
| 126 | static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ | 126 | static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ |
| 127 | static int dead_key_next; | 127 | static int dead_key_next; |
| 128 | static int npadch = -1; /* -1 or number assembled on pad */ | 128 | static int npadch = -1; /* -1 or number assembled on pad */ |
| 129 | static unsigned char diacr; | 129 | static unsigned int diacr; |
| 130 | static char rep; /* flag telling character repeat */ | 130 | static char rep; /* flag telling character repeat */ |
| 131 | 131 | ||
| 132 | static unsigned char ledstate = 0xff; /* undefined */ | 132 | static unsigned char ledstate = 0xff; /* undefined */ |
| @@ -394,22 +394,30 @@ void compute_shiftstate(void) | |||
| 394 | * Otherwise, conclude that DIACR was not combining after all, | 394 | * Otherwise, conclude that DIACR was not combining after all, |
| 395 | * queue it and return CH. | 395 | * queue it and return CH. |
| 396 | */ | 396 | */ |
| 397 | static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) | 397 | static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch) |
| 398 | { | 398 | { |
| 399 | int d = diacr; | 399 | unsigned int d = diacr; |
| 400 | unsigned int i; | 400 | unsigned int i; |
| 401 | 401 | ||
| 402 | diacr = 0; | 402 | diacr = 0; |
| 403 | 403 | ||
| 404 | for (i = 0; i < accent_table_size; i++) { | 404 | if ((d & ~0xff) == BRL_UC_ROW) { |
| 405 | if (accent_table[i].diacr == d && accent_table[i].base == ch) | 405 | if ((ch & ~0xff) == BRL_UC_ROW) |
| 406 | return accent_table[i].result; | 406 | return d | ch; |
| 407 | } else { | ||
| 408 | for (i = 0; i < accent_table_size; i++) | ||
| 409 | if (accent_table[i].diacr == d && accent_table[i].base == ch) | ||
| 410 | return accent_table[i].result; | ||
| 407 | } | 411 | } |
| 408 | 412 | ||
| 409 | if (ch == ' ' || ch == d) | 413 | if (ch == ' ' || ch == (BRL_UC_ROW|0) || ch == d) |
| 410 | return d; | 414 | return d; |
| 411 | 415 | ||
| 412 | put_queue(vc, d); | 416 | if (kbd->kbdmode == VC_UNICODE) |
| 417 | to_utf8(vc, d); | ||
| 418 | else if (d < 0x100) | ||
| 419 | put_queue(vc, d); | ||
| 420 | |||
| 413 | return ch; | 421 | return ch; |
| 414 | } | 422 | } |
| 415 | 423 | ||
| @@ -419,7 +427,10 @@ static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) | |||
| 419 | static void fn_enter(struct vc_data *vc, struct pt_regs *regs) | 427 | static void fn_enter(struct vc_data *vc, struct pt_regs *regs) |
| 420 | { | 428 | { |
| 421 | if (diacr) { | 429 | if (diacr) { |
| 422 | put_queue(vc, diacr); | 430 | if (kbd->kbdmode == VC_UNICODE) |
| 431 | to_utf8(vc, diacr); | ||
| 432 | else if (diacr < 0x100) | ||
| 433 | put_queue(vc, diacr); | ||
| 423 | diacr = 0; | 434 | diacr = 0; |
| 424 | } | 435 | } |
| 425 | put_queue(vc, 13); | 436 | put_queue(vc, 13); |
| @@ -615,7 +626,7 @@ static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag, s | |||
| 615 | printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); | 626 | printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); |
| 616 | } | 627 | } |
| 617 | 628 | ||
| 618 | static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 629 | static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs) |
| 619 | { | 630 | { |
| 620 | if (up_flag) | 631 | if (up_flag) |
| 621 | return; /* no action, if this is a key release */ | 632 | return; /* no action, if this is a key release */ |
| @@ -628,7 +639,10 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
| 628 | diacr = value; | 639 | diacr = value; |
| 629 | return; | 640 | return; |
| 630 | } | 641 | } |
| 631 | put_queue(vc, value); | 642 | if (kbd->kbdmode == VC_UNICODE) |
| 643 | to_utf8(vc, value); | ||
| 644 | else if (value < 0x100) | ||
| 645 | put_queue(vc, value); | ||
| 632 | } | 646 | } |
| 633 | 647 | ||
| 634 | /* | 648 | /* |
| @@ -636,13 +650,23 @@ static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
| 636 | * dead keys modifying the same character. Very useful | 650 | * dead keys modifying the same character. Very useful |
| 637 | * for Vietnamese. | 651 | * for Vietnamese. |
| 638 | */ | 652 | */ |
| 639 | static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 653 | static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag, struct pt_regs *regs) |
| 640 | { | 654 | { |
| 641 | if (up_flag) | 655 | if (up_flag) |
| 642 | return; | 656 | return; |
| 643 | diacr = (diacr ? handle_diacr(vc, value) : value); | 657 | diacr = (diacr ? handle_diacr(vc, value) : value); |
| 644 | } | 658 | } |
| 645 | 659 | ||
| 660 | static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | ||
| 661 | { | ||
| 662 | k_unicode(vc, value, up_flag, regs); | ||
| 663 | } | ||
| 664 | |||
| 665 | static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | ||
| 666 | { | ||
| 667 | k_deadunicode(vc, value, up_flag, regs); | ||
| 668 | } | ||
| 669 | |||
| 646 | /* | 670 | /* |
| 647 | * Obsolete - for backwards compatibility only | 671 | * Obsolete - for backwards compatibility only |
| 648 | */ | 672 | */ |
| @@ -650,7 +674,7 @@ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct | |||
| 650 | { | 674 | { |
| 651 | static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; | 675 | static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; |
| 652 | value = ret_diacr[value]; | 676 | value = ret_diacr[value]; |
| 653 | k_dead2(vc, value, up_flag, regs); | 677 | k_deadunicode(vc, value, up_flag, regs); |
| 654 | } | 678 | } |
| 655 | 679 | ||
| 656 | static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | 680 | static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) |
| @@ -835,6 +859,62 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc | |||
| 835 | } | 859 | } |
| 836 | } | 860 | } |
| 837 | 861 | ||
| 862 | /* by default, 300ms interval for combination release */ | ||
| 863 | static long brl_timeout = 300; | ||
| 864 | MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)"); | ||
| 865 | module_param(brl_timeout, long, 0644); | ||
| 866 | static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) | ||
| 867 | { | ||
| 868 | static unsigned pressed,committing; | ||
| 869 | static unsigned long releasestart; | ||
| 870 | |||
| 871 | if (kbd->kbdmode != VC_UNICODE) { | ||
| 872 | if (!up_flag) | ||
| 873 | printk("keyboard mode must be unicode for braille patterns\n"); | ||
| 874 | return; | ||
| 875 | } | ||
| 876 | |||
| 877 | if (!value) { | ||
| 878 | k_unicode(vc, BRL_UC_ROW, up_flag, regs); | ||
| 879 | return; | ||
| 880 | } | ||
| 881 | |||
| 882 | if (value > 8) | ||
| 883 | return; | ||
| 884 | |||
| 885 | if (brl_timeout < 0) { | ||
| 886 | k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs); | ||
| 887 | return; | ||
| 888 | } | ||
| 889 | |||
| 890 | if (up_flag) { | ||
| 891 | if (brl_timeout) { | ||
| 892 | if (!committing || | ||
| 893 | jiffies - releasestart > (brl_timeout * HZ) / 1000) { | ||
| 894 | committing = pressed; | ||
| 895 | releasestart = jiffies; | ||
| 896 | } | ||
| 897 | pressed &= ~(1 << (value - 1)); | ||
| 898 | if (!pressed) { | ||
| 899 | if (committing) { | ||
| 900 | k_unicode(vc, BRL_UC_ROW | committing, 0, regs); | ||
| 901 | committing = 0; | ||
| 902 | } | ||
| 903 | } | ||
| 904 | } else { | ||
| 905 | if (committing) { | ||
| 906 | k_unicode(vc, BRL_UC_ROW | committing, 0, regs); | ||
| 907 | committing = 0; | ||
| 908 | } | ||
| 909 | pressed &= ~(1 << (value - 1)); | ||
| 910 | } | ||
| 911 | } else { | ||
| 912 | pressed |= 1 << (value - 1); | ||
| 913 | if (!brl_timeout) | ||
| 914 | committing = pressed; | ||
| 915 | } | ||
| 916 | } | ||
| 917 | |||
| 838 | /* | 918 | /* |
| 839 | * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, | 919 | * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, |
| 840 | * or (ii) whatever pattern of lights people want to show using KDSETLED, | 920 | * or (ii) whatever pattern of lights people want to show using KDSETLED, |
| @@ -1125,9 +1205,13 @@ static void kbd_keycode(unsigned int keycode, int down, | |||
| 1125 | } | 1205 | } |
| 1126 | 1206 | ||
| 1127 | if (keycode > NR_KEYS) | 1207 | if (keycode > NR_KEYS) |
| 1128 | return; | 1208 | if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) |
| 1209 | keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1); | ||
| 1210 | else | ||
| 1211 | return; | ||
| 1212 | else | ||
| 1213 | keysym = key_map[keycode]; | ||
| 1129 | 1214 | ||
| 1130 | keysym = key_map[keycode]; | ||
| 1131 | type = KTYP(keysym); | 1215 | type = KTYP(keysym); |
| 1132 | 1216 | ||
| 1133 | if (type < 0xf0) { | 1217 | if (type < 0xf0) { |
diff --git a/include/linux/input.h b/include/linux/input.h index 393da04f4301..b0e612dda0cf 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -512,6 +512,15 @@ struct input_absinfo { | |||
| 512 | #define KEY_FN_S 0x1e3 | 512 | #define KEY_FN_S 0x1e3 |
| 513 | #define KEY_FN_B 0x1e4 | 513 | #define KEY_FN_B 0x1e4 |
| 514 | 514 | ||
| 515 | #define KEY_BRL_DOT1 0x1f1 | ||
| 516 | #define KEY_BRL_DOT2 0x1f2 | ||
| 517 | #define KEY_BRL_DOT3 0x1f3 | ||
| 518 | #define KEY_BRL_DOT4 0x1f4 | ||
| 519 | #define KEY_BRL_DOT5 0x1f5 | ||
| 520 | #define KEY_BRL_DOT6 0x1f6 | ||
| 521 | #define KEY_BRL_DOT7 0x1f7 | ||
| 522 | #define KEY_BRL_DOT8 0x1f8 | ||
| 523 | |||
| 515 | /* We avoid low common keys in module aliases so they don't get huge. */ | 524 | /* We avoid low common keys in module aliases so they don't get huge. */ |
| 516 | #define KEY_MIN_INTERESTING KEY_MUTE | 525 | #define KEY_MIN_INTERESTING KEY_MUTE |
| 517 | #define KEY_MAX 0x1ff | 526 | #define KEY_MAX 0x1ff |
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index e87c32a5c86a..4eb851ece080 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h | |||
| @@ -135,6 +135,8 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag) | |||
| 135 | 135 | ||
| 136 | #define U(x) ((x) ^ 0xf000) | 136 | #define U(x) ((x) ^ 0xf000) |
| 137 | 137 | ||
| 138 | #define BRL_UC_ROW 0x2800 | ||
| 139 | |||
| 138 | /* keyboard.c */ | 140 | /* keyboard.c */ |
| 139 | 141 | ||
| 140 | struct console; | 142 | struct console; |
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h index 08488042d74a..de76843bbe8a 100644 --- a/include/linux/keyboard.h +++ b/include/linux/keyboard.h | |||
| @@ -44,6 +44,7 @@ extern unsigned short plain_map[NR_KEYS]; | |||
| 44 | #define KT_ASCII 9 | 44 | #define KT_ASCII 9 |
| 45 | #define KT_LOCK 10 | 45 | #define KT_LOCK 10 |
| 46 | #define KT_SLOCK 12 | 46 | #define KT_SLOCK 12 |
| 47 | #define KT_BRL 14 | ||
| 47 | 48 | ||
| 48 | #define K(t,v) (((t)<<8)|(v)) | 49 | #define K(t,v) (((t)<<8)|(v)) |
| 49 | #define KTYP(x) ((x) >> 8) | 50 | #define KTYP(x) ((x) >> 8) |
| @@ -427,5 +428,17 @@ extern unsigned short plain_map[NR_KEYS]; | |||
| 427 | 428 | ||
| 428 | #define NR_LOCK 8 | 429 | #define NR_LOCK 8 |
| 429 | 430 | ||
| 431 | #define K_BRL_BLANK K(KT_BRL, 0) | ||
| 432 | #define K_BRL_DOT1 K(KT_BRL, 1) | ||
| 433 | #define K_BRL_DOT2 K(KT_BRL, 2) | ||
| 434 | #define K_BRL_DOT3 K(KT_BRL, 3) | ||
| 435 | #define K_BRL_DOT4 K(KT_BRL, 4) | ||
| 436 | #define K_BRL_DOT5 K(KT_BRL, 5) | ||
| 437 | #define K_BRL_DOT6 K(KT_BRL, 6) | ||
| 438 | #define K_BRL_DOT7 K(KT_BRL, 7) | ||
| 439 | #define K_BRL_DOT8 K(KT_BRL, 8) | ||
| 440 | |||
| 441 | #define NR_BRL 9 | ||
| 442 | |||
| 430 | #define MAX_DIACR 256 | 443 | #define MAX_DIACR 256 |
| 431 | #endif | 444 | #endif |
