Ignore:
File:
1 edited

Legend:

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

    r6d5e378 r5d94b16c  
    3636#include <stdio.h>
    3737#include <adt/prodcons.h>
    38 #include <ipc/input.h>
    39 #include <ipc/console.h>
     38#include <io/input.h>
    4039#include <ipc/vfs.h>
    4140#include <errno.h>
     
    4342#include <loc.h>
    4443#include <event.h>
     44#include <io/con_srv.h>
     45#include <io/kbd_event.h>
    4546#include <io/keycode.h>
    4647#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 */
    8182} console_t;
    8283
    83 /** Session to the input server */
    84 static async_sess_t *input_sess;
     84/** Input server proxy */
     85static input_t *input;
    8586
    8687/** Session to the output server */
     
    101102static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
    102103
     104static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
     105static int input_ev_move(input_t *, int, int);
     106static int input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
     107static int input_ev_button(input_t *, int, int);
     108
     109static 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
     116static int cons_open(con_srvs_t *, con_srv_t *);
     117static int cons_close(con_srv_t *);
     118static int cons_read(con_srv_t *, void *, size_t);
     119static int cons_write(con_srv_t *, void *, size_t);
     120static void cons_sync(con_srv_t *);
     121static void cons_clear(con_srv_t *);
     122static void cons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
     123static int cons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
     124static int cons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
     125static int cons_get_color_cap(con_srv_t *, console_caps_t *);
     126static void cons_set_style(con_srv_t *, console_style_t);
     127static void cons_set_color(con_srv_t *, console_color_t, console_color_t,
     128    console_color_attr_t);
     129static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
     130static void cons_set_cursor_visibility(con_srv_t *, bool);
     131static int cons_get_event(con_srv_t *, kbd_event_t *);
     132
     133static 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
     151static console_t *srv_to_console(con_srv_t *srv)
     152{
     153        return srv->srvs->sarg;
     154}
     155
    103156static void cons_update(console_t *cons)
    104157{
     
    125178        fibril_mutex_unlock(&cons->mtx);
    126179        fibril_mutex_unlock(&switch_mtx);
    127 }
    128 
    129 static 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);
    136180}
    137181
     
    195239}
    196240
    197 static 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         }
     241static 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
     276static int input_ev_move(input_t *input, int dx, int dy)
     277{
     278        return EOK;
     279}
     280
     281static 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
     287static int input_ev_button(input_t *input, int bnum, int bpress)
     288{
     289        return EOK;
    264290}
    265291
     
    293319}
    294320
    295 static 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);
     321static void cons_set_cursor_vis(console_t *cons, bool visible)
     322{
     323        fibril_mutex_lock(&cons->mtx);
     324        chargrid_set_cursor_visibility(cons->frontbuf, visible);
    299325        fibril_mutex_unlock(&cons->mtx);
    300326       
     
    302328}
    303329
    304 static void cons_set_cursor_visibility(console_t *cons, bool visible)
    305 {
    306         fibril_mutex_lock(&cons->mtx);
    307         chargrid_set_cursor_visibility(cons->frontbuf, visible);
    308         fibril_mutex_unlock(&cons->mtx);
    309        
    310         cons_update_cursor(cons);
    311 }
    312 
    313 static 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 
    325 static 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 
    344 static 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        
     330static int cons_open(con_srvs_t *srvs, con_srv_t *srv)
     331{
     332        return EOK;
     333}
     334
     335static int cons_close(con_srv_t *srv)
     336{
     337        return EOK;
     338}
     339
     340static 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);
    361344        size_t pos = 0;
    362345       
     
    369352                /* Copy to the buffer remaining characters. */
    370353                while ((pos < size) && (cons->char_remains_len > 0)) {
    371                         buf[pos] = cons->char_remains[0];
     354                        bbuf[pos] = cons->char_remains[0];
    372355                        pos++;
    373356                       
     
    394377                }
    395378        }
    396        
    397         (void) async_data_read_finalize(callid, buf, size);
    398         async_answer_1(iid, EOK, size);
    399         free(buf);
    400 }
    401 
    402 static void cons_set_style(console_t *cons, console_style_t style)
    403 {
     379
     380        return size;
     381}
     382
     383static 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
     393static void cons_sync(con_srv_t *srv)
     394{
     395        console_t *cons = srv_to_console(srv);
     396       
     397        cons_update(cons);
     398}
     399
     400static 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
     411static 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
     422static 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
     433static 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
     445static 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
     456static void cons_set_style(con_srv_t *srv, console_style_t style)
     457{
     458        console_t *cons = srv_to_console(srv);
     459       
    404460        fibril_mutex_lock(&cons->mtx);
    405461        chargrid_set_style(cons->frontbuf, style);
     
    407463}
    408464
    409 static void cons_set_color(console_t *cons, console_color_t bgcolor,
     465static void cons_set_color(con_srv_t *srv, console_color_t bgcolor,
    410466    console_color_t fgcolor, console_color_attr_t attr)
    411467{
     468        console_t *cons = srv_to_console(srv);
     469       
    412470        fibril_mutex_lock(&cons->mtx);
    413471        chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
     
    415473}
    416474
    417 static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor,
     475static void cons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
    418476    pixel_t fgcolor)
    419477{
     478        console_t *cons = srv_to_console(srv);
     479       
    420480        fibril_mutex_lock(&cons->mtx);
    421481        chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
     
    423483}
    424484
    425 static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
    426 {
     485static 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
     492static int cons_get_event(con_srv_t *srv, kbd_event_t *event)
     493{
     494        console_t *cons = srv_to_console(srv);
    427495        link_t *link = prodcons_consume(&cons->input_pc);
    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);
     496        kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
     497       
     498        *event = *kevent;
     499        free(kevent);
     500        return EOK;
    432501}
    433502
     
    452521       
    453522        if (atomic_postinc(&cons->refcnt) == 0)
    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 
    520 static async_sess_t *input_connect(const char *svc)
     523                cons_set_cursor_vis(cons, true);
     524       
     525        con_conn(iid, icall, &cons->srvs);
     526}
     527
     528
     529static int input_connect(const char *svc)
    521530{
    522531        async_sess_t *sess;
     
    524533       
    525534        int rc = loc_service_get_id(svc, &dsid, 0);
    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        
     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);
    540548        if (rc != EOK) {
    541549                async_hangup(sess);
    542                 printf("%s: Unable to create callback connection to service %s (%s)\n",
     550                printf("%s: Unable to communicate with service %s (%s)\n",
    543551                    NAME, svc, str_error(rc));
    544                 return NULL;
    545         }
    546        
    547         return sess;
     552                return rc;
     553        }
     554       
     555        return EOK;
    548556}
    549557
     
    574582static bool console_srv_init(char *input_svc, char *output_svc)
    575583{
     584        int rc;
     585       
    576586        /* Connect to input service */
    577         input_sess = input_connect(input_svc);
    578         if (input_sess == NULL)
     587        rc = input_connect(input_svc);
     588        if (rc != EOK)
    579589                return false;
    580590       
     
    586596        /* Register server */
    587597        async_set_client_connection(client_connection);
    588         int rc = loc_server_register(NAME);
     598        rc = loc_server_register(NAME);
    589599        if (rc != EOK) {
    590600                printf("%s: Unable to register server (%s)\n", NAME,
     
    628638                }
    629639               
     640                con_srvs_init(&consoles[i].srvs);
     641                consoles[i].srvs.ops = &con_ops;
     642                consoles[i].srvs.sarg = &consoles[i];
     643               
    630644                char vc[LOC_NAME_MAXLEN + 1];
    631645                snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
Note: See TracChangeset for help on using the changeset viewer.