Skip to content

Commit 4002c0e

Browse files
chenhuacaiyetist
authored andcommitted
tty: Add univt framework support
Signed-off-by: Haiyong Sun <sunhy@lemote.com> Signed-off-by: Huacai Chen <chenhc@lemote.com>
1 parent b8a1802 commit 4002c0e

7 files changed

Lines changed: 272 additions & 56 deletions

File tree

drivers/tty/vt/selection.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
221221
}
222222
obp = bp;
223223
}
224+
if (c > 0x80)
225+
i += 2;
224226
}
225227
vc_sel.buf_len = bp - vc_sel.buffer;
226228

drivers/tty/vt/vt.c

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,19 @@ static inline unsigned short *screenpos(const struct vc_data *vc, int offset,
297297
return p;
298298
}
299299

300+
static inline unsigned short *screenpos_utf8(const struct vc_data *vc, int offset, bool viewed)
301+
{
302+
unsigned short *p;
303+
304+
if (!viewed)
305+
p = (unsigned short *)(vc->vc_origin + offset + vc->vc_screenbuf_size);
306+
else if (!vc->vc_sw->con_screen_pos)
307+
p = (unsigned short *)(vc->vc_visible_origin + offset + vc->vc_screenbuf_size);
308+
else
309+
p = vc->vc_sw->con_screen_pos(vc, -offset - 1);
310+
return p;
311+
}
312+
300313
/* Called from the keyboard irq path.. */
301314
static inline void scrolldelta(int lines)
302315
{
@@ -583,6 +596,11 @@ static void con_scroll(struct vc_data *vc, unsigned int top,
583596
}
584597
scr_memmovew(dst, src, (rows - nr) * vc->vc_size_row);
585598
scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr);
599+
600+
dst += (vc->vc_screenbuf_size >> 1);
601+
src += (vc->vc_screenbuf_size >> 1);
602+
scr_memmovew(dst, src, (rows - nr) * vc->vc_size_row);
603+
scr_memsetw(clear, 0, vc->vc_size_row * nr);
586604
}
587605

588606
static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -751,14 +769,16 @@ void complement_pos(struct vc_data *vc, int offset)
751769
static int old_offset = -1;
752770
static unsigned short old;
753771
static unsigned short oldx, oldy;
772+
static unsigned short *p_ext = NULL;
773+
static unsigned short old_ext = 0;
754774

755775
WARN_CONSOLE_UNLOCKED();
756776

757777
if (old_offset != -1 && old_offset >= 0 &&
758778
old_offset < vc->vc_screenbuf_size) {
759779
scr_writew(old, screenpos(vc, old_offset, true));
760780
if (con_should_update(vc))
761-
vc->vc_sw->con_putc(vc, old, oldy, oldx);
781+
vc->vc_sw->con_putc(vc, (old_ext << 16)|old, oldy, oldx);
762782
notify_update(vc);
763783
}
764784

@@ -769,13 +789,15 @@ void complement_pos(struct vc_data *vc, int offset)
769789
unsigned short new;
770790
unsigned short *p;
771791
p = screenpos(vc, offset, true);
792+
p_ext = screenpos_utf8(vc, offset, true);
772793
old = scr_readw(p);
794+
old_ext = scr_readw(p_ext);
773795
new = old ^ vc->vc_complement_mask;
774796
scr_writew(new, p);
775797
if (con_should_update(vc)) {
776798
oldx = (offset >> 1) % vc->vc_cols;
777799
oldy = (offset >> 1) / vc->vc_cols;
778-
vc->vc_sw->con_putc(vc, new, oldy, oldx);
800+
vc->vc_sw->con_putc(vc, (old_ext << 16)|new, oldy, oldx);
779801
}
780802
notify_update(vc);
781803
}
@@ -1088,7 +1110,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
10881110
vc->vc_screenbuf_size > KMALLOC_MAX_SIZE || !vc->vc_screenbuf_size)
10891111
goto err_free;
10901112
err = -ENOMEM;
1091-
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_KERNEL);
1113+
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size * 2, GFP_KERNEL);
10921114
if (!vc->vc_screenbuf)
10931115
goto err_free;
10941116

@@ -1141,7 +1163,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
11411163
{
11421164
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
11431165
unsigned long end;
1144-
unsigned int old_rows, old_row_size, first_copied_row;
1166+
unsigned int old_rows, old_row_size, first_copied_row, old_screen_size;
11451167
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
11461168
unsigned int user;
11471169
unsigned short *oldscreen, *newscreen;
@@ -1185,7 +1207,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
11851207

11861208
if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
11871209
return -EINVAL;
1188-
newscreen = kzalloc(new_screen_size, GFP_USER);
1210+
newscreen = kzalloc(new_screen_size * 2, GFP_USER);
11891211
if (!newscreen)
11901212
return -ENOMEM;
11911213

@@ -1202,6 +1224,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
12021224

12031225
old_rows = vc->vc_rows;
12041226
old_row_size = vc->vc_size_row;
1227+
old_screen_size = vc->vc_screenbuf_size;
12051228

12061229
err = resize_screen(vc, new_cols, new_rows, user);
12071230
if (err) {
@@ -1250,15 +1273,23 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
12501273
while (old_origin < end) {
12511274
scr_memcpyw((unsigned short *) new_origin,
12521275
(unsigned short *) old_origin, rlth);
1253-
if (rrem)
1276+
scr_memcpyw((unsigned short *) new_origin + (new_screen_size >> 1),
1277+
(unsigned short *) old_origin + (old_screen_size >> 1), rlth);
1278+
if (rrem){
12541279
scr_memsetw((void *)(new_origin + rlth),
12551280
vc->vc_video_erase_char, rrem);
1281+
scr_memsetw((void *)(new_origin + rlth + (new_screen_size)),
1282+
0x00, rrem);
1283+
}
12561284
old_origin += old_row_size;
12571285
new_origin += new_row_size;
12581286
}
1259-
if (new_scr_end > new_origin)
1287+
if (new_scr_end > new_origin){
12601288
scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
12611289
new_scr_end - new_origin);
1290+
scr_memsetw((void *)new_origin + (new_screen_size), 0x00,
1291+
new_scr_end - new_origin);
1292+
}
12621293
oldscreen = vc->vc_screenbuf;
12631294
vc->vc_screenbuf = newscreen;
12641295
vc->vc_screenbuf_size = new_screen_size;
@@ -2744,11 +2775,16 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
27442775
u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff;
27452776
u8 width = 1;
27462777
bool inverse = false;
2778+
int is_utf8 = 0;
2779+
int tc_1 = 0xfe;
2780+
uint32_t utf8_c = c;
27472781

27482782
if (vc->vc_utf && !vc->vc_disp_ctrl) {
27492783
if (is_double_width(c))
27502784
width = 2;
27512785
}
2786+
if (utf8_c > 0x7f)
2787+
is_utf8 = 1;
27522788

27532789
/* Now try to find out how to display it */
27542790
tc = conv_uni_to_pc(vc, tc);
@@ -2787,6 +2823,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
27872823
}
27882824

27892825
next_c = c;
2826+
if (is_utf8 == 1){
2827+
tc = 0xff;
2828+
next_c = 0xff;
2829+
}
27902830
while (1) {
27912831
if (vc->vc_need_wrap || vc->vc_decim)
27922832
con_flush(vc, draw);
@@ -2805,6 +2845,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
28052845

28062846
scr_writew(tc, (u16 *)vc->vc_pos);
28072847

2848+
if (is_utf8 == 1) {
2849+
scr_writew(utf8_c, (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
2850+
}
2851+
28082852
if (con_should_update(vc) && draw->x < 0) {
28092853
draw->x = vc->state.x;
28102854
draw->from = vc->vc_pos;
@@ -2821,10 +2865,10 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
28212865
break;
28222866

28232867
/* A space is printed in the second column */
2824-
tc = conv_uni_to_pc(vc, ' ');
2868+
tc = conv_uni_to_pc(vc, tc_1);
28252869
if (tc < 0)
2826-
tc = ' ';
2827-
next_c = ' ';
2870+
tc = tc_1;
2871+
next_c = tc_1;
28282872
}
28292873
notify_write(vc, c);
28302874

@@ -3472,7 +3516,7 @@ static int __init con_init(void)
34723516
tty_port_init(&vc->port);
34733517
visual_init(vc, currcons, 1);
34743518
/* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
3475-
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
3519+
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size * 2, GFP_NOWAIT);
34763520
vc_init(vc, vc->vc_rows, vc->vc_cols,
34773521
currcons || !vc->vc_sw->con_save_screen);
34783522
}
@@ -4599,8 +4643,6 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
45994643
return -EINVAL;
46004644
if (!op->data)
46014645
return -EINVAL;
4602-
if (op->charcount > max_font_glyphs)
4603-
return -EINVAL;
46044646
if (op->width <= 0 || op->width > max_font_width || !op->height ||
46054647
op->height > max_font_height)
46064648
return -EINVAL;
@@ -4694,9 +4736,15 @@ u16 screen_glyph(const struct vc_data *vc, int offset)
46944736
u16 w = scr_readw(screenpos(vc, offset, true));
46954737
u16 c = w & 0xff;
46964738

4739+
u16 c_utf8 = scr_readw(screenpos_utf8(vc, offset, true));
4740+
4741+
if ( (c == 0xff || c == 0xfe) && c_utf8 != 0){
4742+
return c_utf8;
4743+
}else{
46974744
if (w & vc->vc_hi_font_mask)
46984745
c |= 0x100;
46994746
return c;
4747+
}
47004748
}
47014749
EXPORT_SYMBOL_GPL(screen_glyph);
47024750

@@ -4707,7 +4755,7 @@ u32 screen_glyph_unicode(const struct vc_data *vc, int n)
47074755
if (uni_lines)
47084756
return uni_lines[n / vc->vc_cols][n % vc->vc_cols];
47094757

4710-
return inverse_translate(vc, screen_glyph(vc, n * 2), true);
4758+
return screen_glyph(vc, n * 2);
47114759
}
47124760
EXPORT_SYMBOL_GPL(screen_glyph_unicode);
47134761

drivers/video/fbdev/core/bitblit.c

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ static void update_attr(u8 *dst, u8 *src, int attribute,
4343
}
4444
}
4545

46+
u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8)
47+
{
48+
unsigned long p = (long)utf8;
49+
if (vc->vc_font.charcount <= 512) return 0;
50+
if (p >= vc->vc_origin && p < vc->vc_scr_end) {
51+
return scr_readw((unsigned short *)(p + vc->vc_screenbuf_size));
52+
} else {
53+
u16 extra_c;
54+
int c = *(int*)utf8;
55+
extra_c = (c >> 16 ) & 0x0000ffff;
56+
return extra_c;
57+
}
58+
}
59+
4660
static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
4761
int sx, int dy, int dx, int height, int width)
4862
{
@@ -83,14 +97,25 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
8397
u32 idx = vc->vc_font.width >> 3;
8498
u8 *src;
8599

100+
int utf8_c = 0;
86101
while (cnt--) {
87-
src = vc->vc_font.data + (scr_readw(s++)&
88-
charmask)*cellsize;
89-
102+
utf8_c = utf8_pos(vc, s);
103+
if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){
104+
utf8_c -= 128;
105+
if((scr_readw(s) & charmask) == 0xff){
106+
src = vc->vc_font.data + (utf8_c * 32);
107+
}else{
108+
src = vc->vc_font.data + (utf8_c * 32 + 16);
109+
}
110+
}else{
111+
src = vc->vc_font.data + (scr_readw(s) &
112+
charmask) * cellsize;
113+
}
90114
if (attr) {
91115
update_attr(buf, src, attr, vc);
92116
src = buf;
93117
}
118+
s++;
94119

95120
if (likely(idx == 1))
96121
__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
@@ -118,14 +143,25 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
118143
u32 idx = vc->vc_font.width >> 3;
119144
u8 *src;
120145

146+
int utf8_c = 0;
121147
while (cnt--) {
122-
src = vc->vc_font.data + (scr_readw(s++)&
123-
charmask)*cellsize;
124-
148+
utf8_c = utf8_pos(vc, s);
149+
if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask) == 0xfe ) && utf8_c != 0){
150+
utf8_c -= 128;
151+
if((scr_readw(s) & charmask) == 0xff){
152+
src = vc->vc_font.data + (utf8_c * 32);
153+
}else{
154+
src = vc->vc_font.data + (utf8_c * 32 + 16);
155+
}
156+
}else{
157+
src = vc->vc_font.data + (scr_readw(s) &
158+
charmask) * cellsize;
159+
}
125160
if (attr) {
126161
update_attr(buf, src, attr, vc);
127162
src = buf;
128163
}
164+
s++;
129165

130166
fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
131167
image->height, shift_high,
@@ -239,7 +275,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
239275
struct fb_cursor cursor;
240276
struct fbcon_ops *ops = info->fbcon_par;
241277
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
242-
int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
278+
int w = DIV_ROUND_UP(vc->vc_font.width, 8), c, c_extra;
243279
int y = real_y(ops->p, vc->state.y);
244280
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
245281
int err = 1;
@@ -248,8 +284,18 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
248284
cursor.set = 0;
249285

250286
c = scr_readw((u16 *) vc->vc_pos);
287+
c_extra = utf8_pos(vc, (u16 *) vc->vc_pos);
251288
attribute = get_attribute(info, c);
252-
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
289+
if(((c&charmask) == 0xff || (c & charmask) == 0xfe) && c_extra != 0){
290+
c_extra -= 128;
291+
if((c & charmask) == 0xff){
292+
src = (char *) (vc->vc_font.data + (c_extra * 32));
293+
}else{
294+
src = (char *) (vc->vc_font.data + (c_extra * 32 + 16));
295+
}
296+
}else{
297+
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
298+
}
253299

254300
if (ops->cursor_state.image.data != src ||
255301
ops->cursor_reset) {

0 commit comments

Comments
 (0)