Ignore:
File:
1 edited

Legend:

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

    r593e023 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>
     
    8384/** Input server proxy */
    8485static input_t *input;
    85 static bool active = false;
    8686
    8787/** Session to the output server */
     
    9898static FIBRIL_MUTEX_INITIALIZE(switch_mtx);
    9999
     100static console_t *prev_console = &consoles[0];
    100101static console_t *active_console = &consoles[0];
    101 
    102 static int input_ev_active(input_t *);
    103 static int input_ev_deactive(input_t *);
     102static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
     103
    104104static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
    105105static int input_ev_move(input_t *, int, int);
     
    108108
    109109static input_ev_ops_t input_ev_ops = {
    110         .active = input_ev_active,
    111         .deactive = input_ev_deactive,
    112110        .key = input_ev_key,
    113111        .move = input_ev_move,
     
    161159        fibril_mutex_lock(&cons->mtx);
    162160       
    163         if ((active) && (cons == active_console)) {
     161        if ((cons == active_console) && (active_console != kernel_console)) {
    164162                output_update(output_sess, cons->fbid);
    165163                output_cursor_update(output_sess, cons->fbid);
     
    175173        fibril_mutex_lock(&cons->mtx);
    176174       
    177         if ((active) && (cons == active_console))
     175        if ((cons == active_console) && (active_console != kernel_console))
    178176                output_cursor_update(output_sess, cons->fbid);
    179177       
     
    187185        fibril_mutex_lock(&cons->mtx);
    188186       
    189         if ((active) && (cons == active_console)) {
     187        if ((cons == active_console) && (active_console != kernel_console)) {
    190188                output_damage(output_sess, cons->fbid, 0, 0, cons->cols,
    191189                    cons->rows);
     
    197195}
    198196
    199 static void cons_switch(unsigned int index)
    200 {
    201         /*
    202          * The first undefined index is reserved
    203          * for switching to the kernel console.
    204          */
    205         if (index == CONSOLE_COUNT) {
    206                 if (console_kcon())
    207                         active = false;
    208                
    209                 return;
    210         }
    211        
    212         if (index > CONSOLE_COUNT)
    213                 return;
    214        
    215         console_t *cons = &consoles[index];
    216        
     197static void cons_switch(console_t *cons)
     198{
    217199        fibril_mutex_lock(&switch_mtx);
    218200       
     
    222204        }
    223205       
     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;
    224219        active_console = cons;
    225220       
     
    229224}
    230225
    231 static int input_ev_active(input_t *input)
    232 {
    233         active = true;
    234         output_claim(output_sess);
    235         cons_damage(active_console);
    236        
    237         return EOK;
    238 }
    239 
    240 static int input_ev_deactive(input_t *input)
    241 {
    242         active = false;
    243         output_yield(output_sess);
    244        
    245         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;
    246239}
    247240
     
    249242    keymod_t mods, wchar_t c)
    250243{
    251         if ((key >= KC_F1) && (key <= KC_F1 + CONSOLE_COUNT) &&
     244        if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
    252245            ((mods & KM_CTRL) == 0)) {
    253                 cons_switch(key - KC_F1);
     246                cons_switch(&consoles[key - KC_F1]);
    254247        } else {
    255248                /* Got key press/release event */
     
    266259                event->c = c;
    267260               
    268                 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,
    269270                    &event->link);
    270271        }
     
    376377                }
    377378        }
    378        
     379
    379380        return size;
    380381}
     
    387388        while (off < size)
    388389                cons_write_char(cons, str_decode(data, &off, size));
    389        
    390390        return size;
    391391}
     
    498498        event->type = CEV_KEY;
    499499        event->ev.key = *kevent;
    500        
    501500        free(kevent);
    502501        return EOK;
     
    508507       
    509508        for (size_t i = 0; i < CONSOLE_COUNT; i++) {
     509                if (i == KERNEL_CONSOLE)
     510                        continue;
     511               
    510512                if (consoles[i].dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
    511513                        cons = &consoles[i];
     
    524526        con_conn(iid, icall, &cons->srvs);
    525527}
     528
    526529
    527530static int input_connect(const char *svc)
     
    552555       
    553556        return EOK;
     557}
     558
     559static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
     560{
     561        cons_switch(prev_console);
    554562}
    555563
     
    575583static bool console_srv_init(char *input_svc, char *output_svc)
    576584{
     585        int rc;
     586       
    577587        /* Connect to input service */
    578         int rc = input_connect(input_svc);
     588        rc = input_connect(input_svc);
    579589        if (rc != EOK)
    580590                return false;
     
    600610        output_get_caps(output_sess, &ccaps);
    601611       
    602         /*
    603          * Inititalize consoles only if there are
    604          * actually some output devices.
    605          */
    606         if (ccaps != 0) {
    607                 for (size_t i = 0; i < CONSOLE_COUNT; i++) {
    608                         consoles[i].index = i;
    609                         atomic_set(&consoles[i].refcnt, 0);
    610                         fibril_mutex_initialize(&consoles[i].mtx);
    611                         prodcons_initialize(&consoles[i].input_pc);
    612                         consoles[i].char_remains_len = 0;
    613                        
    614                         consoles[i].cols = cols;
    615                         consoles[i].rows = rows;
    616                         consoles[i].ccaps = ccaps;
    617                         consoles[i].frontbuf =
    618                             chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);
    619                        
    620                         if (consoles[i].frontbuf == NULL) {
    621                                 printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i);
    622                                 return false;
    623                         }
    624                        
    625                         consoles[i].fbid = output_frontbuf_create(output_sess,
    626                             consoles[i].frontbuf);
    627                         if (consoles[i].fbid == 0) {
    628                                 printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
    629                                 return false;
    630                         }
    631                        
    632                         con_srvs_init(&consoles[i].srvs);
    633                         consoles[i].srvs.ops = &con_ops;
    634                         consoles[i].srvs.sarg = &consoles[i];
    635                        
    636                         char vc[LOC_NAME_MAXLEN + 1];
    637                         snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
    638                        
    639                         if (loc_service_register(vc, &consoles[i].dsid) != EOK) {
    640                                 printf("%s: Unable to register device %s\n", NAME, vc);
    641                                 return false;
    642                         }
    643                 }
    644                
    645                 input_activate(input);
    646         }
     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));
    647662       
    648663        return true;
Note: See TracChangeset for help on using the changeset viewer.