Ignore:
File:
1 edited

Legend:

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

    r5d94b16c r3123d2a  
    3434
    3535#include <async.h>
     36#include <stdio.h>
     37#include <adt/prodcons.h>
     38#include <ipc/input.h>
     39#include <ipc/console.h>
     40#include <ipc/vfs.h>
    3641#include <errno.h>
    37 #include <io/con_srv.h>
    38 #include <stdio.h>
    39 #include <stdlib.h>
    4042#include <str_error.h>
    4143#include <loc.h>
     
    4345#include <io/keycode.h>
    4446#include <align.h>
     47#include <malloc.h>
     48#include <as.h>
    4549#include <fibril_synch.h>
    4650#include <task.h>
     
    7175    sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t);
    7276
    73 static int remcons_open(con_srvs_t *, con_srv_t *);
    74 static int remcons_close(con_srv_t *);
    75 static int remcons_write(con_srv_t *, void *, size_t);
    76 static void remcons_sync(con_srv_t *);
    77 static void remcons_clear(con_srv_t *);
    78 static void remcons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
    79 static int remcons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
    80 static int remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
    81 static int remcons_get_color_cap(con_srv_t *, console_caps_t *);
    82 static int remcons_get_event(con_srv_t *, kbd_event_t *);
    83 
    84 static con_ops_t con_ops = {
    85         .open = remcons_open,
    86         .close = remcons_close,
    87         .read = NULL,
    88         .write = remcons_write,
    89         .sync = remcons_sync,
    90         .clear = remcons_clear,
    91         .set_pos = remcons_set_pos,
    92         .get_pos = remcons_get_pos,
    93         .get_size = remcons_get_size,
    94         .get_color_cap = remcons_get_color_cap,
    95         .set_style = NULL,
    96         .set_color = NULL,
    97         .set_rgb_color = NULL,
    98         .set_cursor_visibility = NULL,
    99         .get_event = remcons_get_event
    100 };
    101 
    102 static telnet_user_t *srv_to_user(con_srv_t *srv)
    103 {
    104         return srv->srvs->sarg;
    105 }
    106 
    107 static int remcons_open(con_srvs_t *srvs, con_srv_t *srv)
    108 {
    109         telnet_user_t *user = srv_to_user(srv);
    110 
    111         telnet_user_log(user, "New client connected (%p).", srv);
    112 
    113         /* Force character mode. */
    114         send(user->socket, (void *)telnet_force_character_mode_command,
    115             telnet_force_character_mode_command_count, 0);
    116 
    117         return EOK;
    118 }
    119 
    120 static int remcons_close(con_srv_t *srv)
    121 {
    122         telnet_user_t *user = srv_to_user(srv);
    123 
    124         telnet_user_notify_client_disconnected(user);
    125         telnet_user_log(user, "Client disconnected (%p).", srv);
    126 
    127         return EOK;
    128 }
    129 
    130 static int remcons_write(con_srv_t *srv, void *data, size_t size)
    131 {
    132         telnet_user_t *user = srv_to_user(srv);
    133         int rc;
    134 
    135         rc = telnet_user_send_data(user, data, size);
    136         if (rc != EOK)
    137                 return rc;
    138 
    139         return size;
    140 }
    141 
    142 static void remcons_sync(con_srv_t *srv)
    143 {
    144         (void) srv;
    145 }
    146 
    147 static void remcons_clear(con_srv_t *srv)
    148 {
    149         (void) srv;
    150 }
    151 
    152 static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
    153 {
    154         telnet_user_t *user = srv_to_user(srv);
    155 
    156         telnet_user_update_cursor_x(user, col);
    157 }
    158 
    159 static int remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
    160 {
    161         telnet_user_t *user = srv_to_user(srv);
    162 
    163         *col = user->cursor_x;
    164         *row = 0;
    165 
    166         return EOK;
    167 }
    168 
    169 static int remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
    170 {
    171         (void) srv;
    172 
    173         *cols = 100;
    174         *rows = 1;
    175 
    176         return EOK;
    177 }
    178 
    179 static int remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
    180 {
    181         (void) srv;
    182         *ccaps = CONSOLE_CAP_NONE;
    183 
    184         return EOK;
    185 }
    186 
    187 static int remcons_get_event(con_srv_t *srv, kbd_event_t *event)
    188 {
    189         telnet_user_t *user = srv_to_user(srv);
    190         int rc;
    191 
    192         rc = telnet_user_get_next_keyboard_event(user, event);
    193         if (rc != EOK) {
    194                 /* XXX What? */
    195                 memset(event, 0, sizeof(*event));
    196                 return EOK;
    197         }
    198 
    199         return EOK;
     77
     78/** Handling client requests (VFS and console interface).
     79 *
     80 * @param user Telnet user the requests belong to.
     81 */
     82static void client_connection_message_loop(telnet_user_t *user)
     83{
     84        while (true) {
     85                ipc_call_t call;
     86                ipc_callid_t callid = 0;
     87
     88                /*
     89                 * The getterm task might terminate while we are here,
     90                 * waiting for a call. Also, the socket might be closed
     91                 * meanwhile.
     92                 * We want to detect this situation early, so we use a
     93                 * timeout variant of async_get_call().
     94                 */
     95                while (callid == 0) {
     96                        callid = async_get_call_timeout(&call, 1000);
     97
     98                        if (telnet_user_is_zombie(user)) {
     99                                if (callid != 0) {
     100                                        async_answer_0(callid, EINTR);
     101                                }
     102                                return;
     103                        }
     104                }
     105               
     106                if (!IPC_GET_IMETHOD(call)) {
     107                        return;
     108                }
     109
     110                switch (IPC_GET_IMETHOD(call)) {
     111                case CONSOLE_GET_SIZE:
     112                        async_answer_2(callid, EOK, 100, 1);
     113                        break;
     114                case CONSOLE_GET_POS:
     115                        fibril_mutex_lock(&user->guard);
     116                        async_answer_2(callid, EOK, user->cursor_x, 0);
     117                        fibril_mutex_unlock(&user->guard);
     118                        break;
     119                case CONSOLE_GET_EVENT: {
     120                        kbd_event_t event;
     121                        int rc = telnet_user_get_next_keyboard_event(user, &event);
     122                        if (rc != EOK) {
     123                                /* Silently ignore. */
     124                                async_answer_0(callid, EOK);
     125                                break;
     126                        }
     127                        async_answer_4(callid, EOK, event.type, event.key, event.mods, event.c);
     128                        break;
     129                }
     130                case CONSOLE_GOTO: {
     131                        int new_x = IPC_GET_ARG1(call);
     132                        telnet_user_update_cursor_x(user, new_x);
     133                        async_answer_0(callid, ENOTSUP);
     134                        break;
     135                }
     136                case VFS_OUT_READ:
     137                        async_answer_0(callid, ENOTSUP);
     138                        break;
     139                case VFS_OUT_WRITE: {
     140                        uint8_t *buf;
     141                        size_t size;
     142                        int rc = async_data_write_accept((void **)&buf, false, 0, 0, 0, &size);
     143
     144                        if (rc != EOK) {
     145                                async_answer_0(callid, rc);
     146                                break;
     147                        }
     148
     149                        rc = telnet_user_send_data(user, buf, size);
     150                        free(buf);
     151
     152                        if (rc != EOK) {
     153                                async_answer_0(callid, rc);
     154                                break;
     155                        }
     156
     157                        async_answer_1(callid, EOK, size);
     158                        break;
     159                }
     160                case VFS_OUT_SYNC:
     161                        async_answer_0(callid, EOK);
     162                        break;
     163                case CONSOLE_CLEAR:
     164                        async_answer_0(callid, EOK);
     165                        break;
     166
     167                case CONSOLE_GET_COLOR_CAP:
     168                        async_answer_1(callid, EOK, CONSOLE_CAP_NONE);
     169                        break;
     170                case CONSOLE_SET_STYLE:
     171                        async_answer_0(callid, ENOTSUP);
     172                        break;
     173                case CONSOLE_SET_COLOR:
     174                        async_answer_0(callid, ENOTSUP);
     175                        break;
     176                case CONSOLE_SET_RGB_COLOR:
     177                        async_answer_0(callid, ENOTSUP);
     178                        break;
     179
     180                case CONSOLE_CURSOR_VISIBILITY:
     181                        async_answer_0(callid, ENOTSUP);
     182                        break;
     183
     184                default:
     185                        async_answer_0(callid, EINVAL);
     186                        break;
     187                }
     188        }
    200189}
    201190
     
    209198                return;
    210199        }
     200        async_answer_0(iid, EOK);
     201
     202        telnet_user_log(user, "New client connected (%" PRIxn").", iid);
     203
     204        /* Force character mode. */
     205        send(user->socket, (void *)telnet_force_character_mode_command,
     206            telnet_force_character_mode_command_count, 0);
    211207
    212208        /* Handle messages. */
    213         con_conn(iid, icall, &user->srvs);
     209        client_connection_message_loop(user);
     210
     211        telnet_user_notify_client_disconnected(user);
     212        telnet_user_log(user, "Client disconnected (%" PRIxn").", iid);
    214213}
    215214
     
    233232                fibril_mutex_lock(&user->guard);
    234233                user->task_finished = true;
    235                 user->srvs.aborted = true;
    236234                fibril_condvar_signal(&user->refcount_cv);
    237235                fibril_mutex_unlock(&user->guard);
     
    253251        fibril_mutex_lock(&user->guard);
    254252        user->task_finished = true;
    255         user->srvs.aborted = true;
    256253        fibril_condvar_signal(&user->refcount_cv);
    257254        fibril_mutex_unlock(&user->guard);
     
    298295                        closesocket(user->socket);
    299296                        user->socket_closed = true;
    300                         user->srvs.aborted = true;
    301297                        continue;
    302298                } else if (user->socket_closed) {
     
    367363
    368364        printf("%s: HelenOS Remote console service\n", NAME);
    369         task_retval(0);
    370365
    371366        while (true) {
     
    384379                assert(user);
    385380
    386                 con_srvs_init(&user->srvs);
    387                 user->srvs.ops = &con_ops;
    388                 user->srvs.sarg = user;
    389                 user->srvs.abort_timeout = 1000;
    390 
    391                 telnet_user_add(user);
    392 
    393381                fid_t fid = fibril_create(network_user_fibril, user);
    394382                assert(fid);
Note: See TracChangeset for help on using the changeset viewer.