Changeset 6907f26 in mainline for uspace/srv/hid


Ignore:
Timestamp:
2024-10-03T15:42:59Z (15 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
d05c237
Parents:
d31c3ea
git-author:
Jiri Svoboda <jiri@…> (2024-10-02 17:42:46)
git-committer:
Jiri Svoboda <jiri@…> (2024-10-03 15:42:59)
Message:

Parse VT100 keyboard escape sequences in libvt

Location:
uspace/srv/hid/remcons
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/remcons/remcons.c

    rd31c3ea r6907f26  
    3434 */
    3535
     36#include <adt/prodcons.h>
    3637#include <as.h>
    3738#include <async.h>
     
    124125static void remcons_vt_cputs(void *, const char *);
    125126static void remcons_vt_flush(void *);
     127static void remcons_vt_key(void *, keymod_t, keycode_t, char);
    126128
    127129static vt100_cb_t remcons_vt_cb = {
    128130        .putuchar = remcons_vt_putchar,
    129131        .control_puts = remcons_vt_cputs,
    130         .flush = remcons_vt_flush
     132        .flush = remcons_vt_flush,
     133        .key = remcons_vt_key
    131134};
    132135
     
    340343}
    341344
     345/** Creates new keyboard event from given char.
     346 *
     347 * @param type Event type (press / release).
     348 * @param c Pressed character.
     349 */
     350static kbd_event_t *new_kbd_event(kbd_event_type_t type, keymod_t mods,
     351    keycode_t key, char c)
     352{
     353        kbd_event_t *event = malloc(sizeof(kbd_event_t));
     354        assert(event);
     355
     356        link_initialize(&event->link);
     357        event->type = type;
     358        event->mods = mods;
     359        event->key = key;
     360        event->c = c;
     361
     362        return event;
     363}
     364
    342365static errno_t remcons_get_event(con_srv_t *srv, cons_event_t *event)
    343366{
     367        remcons_t *remcons = srv_to_remcons(srv);
    344368        telnet_user_t *user = srv_to_user(srv);
    345         kbd_event_t kevent;
    346         errno_t rc;
    347 
    348         rc = telnet_user_get_next_keyboard_event(user, &kevent);
    349         if (rc != EOK) {
    350                 /* XXX What? */
    351                 memset(event, 0, sizeof(*event));
    352                 return EOK;
    353         }
     369        size_t nread;
     370
     371        while (list_empty(&remcons->in_events.list)) {
     372                char next_byte = 0;
     373
     374                errno_t rc = telnet_user_recv(user, &next_byte, 1,
     375                    &nread);
     376                if (rc != EOK)
     377                        return rc;
     378
     379                vt100_rcvd_char(remcons->vt, next_byte);
     380        }
     381
     382        link_t *link = prodcons_consume(&remcons->in_events);
     383        kbd_event_t *tmp = list_get_instance(link, kbd_event_t, link);
    354384
    355385        event->type = CEV_KEY;
    356         event->ev.key = kevent;
     386        event->ev.key = *tmp;
     387
     388        free(tmp);
    357389
    358390        return EOK;
     
    551583}
    552584
     585static void remcons_vt_key(void *arg, keymod_t mods, keycode_t key, char c)
     586{
     587        remcons_t *remcons = (remcons_t *)arg;
     588
     589        kbd_event_t *down = new_kbd_event(KEY_PRESS, mods, key, c);
     590        kbd_event_t *up = new_kbd_event(KEY_RELEASE, mods, key, c);
     591        assert(down);
     592        assert(up);
     593        prodcons_produce(&remcons->in_events, &down->link);
     594        prodcons_produce(&remcons->in_events, &up->link);
     595}
     596
    553597/** Handle network connection.
    554598 *
     
    567611        remcons->enable_rgb = !no_ctl && !no_rgb;
    568612        remcons->user = user;
     613        prodcons_initialize(&remcons->in_events);
    569614
    570615        if (remcons->enable_ctl) {
  • uspace/srv/hid/remcons/remcons.h

    rd31c3ea r6907f26  
    3737#define REMCONS_H_
    3838
     39#include <adt/prodcons.h>
    3940#include <stdbool.h>
    4041#include <vt/vt100.h>
     
    5455        charfield_t *ubuf;      /**< user buffer */
    5556        bool curs_visible;      /**< cursor is visible */
     57
     58        /** Producer-consumer of kbd_event_t. */
     59        prodcons_t in_events;
    5660} remcons_t;
    5761
  • uspace/srv/hid/remcons/user.c

    rd31c3ea r6907f26  
    8383        user->conn = conn;
    8484        user->service_id = (service_id_t) -1;
    85         prodcons_initialize(&user->in_events);
    8685        link_initialize(&user->link);
    8786        user->socket_buffer_len = 0;
     
    211210}
    212211
    213 /** Receive next byte from a socket (use buffering.
    214  * We need to return the value via extra argument because the read byte
    215  * might be negative.
     212/** Receive next byte from a socket (use buffering).
     213 *
     214 * @param user Telnet user
     215 * @param byte Place to store the received byte
     216 * @return EOK on success or an error code
    216217 */
    217218static errno_t telnet_user_recv_next_byte_locked(telnet_user_t *user, char *byte)
     
    230231}
    231232
    232 errno_t telnet_user_recv(telnet_user_t *user, void *data, size_t size,
    233     size_t *nread)
    234 {
    235         errno_t rc;
    236         size_t nb;
    237 
    238         /* No more buffered data? */
    239         if (user->socket_buffer_len <= user->socket_buffer_pos) {
    240                 rc = telnet_user_fill_recv_buf(user);
    241                 if (rc != EOK)
    242                         return rc;
    243         }
    244 
    245         nb = user->socket_buffer_len - user->socket_buffer_pos;
    246         memcpy(data, user->socket_buffer + user->socket_buffer_pos, nb);
    247         user->socket_buffer_pos += nb;
    248         *nread = nb;
    249         return EOK;
    250 }
    251 
    252 /** Creates new keyboard event from given char.
    253  *
    254  * @param type Event type (press / release).
    255  * @param c Pressed character.
    256  */
    257 static kbd_event_t *new_kbd_event(kbd_event_type_t type, char32_t c)
    258 {
    259         kbd_event_t *event = malloc(sizeof(kbd_event_t));
    260         assert(event);
    261 
    262         link_initialize(&event->link);
    263         event->type = type;
    264         event->c = c;
    265         event->mods = 0;
    266 
    267         switch (c) {
    268         case '\n':
    269                 event->key = KC_ENTER;
    270                 break;
    271         case '\t':
    272                 event->key = KC_TAB;
    273                 break;
    274         case '\b':
    275         case 127: /* This is what Linux telnet sends. */
    276                 event->key = KC_BACKSPACE;
    277                 event->c = '\b';
    278                 break;
    279         default:
    280                 event->key = KC_A;
    281                 break;
    282         }
    283 
    284         return event;
     233/** Determine if a received byte is available without waiting.
     234 *
     235 * @param user Telnet user
     236 * @return @c true iff a byte is currently available
     237 */
     238static bool telnet_user_byte_avail(telnet_user_t *user)
     239{
     240        return user->socket_buffer_len > user->socket_buffer_pos;
    285241}
    286242
     
    303259}
    304260
    305 /** Get next keyboard event.
     261/** Receive data from telnet connection.
    306262 *
    307263 * @param user Telnet user.
    308  * @param event Where to store the keyboard event.
    309  * @return Error code.
    310  */
    311 errno_t telnet_user_get_next_keyboard_event(telnet_user_t *user, kbd_event_t *event)
    312 {
    313         fibril_mutex_lock(&user->guard);
    314         if (list_empty(&user->in_events.list)) {
     264 * @param buf Destination buffer
     265 * @param size Buffer size
     266 * @param nread Place to store number of bytes read (>0 on success)
     267 * @return EOK on success or an error code
     268 */
     269errno_t telnet_user_recv(telnet_user_t *user, void *buf, size_t size,
     270    size_t *nread)
     271{
     272        uint8_t *bp = (uint8_t *)buf;
     273        fibril_mutex_lock(&user->guard);
     274
     275        assert(size > 0);
     276        *nread = 0;
     277
     278        do {
    315279                char next_byte = 0;
    316280                bool inside_telnet_command = false;
     
    319283
    320284                /* Skip zeros, bail-out on error. */
    321                 while (next_byte == 0) {
    322                         fibril_mutex_unlock(&user->guard);
    323 
    324                         errno_t rc = telnet_user_recv_next_byte_locked(user, &next_byte);
    325                         if (rc != EOK)
     285                do {
     286                        errno_t rc = telnet_user_recv_next_byte_locked(user,
     287                            &next_byte);
     288                        if (rc != EOK) {
     289                                fibril_mutex_unlock(&user->guard);
    326290                                return rc;
    327 
     291                        }
    328292                        uint8_t byte = (uint8_t) next_byte;
    329                         fibril_mutex_lock(&user->guard);
    330293
    331294                        /* Skip telnet commands. */
     
    345308                                next_byte = 0;
    346309                        }
    347                 }
     310                } while (next_byte == 0 && telnet_user_byte_avail(user));
    348311
    349312                /* CR-LF conversions. */
     
    352315                }
    353316
    354                 kbd_event_t *down = new_kbd_event(KEY_PRESS, next_byte);
    355                 kbd_event_t *up = new_kbd_event(KEY_RELEASE, next_byte);
    356                 assert(down);
    357                 assert(up);
    358                 prodcons_produce(&user->in_events, &down->link);
    359                 prodcons_produce(&user->in_events, &up->link);
    360         }
    361 
    362         link_t *link = prodcons_consume(&user->in_events);
    363         kbd_event_t *tmp = list_get_instance(link, kbd_event_t, link);
    364 
    365         fibril_mutex_unlock(&user->guard);
    366 
    367         *event = *tmp;
    368 
    369         free(tmp);
    370 
     317                if (next_byte != 0) {
     318                        *bp++ = next_byte;
     319                        ++*nread;
     320                        --size;
     321                }
     322        } while (size > 0 && (telnet_user_byte_avail(user) || *nread == 0));
     323
     324        fibril_mutex_unlock(&user->guard);
    371325        return EOK;
    372326}
  • uspace/srv/hid/remcons/user.h

    rd31c3ea r6907f26  
    3737#define TELNET_USER_H_
    3838
    39 #include <adt/prodcons.h>
    4039#include <fibril_synch.h>
    4140#include <inet/tcp.h>
     
    6261        con_srvs_t srvs;
    6362
    64         /** Producer-consumer of kbd_event_t. */
    65         prodcons_t in_events;
    6663        link_t link;
    6764        char socket_buffer[BUFFER_SIZE];
Note: See TracChangeset for help on using the changeset viewer.