Changeset 8ff0bd2 in mainline for uspace/srv/hid/console/console.c


Ignore:
Timestamp:
2011-09-04T11:30:58Z (13 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
03bc76a
Parents:
d2c67e7 (diff), deac215e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

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

    rd2c67e7 r8ff0bd2  
    11/*
    22 * Copyright (c) 2006 Josef Cejka
     3 * Copyright (c) 2011 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3435
    3536#include <libc.h>
    36 #include <ipc/kbd.h>
     37#include <ipc/input.h>
    3738#include <io/keycode.h>
    38 #include <ipc/mouse.h>
    3939#include <ipc/fb.h>
    4040#include <ipc/services.h>
     
    5353#include <sysinfo.h>
    5454#include <event.h>
    55 #include <devmap.h>
    56 #include <devmap_obsolete.h>
     55#include <loc.h>
    5756#include <fcntl.h>
    5857#include <vfs/vfs.h>
     
    6059#include <io/style.h>
    6160#include <io/screenbuffer.h>
    62 #include <inttypes.h>
    6361
    6462#include "console.h"
     
    6664#include "keybuffer.h"
    6765
    68 // FIXME: remove this header
    69 #include <kernel/ipc/ipc_methods.h>
    70 
    7166#define NAME       "console"
    7267#define NAMESPACE  "term"
    7368
    74 /** Interval for checking for new keyboard (1/4s). */
    75 #define HOTPLUG_WATCH_INTERVAL (1000 * 250)
    76 
    77 /* Kernel defines 32 but does not export it. */
    78 #define MAX_IPC_OUTGOING_PHONES 128
    79 
    80 /** To allow proper phone closing. */
    81 static ipc_callid_t driver_phones[MAX_IPC_OUTGOING_PHONES] = { 0 };
    82 
    83 /** Phone to the keyboard driver. */
    84 static int kbd_phone;
    85 
    86 /** Phone to the mouse driver. */
    87 static int mouse_phone;
     69/** Session with the input server. */
     70static async_sess_t *input_sess;
    8871
    8972/** Information about framebuffer */
     
    9881        size_t index;             /**< Console index */
    9982        size_t refcount;          /**< Connection reference count */
    100         devmap_handle_t devmap_handle;  /**< Device handle */
     83        service_id_t service_id;  /**< Service ID */
    10184        keybuffer_t keybuffer;    /**< Buffer for incoming keys. */
    10285        screenbuffer_t scr;       /**< Screenbuffer for saving screen
     
    125108static FIBRIL_CONDVAR_INITIALIZE(input_cv);
    126109
     110static FIBRIL_MUTEX_INITIALIZE(big_console_lock);
     111
     112static void console_serialize_start(void)
     113{
     114        fibril_mutex_lock(&big_console_lock);
     115}
     116
     117static void console_serialize_end(void)
     118{
     119        fibril_mutex_unlock(&big_console_lock);
     120}
     121
    127122static void curs_visibility(bool visible)
    128123{
     
    155150}
    156151
    157 static void kbd_yield(void)
    158 {
    159         async_obsolete_req_0_0(kbd_phone, KBD_YIELD);
    160 }
    161 
    162 static void kbd_reclaim(void)
    163 {
    164         async_obsolete_req_0_0(kbd_phone, KBD_RECLAIM);
     152static void input_yield(void)
     153{
     154        async_exch_t *exch = async_exchange_begin(input_sess);
     155        if (exch == NULL) {
     156                printf("%s: Failed starting exchange with input device.\n",
     157                    NAME);
     158                return;
     159        }
     160       
     161        async_req_0_0(exch, INPUT_YIELD);
     162        async_exchange_end(exch);
     163}
     164
     165static void input_reclaim(void)
     166{
     167        async_exch_t *exch = async_exchange_begin(input_sess);
     168        if (exch == NULL) {
     169                printf("%s: Failed starting exchange with input device.\n",
     170                    NAME);
     171                return;
     172        }
     173       
     174        async_req_0_0(exch, INPUT_RECLAIM);
     175        async_exchange_end(exch);
    165176}
    166177
     
    339350       
    340351        if (cons == kernel_console) {
    341                 async_obsolete_serialize_start();
     352                console_serialize_start();
    342353                curs_hide_sync();
    343354                gcons_in_kernel();
    344355                screen_yield();
    345                 kbd_yield();
    346                 async_obsolete_serialize_end();
    347                
    348                 if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
     356                input_yield();
     357                console_serialize_end();
     358               
     359                if (console_kcon()) {
    349360                        prev_console = active_console;
    350361                        active_console = kernel_console;
     
    354365       
    355366        if (cons != kernel_console) {
    356                 async_obsolete_serialize_start();
     367                console_serialize_start();
    357368               
    358369                if (active_console == kernel_console) {
    359370                        screen_reclaim();
    360                         kbd_reclaim();
     371                        input_reclaim();
    361372                        gcons_redraw_console();
    362373                }
     
    409420                curs_visibility(cons->scr.is_cursor_visible);
    410421               
    411                 async_obsolete_serialize_end();
    412         }
    413 }
    414 
    415 static void close_driver_phone(ipc_callid_t hash)
    416 {
    417         int i;
    418         for (i = 0; i < MAX_IPC_OUTGOING_PHONES; i++) {
    419                 if (driver_phones[i] == hash) {
    420                         printf("Device %" PRIxn " gone.\n", hash);
    421                         driver_phones[i] = 0;
    422                         async_obsolete_hangup(i);
    423                         return;
    424                 }
    425         }
    426 }
    427 
    428 /** Handler for keyboard */
    429 static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
     422                console_serialize_end();
     423        }
     424}
     425
     426/** Handler for input events */
     427static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    430428{
    431429        /* Ignore parameters, the connection is already opened */
     
    439437                if (!IPC_GET_IMETHOD(call)) {
    440438                        /* TODO: Handle hangup */
    441                         close_driver_phone(iid);
     439                        async_hangup(input_sess);
    442440                        return;
    443441                }
    444442               
    445443                switch (IPC_GET_IMETHOD(call)) {
    446                 case KBD_EVENT:
    447                         /* Got event from keyboard driver. */
     444                case INPUT_EVENT_KEY:
     445                        /* Got key press/release event */
    448446                        retval = 0;
    449447                        ev.type = IPC_GET_ARG1(call);
     
    466464                        fibril_mutex_unlock(&input_mutex);
    467465                        break;
    468                 default:
    469                         retval = ENOENT;
    470                 }
    471                 async_answer_0(callid, retval);
    472         }
    473 }
    474 
    475 /** Handler for mouse events */
    476 static void mouse_events(ipc_callid_t iid, ipc_call_t *icall)
    477 {
    478         /* Ignore parameters, the connection is already opened */
    479         while (true) {
    480                 ipc_call_t call;
    481                 ipc_callid_t callid = async_get_call(&call);
    482                
    483                 int retval;
    484                
    485                 if (!IPC_GET_IMETHOD(call)) {
    486                         /* TODO: Handle hangup */
    487                         close_driver_phone(iid);
    488                         return;
    489                 }
    490                
    491                 switch (IPC_GET_IMETHOD(call)) {
    492                 case MEVENT_BUTTON:
     466                case INPUT_EVENT_MOVE:
     467                        /* Got pointer move event */
     468                        gcons_mouse_move((int) IPC_GET_ARG1(call),
     469                            (int) IPC_GET_ARG2(call));
     470                        retval = 0;
     471                        break;
     472                case INPUT_EVENT_BUTTON:
     473                        /* Got pointer button press/release event */
    493474                        if (IPC_GET_ARG1(call) == 1) {
    494475                                int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
     
    498479                        retval = 0;
    499480                        break;
    500                 case MEVENT_MOVE:
    501                         gcons_mouse_move((int) IPC_GET_ARG1(call),
    502                             (int) IPC_GET_ARG2(call));
    503                         retval = 0;
    504                         break;
    505481                default:
    506482                        retval = ENOENT;
     
    522498        }
    523499       
    524         async_obsolete_serialize_start();
     500        console_serialize_start();
    525501       
    526502        size_t off = 0;
     
    530506        }
    531507       
    532         async_obsolete_serialize_end();
     508        console_serialize_end();
    533509       
    534510        gcons_notify_char(cons->index);
     
    597573
    598574/** Default thread for new connections */
    599 static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
     575static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    600576{
    601577        console_t *cons = NULL;
     
    606582                        continue;
    607583               
    608                 if (consoles[i].devmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) {
     584                if (consoles[i].service_id == (service_id_t) IPC_GET_ARG1(*icall)) {
    609585                        cons = &consoles[i];
    610586                        break;
     
    625601        int rc;
    626602       
    627         async_obsolete_serialize_start();
     603        console_serialize_start();
    628604        if (cons->refcount == 0)
    629605                gcons_notify_connect(cons->index);
     
    635611       
    636612        while (true) {
    637                 async_obsolete_serialize_end();
     613                console_serialize_end();
    638614                callid = async_get_call(&call);
    639                 async_obsolete_serialize_start();
     615                console_serialize_start();
    640616               
    641617                arg1 = 0;
     
    647623                        if (cons->refcount == 0)
    648624                                gcons_notify_disconnect(cons->index);
     625                        console_serialize_end();
    649626                        return;
    650627                }
     
    652629                switch (IPC_GET_IMETHOD(call)) {
    653630                case VFS_OUT_READ:
    654                         async_obsolete_serialize_end();
     631                        console_serialize_end();
    655632                        cons_read(cons, callid, &call);
    656                         async_obsolete_serialize_start();
     633                        console_serialize_start();
    657634                        continue;
    658635                case VFS_OUT_WRITE:
    659                         async_obsolete_serialize_end();
     636                        console_serialize_end();
    660637                        cons_write(cons, callid, &call);
    661                         async_obsolete_serialize_start();
     638                        console_serialize_start();
    662639                        continue;
    663640                case VFS_OUT_SYNC:
     
    730707                        break;
    731708                case CONSOLE_GET_EVENT:
    732                         async_obsolete_serialize_end();
     709                        console_serialize_end();
    733710                        cons_get_event(cons, callid, &call);
    734                         async_obsolete_serialize_start();
     711                        console_serialize_start();
    735712                        continue;
    736                 case CONSOLE_KCON_ENABLE:
    737                         change_console(kernel_console);
    738                         break;
    739713                }
    740714                async_answer_3(callid, EOK, arg1, arg2, arg3);
     
    747721}
    748722
    749 static int async_connect_to_me_hack(int phone, sysarg_t arg1, sysarg_t arg2,
    750     sysarg_t arg3, async_client_conn_t client_receiver, ipc_callid_t *hash)
    751 {
    752         sysarg_t task_hash;
    753         sysarg_t phone_hash;
    754         int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    755             NULL, NULL, NULL, &task_hash, &phone_hash);
    756         if (rc != EOK)
    757                 return rc;
    758        
    759         if (client_receiver != NULL)
    760                 async_new_connection(task_hash, phone_hash, phone_hash, NULL,
    761                     client_receiver);
    762        
    763         if (hash != NULL)
    764                 *hash = phone_hash;
    765        
    766         return EOK;
    767 }
    768 
    769 static int connect_keyboard_or_mouse(const char *devname,
    770     async_client_conn_t handler, const char *dev)
    771 {
    772         int phone;
    773         devmap_handle_t handle;
    774        
    775         int rc = devmap_device_get_handle(dev, &handle, 0);
     723static async_sess_t *connect_input(const char *svc_path)
     724{
     725        async_sess_t *sess;
     726        async_exch_t *exch;
     727        service_id_t service_id;
     728       
     729        int rc = loc_service_get_id(svc_path, &service_id, 0);
    776730        if (rc == EOK) {
    777                 phone = devmap_obsolete_device_connect(handle, 0);
    778                 if (phone < 0) {
    779                         printf("%s: Failed to connect to input device\n", NAME);
    780                         return phone;
    781                 }
    782         } else
    783                 return rc;
     731                sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
     732                if (sess == NULL) {
     733                        printf("%s: Failed to connect to input server\n", NAME);
     734                        return NULL;
     735                }
     736        } else {
     737                return NULL;
     738        }
     739       
     740        exch = async_exchange_begin(sess);
     741        if (exch == NULL) {
     742                printf("%s: Failed to create callback from input server.\n", NAME);
     743                return NULL;
     744        }
    784745       
    785746        /* NB: The callback connection is slotted for removal */
    786         ipc_callid_t hash;
    787         rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone,
    788             handler, &hash);
     747        rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
     748
     749        async_exchange_end(exch);
     750
    789751        if (rc != EOK) {
    790                 async_obsolete_hangup(phone);
    791                 printf("%s: Failed to create callback from input device (%s).\n",
     752                async_hangup(sess);
     753                printf("%s: Failed to create callback from input server (%s).\n",
    792754                    NAME, str_error(rc));
    793                 return rc;
    794         }
    795        
    796         driver_phones[phone] = hash;
    797         printf("%s: found %s \"%s\" (%" PRIxn ").\n", NAME, devname, dev, hash);
    798         return phone;
    799 }
    800 
    801 static int connect_keyboard(const char *dev)
    802 {
    803         return connect_keyboard_or_mouse("keyboard", keyboard_events, dev);
    804 }
    805 
    806 static int connect_mouse(const char *dev)
    807 {
    808         return connect_keyboard_or_mouse("mouse", mouse_events, dev);
    809 }
    810 
    811 struct hid_class_info {
    812         char *classname;
    813         int (*connection_func)(const char *);
    814 };
    815 
    816 /** Periodically check for new keyboards in /dev/class/.
    817  *
    818  * @param arg Class name.
    819  *
    820  * @return This function should never exit.
    821  *
    822  */
    823 static int check_new_device_fibril(void *arg)
    824 {
    825         struct hid_class_info *dev_info = (struct hid_class_info *) arg;
    826        
    827         size_t index = 1;
    828        
    829         while (true) {
    830                 async_usleep(HOTPLUG_WATCH_INTERVAL);
    831                
    832                 char *dev;
    833                 int rc = asprintf(&dev, "class/%s\\%zu",
    834                     dev_info->classname, index);
    835                 if (rc < 0)
    836                         continue;
    837                
    838                 rc = dev_info->connection_func(dev);
    839                 if (rc > 0) {
    840                         /* We do not allow unplug. */
    841                         index++;
    842                 }
    843                
    844                 free(dev);
    845         }
    846        
    847         return EOK;
    848 }
    849 
    850 /** Start a fibril monitoring hot-plugged keyboards.
    851  */
    852 static void check_new_devices_in_background(int (*connection_func)(const char *),
    853     const char *classname)
    854 {
    855         struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info));
    856         if (dev_info == NULL) {
    857                 printf("%s: Out of memory, no hot-plug support.\n", NAME);
    858                 return;
    859         }
    860        
    861         int rc = asprintf(&dev_info->classname, "%s", classname);
    862         if (rc < 0) {
    863                 printf("%s: Failed to format classname: %s.\n", NAME,
    864                     str_error(rc));
    865                 return;
    866         }
    867        
    868         dev_info->connection_func = connection_func;
    869        
    870         fid_t fid = fibril_create(check_new_device_fibril, (void *) dev_info);
    871         if (!fid) {
    872                 printf("%s: Failed to create hot-plug fibril for %s.\n", NAME,
    873                     classname);
    874                 return;
    875         }
    876        
    877         fibril_add_ready(fid);
    878 }
    879 
    880 static bool console_srv_init(char *kdev)
    881 {
    882         /* Connect to input device */
    883         kbd_phone = connect_keyboard(kdev);
    884         if (kbd_phone < 0)
     755                return NULL;
     756        }
     757       
     758        return sess;
     759}
     760
     761static bool console_srv_init(char *input_dev)
     762{
     763        /* Connect to input server */
     764        input_sess = connect_input(input_dev);
     765        if (input_sess == NULL)
    885766                return false;
    886        
    887         mouse_phone = connect_mouse("hid_in/mouse");
    888         if (mouse_phone < 0) {
    889                 printf("%s: Failed to connect to mouse device %s\n", NAME,
    890                     str_error(mouse_phone));
    891         }
    892767       
    893768        /* Connect to framebuffer driver */
     
    898773        }
    899774       
    900         /* Register driver */
    901         int rc = devmap_driver_register(NAME, client_connection);
     775        /* Register server */
     776        int rc = loc_server_register(NAME, client_connection);
    902777        if (rc < 0) {
    903                 printf("%s: Unable to register driver (%d)\n", NAME, rc);
     778                printf("%s: Unable to register server (%d)\n", NAME, rc);
    904779                return false;
    905780        }
     
    945820                        consoles[i].refcount = 0;
    946821                       
    947                         char vc[DEVMAP_NAME_MAXLEN + 1];
    948                         snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
     822                        char vc[LOC_NAME_MAXLEN + 1];
     823                        snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
    949824                       
    950                         if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
    951                                 printf("%s: Unable to register device %s\n", NAME, vc);
     825                        if (loc_service_register(vc, &consoles[i].service_id) != EOK) {
     826                                printf("%s: Unable to register service %s\n", NAME, vc);
    952827                                return false;
    953828                        }
     
    955830        }
    956831       
    957         /* Disable kernel output to the console */
    958         __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
    959        
    960832        /* Initialize the screen */
    961         async_obsolete_serialize_start();
     833        console_serialize_start();
    962834        gcons_redraw_console();
    963835        set_style(STYLE_NORMAL);
     
    965837        curs_goto(0, 0);
    966838        curs_visibility(active_console->scr.is_cursor_visible);
    967         async_obsolete_serialize_end();
     839        console_serialize_end();
    968840       
    969841        /* Receive kernel notifications */
     
    972844                printf("%s: Error registering kconsole notifications\n", NAME);
    973845       
    974         /* Start fibril for checking on hot-plugged keyboards. */
    975         check_new_devices_in_background(connect_keyboard, "keyboard");
    976         check_new_devices_in_background(connect_mouse, "mouse");
    977        
    978846        return true;
    979847}
     
    981849static void usage(void)
    982850{
    983         printf("Usage: console <input>\n");
     851        printf("Usage: console <input_dev>\n");
    984852}
    985853
Note: See TracChangeset for help on using the changeset viewer.