Changeset d3109ff in mainline


Ignore:
Timestamp:
2024-09-24T17:59:36Z (3 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
6a753a9c
Parents:
3fcea34
Message:

Cursor and color control in remote console + RGB

Move vt100 module from output server into separate vt library
Add cursor and color control to remcons using libvt
Add RGB color control to serial console and remote console

Location:
uspace
Files:
1 added
11 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/meson.build

    r3fcea34 rd3109ff  
    121121
    122122        'ui',
     123        'vt',
    123124]
    124125
  • uspace/lib/vt/include/vt/vt100.h

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2011 Martin Decky
    34 * All rights reserved.
     
    2728 */
    2829
    29 /** @addtogroup output
     30/** @addtogroup libvt
    3031 * @{
    3132 */
    3233
    33 #ifndef OUTPUT_PROTO_VT100_H_
    34 #define OUTPUT_PROTO_VT100_H_
     34#ifndef LIBVT_VT100_H_
     35#define LIBVT_VT100_H_
    3536
    3637#include <io/charfield.h>
     38#include <ipc/common.h>
     39#include <uchar.h>
    3740
    38 typedef void (*vt100_putuchar_t)(char32_t ch);
    39 typedef void (*vt100_control_puts_t)(const char *str);
    40 typedef void (*vt100_flush_t)(void);
     41/** Buffer size when creating actual VT100 commands.
     42 *
     43 * This is absurdly large but since we accept numbers via sysarg_t,
     44 * we make it big enough for the largest value to be on the safe side
     45 * (and to silence compiler too).
     46 *
     47 * TODO: find out if VT100 has some hard limits or perhaps simply cut-out
     48 * values larger than 16 bits or something.
     49 */
     50#define MAX_CONTROL 64
     51
     52typedef enum {
     53        CI_BLACK   = 0,
     54        CI_RED     = 1,
     55        CI_GREEN   = 2,
     56        CI_BROWN   = 3,
     57        CI_BLUE    = 4,
     58        CI_MAGENTA = 5,
     59        CI_CYAN    = 6,
     60        CI_WHITE   = 7
     61} sgr_color_index_t;
     62
     63typedef enum {
     64        SGR_RESET       = 0,
     65        SGR_BOLD        = 1,
     66        SGR_UNDERLINE   = 4,
     67        SGR_BLINK       = 5,
     68        SGR_REVERSE     = 7,
     69        SGR_FGCOLOR     = 30,
     70        SGR_BGCOLOR     = 40
     71} sgr_command_t;
     72
     73typedef void (*vt100_putuchar_t)(void *, char32_t ch);
     74typedef void (*vt100_control_puts_t)(void *, const char *str);
     75typedef void (*vt100_flush_t)(void *);
    4176
    4277typedef struct {
     
    4883        char_attrs_t cur_attrs;
    4984
     85        bool enable_rgb;
     86
     87        void *arg;
    5088        vt100_putuchar_t putuchar;
    5189        vt100_control_puts_t control_puts;
     
    5391} vt100_state_t;
    5492
    55 extern vt100_state_t *vt100_state_create(sysarg_t, sysarg_t, vt100_putuchar_t,
    56     vt100_control_puts_t, vt100_flush_t);
     93extern sgr_color_index_t color_map[];
     94
     95extern vt100_state_t *vt100_state_create(void *, sysarg_t, sysarg_t,
     96    vt100_putuchar_t, vt100_control_puts_t, vt100_flush_t);
    5797extern void vt100_state_destroy(vt100_state_t *);
    5898
     
    61101extern void vt100_get_dimensions(vt100_state_t *, sysarg_t *, sysarg_t *);
    62102
     103extern void vt100_cls(vt100_state_t *);
     104extern void vt100_set_pos(vt100_state_t *, sysarg_t, sysarg_t);
    63105extern void vt100_goto(vt100_state_t *, sysarg_t, sysarg_t);
     106extern void vt100_set_sgr(vt100_state_t *, char_attrs_t);
    64107extern void vt100_set_attr(vt100_state_t *, char_attrs_t);
    65108extern void vt100_cursor_visibility(vt100_state_t *, bool);
  • uspace/lib/vt/src/vt100.c

    r3fcea34 rd3109ff  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * Copyright (c) 2011 Martin Decky
    44 * All rights reserved.
     
    2828 */
    2929
    30 /** @addtogroup output
     30/** @addtogroup libvt
    3131 * @{
    3232 */
    3333
    34 #include <inttypes.h>
    3534#include <errno.h>
    36 #include <stddef.h>
     35#include <io/color.h>
    3736#include <stdio.h>
    3837#include <stdlib.h>
    39 #include <io/color.h>
    40 #include <types/common.h>
    41 #include "vt100.h"
    42 
    43 /** Buffer size when creating actual VT100 commands.
    44  *
    45  * This is absurdly large but since we accept numbers via sysarg_t,
    46  * we make it big enough for the largest value to be on the safe side
    47  * (and to silence compiler too).
    48  *
    49  * TODO: find out if VT100 has some hard limits or perhaps simply cut-out
    50  * values larger than 16 bits or something.
    51  */
    52 #define MAX_CONTROL 64
    53 
    54 typedef enum {
    55         CI_BLACK   = 0,
    56         CI_RED     = 1,
    57         CI_GREEN   = 2,
    58         CI_BROWN   = 3,
    59         CI_BLUE    = 4,
    60         CI_MAGENTA = 5,
    61         CI_CYAN    = 6,
    62         CI_WHITE   = 7
    63 } sgr_color_index_t;
    64 
    65 typedef enum {
    66         SGR_RESET       = 0,
    67         SGR_BOLD        = 1,
    68         SGR_UNDERLINE   = 4,
    69         SGR_BLINK       = 5,
    70         SGR_REVERSE     = 7,
    71         SGR_FGCOLOR     = 30,
    72         SGR_BGCOLOR     = 40
    73 } sgr_command_t;
    74 
    75 static sgr_color_index_t color_map[] = {
     38#include <vt/vt100.h>
     39
     40sgr_color_index_t color_map[] = {
    7641        [COLOR_BLACK]   = CI_BLACK,
    7742        [COLOR_BLUE]    = CI_BLUE,
     
    8449};
    8550
     51void vt100_cls(vt100_state_t *state)
     52{
     53        state->control_puts(state->arg, "\033[2J");
     54}
     55
    8656/** ECMA-48 Set Graphics Rendition. */
    8757static void vt100_sgr(vt100_state_t *state, unsigned int mode)
     
    9060
    9161        snprintf(control, MAX_CONTROL, "\033[%um", mode);
    92         state->control_puts(control);
    93 }
    94 
    95 static void vt100_set_pos(vt100_state_t *state, sysarg_t col, sysarg_t row)
     62        state->control_puts(state->arg, control);
     63}
     64
     65/** Set Graphics Rendition with 5 arguments. */
     66static void vt100_sgr5(vt100_state_t *state, unsigned a1, unsigned a2,
     67    unsigned a3, unsigned a4, unsigned a5)
     68{
     69        char control[MAX_CONTROL];
     70
     71        snprintf(control, MAX_CONTROL, "\033[%u;%u;%u;%u;%um",
     72            a1, a2, a3, a4, a5);
     73        state->control_puts(state->arg, control);
     74}
     75
     76void vt100_set_pos(vt100_state_t *state, sysarg_t col, sysarg_t row)
    9677{
    9778        char control[MAX_CONTROL];
     
    9980        snprintf(control, MAX_CONTROL, "\033[%" PRIun ";%" PRIun "f",
    10081            row + 1, col + 1);
    101         state->control_puts(control);
    102 }
    103 
    104 static void vt100_set_sgr(vt100_state_t *state, char_attrs_t attrs)
    105 {
     82        state->control_puts(state->arg, control);
     83}
     84
     85void vt100_set_sgr(vt100_state_t *state, char_attrs_t attrs)
     86{
     87        unsigned color;
     88
    10689        switch (attrs.type) {
    10790        case CHAR_ATTR_STYLE:
     
    140123                break;
    141124        case CHAR_ATTR_RGB:
    142                 vt100_sgr(state, SGR_RESET);
    143 
    144                 if (attrs.val.rgb.bgcolor <= attrs.val.rgb.fgcolor)
    145                         vt100_sgr(state, SGR_REVERSE);
    146 
     125                if (state->enable_rgb == true) {
     126                        vt100_sgr5(state, 48, 2, RED(attrs.val.rgb.bgcolor),
     127                            GREEN(attrs.val.rgb.bgcolor),
     128                            BLUE(attrs.val.rgb.bgcolor));
     129                        vt100_sgr5(state, 38, 2, RED(attrs.val.rgb.fgcolor),
     130                            GREEN(attrs.val.rgb.fgcolor),
     131                            BLUE(attrs.val.rgb.fgcolor));
     132                } else {
     133                        vt100_sgr(state, SGR_RESET);
     134                        color =
     135                            ((RED(attrs.val.rgb.fgcolor) >= 0x80) ? COLOR_RED : 0) |
     136                            ((GREEN(attrs.val.rgb.fgcolor) >= 0x80) ? COLOR_GREEN : 0) |
     137                            ((BLUE(attrs.val.rgb.fgcolor) >= 0x80) ? COLOR_BLUE : 0);
     138                        vt100_sgr(state, SGR_FGCOLOR + color_map[color]);
     139                        color =
     140                            ((RED(attrs.val.rgb.bgcolor) >= 0x80) ? COLOR_RED : 0) |
     141                            ((GREEN(attrs.val.rgb.bgcolor) >= 0x80) ? COLOR_GREEN : 0) |
     142                            ((BLUE(attrs.val.rgb.bgcolor) >= 0x80) ? COLOR_BLUE : 0);
     143                        vt100_sgr(state, SGR_BGCOLOR + color_map[color]);
     144                }
    147145                break;
    148146        }
    149147}
    150148
    151 vt100_state_t *vt100_state_create(sysarg_t cols, sysarg_t rows,
     149vt100_state_t *vt100_state_create(void *arg, sysarg_t cols, sysarg_t rows,
    152150    vt100_putuchar_t putuchar_fn, vt100_control_puts_t control_puts_fn,
    153151    vt100_flush_t flush_fn)
     
    157155                return NULL;
    158156
     157        state->arg = arg;
    159158        state->putuchar = putuchar_fn;
    160159        state->control_puts = control_puts_fn;
     
    169168        state->cur_attrs.type = CHAR_ATTR_STYLE;
    170169        state->cur_attrs.val.style = STYLE_NORMAL;
    171 
    172         /* Initialize graphic rendition attributes */
    173         vt100_sgr(state, SGR_RESET);
    174         vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
    175         vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
    176         state->control_puts("\033[2J");
    177         state->control_puts("\033[?25l");
    178170
    179171        return state;
     
    225217{
    226218        if (visible)
    227                 state->control_puts("\033[?25h");
     219                state->control_puts(state->arg, "\033[?25h");
    228220        else
    229                 state->control_puts("\033[?25l");
     221                state->control_puts(state->arg, "\033[?25l");
    230222}
    231223
    232224void vt100_putuchar(vt100_state_t *state, char32_t ch)
    233225{
    234         state->putuchar(ch == 0 ? ' ' : ch);
     226        state->putuchar(state->arg, ch == 0 ? ' ' : ch);
    235227        state->cur_col++;
    236228
     
    243235void vt100_flush(vt100_state_t *state)
    244236{
    245         state->flush();
     237        state->flush(state->arg);
    246238}
    247239
  • uspace/srv/hid/output/ctl/serial.c

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2006 Ondrej Palkovsky
    34 * Copyright (c) 2008 Martin Decky
     
    3738#include <errno.h>
    3839#include <io/chargrid.h>
     40#include <vt/vt100.h>
    3941#include "../output.h"
    40 #include "../proto/vt100.h"
    4142#include "serial.h"
    4243
     
    8485static console_caps_t serial_get_caps(outdev_t *dev)
    8586{
    86         return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
     87        return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB);
    8788}
    8889
     
    125126    vt100_control_puts_t control_puts_fn, vt100_flush_t flush_fn)
    126127{
     128        char_attrs_t attrs;
    127129        vt100_state_t *state =
    128             vt100_state_create(SERIAL_COLS, SERIAL_ROWS, putuchar_fn,
     130            vt100_state_create(NULL, SERIAL_COLS, SERIAL_ROWS, putuchar_fn,
    129131            control_puts_fn, flush_fn);
    130132        if (state == NULL)
    131133                return ENOMEM;
     134        state->enable_rgb = true;
     135
     136        vt100_cursor_visibility(state, false);
     137        attrs.type = CHAR_ATTR_STYLE;
     138        attrs.val.style = STYLE_NORMAL;
     139        vt100_set_attr(state, attrs);
     140        vt100_cls(state);
    132141
    133142        outdev_t *dev = outdev_register(&serial_ops, state);
  • uspace/srv/hid/output/ctl/serial.h

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2006 Ondrej Palkovsky
    34 * Copyright (c) 2008 Martin Decky
     
    3536#define OUTPUT_CTL_SERIAL_H_
    3637
    37 #include "../proto/vt100.h"
     38#include <vt/vt100.h>
    3839
    3940extern errno_t serial_init(vt100_putuchar_t, vt100_control_puts_t, vt100_flush_t);
  • uspace/srv/hid/output/meson.build

    r3fcea34 rd3109ff  
    11#
     2# Copyright (c) 2024 Jiri Svoboda
    23# Copyright (c) 2005 Martin Decky
    34# Copyright (c) 2007 Jakub Jermar
     
    2829#
    2930
    30 deps = [ 'codepage', 'console', 'drv', 'fbfont', 'pixconv', 'ddev', 'output' ]
     31deps = [ 'codepage', 'console', 'drv', 'fbfont', 'pixconv', 'ddev', 'output',
     32    'vt' ]
    3133src = files(
    3234        'ctl/serial.c',
     
    3436        'port/chardev.c',
    3537        'port/ddev.c',
    36         'proto/vt100.c',
    3738        'output.c',
    3839)
  • uspace/srv/hid/output/output.c

    r3fcea34 rd3109ff  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * Copyright (c) 2011 Martin Decky
    44 * All rights reserved.
     
    4040#include <ipc/output.h>
    4141#include <config.h>
     42#include <vt/vt100.h>
    4243#include "port/ega.h"
    4344#include "port/chardev.h"
  • uspace/srv/hid/output/port/chardev.c

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2016 Jakub Jermar
    3  * Copyright (c) 2017 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    6565static FIBRIL_CONDVAR_INITIALIZE(discovery_cv);
    6666
    67 static void chardev_flush(void)
     67static void chardev_flush(void *arg)
    6868{
    6969        size_t nwr;
     70
     71        (void)arg;
    7072
    7173        if (chardev_bused == 0)
     
    8183{
    8284        if (chardev_bused == chardev_buf_size)
    83                 chardev_flush();
     85                chardev_flush(NULL);
    8486        chardev_buf[chardev_bused++] = (uint8_t) ch;
    8587}
    8688
    87 static void chardev_putuchar(char32_t ch)
     89static void chardev_putuchar(void *arg, char32_t ch)
    8890{
    8991        char buf[STR_BOUNDS(1)];
     
    9294        errno_t rc;
    9395
     96        (void)arg;
     97
    9498        off = 0;
    9599        rc = chr_encode(ch, buf, &off, sizeof(buf));
     
    101105}
    102106
    103 static void chardev_control_puts(const char *str)
     107static void chardev_control_puts(void *arg, const char *str)
    104108{
    105109        const char *p;
     
    107111        p = str;
    108112        while (*p != '\0')
    109                 chardev_putuchar(*p++);
     113                chardev_putuchar(arg, *p++);
    110114}
    111115
  • uspace/srv/hid/remcons/meson.build

    r3fcea34 rd3109ff  
    11#
    2 # Copyright (c) 2021 Jiri Svoboda
     2# Copyright (c) 2024 Jiri Svoboda
    33# Copyright (c) 2012 Vojtech Horky
    44# All rights reserved.
     
    2828#
    2929
    30 deps = [ 'inet', 'console' ]
     30deps = [ 'inet', 'console', 'vt' ]
    3131src = files('remcons.c', 'user.c')
  • uspace/srv/hid/remcons/remcons.c

    r3fcea34 rd3109ff  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * Copyright (c) 2012 Vojtech Horky
    44 * All rights reserved.
     
    5151#include <inttypes.h>
    5252#include <str.h>
     53#include <vt/vt100.h>
    5354#include "telnet.h"
    5455#include "user.h"
     56#include "remcons.h"
    5557
    5658#define APP_GETTERM  "/app/getterm"
     
    7476static errno_t remcons_open(con_srvs_t *, con_srv_t *);
    7577static errno_t remcons_close(con_srv_t *);
     78static errno_t remcons_read(con_srv_t *, void *, size_t, size_t *);
    7679static errno_t remcons_write(con_srv_t *, void *, size_t, size_t *);
    7780static void remcons_sync(con_srv_t *);
     
    8184static errno_t remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
    8285static errno_t remcons_get_color_cap(con_srv_t *, console_caps_t *);
     86static void remcons_set_style(con_srv_t *, console_style_t);
     87static void remcons_set_color(con_srv_t *, console_color_t,
     88    console_color_t, console_color_attr_t);
     89static void remcons_set_color(con_srv_t *, console_color_t,
     90    console_color_t, console_color_attr_t);
     91static void remcons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
     92static void remcons_cursor_visibility(con_srv_t *, bool);
    8393static errno_t remcons_get_event(con_srv_t *, cons_event_t *);
    8494
     
    8696        .open = remcons_open,
    8797        .close = remcons_close,
    88         .read = NULL,
     98        .read = remcons_read,
    8999        .write = remcons_write,
    90100        .sync = remcons_sync,
     
    94104        .get_size = remcons_get_size,
    95105        .get_color_cap = remcons_get_color_cap,
    96         .set_style = NULL,
    97         .set_color = NULL,
    98         .set_rgb_color = NULL,
    99         .set_cursor_visibility = NULL,
     106        .set_style = remcons_set_style,
     107        .set_color = remcons_set_color,
     108        .set_rgb_color = remcons_set_rgb_color,
     109        .set_cursor_visibility = remcons_cursor_visibility,
    100110        .get_event = remcons_get_event
    101111};
     
    115125static telnet_user_t *srv_to_user(con_srv_t *srv)
    116126{
    117         return srv->srvs->sarg;
     127        remcons_t *remcons = (remcons_t *)srv->srvs->sarg;
     128        return remcons->user;
     129}
     130
     131static remcons_t *srv_to_remcons(con_srv_t *srv)
     132{
     133        remcons_t *remcons = (remcons_t *)srv->srvs->sarg;
     134        return remcons;
    118135}
    119136
     
    141158}
    142159
     160static errno_t remcons_read(con_srv_t *srv, void *data, size_t size,
     161    size_t *nread)
     162{
     163        telnet_user_t *user = srv_to_user(srv);
     164        errno_t rc;
     165
     166        rc = telnet_user_recv(user, data, size, nread);
     167        if (rc != EOK)
     168                return rc;
     169
     170        return EOK;
     171}
     172
    143173static errno_t remcons_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
    144174{
     
    161191static void remcons_clear(con_srv_t *srv)
    162192{
    163         (void) srv;
     193        remcons_t *remcons = srv_to_remcons(srv);
     194
     195        if (remcons->enable_ctl) {
     196                vt100_cls(remcons->vt);
     197                vt100_set_pos(remcons->vt, 0, 0);
     198                remcons->user->cursor_x = 0;
     199                remcons->user->cursor_y = 0;
     200        }
    164201}
    165202
    166203static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
    167204{
    168         telnet_user_t *user = srv_to_user(srv);
    169 
    170         telnet_user_update_cursor_x(user, col);
     205        remcons_t *remcons = srv_to_remcons(srv);
     206        telnet_user_t *user = srv_to_user(srv);
     207
     208        if (remcons->enable_ctl) {
     209                vt100_set_pos(remcons->vt, col, row);
     210                remcons->user->cursor_x = col;
     211                remcons->user->cursor_y = row;
     212        } else {
     213                telnet_user_update_cursor_x(user, col);
     214        }
    171215}
    172216
     
    176220
    177221        *col = user->cursor_x;
    178         *row = 0;
     222        *row = user->cursor_y;
    179223
    180224        return EOK;
     
    183227static errno_t remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
    184228{
    185         (void) srv;
    186 
    187         *cols = 100;
    188         *rows = 1;
     229        remcons_t *remcons = srv_to_remcons(srv);
     230
     231        if (remcons->enable_ctl) {
     232                *cols = 80;
     233                *rows = 25;
     234        } else {
     235                *cols = 100;
     236                *rows = 1;
     237        }
    189238
    190239        return EOK;
     
    193242static errno_t remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
    194243{
    195         (void) srv;
    196         *ccaps = CONSOLE_CAP_NONE;
    197 
    198         return EOK;
     244        remcons_t *remcons = srv_to_remcons(srv);
     245
     246        if (remcons->enable_ctl)
     247                *ccaps = CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB;
     248        else
     249                *ccaps = 0;
     250
     251        return EOK;
     252}
     253
     254static void remcons_set_style(con_srv_t *srv, console_style_t style)
     255{
     256        remcons_t *remcons = srv_to_remcons(srv);
     257        char_attrs_t attrs;
     258
     259        if (remcons->enable_ctl) {
     260                attrs.type = CHAR_ATTR_STYLE;
     261                attrs.val.style = style;
     262                vt100_set_attr(remcons->vt, attrs);
     263        }
     264}
     265
     266static void remcons_set_color(con_srv_t *srv, console_color_t bgcolor,
     267    console_color_t fgcolor, console_color_attr_t flags)
     268{
     269        remcons_t *remcons = srv_to_remcons(srv);
     270        char_attrs_t attrs;
     271
     272        if (remcons->enable_ctl) {
     273                attrs.type = CHAR_ATTR_INDEX;
     274                attrs.val.index.bgcolor = bgcolor;
     275                attrs.val.index.fgcolor = fgcolor;
     276                attrs.val.index.attr = flags;
     277                vt100_set_attr(remcons->vt, attrs);
     278        }
     279}
     280
     281static void remcons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
     282    pixel_t fgcolor)
     283{
     284        remcons_t *remcons = srv_to_remcons(srv);
     285        char_attrs_t attrs;
     286
     287        if (remcons->enable_ctl) {
     288                attrs.type = CHAR_ATTR_RGB;
     289                attrs.val.rgb.bgcolor = bgcolor;
     290                attrs.val.rgb.fgcolor = fgcolor;
     291                vt100_set_attr(remcons->vt, attrs);
     292        }
     293}
     294
     295static void remcons_cursor_visibility(con_srv_t *srv, bool visible)
     296{
     297        remcons_t *remcons = srv_to_remcons(srv);
     298
     299        if (remcons->enable_ctl)
     300                vt100_cursor_visibility(remcons->vt, visible);
    199301}
    200302
     
    287389}
    288390
     391static void remcons_vt_putchar(void *arg, char32_t c)
     392{
     393        remcons_t *remcons = (remcons_t *)arg;
     394        char buf[STR_BOUNDS(1)];
     395        size_t off;
     396        errno_t rc;
     397
     398        (void)arg;
     399
     400        off = 0;
     401        rc = chr_encode(c, buf, &off, sizeof(buf));
     402        if (rc != EOK)
     403                return;
     404
     405        (void)telnet_user_send_data(remcons->user, buf, off);
     406}
     407
     408static void remcons_vt_cputs(void *arg, const char *str)
     409{
     410        remcons_t *remcons = (remcons_t *)arg;
     411
     412        (void)telnet_user_send_data(remcons->user, str, str_size(str));
     413}
     414
     415static void remcons_vt_flush(void *arg)
     416{
     417        remcons_t *remcons = (remcons_t *)arg;
     418        (void)remcons;
     419}
     420
    289421/** Handle network connection.
    290422 *
     
    294426static void remcons_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
    295427{
     428        char_attrs_t attrs;
     429        remcons_t *remcons = calloc(1, sizeof(remcons_t));
     430        assert(remcons != NULL); // XXX
    296431        telnet_user_t *user = telnet_user_create(conn);
    297432        assert(user);
    298433
     434        remcons->enable_ctl = true;
     435        remcons->user = user;
     436
     437        if (remcons->enable_ctl) {
     438                user->rows = 25;
     439        } else {
     440                user->rows = 1;
     441        }
     442
     443        remcons->vt = vt100_state_create((void *)remcons, 80, 25,
     444            remcons_vt_putchar, remcons_vt_cputs, remcons_vt_flush);
     445        assert(remcons->vt != NULL); // XXX
     446        remcons->vt->enable_rgb = true;
     447
     448        if (remcons->enable_ctl) {
     449                attrs.type = CHAR_ATTR_STYLE;
     450                attrs.val.style = STYLE_NORMAL;
     451                vt100_set_sgr(remcons->vt, attrs);
     452                vt100_cls(remcons->vt);
     453                vt100_set_pos(remcons->vt, 0, 0);
     454        }
     455
    299456        con_srvs_init(&user->srvs);
    300457        user->srvs.ops = &con_ops;
    301         user->srvs.sarg = user;
     458        user->srvs.sarg = remcons;
    302459        user->srvs.abort_timeout = 1000;
    303460
  • uspace/srv/hid/remcons/remcons.h

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2012 Vojtech Horky
    34 * All rights reserved.
     
    3637#define REMCONS_H_
    3738
     39#include <stdbool.h>
     40#include <vt/vt100.h>
     41#include "user.h"
     42
    3843#define NAME       "remcons"
    3944#define NAMESPACE  "term"
     45
     46typedef struct {
     47        telnet_user_t *user;
     48        vt100_state_t *vt;
     49        bool enable_ctl;
     50} remcons_t;
    4051
    4152#endif
  • uspace/srv/hid/remcons/user.c

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2012 Vojtech Horky
    34 * All rights reserved.
     
    3738#include <adt/prodcons.h>
    3839#include <errno.h>
     40#include <mem.h>
    3941#include <str_error.h>
    4042#include <loc.h>
     
    4850#include <inttypes.h>
    4951#include <assert.h>
     52#include "remcons.h"
    5053#include "user.h"
    5154#include "telnet.h"
     
    9093
    9194        user->cursor_x = 0;
     95        user->cursor_y = 0;
    9296
    9397        return user;
     
    182186}
    183187
     188static errno_t telnet_user_fill_recv_buf(telnet_user_t *user)
     189{
     190        errno_t rc;
     191        size_t recv_length;
     192
     193        rc = tcp_conn_recv_wait(user->conn, user->socket_buffer,
     194            BUFFER_SIZE, &recv_length);
     195        if (rc != EOK)
     196                return rc;
     197
     198        if (recv_length == 0) {
     199                user->socket_closed = true;
     200                user->srvs.aborted = true;
     201                return ENOENT;
     202        }
     203
     204        user->socket_buffer_len = recv_length;
     205        user->socket_buffer_pos = 0;
     206
     207        return EOK;
     208}
     209
    184210/** Receive next byte from a socket (use buffering.
    185211 * We need to return the value via extra argument because the read byte
     
    188214static errno_t telnet_user_recv_next_byte_no_lock(telnet_user_t *user, char *byte)
    189215{
     216        errno_t rc;
     217
    190218        /* No more buffered data? */
    191219        if (user->socket_buffer_len <= user->socket_buffer_pos) {
    192                 errno_t rc;
    193                 size_t recv_length;
    194 
    195                 rc = tcp_conn_recv_wait(user->conn, user->socket_buffer,
    196                     BUFFER_SIZE, &recv_length);
     220                rc = telnet_user_fill_recv_buf(user);
    197221                if (rc != EOK)
    198222                        return rc;
    199 
    200                 if (recv_length == 0) {
    201                         user->socket_closed = true;
    202                         user->srvs.aborted = true;
    203                         return ENOENT;
    204                 }
    205 
    206                 user->socket_buffer_len = recv_length;
    207                 user->socket_buffer_pos = 0;
    208223        }
    209224
    210225        *byte = user->socket_buffer[user->socket_buffer_pos++];
    211 
     226        return EOK;
     227}
     228
     229errno_t telnet_user_recv(telnet_user_t *user, void *data, size_t size,
     230    size_t *nread)
     231{
     232        errno_t rc;
     233        size_t nb;
     234
     235        /* No more buffered data? */
     236        if (user->socket_buffer_len <= user->socket_buffer_pos) {
     237                rc = telnet_user_fill_recv_buf(user);
     238                if (rc != EOK)
     239                        return rc;
     240        }
     241
     242        nb = user->socket_buffer_len - user->socket_buffer_pos;
     243        memcpy(data, user->socket_buffer + user->socket_buffer_pos, nb);
     244        user->socket_buffer_pos += nb;
     245        *nread = nb;
    212246        return EOK;
    213247}
     
    283317                /* Skip zeros, bail-out on error. */
    284318                while (next_byte == 0) {
     319                        fibril_mutex_unlock(&user->guard);
     320
    285321                        errno_t rc = telnet_user_recv_next_byte_no_lock(user, &next_byte);
    286                         if (rc != EOK) {
    287                                 fibril_mutex_unlock(&user->guard);
     322                        if (rc != EOK)
    288323                                return rc;
    289                         }
     324
    290325                        uint8_t byte = (uint8_t) next_byte;
     326                        fibril_mutex_lock(&user->guard);
    291327
    292328                        /* Skip telnet commands. */
     
    339375 * @param size Size of @p data buffer in bytes.
    340376 */
    341 static errno_t telnet_user_send_data_no_lock(telnet_user_t *user, uint8_t *data, size_t size)
     377static errno_t telnet_user_send_data_no_lock(telnet_user_t *user,
     378    const char *data, size_t size)
    342379{
    343380        uint8_t *converted = malloc(3 * size + 1);
     
    351388                        converted[converted_size++] = 10;
    352389                        user->cursor_x = 0;
     390                        if (user->cursor_y < user->rows - 1)
     391                                ++user->cursor_y;
    353392                } else {
    354393                        converted[converted_size++] = data[i];
     
    373412 * @param size Size of @p data buffer in bytes.
    374413 */
    375 errno_t telnet_user_send_data(telnet_user_t *user, uint8_t *data, size_t size)
     414errno_t telnet_user_send_data(telnet_user_t *user, const char *data,
     415    size_t size)
    376416{
    377417        fibril_mutex_lock(&user->guard);
     
    395435        fibril_mutex_lock(&user->guard);
    396436        if (user->cursor_x - 1 == new_x) {
    397                 uint8_t data = '\b';
     437                char data = '\b';
    398438                /* Ignore errors. */
    399439                telnet_user_send_data_no_lock(user, &data, 1);
  • uspace/srv/hid/remcons/user.h

    r3fcea34 rd3109ff  
    11/*
     2 * Copyright (c) 2024 Jiri Svoboda
    23 * Copyright (c) 2012 Vojtech Horky
    34 * All rights reserved.
     
    4142#include <inttypes.h>
    4243#include <io/con_srv.h>
    43 #include "remcons.h"
    4444
    4545#define BUFFER_SIZE 32
     
    7979        /** X position of the cursor. */
    8080        int cursor_x;
     81        /** Y position of the cursor. */
     82        int cursor_y;
     83        /** Total number of rows */
     84        int rows;
    8185} telnet_user_t;
    8286
     
    8892extern void telnet_user_notify_client_disconnected(telnet_user_t *);
    8993extern errno_t telnet_user_get_next_keyboard_event(telnet_user_t *, kbd_event_t *);
    90 extern errno_t telnet_user_send_data(telnet_user_t *, uint8_t *, size_t);
     94extern errno_t telnet_user_send_data(telnet_user_t *, const char *, size_t);
     95extern errno_t telnet_user_recv(telnet_user_t *, void *, size_t, size_t *);
    9196extern void telnet_user_update_cursor_x(telnet_user_t *, int);
    9297
Note: See TracChangeset for help on using the changeset viewer.