Ignore:
File:
1 edited

Legend:

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

    rffa2c8ef r103ae7f8  
    4141#include <ipc/ns.h>
    4242#include <errno.h>
     43#include <str_error.h>
    4344#include <ipc/console.h>
    4445#include <unistd.h>
     
    6465#define NAME       "console"
    6566#define NAMESPACE  "term"
     67/** Interval for checking for new keyboard (1/4s). */
     68#define HOTPLUG_WATCH_INTERVAL (1000 * 250)
    6669
    6770/** Phone to the keyboard driver. */
     
    317320static void change_console(console_t *cons)
    318321{
    319         if (cons == active_console)
     322        if (cons == active_console) {
    320323                return;
     324        }
    321325       
    322326        fb_pending_flush();
     
    458462                        if (IPC_GET_ARG1(call) == 1) {
    459463                                int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
    460                                 if (newcon != -1)
     464                                if (newcon != -1) {
    461465                                        change_console(&consoles[newcon]);
     466                                }
    462467                        }
    463468                        retval = 0;
     
    710715}
    711716
     717static int connect_keyboard_or_mouse(const char *devname,
     718    async_client_conn_t handler, const char *path)
     719{
     720        int fd = open(path, O_RDONLY);
     721        if (fd < 0) {
     722                return fd;
     723        }
     724       
     725        int phone = fd_phone(fd);
     726        if (phone < 0) {
     727                printf(NAME ": Failed to connect to input device\n");
     728                return phone;
     729        }
     730       
     731        int rc = async_connect_to_me(phone, SERVICE_CONSOLE, 0, 0, handler);
     732        if (rc != EOK) {
     733                printf(NAME ": " \
     734                    "Failed to create callback from input device: %s.\n",
     735                    str_error(rc));
     736                return rc;
     737        }
     738       
     739        printf(NAME ": found %s \"%s\".\n", devname, path);
     740
     741        return phone;
     742}
     743
     744static int connect_keyboard(const char *path)
     745{
     746        return connect_keyboard_or_mouse("keyboard", keyboard_events, path);
     747}
     748
     749static int connect_mouse(const char *path)
     750{
     751        return connect_keyboard_or_mouse("mouse", mouse_events, path);
     752}
     753
     754struct hid_class_info {
     755        char *classname;
     756        int (*connection_func)(const char *);
     757};
     758
     759/** Periodically check for new keyboards in /dev/class/.
     760 *
     761 * @param arg Class name.
     762 * @return This function should never exit.
     763 */
     764static int check_new_device_fibril(void *arg)
     765{
     766        struct hid_class_info *dev_info = arg;
     767
     768        size_t index = 1;
     769
     770        while (true) {
     771                async_usleep(HOTPLUG_WATCH_INTERVAL);
     772                char *path;
     773                int rc = asprintf(&path, "/dev/class/%s\\%zu",
     774                    dev_info->classname, index);
     775                if (rc < 0) {
     776                        continue;
     777                }
     778                rc = 0;
     779                rc = dev_info->connection_func(path);
     780                if (rc > 0) {
     781                        /* We do not allow unplug. */
     782                        index++;
     783                }
     784
     785                free(path);
     786        }
     787
     788        return EOK;
     789}
     790
     791
     792/** Start a fibril monitoring hot-plugged keyboards.
     793 */
     794static void check_new_devices_in_background(int (*connection_func)(const char *),
     795    const char *classname)
     796{
     797        struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info));
     798        if (dev_info == NULL) {
     799                printf(NAME ": " \
     800                    "out of memory, will not start hot-plug-watch fibril.\n");
     801                return;
     802        }
     803        int rc;
     804
     805        rc = asprintf(&dev_info->classname, "%s", classname);
     806        if (rc < 0) {
     807                printf(NAME ": failed to format classname: %s.\n",
     808                    str_error(rc));
     809                return;
     810        }
     811        dev_info->connection_func = connection_func;
     812
     813        fid_t fid = fibril_create(check_new_device_fibril, (void *)dev_info);
     814        if (!fid) {
     815                printf(NAME
     816                    ": failed to create hot-plug-watch fibril for %s.\n",
     817                    classname);
     818                return;
     819        }
     820        fibril_add_ready(fid);
     821}
     822
    712823static bool console_init(char *input)
    713824{
    714825        /* 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);
     826        kbd_phone = connect_keyboard(input);
     827        if (kbd_phone < 0) {
    718828                return false;
    719829        }
    720        
    721         kbd_phone = fd_phone(input_fd);
    722         if (kbd_phone < 0) {
    723                 printf(NAME ": Failed to connect to input device\n");
    724                 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);
     830
     831        mouse_phone = connect_mouse("/dev/hid_in/mouse");
    744832        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:
     833                printf(NAME ": Failed to connect to mouse device: %s.\n",
     834                    str_error(mouse_phone));
     835        }
    757836       
    758837        /* Connect to framebuffer driver */
     
    837916                printf(NAME ": Error registering kconsole notifications\n");
    838917       
     918        /* Start fibril for checking on hot-plugged keyboards. */
     919        check_new_devices_in_background(connect_keyboard, "keyboard");
     920        check_new_devices_in_background(connect_mouse, "mouse");
     921
    839922        return true;
    840923}
     
    856939        if (!console_init(argv[1]))
    857940                return -1;
    858        
     941
    859942        printf(NAME ": Accepting connections\n");
    860943        async_manager();
Note: See TracChangeset for help on using the changeset viewer.