diff options
Diffstat (limited to 'drivers/char/vt.c')
-rw-r--r-- | drivers/char/vt.c | 104 |
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 | ||
131 | extern void vcs_make_devfs(struct tty_struct *tty); | 138 | extern void vcs_make_sysfs(struct tty_struct *tty); |
132 | extern void vcs_remove_devfs(struct tty_struct *tty); | 139 | extern void vcs_remove_sysfs(struct tty_struct *tty); |
133 | 140 | ||
134 | extern void console_map_init(void); | 141 | extern 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 | ||
889 | int 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 | ||
882 | void vc_disallocate(unsigned int currcons) | 899 | void 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 */ |
2028 | rescan_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); | 2093 | replacement_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 | ||
2107 | display_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 | */ |
2516 | static void con_close(struct tty_struct *tty, struct file *filp) | 2551 | static 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); | |||
3765 | EXPORT_SYMBOL(update_region); | 3800 | EXPORT_SYMBOL(update_region); |
3766 | EXPORT_SYMBOL(redraw_screen); | 3801 | EXPORT_SYMBOL(redraw_screen); |
3767 | EXPORT_SYMBOL(vc_resize); | 3802 | EXPORT_SYMBOL(vc_resize); |
3803 | EXPORT_SYMBOL(vc_lock_resize); | ||
3768 | EXPORT_SYMBOL(fg_console); | 3804 | EXPORT_SYMBOL(fg_console); |
3769 | EXPORT_SYMBOL(console_blank_hook); | 3805 | EXPORT_SYMBOL(console_blank_hook); |
3770 | EXPORT_SYMBOL(console_blanked); | 3806 | EXPORT_SYMBOL(console_blanked); |