Ignore:
File:
1 edited

Legend:

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

    r854eddd6 r79ae36dd  
    11/*
    22 * Copyright (c) 2006 Josef Cejka
    3  * Copyright (c) 2011 Jiri Svoboda
    43 * All rights reserved.
    54 *
     
    3534
    3635#include <libc.h>
    37 #include <ipc/input.h>
     36#include <ipc/kbd.h>
    3837#include <io/keycode.h>
     38#include <ipc/mouse.h>
    3939#include <ipc/fb.h>
    4040#include <ipc/services.h>
     
    6060#include <io/style.h>
    6161#include <io/screenbuffer.h>
     62#include <inttypes.h>
    6263
    6364#include "console.h"
     
    6566#include "keybuffer.h"
    6667
     68// FIXME: remove this header
     69#include <kernel/ipc/ipc_methods.h>
     70
    6771#define NAME       "console"
    6872#define NAMESPACE  "term"
    6973
    70 /** Phone to the input server. */
    71 static int input_phone;
     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. */
     81static ipc_callid_t driver_phones[MAX_IPC_OUTGOING_PHONES] = { 0 };
     82
     83/** Phone to the keyboard driver. */
     84static int kbd_phone;
     85
     86/** Phone to the mouse driver. */
     87static int mouse_phone;
    7288
    7389/** Information about framebuffer */
     
    139155}
    140156
    141 static void input_yield(void)
    142 {
    143         async_obsolete_req_0_0(input_phone, INPUT_YIELD);
    144 }
    145 
    146 static void input_reclaim(void)
    147 {
    148         async_obsolete_req_0_0(input_phone, INPUT_RECLAIM);
     157static void kbd_yield(void)
     158{
     159        async_obsolete_req_0_0(kbd_phone, KBD_YIELD);
     160}
     161
     162static void kbd_reclaim(void)
     163{
     164        async_obsolete_req_0_0(kbd_phone, KBD_RECLAIM);
    149165}
    150166
     
    327343                gcons_in_kernel();
    328344                screen_yield();
    329                 input_yield();
     345                kbd_yield();
    330346                async_obsolete_serialize_end();
    331347               
     
    342358                if (active_console == kernel_console) {
    343359                        screen_reclaim();
    344                         input_reclaim();
     360                        kbd_reclaim();
    345361                        gcons_redraw_console();
    346362                }
     
    397413}
    398414
    399 /** Handler for input events */
    400 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     415static 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 */
     429static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
    401430{
    402431        /* Ignore parameters, the connection is already opened */
     
    410439                if (!IPC_GET_IMETHOD(call)) {
    411440                        /* TODO: Handle hangup */
    412                         async_obsolete_hangup(input_phone);
     441                        close_driver_phone(iid);
    413442                        return;
    414443                }
    415444               
    416445                switch (IPC_GET_IMETHOD(call)) {
    417                 case INPUT_EVENT_KEY:
    418                         /* Got key press/release event */
     446                case KBD_EVENT:
     447                        /* Got event from keyboard driver. */
    419448                        retval = 0;
    420449                        ev.type = IPC_GET_ARG1(call);
     
    437466                        fibril_mutex_unlock(&input_mutex);
    438467                        break;
    439                 case INPUT_EVENT_MOVE:
    440                         /* Got pointer move event */
    441                         gcons_mouse_move((int) IPC_GET_ARG1(call),
    442                             (int) IPC_GET_ARG2(call));
    443                         retval = 0;
    444                         break;
    445                 case INPUT_EVENT_BUTTON:
    446                         /* Got pointer button press/release event */
     468                default:
     469                        retval = ENOENT;
     470                }
     471                async_answer_0(callid, retval);
     472        }
     473}
     474
     475/** Handler for mouse events */
     476static 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:
    447493                        if (IPC_GET_ARG1(call) == 1) {
    448494                                int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
     
    452498                        retval = 0;
    453499                        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;
    454505                default:
    455506                        retval = ENOENT;
    456507                }
     508
    457509                async_answer_0(callid, retval);
    458510        }
     
    545597
    546598/** Default thread for new connections */
    547 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     599static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
    548600{
    549601        console_t *cons = NULL;
     
    695747}
    696748
    697 static int connect_input(const char *dev_path)
     749static 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
     769static int connect_keyboard_or_mouse(const char *devname,
     770    async_client_conn_t handler, const char *dev)
    698771{
    699772        int phone;
    700773        devmap_handle_t handle;
    701774       
    702         int rc = devmap_device_get_handle(dev_path, &handle, 0);
     775        int rc = devmap_device_get_handle(dev, &handle, 0);
    703776        if (rc == EOK) {
    704777                phone = devmap_obsolete_device_connect(handle, 0);
     
    707780                        return phone;
    708781                }
    709         } else {
     782        } else
    710783                return rc;
    711         }
    712784       
    713785        /* NB: The callback connection is slotted for removal */
    714         rc = async_obsolete_connect_to_me(phone, SERVICE_CONSOLE, 0, 0,
    715             input_events, NULL);
    716 
     786        ipc_callid_t hash;
     787        rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone,
     788            handler, &hash);
    717789        if (rc != EOK) {
    718790                async_obsolete_hangup(phone);
     
    722794        }
    723795       
     796        driver_phones[phone] = hash;
     797        printf("%s: found %s \"%s\" (%" PRIxn ").\n", NAME, devname, dev, hash);
    724798        return phone;
    725799}
    726800
    727 static bool console_srv_init(char *input_dev)
    728 {
    729         /* Connect to input server */
    730         input_phone = connect_input(input_dev);
    731         if (input_phone < 0)
     801static int connect_keyboard(const char *dev)
     802{
     803        return connect_keyboard_or_mouse("keyboard", keyboard_events, dev);
     804}
     805
     806static int connect_mouse(const char *dev)
     807{
     808        return connect_keyboard_or_mouse("mouse", mouse_events, dev);
     809}
     810
     811struct 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 */
     823static 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 */
     852static 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
     880static bool console_srv_init(char *kdev)
     881{
     882        /* Connect to input device */
     883        kbd_phone = connect_keyboard(kdev);
     884        if (kbd_phone < 0)
    732885                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        }
    733892       
    734893        /* Connect to framebuffer driver */
     
    813972                printf("%s: Error registering kconsole notifications\n", NAME);
    814973       
     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       
    815978        return true;
    816979}
     
    818981static void usage(void)
    819982{
    820         printf("Usage: console <input_dev>\n");
     983        printf("Usage: console <input>\n");
    821984}
    822985
Note: See TracChangeset for help on using the changeset viewer.