Ignore:
File:
1 edited

Legend:

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

    r8c74d15 r854eddd6  
    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>
    41 #include <ipc/ns.h>
     41#include <ns.h>
     42#include <ns_obsolete.h>
    4243#include <errno.h>
    4344#include <str_error.h>
     
    4546#include <unistd.h>
    4647#include <async.h>
     48#include <async_obsolete.h>
    4749#include <adt/fifo.h>
    4850#include <sys/mman.h>
     
    5254#include <event.h>
    5355#include <devmap.h>
     56#include <devmap_obsolete.h>
    5457#include <fcntl.h>
    5558#include <vfs/vfs.h>
     
    5760#include <io/style.h>
    5861#include <io/screenbuffer.h>
    59 #include <inttypes.h>
    6062
    6163#include "console.h"
     
    6365#include "keybuffer.h"
    6466
    65 
    6667#define NAME       "console"
    6768#define NAMESPACE  "term"
    68 /** Interval for checking for new keyboard (1/4s). */
    69 #define HOTPLUG_WATCH_INTERVAL (1000 * 250)
    70 
    71 /* Kernel defines 32 but does not export it. */
    72 #define MAX_IPC_OUTGOING_PHONES 128
    73 /** To allow proper phone closing. */
    74 static ipc_callid_t driver_phones[MAX_IPC_OUTGOING_PHONES] = { 0 };
    75 
    76 /** Phone to the keyboard driver. */
    77 static int kbd_phone;
    78 
    79 /** Phone to the mouse driver. */
    80 static int mouse_phone;
     69
     70/** Phone to the input server. */
     71static int input_phone;
    8172
    8273/** Information about framebuffer */
     
    9788} console_t;
    9889
    99 
    100 
    10190/** Array of data for virtual consoles */
    10291static console_t consoles[CONSOLE_COUNT];
     
    122111static void curs_visibility(bool visible)
    123112{
    124         async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
     113        async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
    125114}
    126115
    127116static void curs_hide_sync(void)
    128117{
    129         async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
     118        async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
    130119}
    131120
    132121static void curs_goto(sysarg_t x, sysarg_t y)
    133122{
    134         async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
     123        async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
    135124}
    136125
    137126static void screen_clear(void)
    138127{
    139         async_msg_0(fb_info.phone, FB_CLEAR);
     128        async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
    140129}
    141130
    142131static void screen_yield(void)
    143132{
    144         async_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
     133        async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
    145134}
    146135
    147136static void screen_reclaim(void)
    148137{
    149         async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
    150 }
    151 
    152 static void kbd_yield(void)
    153 {
    154         async_req_0_0(kbd_phone, KBD_YIELD);
    155 }
    156 
    157 static void kbd_reclaim(void)
    158 {
    159         async_req_0_0(kbd_phone, KBD_RECLAIM);
     138        async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
     139}
     140
     141static void input_yield(void)
     142{
     143        async_obsolete_req_0_0(input_phone, INPUT_YIELD);
     144}
     145
     146static void input_reclaim(void)
     147{
     148        async_obsolete_req_0_0(input_phone, INPUT_RECLAIM);
    160149}
    161150
    162151static void set_style(uint8_t style)
    163152{
    164         async_msg_1(fb_info.phone, FB_SET_STYLE, style);
     153        async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);
    165154}
    166155
    167156static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
    168157{
    169         async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
     158        async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
    170159}
    171160
    172161static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
    173162{
    174         async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
     163        async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
    175164}
    176165
     
    227216                }
    228217               
    229                 async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     218                async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
    230219                    x0, y0, width, height);
    231220        }
     
    268257static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row)
    269258{
    270         async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
     259        async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
    271260}
    272261
     
    317306               
    318307                if (cons == active_console)
    319                         async_msg_1(fb_info.phone, FB_SCROLL, 1);
     308                        async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);
    320309        }
    321310       
     
    328317static void change_console(console_t *cons)
    329318{
    330         if (cons == active_console) {
     319        if (cons == active_console)
    331320                return;
    332         }
    333321       
    334322        fb_pending_flush();
    335323       
    336324        if (cons == kernel_console) {
    337                 async_serialize_start();
     325                async_obsolete_serialize_start();
    338326                curs_hide_sync();
    339327                gcons_in_kernel();
    340328                screen_yield();
    341                 kbd_yield();
    342                 async_serialize_end();
     329                input_yield();
     330                async_obsolete_serialize_end();
    343331               
    344332                if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
     
    350338       
    351339        if (cons != kernel_console) {
    352                 async_serialize_start();
     340                async_obsolete_serialize_start();
    353341               
    354342                if (active_console == kernel_console) {
    355343                        screen_reclaim();
    356                         kbd_reclaim();
     344                        input_reclaim();
    357345                        gcons_redraw_console();
    358346                }
     
    377365                       
    378366                        /* This call can preempt, but we are already at the end */
    379                         rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     367                        rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
    380368                            0, 0, cons->scr.size_x,
    381369                            cons->scr.size_y);
     
    405393                curs_visibility(cons->scr.is_cursor_visible);
    406394               
    407                 async_serialize_end();
    408         }
    409 }
    410 
    411 static void close_driver_phone(ipc_callid_t hash)
    412 {
    413         int i;
    414         for (i = 0; i < MAX_IPC_OUTGOING_PHONES; i++) {
    415                 if (driver_phones[i] == hash) {
    416                         printf("Device %" PRIxn " gone.\n", hash);
    417                         driver_phones[i] = 0;
    418                         async_hangup(i);
    419                         return;
    420                 }
    421         }
    422 }
    423 
    424 /** Handler for keyboard */
    425 static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
     395                async_obsolete_serialize_end();
     396        }
     397}
     398
     399/** Handler for input events */
     400static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    426401{
    427402        /* Ignore parameters, the connection is already opened */
     
    431406               
    432407                int retval;
    433                 console_event_t ev;
     408                kbd_event_t ev;
     409               
     410                if (!IPC_GET_IMETHOD(call)) {
     411                        /* TODO: Handle hangup */
     412                        async_obsolete_hangup(input_phone);
     413                        return;
     414                }
    434415               
    435416                switch (IPC_GET_IMETHOD(call)) {
    436                 case IPC_M_PHONE_HUNGUP:
    437                         /* TODO: Handle hangup */
    438                         close_driver_phone(iid);
    439                         return;
    440                 case KBD_EVENT:
    441                         /* Got event from keyboard driver. */
     417                case INPUT_EVENT_KEY:
     418                        /* Got key press/release event */
    442419                        retval = 0;
    443420                        ev.type = IPC_GET_ARG1(call);
     
    460437                        fibril_mutex_unlock(&input_mutex);
    461438                        break;
    462                 default:
    463                         retval = ENOENT;
    464                 }
    465                 async_answer_0(callid, retval);
    466         }
    467 }
    468 
    469 /** Handler for mouse events */
    470 static void mouse_events(ipc_callid_t iid, ipc_call_t *icall)
    471 {
    472         /* Ignore parameters, the connection is already opened */
    473         while (true) {
    474                 ipc_call_t call;
    475                 ipc_callid_t callid = async_get_call(&call);
    476                
    477                 int retval;
    478                
    479                 switch (IPC_GET_IMETHOD(call)) {
    480                 case IPC_M_PHONE_HUNGUP:
    481                         /* TODO: Handle hangup */
    482                         close_driver_phone(iid);
    483                         return;
    484                 case MEVENT_BUTTON:
    485                         if (IPC_GET_ARG1(call) == 1) {
    486                                 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
    487                                 if (newcon != -1) {
    488                                         change_console(&consoles[newcon]);
    489                                 }
    490                         }
    491                         retval = 0;
    492                         break;
    493                 case MEVENT_MOVE:
     439                case INPUT_EVENT_MOVE:
     440                        /* Got pointer move event */
    494441                        gcons_mouse_move((int) IPC_GET_ARG1(call),
    495442                            (int) IPC_GET_ARG2(call));
    496443                        retval = 0;
    497444                        break;
     445                case INPUT_EVENT_BUTTON:
     446                        /* Got pointer button press/release event */
     447                        if (IPC_GET_ARG1(call) == 1) {
     448                                int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
     449                                if (newcon != -1)
     450                                        change_console(&consoles[newcon]);
     451                        }
     452                        retval = 0;
     453                        break;
    498454                default:
    499455                        retval = ENOENT;
    500456                }
    501 
    502457                async_answer_0(callid, retval);
    503458        }
     
    515470        }
    516471       
    517         async_serialize_start();
     472        async_obsolete_serialize_start();
    518473       
    519474        size_t off = 0;
     
    523478        }
    524479       
    525         async_serialize_end();
     480        async_obsolete_serialize_end();
    526481       
    527482        gcons_notify_char(cons->index);
     
    549504       
    550505        size_t pos = 0;
    551         console_event_t ev;
     506        kbd_event_t ev;
    552507        fibril_mutex_lock(&input_mutex);
    553508       
     
    574529static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
    575530{
    576         console_event_t ev;
     531        kbd_event_t ev;
    577532       
    578533        fibril_mutex_lock(&input_mutex);
     
    590545
    591546/** Default thread for new connections */
    592 static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
     547static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    593548{
    594549        console_t *cons = NULL;
     
    618573        int rc;
    619574       
    620         async_serialize_start();
     575        async_obsolete_serialize_start();
    621576        if (cons->refcount == 0)
    622577                gcons_notify_connect(cons->index);
     
    628583       
    629584        while (true) {
    630                 async_serialize_end();
     585                async_obsolete_serialize_end();
    631586                callid = async_get_call(&call);
    632                 async_serialize_start();
     587                async_obsolete_serialize_start();
    633588               
    634589                arg1 = 0;
     
    636591                arg3 = 0;
    637592               
    638                 switch (IPC_GET_IMETHOD(call)) {
    639                 case IPC_M_PHONE_HUNGUP:
     593                if (!IPC_GET_IMETHOD(call)) {
    640594                        cons->refcount--;
    641595                        if (cons->refcount == 0)
    642596                                gcons_notify_disconnect(cons->index);
    643597                        return;
     598                }
     599               
     600                switch (IPC_GET_IMETHOD(call)) {
    644601                case VFS_OUT_READ:
    645                         async_serialize_end();
     602                        async_obsolete_serialize_end();
    646603                        cons_read(cons, callid, &call);
    647                         async_serialize_start();
     604                        async_obsolete_serialize_start();
    648605                        continue;
    649606                case VFS_OUT_WRITE:
    650                         async_serialize_end();
     607                        async_obsolete_serialize_end();
    651608                        cons_write(cons, callid, &call);
    652                         async_serialize_start();
     609                        async_obsolete_serialize_start();
    653610                        continue;
    654611                case VFS_OUT_SYNC:
    655612                        fb_pending_flush();
    656613                        if (cons == active_console) {
    657                                 async_req_0_0(fb_info.phone, FB_FLUSH);
     614                                async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
    658615                                curs_goto(cons->scr.position_x, cons->scr.position_y);
    659616                        }
     
    662619                        /* Send message to fb */
    663620                        if (cons == active_console)
    664                                 async_msg_0(fb_info.phone, FB_CLEAR);
     621                                async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
    665622                       
    666623                        screenbuffer_clear(&cons->scr);
     
    721678                        break;
    722679                case CONSOLE_GET_EVENT:
    723                         async_serialize_end();
     680                        async_obsolete_serialize_end();
    724681                        cons_get_event(cons, callid, &call);
    725                         async_serialize_start();
     682                        async_obsolete_serialize_start();
    726683                        continue;
    727684                case CONSOLE_KCON_ENABLE:
     
    738695}
    739696
    740 static int async_connect_to_me_hack(int phone, sysarg_t arg1, sysarg_t arg2,
    741 sysarg_t arg3, async_client_conn_t client_receiver, ipc_callid_t *hash)
    742 {
    743         sysarg_t task_hash;
    744         sysarg_t phone_hash;
    745         int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    746             NULL, NULL, NULL, &task_hash, &phone_hash);
    747         if (rc != EOK)
     697static int connect_input(const char *dev_path)
     698{
     699        int phone;
     700        devmap_handle_t handle;
     701       
     702        int rc = devmap_device_get_handle(dev_path, &handle, 0);
     703        if (rc == EOK) {
     704                phone = devmap_obsolete_device_connect(handle, 0);
     705                if (phone < 0) {
     706                        printf("%s: Failed to connect to input device\n", NAME);
     707                        return phone;
     708                }
     709        } else {
    748710                return rc;
    749 
    750         if (client_receiver != NULL)
    751                 async_new_connection(task_hash, phone_hash, phone_hash, NULL,
    752                     client_receiver);
    753 
    754         if (hash != NULL) {
    755                 *hash = phone_hash;
    756         }
    757 
    758         return EOK;
    759 }
    760 
    761 static int connect_keyboard_or_mouse(const char *devname,
    762     async_client_conn_t handler, const char *path)
    763 {
    764         int fd = open(path, O_RDONLY);
    765         if (fd < 0) {
    766                 return fd;
    767         }
    768        
    769         int phone = fd_phone(fd);
    770         close(fd);
    771         if (phone < 0) {
    772                 printf(NAME ": Failed to connect to input device\n");
    773                 return phone;
    774         }
    775        
    776         ipc_callid_t hash;
    777         int rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone,
    778             handler, &hash);
     711        }
     712       
     713        /* 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
    779717        if (rc != EOK) {
    780                 async_hangup(phone);
    781                 printf(NAME ": " \
    782                     "Failed to create callback from input device: %s.\n",
    783                     str_error(rc));
     718                async_obsolete_hangup(phone);
     719                printf("%s: Failed to create callback from input device (%s).\n",
     720                    NAME, str_error(rc));
    784721                return rc;
    785722        }
    786723       
    787         driver_phones[phone] = hash;
    788 
    789         printf(NAME ": found %s \"%s\" (%" PRIxn ").\n", devname, path, hash);
    790 
    791724        return phone;
    792725}
    793726
    794 static int connect_keyboard(const char *path)
    795 {
    796         return connect_keyboard_or_mouse("keyboard", keyboard_events, path);
    797 }
    798 
    799 static int connect_mouse(const char *path)
    800 {
    801         return connect_keyboard_or_mouse("mouse", mouse_events, path);
    802 }
    803 
    804 struct hid_class_info {
    805         char *classname;
    806         int (*connection_func)(const char *);
    807 };
    808 
    809 /** Periodically check for new keyboards in /dev/class/.
    810  *
    811  * @param arg Class name.
    812  * @return This function should never exit.
    813  */
    814 static int check_new_device_fibril(void *arg)
    815 {
    816         struct hid_class_info *dev_info = arg;
    817 
    818         size_t index = 1;
    819 
    820         while (true) {
    821                 async_usleep(HOTPLUG_WATCH_INTERVAL);
    822                 char *path;
    823                 int rc = asprintf(&path, "/dev/class/%s\\%zu",
    824                     dev_info->classname, index);
    825                 if (rc < 0) {
    826                         continue;
    827                 }
    828                 rc = 0;
    829                 rc = dev_info->connection_func(path);
    830                 if (rc > 0) {
    831                         /* We do not allow unplug. */
    832                         index++;
    833                 }
    834 
    835                 free(path);
    836         }
    837 
    838         return EOK;
    839 }
    840 
    841 
    842 /** Start a fibril monitoring hot-plugged keyboards.
    843  */
    844 static void check_new_devices_in_background(int (*connection_func)(const char *),
    845     const char *classname)
    846 {
    847         struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info));
    848         if (dev_info == NULL) {
    849                 printf(NAME ": " \
    850                     "out of memory, will not start hot-plug-watch fibril.\n");
    851                 return;
    852         }
    853         int rc;
    854 
    855         rc = asprintf(&dev_info->classname, "%s", classname);
    856         if (rc < 0) {
    857                 printf(NAME ": failed to format classname: %s.\n",
    858                     str_error(rc));
    859                 return;
    860         }
    861         dev_info->connection_func = connection_func;
    862 
    863         fid_t fid = fibril_create(check_new_device_fibril, (void *)dev_info);
    864         if (!fid) {
    865                 printf(NAME
    866                     ": failed to create hot-plug-watch fibril for %s.\n",
    867                     classname);
    868                 return;
    869         }
    870         fibril_add_ready(fid);
    871 }
    872 
    873 static bool console_init(char *input)
    874 {
    875         /* Connect to input device */
    876         kbd_phone = connect_keyboard(input);
    877         if (kbd_phone < 0) {
     727static 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)
    878732                return false;
    879         }
    880 
    881         mouse_phone = connect_mouse("/dev/hid_in/mouse");
    882         if (mouse_phone < 0) {
    883                 printf(NAME ": Failed to connect to mouse device: %s.\n",
    884                     str_error(mouse_phone));
    885         }
    886733       
    887734        /* Connect to framebuffer driver */
    888         fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0);
     735        fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);
    889736        if (fb_info.phone < 0) {
    890                 printf(NAME ": Failed to connect to video service\n");
    891                 return -1;
     737                printf("%s: Failed to connect to video service\n", NAME);
     738                return false;
    892739        }
    893740       
     
    895742        int rc = devmap_driver_register(NAME, client_connection);
    896743        if (rc < 0) {
    897                 printf(NAME ": Unable to register driver (%d)\n", rc);
     744                printf("%s: Unable to register driver (%d)\n", NAME, rc);
    898745                return false;
    899746        }
     
    903750       
    904751        /* Synchronize, the gcons could put something in queue */
    905         async_req_0_0(fb_info.phone, FB_FLUSH);
    906         async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
    907         async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
     752        async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
     753        async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
     754        async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
    908755       
    909756        /* Set up shared memory buffer. */
     
    916763       
    917764        if (interbuffer) {
    918                 if (async_share_out_start(fb_info.phone, interbuffer,
     765                if (async_obsolete_share_out_start(fb_info.phone, interbuffer,
    919766                    AS_AREA_READ) != EOK) {
    920767                        as_area_destroy(interbuffer);
     
    931778                        if (screenbuffer_init(&consoles[i].scr,
    932779                            fb_info.cols, fb_info.rows) == NULL) {
    933                                 printf(NAME ": Unable to allocate screen buffer %zu\n", i);
     780                                printf("%s: Unable to allocate screen buffer %zu\n", NAME, i);
    934781                                return false;
    935782                        }
     
    943790                       
    944791                        if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
    945                                 printf(NAME ": Unable to register device %s\n", vc);
     792                                printf("%s: Unable to register device %s\n", NAME, vc);
    946793                                return false;
    947794                        }
     
    953800       
    954801        /* Initialize the screen */
    955         async_serialize_start();
     802        async_obsolete_serialize_start();
    956803        gcons_redraw_console();
    957804        set_style(STYLE_NORMAL);
     
    959806        curs_goto(0, 0);
    960807        curs_visibility(active_console->scr.is_cursor_visible);
    961         async_serialize_end();
     808        async_obsolete_serialize_end();
    962809       
    963810        /* Receive kernel notifications */
    964811        async_set_interrupt_received(interrupt_received);
    965812        if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
    966                 printf(NAME ": Error registering kconsole notifications\n");
    967        
    968         /* Start fibril for checking on hot-plugged keyboards. */
    969         check_new_devices_in_background(connect_keyboard, "keyboard");
    970         check_new_devices_in_background(connect_mouse, "mouse");
    971 
     813                printf("%s: Error registering kconsole notifications\n", NAME);
     814       
    972815        return true;
    973816}
     
    975818static void usage(void)
    976819{
    977         printf("Usage: console <input>\n");
     820        printf("Usage: console <input_dev>\n");
    978821}
    979822
     
    987830        printf(NAME ": HelenOS Console service\n");
    988831       
    989         if (!console_init(argv[1]))
     832        if (!console_srv_init(argv[1]))
    990833                return -1;
    991 
     834       
    992835        printf(NAME ": Accepting connections\n");
    993836        async_manager();
Note: See TracChangeset for help on using the changeset viewer.