Ignore:
File:
1 edited

Legend:

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

    r2f6ad06 r902f0906  
    4141#include <str_error.h>
    4242#include <loc.h>
     43#include <event.h>
    4344#include <io/con_srv.h>
    4445#include <io/kbd_event.h>
     
    4950#include <malloc.h>
    5051#include <as.h>
    51 #include <task.h>
    5252#include <fibril_synch.h>
    5353#include "console.h"
     
    8484/** Input server proxy */
    8585static input_t *input;
    86 static bool active = false;
    8786
    8887/** Session to the output server */
     
    9998static FIBRIL_MUTEX_INITIALIZE(switch_mtx);
    10099
     100static console_t *prev_console = &consoles[0];
    101101static console_t *active_console = &consoles[0];
    102 
    103 static int input_ev_active(input_t *);
    104 static int input_ev_deactive(input_t *);
     102static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
     103
    105104static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
    106105static int input_ev_move(input_t *, int, int);
     
    109108
    110109static input_ev_ops_t input_ev_ops = {
    111         .active = input_ev_active,
    112         .deactive = input_ev_deactive,
    113110        .key = input_ev_key,
    114111        .move = input_ev_move,
     
    162159        fibril_mutex_lock(&cons->mtx);
    163160       
    164         if ((active) && (cons == active_console)) {
     161        if ((cons == active_console) && (active_console != kernel_console)) {
    165162                output_update(output_sess, cons->fbid);
    166163                output_cursor_update(output_sess, cons->fbid);
     
    176173        fibril_mutex_lock(&cons->mtx);
    177174       
    178         if ((active) && (cons == active_console))
     175        if ((cons == active_console) && (active_console != kernel_console))
    179176                output_cursor_update(output_sess, cons->fbid);
    180177       
     
    188185        fibril_mutex_lock(&cons->mtx);
    189186       
    190         if ((active) && (cons == active_console)) {
     187        if ((cons == active_console) && (active_console != kernel_console)) {
    191188                output_damage(output_sess, cons->fbid, 0, 0, cons->cols,
    192189                    cons->rows);
     
    198195}
    199196
    200 static void cons_switch(unsigned int index)
    201 {
    202         /*
    203          * The first undefined index is reserved
    204          * for switching to the kernel console.
    205          */
    206         if (index == CONSOLE_COUNT) {
    207                 if (console_kcon())
    208                         active = false;
    209                
    210                 return;
    211         }
    212        
    213         if (index > CONSOLE_COUNT)
    214                 return;
    215        
    216         console_t *cons = &consoles[index];
    217        
     197static void cons_switch(console_t *cons)
     198{
    218199        fibril_mutex_lock(&switch_mtx);
    219200       
     
    223204        }
    224205       
     206        if (cons == kernel_console) {
     207                output_yield(output_sess);
     208                if (!console_kcon()) {
     209                        output_claim(output_sess);
     210                        fibril_mutex_unlock(&switch_mtx);
     211                        return;
     212                }
     213        }
     214       
     215        if (active_console == kernel_console)
     216                output_claim(output_sess);
     217       
     218        prev_console = active_console;
    225219        active_console = cons;
    226220       
     
    230224}
    231225
    232 static int input_ev_active(input_t *input)
    233 {
    234         active = true;
    235         output_claim(output_sess);
    236         cons_damage(active_console);
    237        
    238         return EOK;
    239 }
    240 
    241 static int input_ev_deactive(input_t *input)
    242 {
    243         active = false;
    244         output_yield(output_sess);
    245        
    246         return EOK;
     226static console_t *cons_get_active_uspace(void)
     227{
     228        fibril_mutex_lock(&switch_mtx);
     229       
     230        console_t *active_uspace = active_console;
     231        if (active_uspace == kernel_console)
     232                active_uspace = prev_console;
     233       
     234        assert(active_uspace != kernel_console);
     235       
     236        fibril_mutex_unlock(&switch_mtx);
     237       
     238        return active_uspace;
    247239}
    248240
     
    250242    keymod_t mods, wchar_t c)
    251243{
    252         if ((key >= KC_F1) && (key <= KC_F1 + CONSOLE_COUNT) &&
     244        if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
    253245            ((mods & KM_CTRL) == 0)) {
    254                 cons_switch(key - KC_F1);
     246                cons_switch(&consoles[key - KC_F1]);
    255247        } else {
    256248                /* Got key press/release event */
     
    267259                event->c = c;
    268260               
    269                 prodcons_produce(&active_console->input_pc,
     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,
    270270                    &event->link);
    271271        }
     
    377377                }
    378378        }
    379        
     379
    380380        return size;
    381381}
     
    388388        while (off < size)
    389389                cons_write_char(cons, str_decode(data, &off, size));
    390        
    391390        return size;
    392391}
     
    499498        event->type = CEV_KEY;
    500499        event->ev.key = *kevent;
    501        
    502500        free(kevent);
    503501        return EOK;
     
    509507       
    510508        for (size_t i = 0; i < CONSOLE_COUNT; i++) {
    511                 if (consoles[i].dsid == (service_id_t) IPC_GET_ARG2(*icall)) {
     509                if (i == KERNEL_CONSOLE)
     510                        continue;
     511               
     512                if (consoles[i].dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
    512513                        cons = &consoles[i];
    513514                        break;
     
    525526        con_conn(iid, icall, &cons->srvs);
    526527}
     528
    527529
    528530static int input_connect(const char *svc)
     
    537539        }
    538540
    539         sess = loc_service_connect(dsid, INTERFACE_INPUT, 0);
     541        sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
    540542        if (sess == NULL) {
    541543                printf("%s: Unable to connect to input service %s\n", NAME,
     
    555557}
    556558
     559static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
     560{
     561        cons_switch(prev_console);
     562}
     563
    557564static async_sess_t *output_connect(const char *svc)
    558565{
     
    562569        int rc = loc_service_get_id(svc, &dsid, 0);
    563570        if (rc == EOK) {
    564                 sess = loc_service_connect(dsid, INTERFACE_OUTPUT, 0);
     571                sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
    565572                if (sess == NULL) {
    566573                        printf("%s: Unable to connect to output service %s\n",
     
    576583static bool console_srv_init(char *input_svc, char *output_svc)
    577584{
     585        int rc;
     586       
    578587        /* Connect to input service */
    579         int rc = input_connect(input_svc);
     588        rc = input_connect(input_svc);
    580589        if (rc != EOK)
    581590                return false;
     
    587596       
    588597        /* Register server */
    589         async_set_fallback_port_handler(client_connection, NULL);
     598        async_set_client_connection(client_connection);
    590599        rc = loc_server_register(NAME);
    591600        if (rc != EOK) {
     
    601610        output_get_caps(output_sess, &ccaps);
    602611       
    603         /*
    604          * Inititalize consoles only if there are
    605          * actually some output devices.
    606          */
    607         if (ccaps != 0) {
    608                 for (size_t i = 0; i < CONSOLE_COUNT; i++) {
    609                         consoles[i].index = i;
    610                         atomic_set(&consoles[i].refcnt, 0);
    611                         fibril_mutex_initialize(&consoles[i].mtx);
    612                         prodcons_initialize(&consoles[i].input_pc);
    613                         consoles[i].char_remains_len = 0;
    614                        
    615                         consoles[i].cols = cols;
    616                         consoles[i].rows = rows;
    617                         consoles[i].ccaps = ccaps;
    618                         consoles[i].frontbuf =
    619                             chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);
    620                        
    621                         if (consoles[i].frontbuf == NULL) {
    622                                 printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i);
    623                                 return false;
    624                         }
    625                        
    626                         consoles[i].fbid = output_frontbuf_create(output_sess,
    627                             consoles[i].frontbuf);
    628                         if (consoles[i].fbid == 0) {
    629                                 printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
    630                                 return false;
    631                         }
    632                        
    633                         con_srvs_init(&consoles[i].srvs);
    634                         consoles[i].srvs.ops = &con_ops;
    635                         consoles[i].srvs.sarg = &consoles[i];
    636                        
    637                         char vc[LOC_NAME_MAXLEN + 1];
    638                         snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
    639                        
    640                         if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
    641                                 printf("%s: Unable to register device %s\n", NAME, vc);
    642                                 return false;
    643                         }
    644                 }
    645                
    646                 input_activate(input);
    647         }
     612        /* Inititalize consoles */
     613        for (size_t i = 0; i < CONSOLE_COUNT; i++) {
     614                consoles[i].index = i;
     615                atomic_set(&consoles[i].refcnt, 0);
     616                fibril_mutex_initialize(&consoles[i].mtx);
     617                prodcons_initialize(&consoles[i].input_pc);
     618                consoles[i].char_remains_len = 0;
     619               
     620                if (i == KERNEL_CONSOLE)
     621                        continue;
     622               
     623                consoles[i].cols = cols;
     624                consoles[i].rows = rows;
     625                consoles[i].ccaps = ccaps;
     626                consoles[i].frontbuf =
     627                    chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);
     628               
     629                if (consoles[i].frontbuf == NULL) {
     630                        printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i);
     631                        return false;
     632                }
     633               
     634                consoles[i].fbid = output_frontbuf_create(output_sess,
     635                    consoles[i].frontbuf);
     636                if (consoles[i].fbid == 0) {
     637                        printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
     638                        return false;
     639                }
     640               
     641                con_srvs_init(&consoles[i].srvs);
     642                consoles[i].srvs.ops = &con_ops;
     643                consoles[i].srvs.sarg = &consoles[i];
     644               
     645                char vc[LOC_NAME_MAXLEN + 1];
     646                snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
     647               
     648                if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
     649                        printf("%s: Unable to register device %s\n", NAME, vc);
     650                        return false;
     651                }
     652        }
     653       
     654        cons_damage(active_console);
     655       
     656        /* Receive kernel notifications */
     657        async_set_interrupt_received(interrupt_received);
     658        rc = event_subscribe(EVENT_KCONSOLE, 0);
     659        if (rc != EOK)
     660                printf("%s: Failed to register kconsole notifications (%s)\n",
     661                    NAME, str_error(rc));
    648662       
    649663        return true;
Note: See TracChangeset for help on using the changeset viewer.