Commit 33a35bbbe09a9b63b46e86a97d5dfbdae5481401

Authored by Pali Rohár
Committed by Tom Rini
1 parent 318e70e244

cfb_console: Add support for some ANSI terminal escape codes

Add optional support for some ANSI escape sequences to the
cfb_console driver. Define CONFIG_CFB_CONSOLE_ANSI to enable
cursor moving, color reverting and clearing the cfb console
via ANSI escape codes.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>

Showing 2 changed files with 323 additions and 9 deletions Side-by-side Diff

... ... @@ -655,6 +655,10 @@
655 655 additional board info beside
656 656 the logo
657 657  
  658 + When CONFIG_CFB_CONSOLE_ANSI is defined, console will support
  659 + a limited number of ANSI escape sequences (cursor control,
  660 + erase functions and limited graphics rendition control).
  661 +
658 662 When CONFIG_CFB_CONSOLE is defined, video console is
659 663 default i/o. Serial console can be forced with
660 664 environment 'console=serial'.
drivers/video/cfb_console.c
... ... @@ -385,6 +385,13 @@
385 385  
386 386 static int cfb_do_flush_cache;
387 387  
  388 +#ifdef CONFIG_CFB_CONSOLE_ANSI
  389 +static char ansi_buf[10];
  390 +static int ansi_buf_size;
  391 +static int ansi_colors_need_revert;
  392 +static int ansi_cursor_hidden;
  393 +#endif
  394 +
388 395 static const int video_font_draw_table8[] = {
389 396 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
390 397 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
391 398  
... ... @@ -768,9 +775,97 @@
768 775 }
769 776 }
770 777  
771   -static void console_newline(void)
  778 +#ifdef CONFIG_CFB_CONSOLE_ANSI
  779 +
  780 +static void console_clear(void)
772 781 {
773   - console_row++;
  782 +#ifdef VIDEO_HW_RECTFILL
  783 + video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  784 + 0, /* dest pos x */
  785 + video_logo_height, /* dest pos y */
  786 + VIDEO_VISIBLE_COLS, /* frame width */
  787 + VIDEO_VISIBLE_ROWS, /* frame height */
  788 + bgx /* fill color */
  789 + );
  790 +#else
  791 + memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
  792 +#endif
  793 +}
  794 +
  795 +static void console_cursor_fix(void)
  796 +{
  797 + if (console_row < 0)
  798 + console_row = 0;
  799 + if (console_row >= CONSOLE_ROWS)
  800 + console_row = CONSOLE_ROWS - 1;
  801 + if (console_col < 0)
  802 + console_col = 0;
  803 + if (console_col >= CONSOLE_COLS)
  804 + console_col = CONSOLE_COLS - 1;
  805 +}
  806 +
  807 +static void console_cursor_up(int n)
  808 +{
  809 + console_row -= n;
  810 + console_cursor_fix();
  811 +}
  812 +
  813 +static void console_cursor_down(int n)
  814 +{
  815 + console_row += n;
  816 + console_cursor_fix();
  817 +}
  818 +
  819 +static void console_cursor_left(int n)
  820 +{
  821 + console_col -= n;
  822 + console_cursor_fix();
  823 +}
  824 +
  825 +static void console_cursor_right(int n)
  826 +{
  827 + console_col += n;
  828 + console_cursor_fix();
  829 +}
  830 +
  831 +static void console_cursor_set_position(int row, int col)
  832 +{
  833 + if (console_row != -1)
  834 + console_row = row;
  835 + if (console_col != -1)
  836 + console_col = col;
  837 + console_cursor_fix();
  838 +}
  839 +
  840 +static void console_previousline(int n)
  841 +{
  842 + /* FIXME: also scroll terminal ? */
  843 + console_row -= n;
  844 + console_cursor_fix();
  845 +}
  846 +
  847 +static void console_swap_colors(void)
  848 +{
  849 + eorx = fgx;
  850 + fgx = bgx;
  851 + bgx = eorx;
  852 + eorx = fgx ^ bgx;
  853 +}
  854 +
  855 +static inline int console_cursor_is_visible(void)
  856 +{
  857 + return !ansi_cursor_hidden;
  858 +}
  859 +#else
  860 +static inline int console_cursor_is_visible(void)
  861 +{
  862 + return 1;
  863 +}
  864 +#endif
  865 +
  866 +static void console_newline(int n)
  867 +{
  868 + console_row += n;
774 869 console_col = 0;
775 870  
776 871 /* Check if we need to scroll the terminal */
... ... @@ -779,7 +874,7 @@
779 874 console_scrollup();
780 875  
781 876 /* Decrement row number */
782   - console_row--;
  877 + console_row = CONSOLE_ROWS - 1;
783 878 }
784 879 }
785 880  
786 881  
... ... @@ -788,11 +883,12 @@
788 883 console_col = 0;
789 884 }
790 885  
791   -void video_putc(const char c)
  886 +static void parse_putc(const char c)
792 887 {
793 888 static int nl = 1;
794 889  
795   - CURSOR_OFF;
  890 + if (console_cursor_is_visible())
  891 + CURSOR_OFF;
796 892  
797 893 switch (c) {
798 894 case 13: /* back to first column */
... ... @@ -801,7 +897,7 @@
801 897  
802 898 case '\n': /* next line */
803 899 if (console_col || (!console_col && nl))
804   - console_newline();
  900 + console_newline(1);
805 901 nl = 1;
806 902 break;
807 903  
... ... @@ -810,7 +906,7 @@
810 906 console_col &= ~0x0007;
811 907  
812 908 if (console_col >= CONSOLE_COLS)
813   - console_newline();
  909 + console_newline(1);
814 910 break;
815 911  
816 912 case 8: /* backspace */
817 913  
... ... @@ -827,11 +923,225 @@
827 923  
828 924 /* check for newline */
829 925 if (console_col >= CONSOLE_COLS) {
830   - console_newline();
  926 + console_newline(1);
831 927 nl = 0;
832 928 }
833 929 }
834   - CURSOR_SET;
  930 +
  931 + if (console_cursor_is_visible())
  932 + CURSOR_SET;
  933 +}
  934 +
  935 +void video_putc(const char c)
  936 +{
  937 +#ifdef CONFIG_CFB_CONSOLE_ANSI
  938 + int i;
  939 +
  940 + if (c == 27) {
  941 + for (i = 0; i < ansi_buf_size; ++i)
  942 + parse_putc(ansi_buf[i]);
  943 + ansi_buf[0] = 27;
  944 + ansi_buf_size = 1;
  945 + return;
  946 + }
  947 +
  948 + if (ansi_buf_size > 0) {
  949 + /*
  950 + * 0 - ESC
  951 + * 1 - [
  952 + * 2 - num1
  953 + * 3 - ..
  954 + * 4 - ;
  955 + * 5 - num2
  956 + * 6 - ..
  957 + * - cchar
  958 + */
  959 + int next = 0;
  960 +
  961 + int flush = 0;
  962 + int fail = 0;
  963 +
  964 + int num1 = 0;
  965 + int num2 = 0;
  966 + int cchar = 0;
  967 +
  968 + ansi_buf[ansi_buf_size++] = c;
  969 +
  970 + if (ansi_buf_size >= sizeof(ansi_buf))
  971 + fail = 1;
  972 +
  973 + for (i = 0; i < ansi_buf_size; ++i) {
  974 + if (fail)
  975 + break;
  976 +
  977 + switch (next) {
  978 + case 0:
  979 + if (ansi_buf[i] == 27)
  980 + next = 1;
  981 + else
  982 + fail = 1;
  983 + break;
  984 +
  985 + case 1:
  986 + if (ansi_buf[i] == '[')
  987 + next = 2;
  988 + else
  989 + fail = 1;
  990 + break;
  991 +
  992 + case 2:
  993 + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  994 + num1 = ansi_buf[i]-'0';
  995 + next = 3;
  996 + } else if (ansi_buf[i] != '?') {
  997 + --i;
  998 + num1 = 1;
  999 + next = 4;
  1000 + }
  1001 + break;
  1002 +
  1003 + case 3:
  1004 + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  1005 + num1 *= 10;
  1006 + num1 += ansi_buf[i]-'0';
  1007 + } else {
  1008 + --i;
  1009 + next = 4;
  1010 + }
  1011 + break;
  1012 +
  1013 + case 4:
  1014 + if (ansi_buf[i] != ';') {
  1015 + --i;
  1016 + next = 7;
  1017 + } else
  1018 + next = 5;
  1019 + break;
  1020 +
  1021 + case 5:
  1022 + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  1023 + num2 = ansi_buf[i]-'0';
  1024 + next = 6;
  1025 + } else
  1026 + fail = 1;
  1027 + break;
  1028 +
  1029 + case 6:
  1030 + if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  1031 + num2 *= 10;
  1032 + num2 += ansi_buf[i]-'0';
  1033 + } else {
  1034 + --i;
  1035 + next = 7;
  1036 + }
  1037 + break;
  1038 +
  1039 + case 7:
  1040 + if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H')
  1041 + || ansi_buf[i] == 'J'
  1042 + || ansi_buf[i] == 'K'
  1043 + || ansi_buf[i] == 'h'
  1044 + || ansi_buf[i] == 'l'
  1045 + || ansi_buf[i] == 'm') {
  1046 + cchar = ansi_buf[i];
  1047 + flush = 1;
  1048 + } else
  1049 + fail = 1;
  1050 + break;
  1051 + }
  1052 + }
  1053 +
  1054 + if (fail) {
  1055 + for (i = 0; i < ansi_buf_size; ++i)
  1056 + parse_putc(ansi_buf[i]);
  1057 + ansi_buf_size = 0;
  1058 + return;
  1059 + }
  1060 +
  1061 + if (flush) {
  1062 + if (!ansi_cursor_hidden)
  1063 + CURSOR_OFF;
  1064 + ansi_buf_size = 0;
  1065 + switch (cchar) {
  1066 + case 'A':
  1067 + /* move cursor num1 rows up */
  1068 + console_cursor_up(num1);
  1069 + break;
  1070 + case 'B':
  1071 + /* move cursor num1 rows down */
  1072 + console_cursor_down(num1);
  1073 + break;
  1074 + case 'C':
  1075 + /* move cursor num1 columns forward */
  1076 + console_cursor_right(num1);
  1077 + break;
  1078 + case 'D':
  1079 + /* move cursor num1 columns back */
  1080 + console_cursor_left(num1);
  1081 + break;
  1082 + case 'E':
  1083 + /* move cursor num1 rows up at begin of row */
  1084 + console_previousline(num1);
  1085 + break;
  1086 + case 'F':
  1087 + /* move cursor num1 rows down at begin of row */
  1088 + console_newline(num1);
  1089 + break;
  1090 + case 'G':
  1091 + /* move cursor to column num1 */
  1092 + console_cursor_set_position(-1, num1-1);
  1093 + break;
  1094 + case 'H':
  1095 + /* move cursor to row num1, column num2 */
  1096 + console_cursor_set_position(num1-1, num2-1);
  1097 + break;
  1098 + case 'J':
  1099 + /* clear console and move cursor to 0, 0 */
  1100 + console_clear();
  1101 + console_cursor_set_position(0, 0);
  1102 + break;
  1103 + case 'K':
  1104 + /* clear line */
  1105 + if (num1 == 0)
  1106 + console_clear_line(console_row,
  1107 + console_col,
  1108 + CONSOLE_COLS-1);
  1109 + else if (num1 == 1)
  1110 + console_clear_line(console_row,
  1111 + 0, console_col);
  1112 + else
  1113 + console_clear_line(console_row,
  1114 + 0, CONSOLE_COLS-1);
  1115 + break;
  1116 + case 'h':
  1117 + ansi_cursor_hidden = 0;
  1118 + break;
  1119 + case 'l':
  1120 + ansi_cursor_hidden = 1;
  1121 + break;
  1122 + case 'm':
  1123 + if (num1 == 0) { /* reset swapped colors */
  1124 + if (ansi_colors_need_revert) {
  1125 + console_swap_colors();
  1126 + ansi_colors_need_revert = 0;
  1127 + }
  1128 + } else if (num1 == 7) { /* once swap colors */
  1129 + if (!ansi_colors_need_revert) {
  1130 + console_swap_colors();
  1131 + ansi_colors_need_revert = 1;
  1132 + }
  1133 + }
  1134 + break;
  1135 + }
  1136 + if (!ansi_cursor_hidden)
  1137 + CURSOR_SET;
  1138 + }
  1139 + } else {
  1140 + parse_putc(c);
  1141 + }
  1142 +#else
  1143 + parse_putc(c);
  1144 +#endif
835 1145 }
836 1146  
837 1147 void video_puts(const char *s)