Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/fb/serial_console.c

    rb3d513f r32e7411  
    3131/**
    3232 * @defgroup serial Serial console
    33  * @brief    Serial console services (putc, puts, clear screen, cursor goto,...)
     33 * @brief Serial console services (putc, puts, clear screen, cursor goto,...)
    3434 * @{
    35  */ 
     35 */
    3636
    3737/** @file
     
    4646#include <io/color.h>
    4747#include <io/style.h>
    48 #include <string.h>
    49 
    50 #include "../console/screenbuffer.h"
     48#include <str.h>
     49#include <io/screenbuffer.h>
     50
    5151#include "main.h"
    5252#include "serial_console.h"
     
    5454#define MAX_CONTROL 20
    5555
    56 static void serial_sgr(const unsigned int mode);
    57 void serial_putchar(wchar_t ch);
    58 
    59 static int scr_width;
    60 static int scr_height;
    61 static bool color = true;       /** True if producing color output. */
    62 static bool utf8 = false;       /** True if producing UTF8 output. */
     56static ipcarg_t scr_width;
     57static ipcarg_t scr_height;
     58static bool color = true;    /**< True if producing color output. */
     59static bool utf8 = false;    /**< True if producing UTF8 output. */
    6360static putc_function_t putc_function;
     61
     62static ipcarg_t lastcol = 0;
     63static ipcarg_t lastrow = 0;
     64static attrs_t cur_attr = {
     65        .t = at_style,
     66        .a.s.style = STYLE_NORMAL
     67};
    6468
    6569/* Allow only 1 connection */
     
    6771
    6872enum sgr_color_index {
    69         CI_BLACK        = 0,
    70         CI_RED          = 1,
    71         CI_GREEN        = 2,
    72         CI_BROWN        = 3,
    73         CI_BLUE         = 4,
    74         CI_MAGENTA      = 5,
    75         CI_CYAN         = 6,
    76         CI_WHITE        = 7,
     73        CI_BLACK   = 0,
     74        CI_RED     = 1,
     75        CI_GREEN   = 2,
     76        CI_BROWN   = 3,
     77        CI_BLUE    = 4,
     78        CI_MAGENTA = 5,
     79        CI_CYAN    = 6,
     80        CI_WHITE   = 7
    7781};
    7882
    7983enum sgr_command {
    80         SGR_RESET       = 0,
    81         SGR_BOLD        = 1,
    82         SGR_BLINK       = 5,
    83         SGR_REVERSE     = 7,
    84         SGR_NORMAL_INT  = 22,
    85         SGR_BLINK_OFF   = 25,
    86         SGR_REVERSE_OFF = 27,
    87         SGR_FGCOLOR     = 30,
    88         SGR_BGCOLOR     = 40
     84        SGR_RESET       = 0,
     85        SGR_BOLD        = 1,
     86        SGR_UNDERLINE   = 4,
     87        SGR_BLINK       = 5,
     88        SGR_REVERSE     = 7,
     89        SGR_FGCOLOR     = 30,
     90        SGR_BGCOLOR     = 40
    8991};
    9092
    9193static int color_map[] = {
    92         [COLOR_BLACK]   = CI_BLACK,
    93         [COLOR_BLUE]    = CI_RED,
    94         [COLOR_GREEN]   = CI_GREEN,
    95         [COLOR_CYAN]    = CI_CYAN,
    96         [COLOR_RED]     = CI_RED,
     94        [COLOR_BLACK]   = CI_BLACK,
     95        [COLOR_BLUE]    = CI_RED,
     96        [COLOR_GREEN]   = CI_GREEN,
     97        [COLOR_CYAN]    = CI_CYAN,
     98        [COLOR_RED]     = CI_RED,
    9799        [COLOR_MAGENTA] = CI_MAGENTA,
    98         [COLOR_YELLOW]  = CI_BROWN,
    99         [COLOR_WHITE]   = CI_WHITE
     100        [COLOR_YELLOW]  = CI_BROWN,
     101        [COLOR_WHITE]   = CI_WHITE
    100102};
    101103
    102 void serial_puts(char *str)
     104void serial_puts(const char *str)
    103105{
    104106        while (*str)
     
    106108}
    107109
    108 void serial_putchar(wchar_t ch)
    109 {
    110         uint8_t buf[STR_BOUNDS(1)];
    111         size_t offs;
    112         size_t i;
    113 
     110static void serial_putchar(wchar_t ch)
     111{
    114112        if (utf8 != true) {
    115113                if (ch >= 0 && ch < 128)
    116114                        (*putc_function)((uint8_t) ch);
    117                 else 
     115                else
    118116                        (*putc_function)('?');
     117               
    119118                return;
    120119        }
    121 
    122         offs = 0;
     120       
     121        size_t offs = 0;
     122        char buf[STR_BOUNDS(1)];
    123123        if (chr_encode(ch, buf, &offs, STR_BOUNDS(1)) == EOK) {
     124                size_t i;
    124125                for (i = 0; i < offs; i++)
    125126                        (*putc_function)(buf[i]);
    126         } else {
     127        } else
    127128                (*putc_function)('?');
    128         }
    129 
    130 }
    131 
    132 void serial_goto(const unsigned int col, const unsigned int row)
     129}
     130
     131void serial_goto(const ipcarg_t col, const ipcarg_t row)
    133132{
    134133        if ((col > scr_width) || (row > scr_height))
     
    138137        snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
    139138        serial_puts(control);
     139}
     140
     141/** ECMA-48 Set Graphics Rendition. */
     142static void serial_sgr(const unsigned int mode)
     143{
     144        char control[MAX_CONTROL];
     145        snprintf(control, MAX_CONTROL, "\033[%um", mode);
     146        serial_puts(control);
     147}
     148
     149static void serial_set_style(console_style_t style)
     150{
     151        switch (style) {
     152        case STYLE_EMPHASIS:
     153                serial_sgr(SGR_RESET);
     154                if (color) {
     155                        serial_sgr(SGR_FGCOLOR + CI_RED);
     156                        serial_sgr(SGR_BGCOLOR + CI_WHITE);
     157                }
     158                serial_sgr(SGR_BOLD);
     159                break;
     160        case STYLE_INVERTED:
     161                serial_sgr(SGR_RESET);
     162                if (color) {
     163                        serial_sgr(SGR_FGCOLOR + CI_WHITE);
     164                        serial_sgr(SGR_BGCOLOR + CI_BLACK);
     165                } else
     166                        serial_sgr(SGR_REVERSE);
     167                break;
     168        case STYLE_SELECTED:
     169                serial_sgr(SGR_RESET);
     170                if (color) {
     171                        serial_sgr(SGR_FGCOLOR + CI_WHITE);
     172                        serial_sgr(SGR_BGCOLOR + CI_RED);
     173                } else
     174                        serial_sgr(SGR_UNDERLINE);
     175                break;
     176        default:
     177                serial_sgr(SGR_RESET);
     178                if (color) {
     179                        serial_sgr(SGR_FGCOLOR + CI_BLACK);
     180                        serial_sgr(SGR_BGCOLOR + CI_WHITE);
     181                }
     182        }
     183}
     184
     185static void serial_set_idx(uint8_t fgcolor, uint8_t bgcolor,
     186    uint8_t flags)
     187{
     188        serial_sgr(SGR_RESET);
     189        if (color) {
     190                serial_sgr(SGR_FGCOLOR + color_map[fgcolor & 7]);
     191                serial_sgr(SGR_BGCOLOR + color_map[bgcolor & 7]);
     192                if (flags & CATTR_BRIGHT)
     193                        serial_sgr(SGR_BOLD);
     194        } else {
     195                if (fgcolor >= bgcolor)
     196                        serial_sgr(SGR_REVERSE);
     197        }
     198}
     199
     200static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
     201{
     202        serial_sgr(SGR_RESET);
     203       
     204        if (fgcolor >= bgcolor)
     205                serial_sgr(SGR_REVERSE);
     206}
     207
     208static void serial_set_attrs(attrs_t *a)
     209{
     210        switch (a->t) {
     211        case at_style:
     212                serial_set_style(a->a.s.style);
     213                break;
     214        case at_rgb:
     215                serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
     216                break;
     217        case at_idx:
     218                serial_set_idx(a->a.i.fg_color, a->a.i.bg_color,
     219                    a->a.i.flags);
     220                break;
     221        }
    140222}
    141223
     
    148230                serial_sgr(SGR_BGCOLOR + CI_WHITE);
    149231        }
    150 
     232       
    151233        serial_puts("\033[2J");
    152 }
    153 
    154 void serial_scroll(int i)
     234       
     235        serial_set_attrs(&cur_attr);
     236}
     237
     238void serial_scroll(ssize_t i)
    155239{
    156240        if (i > 0) {
     
    165249}
    166250
    167 /** ECMA-48 Set Graphics Rendition. */
    168 static void serial_sgr(const unsigned int mode)
    169 {
    170         char control[MAX_CONTROL];
    171         snprintf(control, MAX_CONTROL, "\033[%um", mode);
    172         serial_puts(control);
    173 }
    174 
    175251/** Set scrolling region. */
    176 void serial_set_scroll_region(unsigned last_row)
     252void serial_set_scroll_region(ipcarg_t last_row)
    177253{
    178254        char control[MAX_CONTROL];
     
    191267}
    192268
    193 void serial_console_init(putc_function_t putc_fn, uint32_t w, uint32_t h)
     269void serial_console_init(putc_function_t putc_fn, ipcarg_t w, ipcarg_t h)
    194270{
    195271        scr_width = w;
     
    198274}
    199275
    200 static void serial_set_style(int style)
    201 {
    202         if (style == STYLE_EMPHASIS) {
    203                 if (color) {
    204                         serial_sgr(SGR_RESET);
    205                         serial_sgr(SGR_FGCOLOR + CI_RED);
    206                         serial_sgr(SGR_BGCOLOR + CI_WHITE);
    207                 }
    208                 serial_sgr(SGR_BOLD);
    209         } else {
    210                 if (color) {
    211                         serial_sgr(SGR_RESET);
    212                         serial_sgr(SGR_FGCOLOR + CI_BLACK);
    213                         serial_sgr(SGR_BGCOLOR + CI_WHITE);
    214                 }
    215                 serial_sgr(SGR_NORMAL_INT);
    216         }
    217 }
    218 
    219 static void serial_set_idx(unsigned fgcolor, unsigned bgcolor,
    220     unsigned flags)
    221 {
    222         if (color) {
    223                 serial_sgr(SGR_RESET);
    224                 serial_sgr(SGR_FGCOLOR + color_map[fgcolor]);
    225                 serial_sgr(SGR_BGCOLOR + color_map[bgcolor]);
    226         } else {
    227                 if (fgcolor < bgcolor)
    228                         serial_sgr(SGR_RESET);
    229                 else
    230                         serial_sgr(SGR_REVERSE);
    231         }       
    232 }
    233 
    234 static void serial_set_rgb(uint32_t fgcolor, uint32_t bgcolor)
    235 {
    236         if (fgcolor < bgcolor)
    237                 serial_sgr(SGR_REVERSE_OFF);
    238         else
    239                 serial_sgr(SGR_REVERSE);
    240 }
    241 
    242 static void serial_set_attrs(const attrs_t *a)
    243 {
    244         switch (a->t) {
    245         case at_style:
    246                 serial_set_style(a->a.s.style);
    247                 break;
    248         case at_rgb:
    249                 serial_set_rgb(a->a.r.fg_color, a->a.r.bg_color);
    250                 break;
    251         case at_idx:
    252                 serial_set_idx(a->a.i.fg_color,
    253                     a->a.i.bg_color, a->a.i.flags);
    254                 break;
    255         default:
    256                 break;
    257         }
    258 }
    259 
    260276/** Draw text data to viewport.
    261277 *
    262  * @param vport Viewport id
    263  * @param data  Text data.
    264  * @param x     Leftmost column of the area.
    265  * @param y     Topmost row of the area.
    266  * @param w     Number of rows.
    267  * @param h     Number of columns.
    268  */
    269 static void draw_text_data(keyfield_t *data, unsigned int x,
    270     unsigned int y, unsigned int w, unsigned int h)
    271 {
    272         unsigned int i, j;
    273         keyfield_t *field;
    274         attrs_t *a0, *a1;
    275 
    276         serial_goto(x, y);
    277         a0 = &data[0].attrs;
     278 * @param vport  Viewport id
     279 * @param data   Text data.
     280 * @param x0     Leftmost column of the area.
     281 * @param y0     Topmost row of the area.
     282 * @param width  Number of rows.
     283 * @param height Number of columns.
     284 *
     285 */
     286static void draw_text_data(keyfield_t *data, ipcarg_t x0, ipcarg_t y0,
     287    ipcarg_t width, ipcarg_t height)
     288{
     289        attrs_t *a0 = &data[0].attrs;
    278290        serial_set_attrs(a0);
    279 
    280         for (j = 0; j < h; j++) {
    281                 if (j > 0 && w != scr_width)
    282                         serial_goto(x, j);
    283 
    284                 for (i = 0; i < w; i++) {
    285                         field = &data[j * w + i];
    286 
    287                         a1 = &field->attrs;
    288                         if (!attrs_same(*a0, *a1))
    289                                 serial_set_attrs(a1);
    290                         serial_putchar(field->character);
    291                         a0 = a1;
     291       
     292        ipcarg_t y;
     293        for (y = 0; y < height; y++) {
     294                serial_goto(x0, y0 + y);
     295               
     296                ipcarg_t x;
     297                for (x = 0; x < width; x++) {
     298                        attrs_t *attr = &data[y * width + x].attrs;
     299                       
     300                        if (!attrs_same(*a0, *attr)) {
     301                                serial_set_attrs(attr);
     302                                a0 = attr;
     303                        }
     304                       
     305                        serial_putchar(data[y * width + x].character);
    292306                }
    293307        }
    294308}
    295 
    296 int lastcol = 0;
    297 int lastrow = 0;
    298309
    299310/**
     
    302313void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    303314{
    304         int retval;
    305         ipc_callid_t callid;
    306         ipc_call_t call;
    307315        keyfield_t *interbuf = NULL;
    308316        size_t intersize = 0;
    309 
    310         wchar_t c;
    311         int col, row, w, h;
    312         int i;
    313 
    314         attrs_t cur_attr;
    315317       
    316318        if (client_connected) {
     
    321323        client_connected = 1;
    322324        ipc_answer_0(iid, EOK);
    323 
    324         cur_attr.t = at_style;
    325         cur_attr.a.s.style = STYLE_NORMAL;
    326325       
    327326        /* Clear the terminal, set scrolling region
     
    332331       
    333332        while (true) {
    334                 callid = async_get_call(&call);
     333                ipc_call_t call;
     334                ipc_callid_t callid = async_get_call(&call);
     335               
     336                wchar_t c;
     337                ipcarg_t col;
     338                ipcarg_t row;
     339                ipcarg_t w;
     340                ipcarg_t h;
     341                ssize_t rows;
     342               
     343                int retval;
     344               
    335345                switch (IPC_GET_METHOD(call)) {
    336346                case IPC_M_PHONE_HUNGUP:
    337347                        client_connected = 0;
    338348                        ipc_answer_0(callid, EOK);
     349                       
     350                        /* Exit thread */
    339351                        return;
    340352                case IPC_M_SHARE_OUT:
     
    347359                                continue;
    348360                        }
     361                       
    349362                        retval = EINVAL;
    350363                        break;
     
    354367                        w = IPC_GET_ARG3(call);
    355368                        h = IPC_GET_ARG4(call);
     369                       
    356370                        if (!interbuf) {
    357371                                retval = EINVAL;
    358372                                break;
    359373                        }
    360                         if (col + w > scr_width || row + h > scr_height) {
     374                       
     375                        if ((col + w > scr_width) || (row + h > scr_height)) {
    361376                                retval = EINVAL;
    362377                                break;
    363378                        }
     379                       
    364380                        draw_text_data(interbuf, col, row, w, h);
    365381                        lastcol = col + w;
     
    371387                        col = IPC_GET_ARG2(call);
    372388                        row = IPC_GET_ARG3(call);
     389                       
    373390                        if ((lastcol != col) || (lastrow != row))
    374391                                serial_goto(col, row);
     392                       
    375393                        lastcol = col + 1;
    376394                        lastrow = row;
     
    400418                        cur_attr.t = at_style;
    401419                        cur_attr.a.s.style = IPC_GET_ARG1(call);
    402                         cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
    403420                        serial_set_attrs(&cur_attr);
    404 
    405421                        retval = 0;
    406422                        break;
     
    411427                        cur_attr.a.i.flags = IPC_GET_ARG3(call);
    412428                        serial_set_attrs(&cur_attr);
    413 
    414429                        retval = 0;
    415430                        break;
    416431                case FB_SET_RGB_COLOR:
    417432                        cur_attr.t = at_rgb;
    418                         cur_attr.a.i.fg_color = IPC_GET_ARG1(call);
    419                         cur_attr.a.i.bg_color = IPC_GET_ARG2(call);
     433                        cur_attr.a.r.fg_color = IPC_GET_ARG1(call);
     434                        cur_attr.a.r.bg_color = IPC_GET_ARG2(call);
    420435                        serial_set_attrs(&cur_attr);
    421 
    422436                        retval = 0;
    423437                        break;
    424438                case FB_SCROLL:
    425                         i = IPC_GET_ARG1(call);
    426                         if ((i > scr_height) || (i < -scr_height)) {
    427                                 retval = EINVAL;
    428                                 break;
     439                        rows = IPC_GET_ARG1(call);
     440                       
     441                        if (rows >= 0) {
     442                                if ((ipcarg_t) rows > scr_height) {
     443                                        retval = EINVAL;
     444                                        break;
     445                                }
     446                        } else {
     447                                if ((ipcarg_t) (-rows) > scr_height) {
     448                                        retval = EINVAL;
     449                                        break;
     450                                }
    429451                        }
    430                         serial_scroll(i);
     452                       
     453                        serial_scroll(rows);
    431454                        serial_goto(lastcol, lastrow);
    432455                        retval = 0;
     
    448471                case FB_SCREEN_RECLAIM:
    449472                        serial_clrscr();
    450                         serial_set_attrs(&cur_attr);
    451473                        retval = 0;
    452474                        break;
Note: See TracChangeset for help on using the changeset viewer.