From 2c7337e10bb891d436c8ed30645d6b63593aec9e Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Tue, 6 Aug 2019 10:39:37 +0800 Subject: [PATCH] tty: Add univt framework support Signed-off-by: Haiyong Sun Signed-off-by: Huacai Chen --- drivers/tty/vt/selection.c | 2 + drivers/tty/vt/vt.c | 81 ++++++++++++++++++++++------ drivers/video/fbdev/core/bitblit.c | 62 ++++++++++++++++++--- drivers/video/fbdev/core/fbcon.c | 39 +++++++------- drivers/video/fbdev/core/fbcon_ccw.c | 40 ++++++++++++-- drivers/video/fbdev/core/fbcon_cw.c | 40 ++++++++++++-- drivers/video/fbdev/core/fbcon_ud.c | 60 +++++++++++++++++++-- 7 files changed, 271 insertions(+), 53 deletions(-) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 564341f1a74f3..59d1cfbb11884 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -230,6 +230,8 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode) } obp = bp; } + if (c > 0x80) + i += 2; } vc_sel.buf_len = bp - vc_sel.buffer; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index cd87e3d1291ed..a2ab3c599d79f 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -294,6 +294,13 @@ static inline u16 *screenpos(const struct vc_data *vc, unsigned int offset, return (u16 *)(origin + offset); } +static inline u16 *screenpos_utf8(const struct vc_data *vc, int offset, bool viewed) +{ + unsigned long origin = viewed ? vc->vc_visible_origin : vc->vc_origin; + + return (u16 *)(origin + offset + vc->vc_screenbuf_size); +} + static void con_putc(struct vc_data *vc, u16 ca, unsigned int y, unsigned int x) { if (vc->vc_sw->con_putc) @@ -588,6 +595,11 @@ static void con_scroll(struct vc_data *vc, unsigned int top, } scr_memmovew(dst, src, (rows - nr) * vc->vc_size_row); scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr); + + dst += (vc->vc_screenbuf_size >> 1); + src += (vc->vc_screenbuf_size >> 1); + scr_memmovew(dst, src, (rows - nr) * vc->vc_size_row); + scr_memsetw(clear, 0, vc->vc_size_row * nr); } static void do_update_region(struct vc_data *vc, unsigned long start, int count) @@ -747,14 +759,17 @@ void complement_pos(struct vc_data *vc, int offset) static int old_offset = -1; static unsigned short old; static unsigned short oldx, oldy; + static unsigned short old_ext = 0; + int c_utf8 = 0; WARN_CONSOLE_UNLOCKED(); if (old_offset != -1 && old_offset >= 0 && old_offset < vc->vc_screenbuf_size) { scr_writew(old, screenpos(vc, old_offset, true)); + c_utf8=(old_ext << 16)|old; if (con_should_update(vc)) - con_putc(vc, old, oldy, oldx); + vc->vc_sw->con_putcs(vc, (u16 *)&c_utf8, 1, oldy, oldx); notify_update(vc); } @@ -764,13 +779,17 @@ void complement_pos(struct vc_data *vc, int offset) offset < vc->vc_screenbuf_size) { unsigned short new; u16 *p = screenpos(vc, offset, true); + u16 *p_ext = screenpos_utf8(vc, offset, true); old = scr_readw(p); + old_ext = scr_readw(p_ext); new = old ^ vc->vc_complement_mask; + c_utf8=(old_ext << 16)|new; scr_writew(new, p); + scr_writew(old_ext, p_ext); if (con_should_update(vc)) { oldx = (offset >> 1) % vc->vc_cols; oldy = (offset >> 1) / vc->vc_cols; - con_putc(vc, new, oldy, oldx); + vc->vc_sw->con_putcs(vc, (u16 *)&c_utf8, 1, oldy, oldx); } notify_update(vc); } @@ -783,6 +802,8 @@ static void insert_char(struct vc_data *vc, unsigned int nr) vc_uniscr_insert(vc, nr); scr_memmovew(p + nr, p, (vc->vc_cols - vc->state.x - nr) * 2); scr_memsetw(p, vc->vc_video_erase_char, nr * 2); + scr_memmovew(p + nr + (vc->vc_screenbuf_size >> 1), p + (vc->vc_screenbuf_size >> 1), (vc->vc_cols - vc->state.x - nr) * 2); + scr_memsetw(p + (vc->vc_screenbuf_size >> 1), 0, nr * 2); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) p, @@ -797,6 +818,9 @@ static void delete_char(struct vc_data *vc, unsigned int nr) scr_memmovew(p, p + nr, (vc->vc_cols - vc->state.x - nr) * 2); scr_memsetw(p + vc->vc_cols - vc->state.x - nr, vc->vc_video_erase_char, nr * 2); + scr_memmovew(p + (vc->vc_screenbuf_size >> 1), p + nr + (vc->vc_screenbuf_size >> 1), (vc->vc_cols - vc->state.x - nr) * 2); + scr_memsetw(p + vc->vc_cols - vc->state.x - nr + (vc->vc_screenbuf_size >> 1), 0, + nr * 2); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) p, @@ -808,6 +832,7 @@ static int softcursor_original = -1; static void add_softcursor(struct vc_data *vc) { int i = scr_readw((u16 *) vc->vc_pos); + u32 type = vc->vc_cursor_type; if (!(type & CUR_SW)) @@ -1081,7 +1106,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ vc->vc_screenbuf_size > KMALLOC_MAX_SIZE || !vc->vc_screenbuf_size) goto err_free; err = -ENOMEM; - vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_KERNEL); + vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size * 2, GFP_KERNEL); if (!vc->vc_screenbuf) goto err_free; @@ -1134,7 +1159,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned long end; - unsigned int old_rows, old_row_size, first_copied_row; + unsigned int old_rows, old_row_size, first_copied_row, old_screen_size; unsigned int new_cols, new_rows, new_row_size, new_screen_size; unsigned short *oldscreen, *newscreen; u32 **new_uniscr = NULL; @@ -1171,7 +1196,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size) return -EINVAL; - newscreen = kzalloc(new_screen_size, GFP_USER); + newscreen = kzalloc(new_screen_size * 2, GFP_USER); if (!newscreen) return -ENOMEM; @@ -1188,6 +1213,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, old_rows = vc->vc_rows; old_row_size = vc->vc_size_row; + old_screen_size = vc->vc_screenbuf_size; err = resize_screen(vc, new_cols, new_rows, from_user); if (err) { @@ -1236,15 +1262,23 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, while (old_origin < end) { scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth); - if (rrem) + scr_memcpyw((unsigned short *) new_origin + (new_screen_size >> 1), + (unsigned short *) old_origin + (old_screen_size >> 1), rlth); + if (rrem){ scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem); + scr_memsetw((void *)(new_origin + rlth + (new_screen_size)), + 0x00, rrem); + } old_origin += old_row_size; new_origin += new_row_size; } - if (new_scr_end > new_origin) + if (new_scr_end > new_origin){ scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin); + scr_memsetw((void *)new_origin + (new_screen_size), 0x00, + new_scr_end - new_origin); + } oldscreen = vc->vc_screenbuf; vc->vc_screenbuf = newscreen; vc->vc_screenbuf_size = new_screen_size; @@ -2948,11 +2982,16 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff; u8 width = 1; bool inverse = false; + int is_utf8 = 0; + int tc_1 = 0xfe; + uint32_t utf8_c = c; if (vc->vc_utf && !vc->vc_disp_ctrl) { if (is_double_width(c)) width = 2; } + if (utf8_c > 0x7f) + is_utf8 = 1; /* Now try to find out how to display it */ tc = conv_uni_to_pc(vc, tc); @@ -2991,6 +3030,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, } next_c = c; + if (is_utf8 == 1){ + tc = 0xff; + next_c = 0xff; + } while (1) { if (vc->vc_need_wrap || vc->vc_decim) con_flush(vc, draw); @@ -3009,6 +3052,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, scr_writew(tc, (u16 *)vc->vc_pos); + if (is_utf8 == 1) { + scr_writew(utf8_c, (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1)); + } + if (con_should_update(vc) && draw->x < 0) { draw->x = vc->state.x; draw->from = vc->vc_pos; @@ -3025,10 +3072,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, break; /* A space is printed in the second column */ - tc = conv_uni_to_pc(vc, ' '); + tc = conv_uni_to_pc(vc, tc_1); if (tc < 0) - tc = ' '; - next_c = ' '; + tc = tc_1; + next_c = tc_1; } notify_write(vc, c); @@ -3662,7 +3709,7 @@ static int __init con_init(void) tty_port_init(&vc->port); visual_init(vc, currcons, true); /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */ - vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); + vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size * 2, GFP_NOWAIT); vc_init(vc, currcons || !vc->vc_sw->con_save_screen); } currcons = fg_console = 0; @@ -4713,7 +4760,7 @@ void reset_palette(struct vc_data *vc) #define max_font_width 64 #define max_font_height 128 #define max_font_glyphs 512 -#define max_font_size (max_font_glyphs*max_font_width*max_font_height) +#define max_font_size (max_font_glyphs*max_font_width*max_font_height >= 65536 * 2 * 8 * 16 ? max_font_glyphs*max_font_width*max_font_height : 65536 * 2 * 8 * 16) static int con_font_get(struct vc_data *vc, struct console_font_op *op) { @@ -4776,8 +4823,6 @@ static int con_font_set(struct vc_data *vc, const struct console_font_op *op) return -EINVAL; if (!op->data) return -EINVAL; - if (op->charcount > max_font_glyphs) - return -EINVAL; if (op->width <= 0 || op->width > max_font_width || !op->height || op->height > max_font_height) return -EINVAL; @@ -4871,9 +4916,15 @@ u16 screen_glyph(const struct vc_data *vc, int offset) u16 w = scr_readw(screenpos(vc, offset, true)); u16 c = w & 0xff; + u16 c_utf8 = scr_readw(screenpos_utf8(vc, offset, true)); + + if ( (c == 0xff || c == 0xfe) && c_utf8 != 0){ + return c_utf8; + }else{ if (w & vc->vc_hi_font_mask) c |= 0x100; return c; + } } EXPORT_SYMBOL_GPL(screen_glyph); @@ -4884,7 +4935,7 @@ u32 screen_glyph_unicode(const struct vc_data *vc, int n) if (uni_lines) return uni_lines[n / vc->vc_cols][n % vc->vc_cols]; - return inverse_translate(vc, screen_glyph(vc, n * 2), true); + return screen_glyph(vc, n * 2); } EXPORT_SYMBOL_GPL(screen_glyph_unicode); diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 3ff1b2a8659e8..1e6e06243a090 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -43,6 +43,20 @@ static void update_attr(u8 *dst, u8 *src, int attribute, } } +u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8) +{ + unsigned long p = (long)utf8; + if (vc->vc_font.charcount <= 512) return 0; + if (p >= vc->vc_origin && p < vc->vc_scr_end) { + return scr_readw((unsigned short *)(p + vc->vc_screenbuf_size)); + } else { + u16 extra_c; + int c = *(int*)utf8; + extra_c = (c >> 16 ) & 0x0000ffff; + return extra_c; + } +} + static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width) { @@ -83,14 +97,25 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 idx = vc->vc_font.width >> 3; u8 *src; + int utf8_c = 0; while (cnt--) { - src = vc->vc_font.data + (scr_readw(s++)& - charmask)*cellsize; - + utf8_c = utf8_pos(vc, s); + if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){ + utf8_c -= 128; + if((scr_readw(s) & charmask) == 0xff){ + src = vc->vc_font.data + (utf8_c * 32); + }else{ + src = vc->vc_font.data + (utf8_c * 32 + 16); + } + }else{ + src = vc->vc_font.data + (scr_readw(s) & + charmask) * cellsize; + } if (attr) { update_attr(buf, src, attr, vc); src = buf; } + s++; if (likely(idx == 1)) __fb_pad_aligned_buffer(dst, d_pitch, src, idx, @@ -118,14 +143,25 @@ static inline void bit_putcs_unaligned(struct vc_data *vc, u32 idx = vc->vc_font.width >> 3; u8 *src; + int utf8_c = 0; while (cnt--) { - src = vc->vc_font.data + (scr_readw(s++)& - charmask)*cellsize; - + utf8_c = utf8_pos(vc, s); + if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){ + utf8_c -= 128; + if((scr_readw(s) & charmask) == 0xff){ + src = vc->vc_font.data + (utf8_c * 32); + }else{ + src = vc->vc_font.data + (utf8_c * 32 + 16); + } + }else{ + src = vc->vc_font.data + (scr_readw(s) & + charmask) * cellsize; + } if (attr) { update_attr(buf, src, attr, vc); src = buf; } + s++; fb_pad_unaligned_buffer(dst, d_pitch, src, idx, image->height, shift_high, @@ -239,7 +275,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, struct fb_cursor cursor; struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; - int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; + int w = DIV_ROUND_UP(vc->vc_font.width, 8), c, c_extra; int y = real_y(ops->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1; @@ -251,8 +287,18 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, return; c = scr_readw((u16 *) vc->vc_pos); + c_extra = scr_readw((u16 *) vc->vc_pos + ( vc->vc_screenbuf_size >> 1)); attribute = get_attribute(info, c); - src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); + if(((c&charmask) == 0xff || (c & charmask) == 0xfe) && c_extra != 0){ + c_extra -= 128; + if((c & charmask) == 0xff){ + src = (char *) (vc->vc_font.data + (c_extra * 32)); + }else{ + src = (char *) (vc->vc_font.data + (c_extra * 32 + 16)); + } + }else{ + src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); + } if (ops->cursor_state.image.data != src || ops->cursor_reset) { diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 2e093535884b4..a0d87e5ef5ed4 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1064,7 +1064,7 @@ static void fbcon_init(struct vc_data *vc, bool init) vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; - if (vc->vc_font.charcount == 256) { + if (vc->vc_font.charcount == 256 || vc->vc_font.charcount > 512) { vc->vc_hi_font_mask = 0; } else { vc->vc_hi_font_mask = 0x100; @@ -1383,7 +1383,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, ops->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; - if (vc->vc_font.charcount == 256) { + if (vc->vc_font.charcount == 256 || vc->vc_font.charcount > 512) { vc->vc_hi_font_mask = 0; } else { vc->vc_hi_font_mask = 0x100; @@ -1606,6 +1606,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, } scr_writew(c, d); + scr_writew(scr_readw(s + (vc->vc_screenbuf_size >> 1)), d + (vc->vc_screenbuf_size >> 1)); console_conditional_schedule(); s++; d++; @@ -1627,6 +1628,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset) { + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; unsigned short *d = (unsigned short *) (vc->vc_origin + vc->vc_size_row * line); unsigned short *s = d + offset; @@ -1649,18 +1651,22 @@ static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset) start = s; } } - if (c == scr_readw(d)) { - if (s > start) { - fbcon_putcs(vc, start, s - start, - line, x); - x += s - start + 1; - start = s + 1; - } else { - x++; - start++; + if( ((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe) && scr_readw(s + (vc->vc_screenbuf_size >> 1)) != 0){ + }else{ + if (c == scr_readw(d)) { + if (s > start) { + fbcon_putcs(vc, start, s - start, + line, x); + x += s - start + 1; + start = s + 1; + } else { + x++; + start++; + } } } scr_writew(c, d); + scr_writew(scr_readw(s + (vc->vc_screenbuf_size >> 1)), d + (vc->vc_screenbuf_size >> 1)); console_conditional_schedule(); s++; d++; @@ -2152,7 +2158,7 @@ static bool fbcon_switch(struct vc_data *vc) vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; - if (vc->vc_font.charcount > 256) + if (vc->vc_font.charcount > 256 && vc->vc_font.charcount <= 512) vc->vc_complement_mask <<= 1; updatescrollmode(p, info, vc); @@ -2286,7 +2292,7 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigne font->height = vc->vc_font.height; if (font->height > vpitch) return -ENOSPC; - font->charcount = vc->vc_hi_font_mask ? 512 : 256; + font->charcount = vc->vc_font.charcount; if (!font->data) return 0; @@ -2424,7 +2430,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, vc->vc_font.width = w; vc->vc_font.height = h; vc->vc_font.charcount = charcount; - if (vc->vc_hi_font_mask && charcount == 256) + if (vc->vc_hi_font_mask && (charcount == 256 || charcount > 512)) set_vc_hi_font(vc, false); else if (!vc->vc_hi_font_mask && charcount == 512) set_vc_hi_font(vc, true); @@ -2483,11 +2489,6 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font, u8 *new_data, *data = font->data; int pitch = PITCH(font->width); - /* Is there a reason why fbconsole couldn't handle any charcount >256? - * If not this check should be changed to charcount < 256 */ - if (charcount != 256 && charcount != 512) - return -EINVAL; - /* font bigger than screen resolution ? */ if (w > FBCON_SWAP(info->var.rotate, info->var.xres, info->var.yres) || h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres)) diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index f9b794ff7d396..4d8293ed91f86 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -18,6 +18,8 @@ #include "fbcon.h" #include "fbcon_rotate.h" +extern u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8); + /* * Rotation 270 degrees */ @@ -105,13 +107,29 @@ static inline void ccw_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 idx = (vc->vc_font.height + 7) >> 3; u8 *src; + int utf8_c = 0; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; - + utf8_c = utf8_pos(vc, s); + if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){ + char dst[16]; + utf8_c -= 128; + if((scr_readw(s) & charmask) == 0xff){ + src = vc->vc_font.data + (utf8_c * 32); + }else{ + src = vc->vc_font.data + (utf8_c * 32 + 16); + } + memset(dst, 0, 16); + rotate_ccw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize; + } if (attr) { ccw_update_attr(buf, src, attr, vc); src = buf; } + s--; if (likely(idx == 1)) __fb_pad_aligned_buffer(dst, d_pitch, src, idx, @@ -224,6 +242,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, struct fb_cursor cursor; struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int c_extra; int w = (vc->vc_font.height + 7) >> 3, c; int y = real_y(ops->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; @@ -237,8 +256,23 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, cursor.set = 0; c = scr_readw((u16 *) vc->vc_pos); + c_extra = utf8_pos(vc, (u16 *) vc->vc_pos); attribute = get_attribute(info, c); - src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + if(((c&charmask) == 0xff || (c & charmask) == 0xfe) && c_extra != 0){ + char dst[16]; + c_extra -= 128; + if((c & charmask) == 0xff){ + src = vc->vc_font.data + (c_extra * 32); + }else{ + src = vc->vc_font.data + (c_extra * 32 + 16); + } + memset(dst, 0, 16); + rotate_ccw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + } if (ops->cursor_state.image.data != src || ops->cursor_reset) { diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index 903f6fc174e14..6be607c97ae75 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -18,6 +18,8 @@ #include "fbcon.h" #include "fbcon_rotate.h" +extern u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8); + /* * Rotation 90 degrees */ @@ -90,13 +92,29 @@ static inline void cw_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 idx = (vc->vc_font.height + 7) >> 3; u8 *src; + int utf8_c = 0; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize; - + utf8_c = utf8_pos(vc, s); + if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){ + char dst[16]; + utf8_c -= 128; + if((scr_readw(s) & charmask) == 0xff){ + src = vc->vc_font.data + (utf8_c * 32); + }else{ + src = vc->vc_font.data + (utf8_c * 32 + 16); + } + memset(dst, 0, 16); + rotate_cw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize; + } if (attr) { cw_update_attr(buf, src, attr, vc); src = buf; } + s++; if (likely(idx == 1)) __fb_pad_aligned_buffer(dst, d_pitch, src, idx, @@ -207,6 +225,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, struct fb_cursor cursor; struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int c_extra; int w = (vc->vc_font.height + 7) >> 3, c; int y = real_y(ops->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; @@ -220,8 +239,23 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, cursor.set = 0; c = scr_readw((u16 *) vc->vc_pos); + c_extra = utf8_pos(vc, (u16 *) vc->vc_pos); attribute = get_attribute(info, c); - src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + if(((c&charmask) == 0xff || (c & charmask) == 0xfe) && c_extra != 0){ + char dst[16]; + c_extra -= 128; + if((c & charmask) == 0xff){ + src = vc->vc_font.data + (c_extra * 32); + }else{ + src = vc->vc_font.data + (c_extra * 32 + 16); + } + memset(dst, 0, 16); + rotate_cw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + } if (ops->cursor_state.image.data != src || ops->cursor_reset) { diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 594331936fd3c..b8988f9e6e561 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -18,6 +18,8 @@ #include "fbcon.h" #include "fbcon_rotate.h" +extern u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8); + /* * Rotation 180 degrees */ @@ -92,13 +94,29 @@ static inline void ud_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 idx = vc->vc_font.width >> 3; u8 *src; + int utf8_c = 0; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; - + utf8_c = utf8_pos(vc, s); + if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){ + char dst[16]; + utf8_c -= 128; + if((scr_readw(s) & charmask) == 0xff){ + src = vc->vc_font.data + (utf8_c * 32); + }else{ + src = vc->vc_font.data + (utf8_c * 32 + 16); + } + memset(dst, 0, 16); + rotate_ud(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize; + } if (attr) { ud_update_attr(buf, src, attr, vc); src = buf; } + s--; if (likely(idx == 1)) __fb_pad_aligned_buffer(dst, d_pitch, src, idx, @@ -127,13 +145,29 @@ static inline void ud_putcs_unaligned(struct vc_data *vc, u32 idx = vc->vc_font.width >> 3; u8 *src; + int utf8_c = 0; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; - + utf8_c = utf8_pos(vc, s); + if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){ + char dst[16]; + utf8_c -= 128; + if((scr_readw(s) & charmask) == 0xff){ + src = vc->vc_font.data + (utf8_c * 32); + }else{ + src = vc->vc_font.data + (utf8_c * 32 + 16); + } + memset(dst, 0, 16); + rotate_ud(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize; + } if (attr) { ud_update_attr(buf, src, attr, vc); src = buf; } + s--; fb_pad_unaligned_buffer(dst, d_pitch, src, idx, image->height, shift_high, @@ -254,6 +288,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, struct fb_cursor cursor; struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int c_extra; int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(ops->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; @@ -268,8 +303,23 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, cursor.set = 0; c = scr_readw((u16 *) vc->vc_pos); + c_extra = utf8_pos(vc, (u16 *) vc->vc_pos); attribute = get_attribute(info, c); - src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); + if(((c&charmask) == 0xff || (c & charmask) == 0xfe) && c_extra != 0){ + char dst[16]; + c_extra -= 128; + if((c & charmask) == 0xff){ + src = vc->vc_font.data + (c_extra * 32); + }else{ + src = vc->vc_font.data + (c_extra * 32 + 16); + } + memset(dst, 0, 16); + rotate_ud(src, dst, vc->vc_font.width, + vc->vc_font.height); + src = dst; + }else{ + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); + } if (ops->cursor_state.image.data != src || ops->cursor_reset) {