Changeset d3109ff in mainline for uspace/srv/hid


Ignore:
Timestamp:
2024-09-24T17:59:36Z (13 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/srv/hid
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • 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.