diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/consolemap.c | 22 | ||||
-rw-r--r-- | drivers/char/defkeymap.c_shipped | 2 | ||||
-rw-r--r-- | drivers/char/keyboard.c | 35 | ||||
-rw-r--r-- | drivers/char/vt_ioctl.c | 46 |
4 files changed, 86 insertions, 19 deletions
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 */ |
673 | u32 conv_8bit_to_uni(unsigned char c) | 679 | u32 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 | ||
685 | int 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 | |||
685 | int | 695 | int |
686 | conv_uni_to_pc(struct vc_data *conp, long ucs) | 696 | conv_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 | ||
225 | struct kbdiacr accent_table[MAX_DIACR] = { | 225 | struct 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 | ||
647 | static void k_self(struct vc_data *vc, unsigned char value, char up_flag) | 657 | static 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 | ||
652 | static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag) | 667 | static 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 | } |