Ignore:
File:
1 edited

Legend:

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

    r5d94b16c r6d5e378  
    3636#include <stdio.h>
    3737#include <adt/prodcons.h>
    38 #include <io/input.h>
     38#include <ipc/input.h>
     39#include <ipc/console.h>
    3940#include <ipc/vfs.h>
    4041#include <errno.h>
     
    4243#include <loc.h>
    4344#include <event.h>
    44 #include <io/con_srv.h>
    45 #include <io/kbd_event.h>
    4645#include <io/keycode.h>
    4746#include <io/chargrid.h>
     47#include <io/console.h>
    4848#include <io/output.h>
    4949#include <align.h>
     
    7979        chargrid_t *frontbuf;    /**< Front buffer */
    8080        frontbuf_handle_t fbid;  /**< Front buffer handle */
    81         con_srvs_t srvs;         /**< Console service setup */
    8281} console_t;
    8382
    84 /** Input server proxy */
    85 static input_t *input;
     83/** Session to the input server */
     84static async_sess_t *input_sess;
    8685
    8786/** Session to the output server */
     
    102101static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
    103102
    104 static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
    105 static int input_ev_move(input_t *, int, int);
    106 static int input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
    107 static int input_ev_button(input_t *, int, int);
    108 
    109 static input_ev_ops_t input_ev_ops = {
    110         .key = input_ev_key,
    111         .move = input_ev_move,
    112         .abs_move = input_ev_abs_move,
    113         .button = input_ev_button
    114 };
    115 
    116 static int cons_open(con_srvs_t *, con_srv_t *);
    117 static int cons_close(con_srv_t *);
    118 static int cons_read(con_srv_t *, void *, size_t);
    119 static int cons_write(con_srv_t *, void *, size_t);
    120 static void cons_sync(con_srv_t *);
    121 static void cons_clear(con_srv_t *);
    122 static void cons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
    123 static int cons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
    124 static int cons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
    125 static int cons_get_color_cap(con_srv_t *, console_caps_t *);
    126 static void cons_set_style(con_srv_t *, console_style_t);
    127 static void cons_set_color(con_srv_t *, console_color_t, console_color_t,
    128     console_color_attr_t);
    129 static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
    130 static void cons_set_cursor_visibility(con_srv_t *, bool);
    131 static int cons_get_event(con_srv_t *, kbd_event_t *);
    132 
    133 static con_ops_t con_ops = {
    134         .open = cons_open,
    135         .close = cons_close,
    136         .read = cons_read,
    137         .write = cons_write,
    138         .sync = cons_sync,
    139         .clear = cons_clear,
    140         .set_pos = cons_set_pos,
    141         .get_pos = cons_get_pos,
    142         .get_size = cons_get_size,
    143         .get_color_cap = cons_get_color_cap,
    144         .set_style = cons_set_style,
    145         .set_color = cons_set_color,
    146         .set_rgb_color = cons_set_rgb_color,
    147         .set_cursor_visibility = cons_set_cursor_visibility,
    148         .get_event = cons_get_event
    149 };
    150 
    151 static console_t *srv_to_console(con_srv_t *srv)
    152 {
    153         return srv->srvs->sarg;
    154 }
    155 
    156103static void cons_update(console_t *cons)
    157104{
     
    178125        fibril_mutex_unlock(&cons->mtx);
    179126        fibril_mutex_unlock(&switch_mtx);
     127}
     128
     129static void cons_clear(console_t *cons)
     130{
     131        fibril_mutex_lock(&cons->mtx);
     132        chargrid_clear(cons->frontbuf);
     133        fibril_mutex_unlock(&cons->mtx);
     134       
     135        cons_update(cons);
    180136}
    181137
     
    239195}
    240196
    241 static int input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
    242     keymod_t mods, wchar_t c)
    243 {
    244         if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
    245             ((mods & KM_CTRL) == 0)) {
    246                 cons_switch(&consoles[key - KC_F1]);
    247         } else {
    248                 /* Got key press/release event */
    249                 kbd_event_t *event =
    250                     (kbd_event_t *) malloc(sizeof(kbd_event_t));
    251                 if (event == NULL) {
    252                         return ENOMEM;
    253                 }
    254                
    255                 link_initialize(&event->link);
    256                 event->type = type;
    257                 event->key = key;
    258                 event->mods = mods;
    259                 event->c = c;
    260                
    261                 /*
    262                  * Kernel console does not read events
    263                  * from us, so we will redirect them
    264                  * to the (last) active userspace console
    265                  * if necessary.
    266                  */
    267                 console_t *target_console = cons_get_active_uspace();
    268                
    269                 prodcons_produce(&target_console->input_pc,
    270                     &event->link);
    271         }
    272        
    273         return EOK;
    274 }
    275 
    276 static int input_ev_move(input_t *input, int dx, int dy)
    277 {
    278         return EOK;
    279 }
    280 
    281 static int input_ev_abs_move(input_t *input, unsigned x , unsigned y,
    282     unsigned max_x, unsigned max_y)
    283 {
    284         return EOK;
    285 }
    286 
    287 static int input_ev_button(input_t *input, int bnum, int bpress)
    288 {
    289         return EOK;
     197static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     198{
     199        /* Ignore parameters, the connection is already opened */
     200        while (true) {
     201                ipc_call_t call;
     202                ipc_callid_t callid = async_get_call(&call);
     203               
     204                if (!IPC_GET_IMETHOD(call)) {
     205                        /* TODO: Handle hangup */
     206                        async_hangup(input_sess);
     207                        return;
     208                }
     209               
     210                kbd_event_type_t type;
     211                keycode_t key;
     212                keymod_t mods;
     213                wchar_t c;
     214               
     215                switch (IPC_GET_IMETHOD(call)) {
     216                case INPUT_EVENT_KEY:
     217                        type = IPC_GET_ARG1(call);
     218                        key = IPC_GET_ARG2(call);
     219                        mods = IPC_GET_ARG3(call);
     220                        c = IPC_GET_ARG4(call);
     221                       
     222                        if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
     223                            ((mods & KM_CTRL) == 0))
     224                                cons_switch(&consoles[key - KC_F1]);
     225                        else {
     226                                /* Got key press/release event */
     227                                kbd_event_t *event =
     228                                    (kbd_event_t *) malloc(sizeof(kbd_event_t));
     229                                if (event == NULL) {
     230                                        async_answer_0(callid, ENOMEM);
     231                                        break;
     232                                }
     233                               
     234                                link_initialize(&event->link);
     235                                event->type = type;
     236                                event->key = key;
     237                                event->mods = mods;
     238                                event->c = c;
     239                               
     240                                /*
     241                                 * Kernel console does not read events
     242                                 * from us, so we will redirect them
     243                                 * to the (last) active userspace console
     244                                 * if necessary.
     245                                 */
     246                                console_t *target_console = cons_get_active_uspace();
     247                               
     248                                prodcons_produce(&target_console->input_pc,
     249                                    &event->link);
     250                        }
     251                       
     252                        async_answer_0(callid, EOK);
     253                        break;
     254                case INPUT_EVENT_MOVE:
     255                        async_answer_0(callid, EOK);
     256                        break;
     257                case INPUT_EVENT_BUTTON:
     258                        async_answer_0(callid, EOK);
     259                        break;
     260                default:
     261                        async_answer_0(callid, EINVAL);
     262                }
     263        }
    290264}
    291265
     
    319293}
    320294
    321 static void cons_set_cursor_vis(console_t *cons, bool visible)
     295static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row)
     296{
     297        fibril_mutex_lock(&cons->mtx);
     298        chargrid_set_cursor(cons->frontbuf, col, row);
     299        fibril_mutex_unlock(&cons->mtx);
     300       
     301        cons_update_cursor(cons);
     302}
     303
     304static void cons_set_cursor_visibility(console_t *cons, bool visible)
    322305{
    323306        fibril_mutex_lock(&cons->mtx);
     
    328311}
    329312
    330 static int cons_open(con_srvs_t *srvs, con_srv_t *srv)
    331 {
    332         return EOK;
    333 }
    334 
    335 static int cons_close(con_srv_t *srv)
    336 {
    337         return EOK;
    338 }
    339 
    340 static int cons_read(con_srv_t *srv, void *buf, size_t size)
    341 {
    342         uint8_t *bbuf = buf;
    343         console_t *cons = srv_to_console(srv);
     313static void cons_get_cursor(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
     314{
     315        sysarg_t col;
     316        sysarg_t row;
     317       
     318        fibril_mutex_lock(&cons->mtx);
     319        chargrid_get_cursor(cons->frontbuf, &col, &row);
     320        fibril_mutex_unlock(&cons->mtx);
     321       
     322        async_answer_2(iid, EOK, col, row);
     323}
     324
     325static void cons_write(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
     326{
     327        void *buf;
     328        size_t size;
     329        int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size);
     330       
     331        if (rc != EOK) {
     332                async_answer_0(iid, rc);
     333                return;
     334        }
     335       
     336        size_t off = 0;
     337        while (off < size)
     338                cons_write_char(cons, str_decode(buf, &off, size));
     339       
     340        async_answer_1(iid, EOK, size);
     341        free(buf);
     342}
     343
     344static void cons_read(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
     345{
     346        ipc_callid_t callid;
     347        size_t size;
     348        if (!async_data_read_receive(&callid, &size)) {
     349                async_answer_0(callid, EINVAL);
     350                async_answer_0(iid, EINVAL);
     351                return;
     352        }
     353       
     354        char *buf = (char *) malloc(size);
     355        if (buf == NULL) {
     356                async_answer_0(callid, ENOMEM);
     357                async_answer_0(iid, ENOMEM);
     358                return;
     359        }
     360       
    344361        size_t pos = 0;
    345362       
     
    352369                /* Copy to the buffer remaining characters. */
    353370                while ((pos < size) && (cons->char_remains_len > 0)) {
    354                         bbuf[pos] = cons->char_remains[0];
     371                        buf[pos] = cons->char_remains[0];
    355372                        pos++;
    356373                       
     
    377394                }
    378395        }
    379 
    380         return size;
    381 }
    382 
    383 static int cons_write(con_srv_t *srv, void *data, size_t size)
    384 {
    385         console_t *cons = srv_to_console(srv);
    386 
    387         size_t off = 0;
    388         while (off < size)
    389                 cons_write_char(cons, str_decode(data, &off, size));
    390         return size;
    391 }
    392 
    393 static void cons_sync(con_srv_t *srv)
    394 {
    395         console_t *cons = srv_to_console(srv);
    396        
    397         cons_update(cons);
    398 }
    399 
    400 static void cons_clear(con_srv_t *srv)
    401 {
    402         console_t *cons = srv_to_console(srv);
    403        
    404         fibril_mutex_lock(&cons->mtx);
    405         chargrid_clear(cons->frontbuf);
    406         fibril_mutex_unlock(&cons->mtx);
    407        
    408         cons_update(cons);
    409 }
    410 
    411 static void cons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
    412 {
    413         console_t *cons = srv_to_console(srv);
    414        
    415         fibril_mutex_lock(&cons->mtx);
    416         chargrid_set_cursor(cons->frontbuf, col, row);
    417         fibril_mutex_unlock(&cons->mtx);
    418        
    419         cons_update_cursor(cons);
    420 }
    421 
    422 static int cons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
    423 {
    424         console_t *cons = srv_to_console(srv);
    425        
    426         fibril_mutex_lock(&cons->mtx);
    427         chargrid_get_cursor(cons->frontbuf, col, row);
    428         fibril_mutex_unlock(&cons->mtx);
    429        
    430         return EOK;
    431 }
    432 
    433 static int cons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
    434 {
    435         console_t *cons = srv_to_console(srv);
    436        
    437         fibril_mutex_lock(&cons->mtx);
    438         *cols = cons->cols;
    439         *rows = cons->rows;
    440         fibril_mutex_unlock(&cons->mtx);
    441        
    442         return EOK;
    443 }
    444 
    445 static int cons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
    446 {
    447         console_t *cons = srv_to_console(srv);
    448        
    449         fibril_mutex_lock(&cons->mtx);
    450         *ccaps = cons->ccaps;
    451         fibril_mutex_unlock(&cons->mtx);
    452        
    453         return EOK;
    454 }
    455 
    456 static void cons_set_style(con_srv_t *srv, console_style_t style)
    457 {
    458         console_t *cons = srv_to_console(srv);
    459        
     396       
     397        (void) async_data_read_finalize(callid, buf, size);
     398        async_answer_1(iid, EOK, size);
     399        free(buf);
     400}
     401
     402static void cons_set_style(console_t *cons, console_style_t style)
     403{
    460404        fibril_mutex_lock(&cons->mtx);
    461405        chargrid_set_style(cons->frontbuf, style);
     
    463407}
    464408
    465 static void cons_set_color(con_srv_t *srv, console_color_t bgcolor,
     409static void cons_set_color(console_t *cons, console_color_t bgcolor,
    466410    console_color_t fgcolor, console_color_attr_t attr)
    467411{
    468         console_t *cons = srv_to_console(srv);
    469        
    470412        fibril_mutex_lock(&cons->mtx);
    471413        chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
     
    473415}
    474416
    475 static void cons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
     417static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor,
    476418    pixel_t fgcolor)
    477419{
    478         console_t *cons = srv_to_console(srv);
    479        
    480420        fibril_mutex_lock(&cons->mtx);
    481421        chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
     
    483423}
    484424
    485 static void cons_set_cursor_visibility(con_srv_t *srv, bool visible)
    486 {
    487         console_t *cons = srv_to_console(srv);
    488        
    489         cons_set_cursor_vis(cons, visible);
    490 }
    491 
    492 static int cons_get_event(con_srv_t *srv, kbd_event_t *event)
    493 {
    494         console_t *cons = srv_to_console(srv);
     425static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
     426{
    495427        link_t *link = prodcons_consume(&cons->input_pc);
    496         kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
    497        
    498         *event = *kevent;
    499         free(kevent);
    500         return EOK;
     428        kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
     429       
     430        async_answer_4(iid, EOK, event->type, event->key, event->mods, event->c);
     431        free(event);
    501432}
    502433
     
    521452       
    522453        if (atomic_postinc(&cons->refcnt) == 0)
    523                 cons_set_cursor_vis(cons, true);
    524        
    525         con_conn(iid, icall, &cons->srvs);
    526 }
    527 
    528 
    529 static int input_connect(const char *svc)
     454                cons_set_cursor_visibility(cons, true);
     455       
     456        /* Accept the connection */
     457        async_answer_0(iid, EOK);
     458       
     459        while (true) {
     460                ipc_call_t call;
     461                ipc_callid_t callid = async_get_call(&call);
     462               
     463                if (!IPC_GET_IMETHOD(call))
     464                        return;
     465               
     466                switch (IPC_GET_IMETHOD(call)) {
     467                case VFS_OUT_READ:
     468                        cons_read(cons, callid, &call);
     469                        break;
     470                case VFS_OUT_WRITE:
     471                        cons_write(cons, callid, &call);
     472                        break;
     473                case VFS_OUT_SYNC:
     474                        cons_update(cons);
     475                        async_answer_0(callid, EOK);
     476                        break;
     477                case CONSOLE_CLEAR:
     478                        cons_clear(cons);
     479                        async_answer_0(callid, EOK);
     480                        break;
     481                case CONSOLE_GOTO:
     482                        cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     483                        async_answer_0(callid, EOK);
     484                        break;
     485                case CONSOLE_GET_POS:
     486                        cons_get_cursor(cons, callid, &call);
     487                        break;
     488                case CONSOLE_GET_SIZE:
     489                        async_answer_2(callid, EOK, cons->cols, cons->rows);
     490                        break;
     491                case CONSOLE_GET_COLOR_CAP:
     492                        async_answer_1(callid, EOK, cons->ccaps);
     493                        break;
     494                case CONSOLE_SET_STYLE:
     495                        cons_set_style(cons, IPC_GET_ARG1(call));
     496                        async_answer_0(callid, EOK);
     497                        break;
     498                case CONSOLE_SET_COLOR:
     499                        cons_set_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call),
     500                            IPC_GET_ARG3(call));
     501                        async_answer_0(callid, EOK);
     502                        break;
     503                case CONSOLE_SET_RGB_COLOR:
     504                        cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
     505                        async_answer_0(callid, EOK);
     506                        break;
     507                case CONSOLE_CURSOR_VISIBILITY:
     508                        cons_set_cursor_visibility(cons, IPC_GET_ARG1(call));
     509                        async_answer_0(callid, EOK);
     510                        break;
     511                case CONSOLE_GET_EVENT:
     512                        cons_get_event(cons, callid, &call);
     513                        break;
     514                default:
     515                        async_answer_0(callid, EINVAL);
     516                }
     517        }
     518}
     519
     520static async_sess_t *input_connect(const char *svc)
    530521{
    531522        async_sess_t *sess;
     
    533524       
    534525        int rc = loc_service_get_id(svc, &dsid, 0);
    535         if (rc != EOK) {
    536                 printf("%s: Input service %s not found\n", NAME, svc);
    537                 return rc;
    538         }
    539 
    540         sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
    541         if (sess == NULL) {
    542                 printf("%s: Unable to connect to input service %s\n", NAME,
    543                     svc);
    544                 return EIO;
    545         }
    546        
    547         rc = input_open(sess, &input_ev_ops, NULL, &input);
     526        if (rc == EOK) {
     527                sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
     528                if (sess == NULL) {
     529                        printf("%s: Unable to connect to input service %s\n", NAME,
     530                            svc);
     531                        return NULL;
     532                }
     533        } else
     534                return NULL;
     535       
     536        async_exch_t *exch = async_exchange_begin(sess);
     537        rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
     538        async_exchange_end(exch);
     539       
    548540        if (rc != EOK) {
    549541                async_hangup(sess);
    550                 printf("%s: Unable to communicate with service %s (%s)\n",
     542                printf("%s: Unable to create callback connection to service %s (%s)\n",
    551543                    NAME, svc, str_error(rc));
    552                 return rc;
    553         }
    554        
    555         return EOK;
     544                return NULL;
     545        }
     546       
     547        return sess;
    556548}
    557549
     
    582574static bool console_srv_init(char *input_svc, char *output_svc)
    583575{
    584         int rc;
    585        
    586576        /* Connect to input service */
    587         rc = input_connect(input_svc);
    588         if (rc != EOK)
     577        input_sess = input_connect(input_svc);
     578        if (input_sess == NULL)
    589579                return false;
    590580       
     
    596586        /* Register server */
    597587        async_set_client_connection(client_connection);
    598         rc = loc_server_register(NAME);
     588        int rc = loc_server_register(NAME);
    599589        if (rc != EOK) {
    600590                printf("%s: Unable to register server (%s)\n", NAME,
     
    638628                }
    639629               
    640                 con_srvs_init(&consoles[i].srvs);
    641                 consoles[i].srvs.ops = &con_ops;
    642                 consoles[i].srvs.sarg = &consoles[i];
    643                
    644630                char vc[LOC_NAME_MAXLEN + 1];
    645631                snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
Note: See TracChangeset for help on using the changeset viewer.