aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-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
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 */
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 }