aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/vt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/vt.c')
-rw-r--r--drivers/char/vt.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index da7e66a2a38b..fb75da940b59 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -63,6 +63,13 @@
63 * 63 *
64 * Removed console_lock, enabled interrupts across all console operations 64 * Removed console_lock, enabled interrupts across all console operations
65 * 13 March 2001, Andrew Morton 65 * 13 March 2001, Andrew Morton
66 *
67 * Fixed UTF-8 mode so alternate charset modes always work according
68 * to control sequences interpreted in do_con_trol function
69 * preserving backward VT100 semigraphics compatibility,
70 * malformed UTF sequences represented as sequences of replacement glyphs,
71 * original codes or '?' as a last resort if replacement glyph is undefined
72 * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
66 */ 73 */
67 74
68#include <linux/module.h> 75#include <linux/module.h>
@@ -128,8 +135,8 @@ const struct consw *conswitchp;
128#define DEFAULT_BELL_PITCH 750 135#define DEFAULT_BELL_PITCH 750
129#define DEFAULT_BELL_DURATION (HZ/8) 136#define DEFAULT_BELL_DURATION (HZ/8)
130 137
131extern void vcs_make_devfs(struct tty_struct *tty); 138extern void vcs_make_sysfs(struct tty_struct *tty);
132extern void vcs_remove_devfs(struct tty_struct *tty); 139extern void vcs_remove_sysfs(struct tty_struct *tty);
133 140
134extern void console_map_init(void); 141extern void console_map_init(void);
135#ifdef CONFIG_PROM_CONSOLE 142#ifdef CONFIG_PROM_CONSOLE
@@ -730,7 +737,8 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
730 visual_init(vc, currcons, 1); 737 visual_init(vc, currcons, 1);
731 if (!*vc->vc_uni_pagedir_loc) 738 if (!*vc->vc_uni_pagedir_loc)
732 con_set_default_unimap(vc); 739 con_set_default_unimap(vc);
733 vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL); 740 if (!vc->vc_kmalloced)
741 vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
734 if (!vc->vc_screenbuf) { 742 if (!vc->vc_screenbuf) {
735 kfree(vc); 743 kfree(vc);
736 vc_cons[currcons].d = NULL; 744 vc_cons[currcons].d = NULL;
@@ -878,8 +886,17 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
878 return err; 886 return err;
879} 887}
880 888
889int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
890{
891 int rc;
892
893 acquire_console_sem();
894 rc = vc_resize(vc, cols, lines);
895 release_console_sem();
896 return rc;
897}
881 898
882void vc_disallocate(unsigned int currcons) 899void vc_deallocate(unsigned int currcons)
883{ 900{
884 WARN_CONSOLE_UNLOCKED(); 901 WARN_CONSOLE_UNLOCKED();
885 902
@@ -2005,17 +2022,23 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2005 /* Do no translation at all in control states */ 2022 /* Do no translation at all in control states */
2006 if (vc->vc_state != ESnormal) { 2023 if (vc->vc_state != ESnormal) {
2007 tc = c; 2024 tc = c;
2008 } else if (vc->vc_utf) { 2025 } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
2009 /* Combine UTF-8 into Unicode */ 2026 /* Combine UTF-8 into Unicode */
2010 /* Incomplete characters silently ignored */ 2027 /* Malformed sequences as sequences of replacement glyphs */
2028rescan_last_byte:
2011 if(c > 0x7f) { 2029 if(c > 0x7f) {
2012 if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) { 2030 if (vc->vc_utf_count) {
2013 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); 2031 if ((c & 0xc0) == 0x80) {
2014 vc->vc_utf_count--; 2032 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
2015 if (vc->vc_utf_count == 0) 2033 if (--vc->vc_utf_count) {
2016 tc = c = vc->vc_utf_char; 2034 vc->vc_npar++;
2017 else continue; 2035 continue;
2036 }
2037 tc = c = vc->vc_utf_char;
2038 } else
2039 goto replacement_glyph;
2018 } else { 2040 } else {
2041 vc->vc_npar = 0;
2019 if ((c & 0xe0) == 0xc0) { 2042 if ((c & 0xe0) == 0xc0) {
2020 vc->vc_utf_count = 1; 2043 vc->vc_utf_count = 1;
2021 vc->vc_utf_char = (c & 0x1f); 2044 vc->vc_utf_char = (c & 0x1f);
@@ -2032,14 +2055,15 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2032 vc->vc_utf_count = 5; 2055 vc->vc_utf_count = 5;
2033 vc->vc_utf_char = (c & 0x01); 2056 vc->vc_utf_char = (c & 0x01);
2034 } else 2057 } else
2035 vc->vc_utf_count = 0; 2058 goto replacement_glyph;
2036 continue; 2059 continue;
2037 } 2060 }
2038 } else { 2061 } else {
2062 if (vc->vc_utf_count)
2063 goto replacement_glyph;
2039 tc = c; 2064 tc = c;
2040 vc->vc_utf_count = 0;
2041 } 2065 }
2042 } else { /* no utf */ 2066 } else { /* no utf or alternate charset mode */
2043 tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; 2067 tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
2044 } 2068 }
2045 2069
@@ -2054,31 +2078,33 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2054 * direct-to-font zone in UTF-8 mode. 2078 * direct-to-font zone in UTF-8 mode.
2055 */ 2079 */
2056 ok = tc && (c >= 32 || 2080 ok = tc && (c >= 32 ||
2057 (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS 2081 !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
2058 : CTRL_ACTION) >> c) & 1))) 2082 vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
2059 && (c != 127 || vc->vc_disp_ctrl) 2083 && (c != 127 || vc->vc_disp_ctrl)
2060 && (c != 128+27); 2084 && (c != 128+27);
2061 2085
2062 if (vc->vc_state == ESnormal && ok) { 2086 if (vc->vc_state == ESnormal && ok) {
2063 /* Now try to find out how to display it */ 2087 /* Now try to find out how to display it */
2064 tc = conv_uni_to_pc(vc, tc); 2088 tc = conv_uni_to_pc(vc, tc);
2065 if ( tc == -4 ) { 2089 if (tc & ~charmask) {
2090 if ( tc == -4 ) {
2066 /* If we got -4 (not found) then see if we have 2091 /* If we got -4 (not found) then see if we have
2067 defined a replacement character (U+FFFD) */ 2092 defined a replacement character (U+FFFD) */
2068 tc = conv_uni_to_pc(vc, 0xfffd); 2093replacement_glyph:
2069 2094 tc = conv_uni_to_pc(vc, 0xfffd);
2070 /* One reason for the -4 can be that we just 2095 if (!(tc & ~charmask))
2071 did a clear_unimap(); 2096 goto display_glyph;
2072 try at least to show something. */ 2097 } else if ( tc != -3 )
2073 if (tc == -4) 2098 continue; /* nothing to display */
2074 tc = c; 2099 /* no hash table or no replacement --
2075 } else if ( tc == -3 ) { 2100 * hope for the best */
2076 /* Bad hash table -- hope for the best */ 2101 if ( c & ~charmask )
2077 tc = c; 2102 tc = '?';
2078 } 2103 else
2079 if (tc & ~charmask) 2104 tc = c;
2080 continue; /* Conversion failed */ 2105 }
2081 2106
2107display_glyph:
2082 if (vc->vc_need_wrap || vc->vc_decim) 2108 if (vc->vc_need_wrap || vc->vc_decim)
2083 FLUSH 2109 FLUSH
2084 if (vc->vc_need_wrap) { 2110 if (vc->vc_need_wrap) {
@@ -2102,6 +2128,15 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2102 vc->vc_x++; 2128 vc->vc_x++;
2103 draw_to = (vc->vc_pos += 2); 2129 draw_to = (vc->vc_pos += 2);
2104 } 2130 }
2131 if (vc->vc_utf_count) {
2132 if (vc->vc_npar) {
2133 vc->vc_npar--;
2134 goto display_glyph;
2135 }
2136 vc->vc_utf_count = 0;
2137 c = orig;
2138 goto rescan_last_byte;
2139 }
2105 continue; 2140 continue;
2106 } 2141 }
2107 FLUSH 2142 FLUSH
@@ -2498,7 +2533,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2498 tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; 2533 tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
2499 } 2534 }
2500 release_console_sem(); 2535 release_console_sem();
2501 vcs_make_devfs(tty); 2536 vcs_make_sysfs(tty);
2502 return ret; 2537 return ret;
2503 } 2538 }
2504 } 2539 }
@@ -2511,7 +2546,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2511 * and taking a ref against the tty while we're in the process of forgetting 2546 * and taking a ref against the tty while we're in the process of forgetting
2512 * about it and cleaning things up. 2547 * about it and cleaning things up.
2513 * 2548 *
2514 * This is because vcs_remove_devfs() can sleep and will drop the BKL. 2549 * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
2515 */ 2550 */
2516static void con_close(struct tty_struct *tty, struct file *filp) 2551static void con_close(struct tty_struct *tty, struct file *filp)
2517{ 2552{
@@ -2524,7 +2559,7 @@ static void con_close(struct tty_struct *tty, struct file *filp)
2524 vc->vc_tty = NULL; 2559 vc->vc_tty = NULL;
2525 tty->driver_data = NULL; 2560 tty->driver_data = NULL;
2526 release_console_sem(); 2561 release_console_sem();
2527 vcs_remove_devfs(tty); 2562 vcs_remove_sysfs(tty);
2528 mutex_unlock(&tty_mutex); 2563 mutex_unlock(&tty_mutex);
2529 /* 2564 /*
2530 * tty_mutex is released, but we still hold BKL, so there is 2565 * tty_mutex is released, but we still hold BKL, so there is
@@ -3765,6 +3800,7 @@ EXPORT_SYMBOL(default_blu);
3765EXPORT_SYMBOL(update_region); 3800EXPORT_SYMBOL(update_region);
3766EXPORT_SYMBOL(redraw_screen); 3801EXPORT_SYMBOL(redraw_screen);
3767EXPORT_SYMBOL(vc_resize); 3802EXPORT_SYMBOL(vc_resize);
3803EXPORT_SYMBOL(vc_lock_resize);
3768EXPORT_SYMBOL(fg_console); 3804EXPORT_SYMBOL(fg_console);
3769EXPORT_SYMBOL(console_blank_hook); 3805EXPORT_SYMBOL(console_blank_hook);
3770EXPORT_SYMBOL(console_blanked); 3806EXPORT_SYMBOL(console_blanked);