aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2006-04-02 00:10:28 -0500
committerDmitry Torokhov <dtor_core@ameritech.net>2006-04-02 00:10:28 -0500
commitb9ec4e109d7a342e83e1210e05797222e36555c3 (patch)
tree47ff5cb19c3b43f9907006e7b491df547f29b71e
parent53a2670cd9611cf7c3b3bf9875b0b4041160fa60 (diff)
Input: add support for Braille devices
- Add KEY_BRL_* input keys and K_BRL_* keycodes; - Add emulation of how braille keyboards usually combine braille dots to the console keyboard driver; - Add handling of unicode U+28xy diacritics. Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/char/keyboard.c118
-rw-r--r--include/linux/input.h9
-rw-r--r--include/linux/kbd_kern.h2
-rw-r--r--include/linux/keyboard.h13
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
79typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, 79typedef 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 };
100const int max_vals[] = { 100const 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
106const int NR_TYPES = ARRAY_SIZE(max_vals); 106const int NR_TYPES = ARRAY_SIZE(max_vals);
@@ -126,7 +126,7 @@ static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */
126static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ 126static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
127static int dead_key_next; 127static int dead_key_next;
128static int npadch = -1; /* -1 or number assembled on pad */ 128static int npadch = -1; /* -1 or number assembled on pad */
129static unsigned char diacr; 129static unsigned int diacr;
130static char rep; /* flag telling character repeat */ 130static char rep; /* flag telling character repeat */
131 131
132static unsigned char ledstate = 0xff; /* undefined */ 132static 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 */
397static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) 397static 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)
419static void fn_enter(struct vc_data *vc, struct pt_regs *regs) 427static 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
618static void k_self(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) 629static 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 */
639static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) 653static 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
660static 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
665static 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
656static void k_cons(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) 680static 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 */
863static long brl_timeout = 300;
864MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)");
865module_param(brl_timeout, long, 0644);
866static 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
140struct console; 142struct 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