Changeset 41811af in mainline for uspace/srv/hid/console/console.c


Ignore:
Timestamp:
2011-06-10T10:14:26Z (14 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ab547063
Parents:
9536e6e (diff), 390d80d (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

File:
1 edited

Legend:

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

    r9536e6e r41811af  
    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>
     44#include <str_error.h>
    4345#include <ipc/console.h>
    4446#include <unistd.h>
    4547#include <async.h>
     48#include <async_obsolete.h>
    4649#include <adt/fifo.h>
    4750#include <sys/mman.h>
     
    5154#include <event.h>
    5255#include <devmap.h>
     56#include <devmap_obsolete.h>
    5357#include <fcntl.h>
    5458#include <vfs/vfs.h>
     
    5660#include <io/style.h>
    5761#include <io/screenbuffer.h>
     62#include <inttypes.h>
    5863
    5964#include "console.h"
     
    6166#include "keybuffer.h"
    6267
     68// FIXME: remove this header
     69#include <kernel/ipc/ipc_methods.h>
    6370
    6471#define NAME       "console"
    6572#define NAMESPACE  "term"
     73
     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 };
    6682
    6783/** Phone to the keyboard driver. */
     
    111127static void curs_visibility(bool visible)
    112128{
    113         async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
     129        async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
    114130}
    115131
    116132static void curs_hide_sync(void)
    117133{
    118         async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
     134        async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
    119135}
    120136
    121137static void curs_goto(sysarg_t x, sysarg_t y)
    122138{
    123         async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
     139        async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
    124140}
    125141
    126142static void screen_clear(void)
    127143{
    128         async_msg_0(fb_info.phone, FB_CLEAR);
     144        async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
    129145}
    130146
    131147static void screen_yield(void)
    132148{
    133         async_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
     149        async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
    134150}
    135151
    136152static void screen_reclaim(void)
    137153{
    138         async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
     154        async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
    139155}
    140156
    141157static void kbd_yield(void)
    142158{
    143         async_req_0_0(kbd_phone, KBD_YIELD);
     159        async_obsolete_req_0_0(kbd_phone, KBD_YIELD);
    144160}
    145161
    146162static void kbd_reclaim(void)
    147163{
    148         async_req_0_0(kbd_phone, KBD_RECLAIM);
     164        async_obsolete_req_0_0(kbd_phone, KBD_RECLAIM);
    149165}
    150166
    151167static void set_style(uint8_t style)
    152168{
    153         async_msg_1(fb_info.phone, FB_SET_STYLE, style);
     169        async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);
    154170}
    155171
    156172static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
    157173{
    158         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);
    159175}
    160176
    161177static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
    162178{
    163         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);
    164180}
    165181
     
    216232                }
    217233               
    218                 async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     234                async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
    219235                    x0, y0, width, height);
    220236        }
     
    257273static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row)
    258274{
    259         async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
     275        async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
    260276}
    261277
     
    306322               
    307323                if (cons == active_console)
    308                         async_msg_1(fb_info.phone, FB_SCROLL, 1);
     324                        async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);
    309325        }
    310326       
     
    323339       
    324340        if (cons == kernel_console) {
    325                 async_serialize_start();
     341                async_obsolete_serialize_start();
    326342                curs_hide_sync();
    327343                gcons_in_kernel();
    328344                screen_yield();
    329345                kbd_yield();
    330                 async_serialize_end();
     346                async_obsolete_serialize_end();
    331347               
    332348                if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
     
    338354       
    339355        if (cons != kernel_console) {
    340                 async_serialize_start();
     356                async_obsolete_serialize_start();
    341357               
    342358                if (active_console == kernel_console) {
     
    365381                       
    366382                        /* This call can preempt, but we are already at the end */
    367                         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,
    368384                            0, 0, cons->scr.size_x,
    369385                            cons->scr.size_y);
     
    393409                curs_visibility(cons->scr.is_cursor_visible);
    394410               
    395                 async_serialize_end();
     411                async_obsolete_serialize_end();
     412        }
     413}
     414
     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                }
    396425        }
    397426}
     
    406435               
    407436                int retval;
    408                 console_event_t ev;
     437                kbd_event_t ev;
     438               
     439                if (!IPC_GET_IMETHOD(call)) {
     440                        /* TODO: Handle hangup */
     441                        close_driver_phone(iid);
     442                        return;
     443                }
    409444               
    410445                switch (IPC_GET_IMETHOD(call)) {
    411                 case IPC_M_PHONE_HUNGUP:
    412                         /* TODO: Handle hangup */
    413                         return;
    414446                case KBD_EVENT:
    415447                        /* Got event from keyboard driver. */
     
    451483                int retval;
    452484               
     485                if (!IPC_GET_IMETHOD(call)) {
     486                        /* TODO: Handle hangup */
     487                        close_driver_phone(iid);
     488                        return;
     489                }
     490               
    453491                switch (IPC_GET_IMETHOD(call)) {
    454                 case IPC_M_PHONE_HUNGUP:
    455                         /* TODO: Handle hangup */
    456                         return;
    457492                case MEVENT_BUTTON:
    458493                        if (IPC_GET_ARG1(call) == 1) {
     
    487522        }
    488523       
    489         async_serialize_start();
     524        async_obsolete_serialize_start();
    490525       
    491526        size_t off = 0;
     
    495530        }
    496531       
    497         async_serialize_end();
     532        async_obsolete_serialize_end();
    498533       
    499534        gcons_notify_char(cons->index);
     
    521556       
    522557        size_t pos = 0;
    523         console_event_t ev;
     558        kbd_event_t ev;
    524559        fibril_mutex_lock(&input_mutex);
    525560       
     
    546581static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
    547582{
    548         console_event_t ev;
     583        kbd_event_t ev;
    549584       
    550585        fibril_mutex_lock(&input_mutex);
     
    590625        int rc;
    591626       
    592         async_serialize_start();
     627        async_obsolete_serialize_start();
    593628        if (cons->refcount == 0)
    594629                gcons_notify_connect(cons->index);
     
    600635       
    601636        while (true) {
    602                 async_serialize_end();
     637                async_obsolete_serialize_end();
    603638                callid = async_get_call(&call);
    604                 async_serialize_start();
     639                async_obsolete_serialize_start();
    605640               
    606641                arg1 = 0;
     
    608643                arg3 = 0;
    609644               
    610                 switch (IPC_GET_IMETHOD(call)) {
    611                 case IPC_M_PHONE_HUNGUP:
     645                if (!IPC_GET_IMETHOD(call)) {
    612646                        cons->refcount--;
    613647                        if (cons->refcount == 0)
    614648                                gcons_notify_disconnect(cons->index);
    615649                        return;
     650                }
     651               
     652                switch (IPC_GET_IMETHOD(call)) {
    616653                case VFS_OUT_READ:
    617                         async_serialize_end();
     654                        async_obsolete_serialize_end();
    618655                        cons_read(cons, callid, &call);
    619                         async_serialize_start();
     656                        async_obsolete_serialize_start();
    620657                        continue;
    621658                case VFS_OUT_WRITE:
    622                         async_serialize_end();
     659                        async_obsolete_serialize_end();
    623660                        cons_write(cons, callid, &call);
    624                         async_serialize_start();
     661                        async_obsolete_serialize_start();
    625662                        continue;
    626663                case VFS_OUT_SYNC:
    627664                        fb_pending_flush();
    628665                        if (cons == active_console) {
    629                                 async_req_0_0(fb_info.phone, FB_FLUSH);
     666                                async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
    630667                                curs_goto(cons->scr.position_x, cons->scr.position_y);
    631668                        }
     
    634671                        /* Send message to fb */
    635672                        if (cons == active_console)
    636                                 async_msg_0(fb_info.phone, FB_CLEAR);
     673                                async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
    637674                       
    638675                        screenbuffer_clear(&cons->scr);
     
    693730                        break;
    694731                case CONSOLE_GET_EVENT:
    695                         async_serialize_end();
     732                        async_obsolete_serialize_end();
    696733                        cons_get_event(cons, callid, &call);
    697                         async_serialize_start();
     734                        async_obsolete_serialize_start();
    698735                        continue;
    699736                case CONSOLE_KCON_ENABLE:
     
    710747}
    711748
    712 static bool console_init(char *input)
     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)
     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 */
     786        ipc_callid_t hash;
     787        rc = async_connect_to_me_hack(phone, SERVICE_CONSOLE, 0, phone,
     788            handler, &hash);
     789        if (rc != EOK) {
     790                async_obsolete_hangup(phone);
     791                printf("%s: Failed to create callback from input device (%s).\n",
     792                    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
     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)
    713881{
    714882        /* Connect to input device */
    715         int input_fd = open(input, O_RDONLY);
    716         if (input_fd < 0) {
    717                 printf(NAME ": Failed opening %s\n", input);
     883        kbd_phone = connect_keyboard(kdev);
     884        if (kbd_phone < 0)
    718885                return false;
    719         }
    720        
    721         kbd_phone = fd_phone(input_fd);
    722         if (kbd_phone < 0) {
    723                 printf(NAME ": Failed to connect to input device\n");
     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        }
     892       
     893        /* Connect to framebuffer driver */
     894        fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);
     895        if (fb_info.phone < 0) {
     896                printf("%s: Failed to connect to video service\n", NAME);
    724897                return false;
    725         }
    726        
    727         /* NB: The callback connection is slotted for removal */
    728         if (async_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, keyboard_events)
    729             != 0) {
    730                 printf(NAME ": Failed to create callback from input device\n");
    731                 return false;
    732         }
    733        
    734         /* Connect to mouse device */
    735         mouse_phone = -1;
    736         int mouse_fd = open("/dev/hid_in/mouse", O_RDONLY);
    737        
    738         if (mouse_fd < 0) {
    739                 printf(NAME ": Notice - failed opening %s\n", "/dev/hid_in/mouse");
    740                 goto skip_mouse;
    741         }
    742        
    743         mouse_phone = fd_phone(mouse_fd);
    744         if (mouse_phone < 0) {
    745                 printf(NAME ": Failed to connect to mouse device\n");
    746                 goto skip_mouse;
    747         }
    748        
    749         if (async_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, mouse_events)
    750             != 0) {
    751                 printf(NAME ": Failed to create callback from mouse device\n");
    752                 mouse_phone = -1;
    753                 goto skip_mouse;
    754         }
    755        
    756 skip_mouse:
    757        
    758         /* Connect to framebuffer driver */
    759         fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0);
    760         if (fb_info.phone < 0) {
    761                 printf(NAME ": Failed to connect to video service\n");
    762                 return -1;
    763898        }
    764899       
     
    766901        int rc = devmap_driver_register(NAME, client_connection);
    767902        if (rc < 0) {
    768                 printf(NAME ": Unable to register driver (%d)\n", rc);
     903                printf("%s: Unable to register driver (%d)\n", NAME, rc);
    769904                return false;
    770905        }
     
    774909       
    775910        /* Synchronize, the gcons could put something in queue */
    776         async_req_0_0(fb_info.phone, FB_FLUSH);
    777         async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
    778         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);
    779914       
    780915        /* Set up shared memory buffer. */
     
    787922       
    788923        if (interbuffer) {
    789                 if (async_share_out_start(fb_info.phone, interbuffer,
     924                if (async_obsolete_share_out_start(fb_info.phone, interbuffer,
    790925                    AS_AREA_READ) != EOK) {
    791926                        as_area_destroy(interbuffer);
     
    802937                        if (screenbuffer_init(&consoles[i].scr,
    803938                            fb_info.cols, fb_info.rows) == NULL) {
    804                                 printf(NAME ": Unable to allocate screen buffer %zu\n", i);
     939                                printf("%s: Unable to allocate screen buffer %zu\n", NAME, i);
    805940                                return false;
    806941                        }
     
    814949                       
    815950                        if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
    816                                 printf(NAME ": Unable to register device %s\n", vc);
     951                                printf("%s: Unable to register device %s\n", NAME, vc);
    817952                                return false;
    818953                        }
     
    824959       
    825960        /* Initialize the screen */
    826         async_serialize_start();
     961        async_obsolete_serialize_start();
    827962        gcons_redraw_console();
    828963        set_style(STYLE_NORMAL);
     
    830965        curs_goto(0, 0);
    831966        curs_visibility(active_console->scr.is_cursor_visible);
    832         async_serialize_end();
     967        async_obsolete_serialize_end();
    833968       
    834969        /* Receive kernel notifications */
    835970        async_set_interrupt_received(interrupt_received);
    836971        if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
    837                 printf(NAME ": Error registering kconsole notifications\n");
     972                printf("%s: Error registering kconsole notifications\n", NAME);
     973       
     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");
    838977       
    839978        return true;
     
    854993        printf(NAME ": HelenOS Console service\n");
    855994       
    856         if (!console_init(argv[1]))
     995        if (!console_srv_init(argv[1]))
    857996                return -1;
    858997       
Note: See TracChangeset for help on using the changeset viewer.