Skip to content

Commit

Permalink
tty: Add univt framework support
Browse files Browse the repository at this point in the history
Signed-off-by: Haiyong Sun <[email protected]>
Signed-off-by: Huacai Chen <[email protected]>
  • Loading branch information
chenhuacai committed Sep 28, 2024
1 parent aab6019 commit 2c7337e
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 53 deletions.
2 changes: 2 additions & 0 deletions drivers/tty/vt/selection.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
81 changes: 66 additions & 15 deletions drivers/tty/vt/vt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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))
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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);

Expand Down
62 changes: 54 additions & 8 deletions drivers/video/fbdev/core/bitblit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
Loading

0 comments on commit 2c7337e

Please sign in to comment.