Changeset 79ae36dd in mainline for uspace/srv/hid/console/console.c


Ignore:
Timestamp:
2011-06-08T19:01:55Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0eff68e
Parents:
764d71e
Message:

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
File:
1 edited

Legend:

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

    r764d71e r79ae36dd  
    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>
     
    6366#include "keybuffer.h"
    6467
     68// FIXME: remove this header
     69#include <kernel/ipc/ipc_methods.h>
    6570
    6671#define NAME       "console"
    6772#define NAMESPACE  "term"
     73
    6874/** Interval for checking for new keyboard (1/4s). */
    6975#define HOTPLUG_WATCH_INTERVAL (1000 * 250)
     
    7177/* Kernel defines 32 but does not export it. */
    7278#define MAX_IPC_OUTGOING_PHONES 128
     79
    7380/** To allow proper phone closing. */
    7481static ipc_callid_t driver_phones[MAX_IPC_OUTGOING_PHONES] = { 0 };
     
    97104} console_t;
    98105
    99 
    100 
    101106/** Array of data for virtual consoles */
    102107static console_t consoles[CONSOLE_COUNT];
     
    122127static void curs_visibility(bool visible)
    123128{
    124         async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
     129        async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
    125130}
    126131
    127132static void curs_hide_sync(void)
    128133{
    129         async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
     134        async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
    130135}
    131136
    132137static void curs_goto(sysarg_t x, sysarg_t y)
    133138{
    134         async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
     139        async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
    135140}
    136141
    137142static void screen_clear(void)
    138143{
    139         async_msg_0(fb_info.phone, FB_CLEAR);
     144        async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
    140145}
    141146
    142147static void screen_yield(void)
    143148{
    144         async_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
     149        async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
    145150}
    146151
    147152static void screen_reclaim(void)
    148153{
    149         async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
     154        async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
    150155}
    151156
    152157static void kbd_yield(void)
    153158{
    154         async_req_0_0(kbd_phone, KBD_YIELD);
     159        async_obsolete_req_0_0(kbd_phone, KBD_YIELD);
    155160}
    156161
    157162static void kbd_reclaim(void)
    158163{
    159         async_req_0_0(kbd_phone, KBD_RECLAIM);
     164        async_obsolete_req_0_0(kbd_phone, KBD_RECLAIM);
    160165}
    161166
    162167static void set_style(uint8_t style)
    163168{
    164         async_msg_1(fb_info.phone, FB_SET_STYLE, style);
     169        async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);
    165170}
    166171
    167172static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
    168173{
    169         async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
     174        async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
    170175}
    171176
    172177static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
    173178{
    174         async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
     179        async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
    175180}
    176181
     
    227232                }
    228233               
    229                 async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     234                async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
    230235                    x0, y0, width, height);
    231236        }
     
    268273static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row)
    269274{
    270         async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
     275        async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
    271276}
    272277
     
    317322               
    318323                if (cons == active_console)
    319                         async_msg_1(fb_info.phone, FB_SCROLL, 1);
     324                        async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);
    320325        }
    321326       
     
    328333static void change_console(console_t *cons)
    329334{
    330         if (cons == active_console) {
     335        if (cons == active_console)
    331336                return;
    332         }
    333337       
    334338        fb_pending_flush();
    335339       
    336340        if (cons == kernel_console) {
    337                 async_serialize_start();
     341                async_obsolete_serialize_start();
    338342                curs_hide_sync();
    339343                gcons_in_kernel();
    340344                screen_yield();
    341345                kbd_yield();
    342                 async_serialize_end();
     346                async_obsolete_serialize_end();
    343347               
    344348                if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
     
    350354       
    351355        if (cons != kernel_console) {
    352                 async_serialize_start();
     356                async_obsolete_serialize_start();
    353357               
    354358                if (active_console == kernel_console) {
     
    377381                       
    378382                        /* This call can preempt, but we are already at the end */
    379                         rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     383                        rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
    380384                            0, 0, cons->scr.size_x,
    381385                            cons->scr.size_y);
     
    405409                curs_visibility(cons->scr.is_cursor_visible);
    406410               
    407                 async_serialize_end();
     411                async_obsolete_serialize_end();
    408412        }
    409413}
     
    416420                        printf("Device %" PRIxn " gone.\n", hash);
    417421                        driver_phones[i] = 0;
    418                         async_hangup(i);
     422                        async_obsolete_hangup(i);
    419423                        return;
    420424                }
     
    431435               
    432436                int retval;
    433                 console_event_t ev;
    434                
    435                 switch (IPC_GET_IMETHOD(call)) {
    436                 case IPC_M_PHONE_HUNGUP:
     437                kbd_event_t ev;
     438               
     439                if (!IPC_GET_IMETHOD(call)) {
    437440                        /* TODO: Handle hangup */
    438441                        close_driver_phone(iid);
    439442                        return;
     443                }
     444               
     445                switch (IPC_GET_IMETHOD(call)) {
    440446                case KBD_EVENT:
    441447                        /* Got event from keyboard driver. */
     
    477483                int retval;
    478484               
    479                 switch (IPC_GET_IMETHOD(call)) {
    480                 case IPC_M_PHONE_HUNGUP:
     485                if (!IPC_GET_IMETHOD(call)) {
    481486                        /* TODO: Handle hangup */
    482487                        close_driver_phone(iid);
    483488                        return;
     489                }
     490               
     491                switch (IPC_GET_IMETHOD(call)) {
    484492                case MEVENT_BUTTON:
    485493                        if (IPC_GET_ARG1(call) == 1) {
    486494                                int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
    487                                 if (newcon != -1) {
     495                                if (newcon != -1)
    488496                                        change_console(&consoles[newcon]);
    489                                 }
    490497                        }
    491498                        retval = 0;
     
    515522        }
    516523       
    517         async_serialize_start();
     524        async_obsolete_serialize_start();
    518525       
    519526        size_t off = 0;
     
    523530        }
    524531       
    525         async_serialize_end();
     532        async_obsolete_serialize_end();
    526533       
    527534        gcons_notify_char(cons->index);
     
    549556       
    550557        size_t pos = 0;
    551         console_event_t ev;
     558        kbd_event_t ev;
    552559        fibril_mutex_lock(&input_mutex);
    553560       
     
    574581static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
    575582{
    576         console_event_t ev;
     583        kbd_event_t ev;
    577584       
    578585        fibril_mutex_lock(&input_mutex);
     
    618625        int rc;
    619626       
    620         async_serialize_start();
     627        async_obsolete_serialize_start();
    621628        if (cons->refcount == 0)
    622629                gcons_notify_connect(cons->index);
     
    628635       
    629636        while (true) {
    630                 async_serialize_end();
     637                async_obsolete_serialize_end();
    631638                callid = async_get_call(&call);
    632                 async_serialize_start();
     639                async_obsolete_serialize_start();
    633640               
    634641                arg1 = 0;
     
    636643                arg3 = 0;
    637644               
    638                 switch (IPC_GET_IMETHOD(call)) {
    639                 case IPC_M_PHONE_HUNGUP:
     645                if (!IPC_GET_IMETHOD(call)) {
    640646                        cons->refcount--;
    641647                        if (cons->refcount == 0)
    642648                                gcons_notify_disconnect(cons->index);
    643649                        return;
     650                }
     651               
     652                switch (IPC_GET_IMETHOD(call)) {
    644653                case VFS_OUT_READ:
    645                         async_serialize_end();
     654                        async_obsolete_serialize_end();
    646655                        cons_read(cons, callid, &call);
    647                         async_serialize_start();
     656                        async_obsolete_serialize_start();
    648657                        continue;
    649658                case VFS_OUT_WRITE:
    650                         async_serialize_end();
     659                        async_obsolete_serialize_end();
    651660                        cons_write(cons, callid, &call);
    652                         async_serialize_start();
     661                        async_obsolete_serialize_start();
    653662                        continue;
    654663                case VFS_OUT_SYNC:
    655664                        fb_pending_flush();
    656665                        if (cons == active_console) {
    657                                 async_req_0_0(fb_info.phone, FB_FLUSH);
     666                                async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
    658667                                curs_goto(cons->scr.position_x, cons->scr.position_y);
    659668                        }
     
    662671                        /* Send message to fb */
    663672                        if (cons == active_console)
    664                                 async_msg_0(fb_info.phone, FB_CLEAR);
     673                                async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
    665674                       
    666675                        screenbuffer_clear(&cons->scr);
     
    721730                        break;
    722731                case CONSOLE_GET_EVENT:
    723                         async_serialize_end();
     732                        async_obsolete_serialize_end();
    724733                        cons_get_event(cons, callid, &call);
    725                         async_serialize_start();
     734                        async_obsolete_serialize_start();
    726735                        continue;
    727736                case CONSOLE_KCON_ENABLE:
     
    739748
    740749static 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)
     750    sysarg_t arg3, async_client_conn_t client_receiver, ipc_callid_t *hash)
    742751{
    743752        sysarg_t task_hash;
    744753        sysarg_t phone_hash;
    745         int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
     754        int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
    746755            NULL, NULL, NULL, &task_hash, &phone_hash);
    747756        if (rc != EOK)
    748757                return rc;
    749 
     758       
    750759        if (client_receiver != NULL)
    751760                async_new_connection(task_hash, phone_hash, phone_hash, NULL,
    752761                    client_receiver);
    753 
    754         if (hash != NULL) {
     762       
     763        if (hash != NULL)
    755764                *hash = phone_hash;
    756         }
    757 
     765       
    758766        return EOK;
    759767}
    760768
    761769static 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        
     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);
     776        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;
     784       
     785        /* NB: The callback connection is slotted for removal */
    776786        ipc_callid_t hash;
    777         int rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone,
     787        rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone,
    778788            handler, &hash);
    779789        if (rc != EOK) {
    780                 async_hangup(phone);
    781                 printf(NAME ": " \
    782                     "Failed to create callback from input device: %s.\n",
    783                     str_error(rc));
     790                async_obsolete_hangup(phone);
     791                printf("%s: Failed to create callback from input device (%s).\n",
     792                    NAME, str_error(rc));
    784793                return rc;
    785794        }
    786795       
    787796        driver_phones[phone] = hash;
    788 
    789         printf(NAME ": found %s \"%s\" (%" PRIxn ").\n", devname, path, hash);
    790 
     797        printf("%s: found %s \"%s\" (%" PRIxn ").\n", NAME, devname, dev, hash);
    791798        return phone;
    792799}
    793800
    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);
     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);
    802809}
    803810
     
    810817 *
    811818 * @param arg Class name.
     819 *
    812820 * @return This function should never exit.
     821 *
    813822 */
    814823static int check_new_device_fibril(void *arg)
    815824{
    816         struct hid_class_info *dev_info = arg;
    817 
     825        struct hid_class_info *dev_info = (struct hid_class_info *) arg;
     826       
    818827        size_t index = 1;
    819 
     828       
    820829        while (true) {
    821830                async_usleep(HOTPLUG_WATCH_INTERVAL);
    822                 char *path;
    823                 int rc = asprintf(&path, "/dev/class/%s\\%zu",
     831               
     832                char *dev;
     833                int rc = asprintf(&dev, "class/%s\\%zu",
    824834                    dev_info->classname, index);
    825                 if (rc < 0) {
     835                if (rc < 0)
    826836                        continue;
    827                 }
    828                 rc = 0;
    829                 rc = dev_info->connection_func(path);
     837               
     838                rc = dev_info->connection_func(dev);
    830839                if (rc > 0) {
    831840                        /* We do not allow unplug. */
    832841                        index++;
    833842                }
    834 
    835                 free(path);
    836         }
    837 
     843               
     844                free(dev);
     845        }
     846       
    838847        return EOK;
    839848}
    840 
    841849
    842850/** Start a fibril monitoring hot-plugged keyboards.
     
    847855        struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info));
    848856        if (dev_info == NULL) {
    849                 printf(NAME ": " \
    850                     "out of memory, will not start hot-plug-watch fibril.\n");
     857                printf("%s: Out of memory, no hot-plug support.\n", NAME);
    851858                return;
    852859        }
    853         int rc;
    854 
    855         rc = asprintf(&dev_info->classname, "%s", classname);
     860       
     861        int rc = asprintf(&dev_info->classname, "%s", classname);
    856862        if (rc < 0) {
    857                 printf(NAME ": failed to format classname: %s.\n",
     863                printf("%s: Failed to format classname: %s.\n", NAME,
    858864                    str_error(rc));
    859865                return;
    860866        }
     867       
    861868        dev_info->connection_func = connection_func;
    862 
    863         fid_t fid = fibril_create(check_new_device_fibril, (void *)dev_info);
     869       
     870        fid_t fid = fibril_create(check_new_device_fibril, (void *) dev_info);
    864871        if (!fid) {
    865                 printf(NAME
    866                     ": failed to create hot-plug-watch fibril for %s.\n",
     872                printf("%s: Failed to create hot-plug fibril for %s.\n", NAME,
    867873                    classname);
    868874                return;
    869875        }
     876       
    870877        fibril_add_ready(fid);
    871878}
    872879
    873 static bool console_init(char *input)
     880static bool console_srv_init(char *kdev)
    874881{
    875882        /* Connect to input device */
    876         kbd_phone = connect_keyboard(input);
    877         if (kbd_phone < 0) {
     883        kbd_phone = connect_keyboard(kdev);
     884        if (kbd_phone < 0)
    878885                return false;
    879         }
    880 
    881         mouse_phone = connect_mouse("/dev/hid_in/mouse");
     886       
     887        mouse_phone = connect_mouse("hid_in/mouse");
    882888        if (mouse_phone < 0) {
    883                 printf(NAME ": Failed to connect to mouse device: %s.\n",
     889                printf("%s: Failed to connect to mouse device %s\n", NAME,
    884890                    str_error(mouse_phone));
    885891        }
    886892       
    887893        /* Connect to framebuffer driver */
    888         fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0);
     894        fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);
    889895        if (fb_info.phone < 0) {
    890                 printf(NAME ": Failed to connect to video service\n");
    891                 return -1;
     896                printf("%s: Failed to connect to video service\n", NAME);
     897                return false;
    892898        }
    893899       
     
    895901        int rc = devmap_driver_register(NAME, client_connection);
    896902        if (rc < 0) {
    897                 printf(NAME ": Unable to register driver (%d)\n", rc);
     903                printf("%s: Unable to register driver (%d)\n", NAME, rc);
    898904                return false;
    899905        }
     
    903909       
    904910        /* 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);
     911        async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
     912        async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
     913        async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
    908914       
    909915        /* Set up shared memory buffer. */
     
    916922       
    917923        if (interbuffer) {
    918                 if (async_share_out_start(fb_info.phone, interbuffer,
     924                if (async_obsolete_share_out_start(fb_info.phone, interbuffer,
    919925                    AS_AREA_READ) != EOK) {
    920926                        as_area_destroy(interbuffer);
     
    931937                        if (screenbuffer_init(&consoles[i].scr,
    932938                            fb_info.cols, fb_info.rows) == NULL) {
    933                                 printf(NAME ": Unable to allocate screen buffer %zu\n", i);
     939                                printf("%s: Unable to allocate screen buffer %zu\n", NAME, i);
    934940                                return false;
    935941                        }
     
    943949                       
    944950                        if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
    945                                 printf(NAME ": Unable to register device %s\n", vc);
     951                                printf("%s: Unable to register device %s\n", NAME, vc);
    946952                                return false;
    947953                        }
     
    953959       
    954960        /* Initialize the screen */
    955         async_serialize_start();
     961        async_obsolete_serialize_start();
    956962        gcons_redraw_console();
    957963        set_style(STYLE_NORMAL);
     
    959965        curs_goto(0, 0);
    960966        curs_visibility(active_console->scr.is_cursor_visible);
    961         async_serialize_end();
     967        async_obsolete_serialize_end();
    962968       
    963969        /* Receive kernel notifications */
    964970        async_set_interrupt_received(interrupt_received);
    965971        if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
    966                 printf(NAME ": Error registering kconsole notifications\n");
     972                printf("%s: Error registering kconsole notifications\n", NAME);
    967973       
    968974        /* Start fibril for checking on hot-plugged keyboards. */
    969975        check_new_devices_in_background(connect_keyboard, "keyboard");
    970976        check_new_devices_in_background(connect_mouse, "mouse");
    971 
     977       
    972978        return true;
    973979}
     
    987993        printf(NAME ": HelenOS Console service\n");
    988994       
    989         if (!console_init(argv[1]))
     995        if (!console_srv_init(argv[1]))
    990996                return -1;
    991 
     997       
    992998        printf(NAME ": Accepting connections\n");
    993999        async_manager();
Note: See TracChangeset for help on using the changeset viewer.