Changeset 593e023 in mainline for uspace/srv/hid/input/input.c


Ignore:
Timestamp:
2014-08-12T17:14:32Z (10 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c3bdc92
Parents:
ce3efa0
Message:

allow compositor and console to coexist side-by-side, use the input server as a poor man's seat arbitrator

  • kernel console notifies both about the release and grab events
  • input server arbitrates the seat selection between kernel console and any number of user space UIs (currently the console server and the compositor server)
  • input port yield and reclaim methods have been removed (they are used only on Ski and Niagara, both already need a more generic mechanism for the kernel/user space cooperation)
  • console and compositor server keep track of the kernel console via the input arbitration
  • move the waiting for a character device from init and terminal widget to getterm
File:
1 edited

Legend:

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

    rce3efa0 r593e023  
    5454#include <io/keycode.h>
    5555#include <loc.h>
     56#include <event.h>
     57#include <str_error.h>
    5658#include "layout.h"
    5759#include "kbd.h"
     
    6264#include "input.h"
    6365
     66bool irc_service = false;
     67async_sess_t *irc_sess = NULL;
     68
    6469#define NUM_LAYOUTS  4
    6570
     
    7176};
    7277
    73 static void kbd_devs_yield(void);
    74 static void kbd_devs_reclaim(void);
    75 
    76 async_sess_t *client_sess = NULL;
     78typedef struct {
     79        /** Link into the list of clients */
     80        link_t link;
     81       
     82        /** Indicate whether the client is active */
     83        bool active;
     84       
     85        /** Client callback session */
     86        async_sess_t *sess;
     87} client_t;
     88
     89/** List of clients */
     90static list_t clients;
     91static client_t *active_client = NULL;
    7792
    7893/** List of keyboard devices */
     
    8297static list_t mouse_devs;
    8398
    84 bool irc_service = false;
    85 async_sess_t *irc_sess = NULL;
    86 
    8799static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
     100
     101static void *client_data_create(void)
     102{
     103        client_t *client = (client_t *) calloc(1, sizeof(client_t));
     104        if (client == NULL)
     105                return NULL;
     106       
     107        link_initialize(&client->link);
     108        client->active = false;
     109        client->sess = NULL;
     110       
     111        list_append(&client->link, &clients);
     112       
     113        return client;
     114}
     115
     116static void client_data_destroy(void *data)
     117{
     118        client_t *client = (client_t *) data;
     119       
     120        list_remove(&client->link);
     121        free(client);
     122}
    88123
    89124void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
     
    199234        ev.c = layout_parse_ev(kdev->active_layout, &ev);
    200235       
    201         async_exch_t *exch = async_exchange_begin(client_sess);
    202         async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
    203         async_exchange_end(exch);
    204 }
    205 
    206 /** Mouse pointer has moved. */
     236        list_foreach(clients, link, client_t, client) {
     237                if (client->active) {
     238                        async_exch_t *exch = async_exchange_begin(client->sess);
     239                        async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
     240                        async_exchange_end(exch);
     241                }
     242        }
     243}
     244
     245/** Mouse pointer has moved (relative mode). */
    207246void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz)
    208247{
    209         async_exch_t *exch = async_exchange_begin(client_sess);
    210         if (dx || dy)
    211                 async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
    212         if (dz) {
    213                 // TODO: Implement proper wheel support
    214                 keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
    215                 for (int i = 0; i < 3; ++i) {
    216                         async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
    217                 }
    218                 async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
    219         }
    220         async_exchange_end(exch);
    221 }
    222 
    223 /** Mouse pointer has moved in absolute mode. */
     248        list_foreach(clients, link, client_t, client) {
     249                if (client->active) {
     250                        async_exch_t *exch = async_exchange_begin(client->sess);
     251                       
     252                        if ((dx) || (dy))
     253                                async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
     254                       
     255                        if (dz) {
     256                                // TODO: Implement proper wheel support
     257                                keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
     258                               
     259                                for (unsigned int i = 0; i < 3; i++)
     260                                        async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
     261                               
     262                                async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
     263                        }
     264                       
     265                        async_exchange_end(exch);
     266                }
     267        }
     268}
     269
     270/** Mouse pointer has moved (absolute mode). */
    224271void mouse_push_event_abs_move(mouse_dev_t *mdev, unsigned int x, unsigned int y,
    225272    unsigned int max_x, unsigned int max_y)
    226273{
    227         if (max_x && max_y) {
    228                 async_exch_t *exch = async_exchange_begin(client_sess);
    229                 async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
    230                 async_exchange_end(exch);
     274        list_foreach(clients, link, client_t, client) {
     275                if (client->active) {
     276                        if ((max_x) && (max_y)) {
     277                                async_exch_t *exch = async_exchange_begin(client->sess);
     278                                async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
     279                                async_exchange_end(exch);
     280                        }
     281                }
    231282        }
    232283}
     
    235286void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
    236287{
    237         async_exch_t *exch = async_exchange_begin(client_sess);
    238         async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
    239         async_exchange_end(exch);
    240 }
    241 
     288        list_foreach(clients, link, client_t, client) {
     289                if (client->active) {
     290                        async_exch_t *exch = async_exchange_begin(client->sess);
     291                        async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
     292                        async_exchange_end(exch);
     293                }
     294        }
     295}
     296
     297/** Arbitrate client actiovation */
     298static void client_arbitration(client_t *req)
     299{
     300        /* Mutual exclusion of active clients */
     301        list_foreach(clients, link, client_t, client)
     302                client->active = (client == req);
     303       
     304        /* Notify clients about the arbitration */
     305        list_foreach(clients, link, client_t, client) {
     306                async_exch_t *exch = async_exchange_begin(client->sess);
     307                async_msg_0(exch, client->active ?
     308                    INPUT_EVENT_ACTIVE : INPUT_EVENT_DEACTIVE);
     309                async_exchange_end(exch);
     310        }
     311}
     312
     313/** New client connection */
    242314static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    243315{
     316        client_t *client = (client_t *) async_get_client_data();
     317        if (client == NULL) {
     318                async_answer_0(iid, ENOMEM);
     319                return;
     320        }
     321       
    244322        async_answer_0(iid, EOK);
    245323       
     
    249327               
    250328                if (!IPC_GET_IMETHOD(call)) {
    251                         if (client_sess != NULL) {
    252                                 async_hangup(client_sess);
    253                                 client_sess = NULL;
     329                        if (client->sess != NULL) {
     330                                async_hangup(client->sess);
     331                                client->sess = NULL;
    254332                        }
    255333                       
     
    261339                    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    262340                if (sess != NULL) {
    263                         if (client_sess == NULL) {
    264                                 client_sess = sess;
     341                        if (client->sess == NULL) {
     342                                client->sess = sess;
    265343                                async_answer_0(callid, EOK);
    266344                        } else
     
    268346                } else {
    269347                        switch (IPC_GET_IMETHOD(call)) {
    270                         case INPUT_YIELD:
    271                                 kbd_devs_yield();
    272                                 async_answer_0(callid, EOK);
    273                                 break;
    274                         case INPUT_RECLAIM:
    275                                 kbd_devs_reclaim();
     348                        case INPUT_ACTIVATE:
     349                                active_client = client;
     350                                client_arbitration(client);
    276351                                async_answer_0(callid, EOK);
    277352                                break;
     
    283358}
    284359
     360static void kconsole_event_received(ipc_callid_t callid, ipc_call_t *call)
     361{
     362        if (IPC_GET_ARG1(*call)) {
     363                /* Kernel console activated */
     364                client_arbitration(NULL);
     365        } else {
     366                /* Kernel console deactivated */
     367                client_arbitration(active_client);
     368        }
     369}
     370
    285371static kbd_dev_t *kbd_dev_new(void)
    286372{
     
    292378        }
    293379       
    294         link_initialize(&kdev->kbd_devs);
     380        link_initialize(&kdev->link);
    295381       
    296382        kdev->mods = KM_NUM_LOCK;
     
    310396        }
    311397       
    312         link_initialize(&mdev->mouse_devs);
     398        link_initialize(&mdev->link);
    313399       
    314400        return mdev;
     
    336422        }
    337423       
    338         list_append(&kdev->kbd_devs, &kbd_devs);
     424        list_append(&kdev->link, &kbd_devs);
    339425        return;
    340426       
     
    364450        }
    365451       
    366         list_append(&mdev->mouse_devs, &mouse_devs);
     452        list_append(&mdev->link, &mouse_devs);
    367453        return;
    368454       
     
    373459/** Add new kbdev device.
    374460 *
    375  * @param service_id    Service ID of the keyboard device
     461 * @param service_id Service ID of the keyboard device
    376462 *
    377463 */
     
    397483        }
    398484       
    399         list_append(&kdev->kbd_devs, &kbd_devs);
     485        list_append(&kdev->link, &kbd_devs);
    400486        *kdevp = kdev;
    401487        return EOK;
     
    410496/** Add new mousedev device.
    411497 *
    412  * @param service_id    Service ID of the mouse device
     498 * @param service_id Service ID of the mouse device
    413499 *
    414500 */
     
    434520        }
    435521       
    436         list_append(&mdev->mouse_devs, &mouse_devs);
     522        list_append(&mdev->link, &mouse_devs);
    437523        *mdevp = mdev;
    438524        return EOK;
     
    489575}
    490576
    491 static void kbd_devs_yield(void)
    492 {
    493         /* For each keyboard device */
    494         list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
    495                 /* Yield port */
    496                 if (kdev->port_ops != NULL)
    497                         (*kdev->port_ops->yield)();
    498         }
    499 }
    500 
    501 static void kbd_devs_reclaim(void)
    502 {
    503         /* For each keyboard device */
    504         list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
    505                 /* Reclaim port */
    506                 if (kdev->port_ops != NULL)
    507                         (*kdev->port_ops->reclaim)();
    508         }
    509 }
    510 
    511577static int dev_check_new_kbdevs(void)
    512578{
     
    537603               
    538604                /* Determine whether we already know this device. */
    539                 list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
     605                list_foreach(kbd_devs, link, kbd_dev_t, kdev) {
    540606                        if (kdev->svc_id == svcs[i]) {
    541607                                already_known = true;
     
    588654               
    589655                /* Determine whether we already know this device. */
    590                 list_foreach(mouse_devs, mouse_devs, mouse_dev_t, mdev) {
     656                list_foreach(mouse_devs, link, mouse_dev_t, mdev) {
    591657                        if (mdev->svc_id == svcs[i]) {
    592658                                already_known = true;
     
    668734        sysarg_t obio;
    669735       
     736        list_initialize(&clients);
    670737        list_initialize(&kbd_devs);
    671738        list_initialize(&mouse_devs);
     
    687754       
    688755        /* Register driver */
     756        async_set_client_data_constructor(client_data_create);
     757        async_set_client_data_destructor(client_data_destroy);
    689758        async_set_client_connection(client_connection);
    690759       
     
    701770                return rc;
    702771        }
     772       
     773        /* Receive kernel notifications */
     774        async_set_interrupt_received(kconsole_event_received);
     775        rc = event_subscribe(EVENT_KCONSOLE, 0);
     776        if (rc != EOK)
     777                printf("%s: Failed to register kconsole notifications (%s)\n",
     778                    NAME, str_error(rc));
    703779       
    704780        /* Start looking for new input devices */
Note: See TracChangeset for help on using the changeset viewer.