Changeset 6907f26 in mainline for uspace/srv/hid/remcons/user.c


Ignore:
Timestamp:
2024-10-03T15:42:59Z (8 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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.