aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acorn/char/defkeymap-l7200.c2
-rw-r--r--drivers/char/consolemap.c22
-rw-r--r--drivers/char/defkeymap.c_shipped2
-rw-r--r--drivers/char/keyboard.c35
-rw-r--r--drivers/char/vt_ioctl.c46
-rw-r--r--drivers/s390/char/defkeymap.c2
-rw-r--r--drivers/s390/char/keyboard.c66
-rw-r--r--drivers/s390/char/keyboard.h4
-rw-r--r--drivers/tc/lk201-map.c_shipped2
-rw-r--r--include/linux/consolemap.h1
-rw-r--r--include/linux/kbd_diacr.h2
-rw-r--r--include/linux/kd.h10
12 files changed, 158 insertions, 36 deletions
diff --git a/drivers/acorn/char/defkeymap-l7200.c b/drivers/acorn/char/defkeymap-l7200.c
index 9e18ce742e38..28a5fbc6aa1a 100644
--- a/drivers/acorn/char/defkeymap-l7200.c
+++ b/drivers/acorn/char/defkeymap-l7200.c
@@ -346,7 +346,7 @@ char *func_table[MAX_NR_FUNC] = {
346 0, 346 0,
347}; 347};
348 348
349struct kbdiacr accent_table[MAX_DIACR] = { 349struct kbdiacruc accent_table[MAX_DIACR] = {
350 {'`', 'A', '\300'}, {'`', 'a', '\340'}, 350 {'`', 'A', '\300'}, {'`', 'a', '\340'},
351 {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, 351 {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
352 {'^', 'A', '\302'}, {'^', 'a', '\342'}, 352 {'^', 'A', '\302'}, {'^', 'a', '\342'},
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 163f3fce3f84..6b104e45a322 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -669,19 +669,29 @@ void con_protect_unimap(struct vc_data *vc, int rdonly)
669 p->readonly = rdonly; 669 p->readonly = rdonly;
670} 670}
671 671
672/*
673 * Always use USER_MAP. These functions are used by the keyboard,
674 * which shouldn't be affected by G0/G1 switching, etc.
675 * If the user map still contains default values, i.e. the
676 * direct-to-font mapping, then assume user is using Latin1.
677 */
672/* may be called during an interrupt */ 678/* may be called during an interrupt */
673u32 conv_8bit_to_uni(unsigned char c) 679u32 conv_8bit_to_uni(unsigned char c)
674{ 680{
675 /*
676 * Always use USER_MAP. This function is used by the keyboard,
677 * which shouldn't be affected by G0/G1 switching, etc.
678 * If the user map still contains default values, i.e. the
679 * direct-to-font mapping, then assume user is using Latin1.
680 */
681 unsigned short uni = translations[USER_MAP][c]; 681 unsigned short uni = translations[USER_MAP][c];
682 return uni == (0xf000 | c) ? c : uni; 682 return uni == (0xf000 | c) ? c : uni;
683} 683}
684 684
685int conv_uni_to_8bit(u32 uni)
686{
687 int c;
688 for (c = 0; c < 0x100; c++)
689 if (translations[USER_MAP][c] == uni ||
690 (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
691 return c;
692 return -1;
693}
694
685int 695int
686conv_uni_to_pc(struct vc_data *conp, long ucs) 696conv_uni_to_pc(struct vc_data *conp, long ucs)
687{ 697{
diff --git a/drivers/char/defkeymap.c_shipped b/drivers/char/defkeymap.c_shipped
index 453a2f1ffa15..0aa419a61767 100644
--- a/drivers/char/defkeymap.c_shipped
+++ b/drivers/char/defkeymap.c_shipped
@@ -222,7 +222,7 @@ char *func_table[MAX_NR_FUNC] = {
222 NULL, 222 NULL,
223}; 223};
224 224
225struct kbdiacr accent_table[MAX_DIACR] = { 225struct kbdiacruc accent_table[MAX_DIACR] = {
226 {'`', 'A', '\300'}, {'`', 'a', '\340'}, 226 {'`', 'A', '\300'}, {'`', 'a', '\340'},
227 {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, 227 {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
228 {'^', 'A', '\302'}, {'^', 'a', '\342'}, 228 {'^', 'A', '\302'}, {'^', 'a', '\342'},
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index d95f316afb5a..5ae2a3250c50 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -38,6 +38,7 @@
38#include <linux/kbd_kern.h> 38#include <linux/kbd_kern.h>
39#include <linux/kbd_diacr.h> 39#include <linux/kbd_diacr.h>
40#include <linux/vt_kern.h> 40#include <linux/vt_kern.h>
41#include <linux/consolemap.h>
41#include <linux/sysrq.h> 42#include <linux/sysrq.h>
42#include <linux/input.h> 43#include <linux/input.h>
43#include <linux/reboot.h> 44#include <linux/reboot.h>
@@ -403,9 +404,12 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
403 return d; 404 return d;
404 405
405 if (kbd->kbdmode == VC_UNICODE) 406 if (kbd->kbdmode == VC_UNICODE)
406 to_utf8(vc, conv_8bit_to_uni(d)); 407 to_utf8(vc, d);
407 else if (d < 0x100) 408 else {
408 put_queue(vc, d); 409 int c = conv_uni_to_8bit(d);
410 if (c != -1)
411 put_queue(vc, c);
412 }
409 413
410 return ch; 414 return ch;
411} 415}
@@ -417,9 +421,12 @@ static void fn_enter(struct vc_data *vc)
417{ 421{
418 if (diacr) { 422 if (diacr) {
419 if (kbd->kbdmode == VC_UNICODE) 423 if (kbd->kbdmode == VC_UNICODE)
420 to_utf8(vc, conv_8bit_to_uni(diacr)); 424 to_utf8(vc, diacr);
421 else if (diacr < 0x100) 425 else {
422 put_queue(vc, diacr); 426 int c = conv_uni_to_8bit(diacr);
427 if (c != -1)
428 put_queue(vc, c);
429 }
423 diacr = 0; 430 diacr = 0;
424 } 431 }
425 put_queue(vc, 13); 432 put_queue(vc, 13);
@@ -627,9 +634,12 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
627 return; 634 return;
628 } 635 }
629 if (kbd->kbdmode == VC_UNICODE) 636 if (kbd->kbdmode == VC_UNICODE)
630 to_utf8(vc, conv_8bit_to_uni(value)); 637 to_utf8(vc, value);
631 else if (value < 0x100) 638 else {
632 put_queue(vc, value); 639 int c = conv_uni_to_8bit(value);
640 if (c != -1)
641 put_queue(vc, c);
642 }
633} 643}
634 644
635/* 645/*
@@ -646,7 +656,12 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag)
646 656
647static void k_self(struct vc_data *vc, unsigned char value, char up_flag) 657static void k_self(struct vc_data *vc, unsigned char value, char up_flag)
648{ 658{
649 k_unicode(vc, value, up_flag); 659 unsigned int uni;
660 if (kbd->kbdmode == VC_UNICODE)
661 uni = value;
662 else
663 uni = conv_8bit_to_uni(value);
664 k_unicode(vc, uni, up_flag);
650} 665}
651 666
652static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag) 667static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag)
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index f69a8258095c..6c7384afff13 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -23,6 +23,7 @@
23#include <linux/major.h> 23#include <linux/major.h>
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/console.h> 25#include <linux/console.h>
26#include <linux/consolemap.h>
26#include <linux/signal.h> 27#include <linux/signal.h>
27#include <linux/timex.h> 28#include <linux/timex.h>
28 29
@@ -582,10 +583,27 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
582 case KDGKBDIACR: 583 case KDGKBDIACR:
583 { 584 {
584 struct kbdiacrs __user *a = up; 585 struct kbdiacrs __user *a = up;
586 struct kbdiacr diacr;
587 int i;
585 588
586 if (put_user(accent_table_size, &a->kb_cnt)) 589 if (put_user(accent_table_size, &a->kb_cnt))
587 return -EFAULT; 590 return -EFAULT;
588 if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr))) 591 for (i = 0; i < accent_table_size; i++) {
592 diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr);
593 diacr.base = conv_uni_to_8bit(accent_table[i].base);
594 diacr.result = conv_uni_to_8bit(accent_table[i].result);
595 if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr)))
596 return -EFAULT;
597 }
598 return 0;
599 }
600 case KDGKBDIACRUC:
601 {
602 struct kbdiacrsuc __user *a = up;
603
604 if (put_user(accent_table_size, &a->kb_cnt))
605 return -EFAULT;
606 if (copy_to_user(a->kbdiacruc, accent_table, accent_table_size*sizeof(struct kbdiacruc)))
589 return -EFAULT; 607 return -EFAULT;
590 return 0; 608 return 0;
591 } 609 }
@@ -593,6 +611,30 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
593 case KDSKBDIACR: 611 case KDSKBDIACR:
594 { 612 {
595 struct kbdiacrs __user *a = up; 613 struct kbdiacrs __user *a = up;
614 struct kbdiacr diacr;
615 unsigned int ct;
616 int i;
617
618 if (!perm)
619 return -EPERM;
620 if (get_user(ct,&a->kb_cnt))
621 return -EFAULT;
622 if (ct >= MAX_DIACR)
623 return -EINVAL;
624 accent_table_size = ct;
625 for (i = 0; i < ct; i++) {
626 if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr)))
627 return -EFAULT;
628 accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr);
629 accent_table[i].base = conv_8bit_to_uni(diacr.base);
630 accent_table[i].result = conv_8bit_to_uni(diacr.result);
631 }
632 return 0;
633 }
634
635 case KDSKBDIACRUC:
636 {
637 struct kbdiacrsuc __user *a = up;
596 unsigned int ct; 638 unsigned int ct;
597 639
598 if (!perm) 640 if (!perm)
@@ -602,7 +644,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
602 if (ct >= MAX_DIACR) 644 if (ct >= MAX_DIACR)
603 return -EINVAL; 645 return -EINVAL;
604 accent_table_size = ct; 646 accent_table_size = ct;
605 if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr))) 647 if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc)))
606 return -EFAULT; 648 return -EFAULT;
607 return 0; 649 return 0;
608 } 650 }
diff --git a/drivers/s390/char/defkeymap.c b/drivers/s390/char/defkeymap.c
index 564baca01b7c..389346cda6c8 100644
--- a/drivers/s390/char/defkeymap.c
+++ b/drivers/s390/char/defkeymap.c
@@ -150,7 +150,7 @@ char *func_table[MAX_NR_FUNC] = {
150 NULL, 150 NULL,
151}; 151};
152 152
153struct kbdiacr accent_table[MAX_DIACR] = { 153struct kbdiacruc accent_table[MAX_DIACR] = {
154 {'^', 'c', '\003'}, {'^', 'd', '\004'}, 154 {'^', 'c', '\003'}, {'^', 'd', '\004'},
155 {'^', 'z', '\032'}, {'^', '\012', '\000'}, 155 {'^', 'z', '\032'}, {'^', '\012', '\000'},
156}; 156};
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index f62f9a4e8950..cee4d4e42429 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -11,6 +11,7 @@
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <linux/sysrq.h> 12#include <linux/sysrq.h>
13 13
14#include <linux/consolemap.h>
14#include <linux/kbd_kern.h> 15#include <linux/kbd_kern.h>
15#include <linux/kbd_diacr.h> 16#include <linux/kbd_diacr.h>
16#include <asm/uaccess.h> 17#include <asm/uaccess.h>
@@ -82,11 +83,11 @@ kbd_alloc(void) {
82 if (!kbd->fn_handler) 83 if (!kbd->fn_handler)
83 goto out_func; 84 goto out_func;
84 kbd->accent_table = 85 kbd->accent_table =
85 kmalloc(sizeof(struct kbdiacr)*MAX_DIACR, GFP_KERNEL); 86 kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL);
86 if (!kbd->accent_table) 87 if (!kbd->accent_table)
87 goto out_fn_handler; 88 goto out_fn_handler;
88 memcpy(kbd->accent_table, accent_table, 89 memcpy(kbd->accent_table, accent_table,
89 sizeof(struct kbdiacr)*MAX_DIACR); 90 sizeof(struct kbdiacruc)*MAX_DIACR);
90 kbd->accent_table_size = accent_table_size; 91 kbd->accent_table_size = accent_table_size;
91 return kbd; 92 return kbd;
92 93
@@ -183,8 +184,8 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc)
183 * Otherwise, conclude that DIACR was not combining after all, 184 * Otherwise, conclude that DIACR was not combining after all,
184 * queue it and return CH. 185 * queue it and return CH.
185 */ 186 */
186static unsigned char 187static unsigned int
187handle_diacr(struct kbd_data *kbd, unsigned char ch) 188handle_diacr(struct kbd_data *kbd, unsigned int ch)
188{ 189{
189 int i, d; 190 int i, d;
190 191
@@ -460,7 +461,6 @@ int
460kbd_ioctl(struct kbd_data *kbd, struct file *file, 461kbd_ioctl(struct kbd_data *kbd, struct file *file,
461 unsigned int cmd, unsigned long arg) 462 unsigned int cmd, unsigned long arg)
462{ 463{
463 struct kbdiacrs __user *a;
464 void __user *argp; 464 void __user *argp;
465 int ct, perm; 465 int ct, perm;
466 466
@@ -481,17 +481,40 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
481 case KDSKBSENT: 481 case KDSKBSENT:
482 return do_kdgkb_ioctl(kbd, argp, cmd, perm); 482 return do_kdgkb_ioctl(kbd, argp, cmd, perm);
483 case KDGKBDIACR: 483 case KDGKBDIACR:
484 a = argp; 484 {
485 struct kbdiacrs __user *a = argp;
486 struct kbdiacr diacr;
487 int i;
485 488
486 if (put_user(kbd->accent_table_size, &a->kb_cnt)) 489 if (put_user(kbd->accent_table_size, &a->kb_cnt))
487 return -EFAULT; 490 return -EFAULT;
491 for (i = 0; i < kbd->accent_table_size; i++) {
492 diacr.diacr = kbd->accent_table[i].diacr;
493 diacr.base = kbd->accent_table[i].base;
494 diacr.result = kbd->accent_table[i].result;
495 if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr)))
496 return -EFAULT;
497 }
498 return 0;
499 }
500 case KDGKBDIACRUC:
501 {
502 struct kbdiacrsuc __user *a = argp;
503
488 ct = kbd->accent_table_size; 504 ct = kbd->accent_table_size;
489 if (copy_to_user(a->kbdiacr, kbd->accent_table, 505 if (put_user(ct, &a->kb_cnt))
490 ct * sizeof(struct kbdiacr))) 506 return -EFAULT;
507 if (copy_to_user(a->kbdiacruc, kbd->accent_table,
508 ct * sizeof(struct kbdiacruc)))
491 return -EFAULT; 509 return -EFAULT;
492 return 0; 510 return 0;
511 }
493 case KDSKBDIACR: 512 case KDSKBDIACR:
494 a = argp; 513 {
514 struct kbdiacrs __user *a = argp;
515 struct kbdiacr diacr;
516 int i;
517
495 if (!perm) 518 if (!perm)
496 return -EPERM; 519 return -EPERM;
497 if (get_user(ct, &a->kb_cnt)) 520 if (get_user(ct, &a->kb_cnt))
@@ -499,10 +522,31 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
499 if (ct >= MAX_DIACR) 522 if (ct >= MAX_DIACR)
500 return -EINVAL; 523 return -EINVAL;
501 kbd->accent_table_size = ct; 524 kbd->accent_table_size = ct;
502 if (copy_from_user(kbd->accent_table, a->kbdiacr, 525 for (i = 0; i < ct; i++) {
503 ct * sizeof(struct kbdiacr))) 526 if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr)))
527 return -EFAULT;
528 kbd->accent_table[i].diacr = diacr.diacr;
529 kbd->accent_table[i].base = diacr.base;
530 kbd->accent_table[i].result = diacr.result;
531 }
532 return 0;
533 }
534 case KDSKBDIACRUC:
535 {
536 struct kbdiacrsuc __user *a = argp;
537
538 if (!perm)
539 return -EPERM;
540 if (get_user(ct, &a->kb_cnt))
541 return -EFAULT;
542 if (ct >= MAX_DIACR)
543 return -EINVAL;
544 kbd->accent_table_size = ct;
545 if (copy_from_user(kbd->accent_table, a->kbdiacruc,
546 ct * sizeof(struct kbdiacruc)))
504 return -EFAULT; 547 return -EFAULT;
505 return 0; 548 return 0;
549 }
506 default: 550 default:
507 return -ENOIOCTLCMD; 551 return -ENOIOCTLCMD;
508 } 552 }
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index f7bf45c6bf0d..5ccfe9cf126d 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -25,9 +25,9 @@ struct kbd_data {
25 unsigned short **key_maps; 25 unsigned short **key_maps;
26 char **func_table; 26 char **func_table;
27 fn_handler_fn **fn_handler; 27 fn_handler_fn **fn_handler;
28 struct kbdiacr *accent_table; 28 struct kbdiacruc *accent_table;
29 unsigned int accent_table_size; 29 unsigned int accent_table_size;
30 unsigned char diacr; 30 unsigned int diacr;
31 unsigned short sysrq; 31 unsigned short sysrq;
32}; 32};
33 33
diff --git a/drivers/tc/lk201-map.c_shipped b/drivers/tc/lk201-map.c_shipped
index a9df8f5bf62b..4d2aba597343 100644
--- a/drivers/tc/lk201-map.c_shipped
+++ b/drivers/tc/lk201-map.c_shipped
@@ -225,7 +225,7 @@ char *func_table[MAX_NR_FUNC] = {
225 0, 225 0,
226}; 226};
227 227
228struct kbdiacr accent_table[MAX_DIACR] = { 228struct kbdiacruc accent_table[MAX_DIACR] = {
229 {'`', 'A', 'À'}, {'`', 'a', 'à'}, 229 {'`', 'A', 'À'}, {'`', 'a', 'à'},
230 {'\'', 'A', 'Á'}, {'\'', 'a', 'á'}, 230 {'\'', 'A', 'Á'}, {'\'', 'a', 'á'},
231 {'^', 'A', 'Â'}, {'^', 'a', 'â'}, 231 {'^', 'A', 'Â'}, {'^', 'a', 'â'},
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index 06b2768c603f..e2bf7e5db39a 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -16,4 +16,5 @@ extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
16extern unsigned short *set_translate(int m, struct vc_data *vc); 16extern unsigned short *set_translate(int m, struct vc_data *vc);
17extern int conv_uni_to_pc(struct vc_data *conp, long ucs); 17extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
18extern u32 conv_8bit_to_uni(unsigned char c); 18extern u32 conv_8bit_to_uni(unsigned char c);
19extern int conv_uni_to_8bit(u32 uni);
19void console_map_init(void); 20void console_map_init(void);
diff --git a/include/linux/kbd_diacr.h b/include/linux/kbd_diacr.h
index 1c1a3ff0535b..7274ec68c246 100644
--- a/include/linux/kbd_diacr.h
+++ b/include/linux/kbd_diacr.h
@@ -2,7 +2,7 @@
2#define _DIACR_H 2#define _DIACR_H
3#include <linux/kd.h> 3#include <linux/kd.h>
4 4
5extern struct kbdiacr accent_table[]; 5extern struct kbdiacruc accent_table[];
6extern unsigned int accent_table_size; 6extern unsigned int accent_table_size;
7 7
8#endif /* _DIACR_H */ 8#endif /* _DIACR_H */
diff --git a/include/linux/kd.h b/include/linux/kd.h
index 28be4fbe9044..c91fc0c9c495 100644
--- a/include/linux/kd.h
+++ b/include/linux/kd.h
@@ -125,6 +125,16 @@ struct kbdiacrs {
125#define KDGKBDIACR 0x4B4A /* read kernel accent table */ 125#define KDGKBDIACR 0x4B4A /* read kernel accent table */
126#define KDSKBDIACR 0x4B4B /* write kernel accent table */ 126#define KDSKBDIACR 0x4B4B /* write kernel accent table */
127 127
128struct kbdiacruc {
129 __u32 diacr, base, result;
130};
131struct kbdiacrsuc {
132 unsigned int kb_cnt; /* number of entries in following array */
133 struct kbdiacruc kbdiacruc[256]; /* MAX_DIACR from keyboard.h */
134};
135#define KDGKBDIACRUC 0x4BFA /* read kernel accent table - UCS */
136#define KDSKBDIACRUC 0x4BFB /* write kernel accent table - UCS */
137
128struct kbkeycode { 138struct kbkeycode {
129 unsigned int scancode, keycode; 139 unsigned int scancode, keycode;
130}; 140};