Ignore:
File:
1 edited

Legend:

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

    r8c74d15 rffa2c8ef  
    4141#include <ipc/ns.h>
    4242#include <errno.h>
    43 #include <str_error.h>
    4443#include <ipc/console.h>
    4544#include <unistd.h>
     
    5756#include <io/style.h>
    5857#include <io/screenbuffer.h>
    59 #include <inttypes.h>
    6058
    6159#include "console.h"
     
    6664#define NAME       "console"
    6765#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 };
    7566
    7667/** Phone to the keyboard driver. */
     
    9788} console_t;
    9889
    99 
    100 
    10190/** Array of data for virtual consoles */
    10291static console_t consoles[CONSOLE_COUNT];
     
    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();
     
    409397}
    410398
    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 
    424399/** Handler for keyboard */
    425400static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
     
    436411                case IPC_M_PHONE_HUNGUP:
    437412                        /* TODO: Handle hangup */
    438                         close_driver_phone(iid);
    439413                        return;
    440414                case KBD_EVENT:
     
    480454                case IPC_M_PHONE_HUNGUP:
    481455                        /* TODO: Handle hangup */
    482                         close_driver_phone(iid);
    483456                        return;
    484457                case MEVENT_BUTTON:
    485458                        if (IPC_GET_ARG1(call) == 1) {
    486459                                int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
    487                                 if (newcon != -1) {
     460                                if (newcon != -1)
    488461                                        change_console(&consoles[newcon]);
    489                                 }
    490462                        }
    491463                        retval = 0;
     
    738710}
    739711
    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)
    748                 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) {
     712static bool console_init(char *input)
     713{
     714        /* 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);
     718                return false;
     719        }
     720       
     721        kbd_phone = fd_phone(input_fd);
     722        if (kbd_phone < 0) {
    772723                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);
    779         if (rc != EOK) {
    780                 async_hangup(phone);
    781                 printf(NAME ": " \
    782                     "Failed to create callback from input device: %s.\n",
    783                     str_error(rc));
    784                 return rc;
    785         }
    786        
    787         driver_phones[phone] = hash;
    788 
    789         printf(NAME ": found %s \"%s\" (%" PRIxn ").\n", devname, path, hash);
    790 
    791         return phone;
    792 }
    793 
    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) {
    878724                return false;
    879725        }
    880 
    881         mouse_phone = connect_mouse("/dev/hid_in/mouse");
     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);
    882744        if (mouse_phone < 0) {
    883                 printf(NAME ": Failed to connect to mouse device: %s.\n",
    884                     str_error(mouse_phone));
    885         }
     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       
     756skip_mouse:
    886757       
    887758        /* Connect to framebuffer driver */
     
    966837                printf(NAME ": Error registering kconsole notifications\n");
    967838       
    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 
    972839        return true;
    973840}
     
    989856        if (!console_init(argv[1]))
    990857                return -1;
    991 
     858       
    992859        printf(NAME ": Accepting connections\n");
    993860        async_manager();
Note: See TracChangeset for help on using the changeset viewer.