Ignore:
File:
1 edited

Legend:

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

    rc9d011e4 r380e23a3  
    3838
    3939#include <adt/list.h>
    40 #include <bool.h>
     40#include <stdbool.h>
    4141#include <fibril_synch.h>
    4242#include <ipc/services.h>
     
    5454#include <io/keycode.h>
    5555#include <loc.h>
     56#include <str_error.h>
    5657#include "layout.h"
    5758#include "kbd.h"
     
    6263#include "input.h"
    6364
    64 #define NUM_LAYOUTS  3
     65bool irc_service = false;
     66async_sess_t *irc_sess = NULL;
     67
     68#define NUM_LAYOUTS  4
    6569
    6670static layout_ops_t *layout[NUM_LAYOUTS] = {
    6771        &us_qwerty_ops,
    6872        &us_dvorak_ops,
    69         &cz_ops
     73        &cz_ops,
     74        &ar_ops
    7075};
    7176
    72 static void kbd_devs_yield(void);
    73 static void kbd_devs_reclaim(void);
    74 
    75 async_sess_t *client_sess = NULL;
     77typedef struct {
     78        /** Link into the list of clients */
     79        link_t link;
     80       
     81        /** Indicate whether the client is active */
     82        bool active;
     83       
     84        /** Client callback session */
     85        async_sess_t *sess;
     86} client_t;
     87
     88/** List of clients */
     89static list_t clients;
     90static client_t *active_client = NULL;
     91
     92/** Kernel override */
     93static bool active = true;
    7694
    7795/** List of keyboard devices */
     
    8199static list_t mouse_devs;
    82100
    83 bool irc_service = false;
    84 async_sess_t *irc_sess = NULL;
    85 
    86101static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
     102
     103static void *client_data_create(void)
     104{
     105        client_t *client = (client_t *) calloc(1, sizeof(client_t));
     106        if (client == NULL)
     107                return NULL;
     108       
     109        link_initialize(&client->link);
     110        client->active = false;
     111        client->sess = NULL;
     112       
     113        list_append(&client->link, &clients);
     114       
     115        return client;
     116}
     117
     118static void client_data_destroy(void *data)
     119{
     120        client_t *client = (client_t *) data;
     121       
     122        list_remove(&client->link);
     123        free(client);
     124}
    87125
    88126void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
     
    102140       
    103141        switch (key) {
    104         case KC_LCTRL: mod_mask = KM_LCTRL; break;
    105         case KC_RCTRL: mod_mask = KM_RCTRL; break;
    106         case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
    107         case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
    108         case KC_LALT: mod_mask = KM_LALT; break;
    109         case KC_RALT: mod_mask = KM_RALT; break;
    110         default: mod_mask = 0; break;
     142        case KC_LCTRL:
     143                mod_mask = KM_LCTRL;
     144                break;
     145        case KC_RCTRL:
     146                mod_mask = KM_RCTRL;
     147                break;
     148        case KC_LSHIFT:
     149                mod_mask = KM_LSHIFT;
     150                break;
     151        case KC_RSHIFT:
     152                mod_mask = KM_RSHIFT;
     153                break;
     154        case KC_LALT:
     155                mod_mask = KM_LALT;
     156                break;
     157        case KC_RALT:
     158                mod_mask = KM_RALT;
     159                break;
     160        default:
     161                mod_mask = 0;
    111162        }
    112163       
     
    119170       
    120171        switch (key) {
    121         case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
    122         case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
    123         case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
    124         default: mod_mask = 0; break;
     172        case KC_CAPS_LOCK:
     173                mod_mask = KM_CAPS_LOCK;
     174                break;
     175        case KC_NUM_LOCK:
     176                mod_mask = KM_NUM_LOCK;
     177                break;
     178        case KC_SCROLL_LOCK:
     179                mod_mask = KM_SCROLL_LOCK;
     180                break;
     181        default:
     182                mod_mask = 0;
    125183        }
    126184       
     
    142200        }
    143201       
    144         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    145             key == KC_F1) {
     202        // TODO: More elegant layout switching
     203       
     204        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     205            (key == KC_F1)) {
    146206                layout_destroy(kdev->active_layout);
    147207                kdev->active_layout = layout_create(layout[0]);
     
    149209        }
    150210       
    151         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    152             key == KC_F2) {
     211        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     212            (key == KC_F2)) {
    153213                layout_destroy(kdev->active_layout);
    154214                kdev->active_layout = layout_create(layout[1]);
     
    156216        }
    157217       
    158         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    159             key == KC_F3) {
     218        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     219            (key == KC_F3)) {
    160220                layout_destroy(kdev->active_layout);
    161221                kdev->active_layout = layout_create(layout[2]);
     
    163223        }
    164224       
     225        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     226            (key == KC_F4)) {
     227                layout_destroy(kdev->active_layout);
     228                kdev->active_layout = layout_create(layout[3]);
     229                return;
     230        }
     231       
    165232        ev.type = type;
    166233        ev.key = key;
     
    169236        ev.c = layout_parse_ev(kdev->active_layout, &ev);
    170237       
    171         async_exch_t *exch = async_exchange_begin(client_sess);
    172         async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
    173         async_exchange_end(exch);
    174 }
    175 
    176 /** Mouse pointer has moved. */
     238        list_foreach(clients, link, client_t, client) {
     239                if (client->active) {
     240                        async_exch_t *exch = async_exchange_begin(client->sess);
     241                        async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
     242                        async_exchange_end(exch);
     243                }
     244        }
     245}
     246
     247/** Mouse pointer has moved (relative mode). */
    177248void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz)
    178249{
    179         async_exch_t *exch = async_exchange_begin(client_sess);
    180         if (dx || dy)
    181                 async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
    182         if (dz) {
    183                 // TODO: Implement proper wheel support
    184                 keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
    185                 for (int i = 0; i < 3; ++i) {
    186                         async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
    187                 }
    188                 async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
    189         }
    190         async_exchange_end(exch);
    191 }
    192 
    193 /** Mouse pointer has moved in absolute mode. */
     250        list_foreach(clients, link, client_t, client) {
     251                if (client->active) {
     252                        async_exch_t *exch = async_exchange_begin(client->sess);
     253                       
     254                        if ((dx) || (dy))
     255                                async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
     256                       
     257                        if (dz) {
     258                                // TODO: Implement proper wheel support
     259                                keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
     260                               
     261                                for (unsigned int i = 0; i < 3; i++)
     262                                        async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
     263                               
     264                                async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
     265                        }
     266                       
     267                        async_exchange_end(exch);
     268                }
     269        }
     270}
     271
     272/** Mouse pointer has moved (absolute mode). */
    194273void mouse_push_event_abs_move(mouse_dev_t *mdev, unsigned int x, unsigned int y,
    195274    unsigned int max_x, unsigned int max_y)
    196275{
    197         if (max_x && max_y) {
    198                 async_exch_t *exch = async_exchange_begin(client_sess);
    199                 async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
    200                 async_exchange_end(exch);
     276        list_foreach(clients, link, client_t, client) {
     277                if (client->active) {
     278                        if ((max_x) && (max_y)) {
     279                                async_exch_t *exch = async_exchange_begin(client->sess);
     280                                async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
     281                                async_exchange_end(exch);
     282                        }
     283                }
    201284        }
    202285}
     
    205288void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
    206289{
    207         async_exch_t *exch = async_exchange_begin(client_sess);
    208         async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
    209         async_exchange_end(exch);
    210 }
    211 
     290        list_foreach(clients, link, client_t, client) {
     291                if (client->active) {
     292                        async_exch_t *exch = async_exchange_begin(client->sess);
     293                        async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
     294                        async_exchange_end(exch);
     295                }
     296        }
     297}
     298
     299/** Arbitrate client actiovation */
     300static void client_arbitration(void)
     301{
     302        /* Mutual exclusion of active clients */
     303        list_foreach(clients, link, client_t, client)
     304                client->active = ((active) && (client == active_client));
     305       
     306        /* Notify clients about the arbitration */
     307        list_foreach(clients, link, client_t, client) {
     308                async_exch_t *exch = async_exchange_begin(client->sess);
     309                async_msg_0(exch, client->active ?
     310                    INPUT_EVENT_ACTIVE : INPUT_EVENT_DEACTIVE);
     311                async_exchange_end(exch);
     312        }
     313}
     314
     315/** New client connection */
    212316static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    213317{
     318        client_t *client = (client_t *) async_get_client_data();
     319        if (client == NULL) {
     320                async_answer_0(iid, ENOMEM);
     321                return;
     322        }
     323       
    214324        async_answer_0(iid, EOK);
    215325       
     
    219329               
    220330                if (!IPC_GET_IMETHOD(call)) {
    221                         if (client_sess != NULL) {
    222                                 async_hangup(client_sess);
    223                                 client_sess = NULL;
     331                        if (client->sess != NULL) {
     332                                async_hangup(client->sess);
     333                                client->sess = NULL;
    224334                        }
    225335                       
     
    231341                    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    232342                if (sess != NULL) {
    233                         if (client_sess == NULL) {
    234                                 client_sess = sess;
     343                        if (client->sess == NULL) {
     344                                client->sess = sess;
    235345                                async_answer_0(callid, EOK);
    236346                        } else
     
    238348                } else {
    239349                        switch (IPC_GET_IMETHOD(call)) {
    240                         case INPUT_YIELD:
    241                                 kbd_devs_yield();
    242                                 async_answer_0(callid, EOK);
    243                                 break;
    244                         case INPUT_RECLAIM:
    245                                 kbd_devs_reclaim();
     350                        case INPUT_ACTIVATE:
     351                                active_client = client;
     352                                client_arbitration();
    246353                                async_answer_0(callid, EOK);
    247354                                break;
     
    253360}
    254361
     362static void kconsole_event_handler(ipc_callid_t callid, ipc_call_t *call,
     363    void *arg)
     364{
     365        if (IPC_GET_ARG1(*call)) {
     366                /* Kernel console activated */
     367                active = false;
     368        } else {
     369                /* Kernel console deactivated */
     370                active = true;
     371        }
     372       
     373        client_arbitration();
     374}
     375
    255376static kbd_dev_t *kbd_dev_new(void)
    256377{
     
    262383        }
    263384       
    264         link_initialize(&kdev->kbd_devs);
     385        link_initialize(&kdev->link);
    265386       
    266387        kdev->mods = KM_NUM_LOCK;
     
    280401        }
    281402       
    282         link_initialize(&mdev->mouse_devs);
     403        link_initialize(&mdev->link);
    283404       
    284405        return mdev;
     
    306427        }
    307428       
    308         list_append(&kdev->kbd_devs, &kbd_devs);
     429        list_append(&kdev->link, &kbd_devs);
    309430        return;
    310431       
     
    334455        }
    335456       
    336         list_append(&mdev->mouse_devs, &mouse_devs);
     457        list_append(&mdev->link, &mouse_devs);
    337458        return;
    338459       
     
    343464/** Add new kbdev device.
    344465 *
    345  * @param service_id    Service ID of the keyboard device
     466 * @param service_id Service ID of the keyboard device
    346467 *
    347468 */
     
    367488        }
    368489       
    369         list_append(&kdev->kbd_devs, &kbd_devs);
     490        list_append(&kdev->link, &kbd_devs);
    370491        *kdevp = kdev;
    371492        return EOK;
     
    380501/** Add new mousedev device.
    381502 *
    382  * @param service_id    Service ID of the mouse device
     503 * @param service_id Service ID of the mouse device
    383504 *
    384505 */
     
    404525        }
    405526       
    406         list_append(&mdev->mouse_devs, &mouse_devs);
     527        list_append(&mdev->link, &mouse_devs);
    407528        *mdevp = mdev;
    408529        return EOK;
     
    423544        kbd_add_dev(&chardev_port, &stty_ctl);
    424545#endif
    425 #if defined(UARCH_arm32) && defined(MACHINE_testarm) && defined(CONFIG_FB)
    426         kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
    427 #endif
    428 #if defined(UARCH_arm32) && defined(MACHINE_testarm) && !defined(CONFIG_FB)
    429         kbd_add_dev(&gxemul_port, &stty_ctl);
    430 #endif
    431 #if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
    432         kbd_add_dev(&pl050_port, &pc_ctl);
    433 #endif
    434546#if defined(MACHINE_ski)
    435547        kbd_add_dev(&ski_port, &stty_ctl);
     
    437549#if defined(MACHINE_msim)
    438550        kbd_add_dev(&msim_port, &stty_ctl);
    439 #endif
    440 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
    441         kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
    442 #endif
    443 #if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)
    444         kbd_add_dev(&gxemul_port, &stty_ctl);
    445551#endif
    446552#if defined(UARCH_ppc32)
     
    471577}
    472578
    473 static void kbd_devs_yield(void)
    474 {
    475         /* For each keyboard device */
    476         list_foreach(kbd_devs, kdev_link) {
    477                 kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
    478                     kbd_devs);
    479                
    480                 /* Yield port */
    481                 if (kdev->port_ops != NULL)
    482                         (*kdev->port_ops->yield)();
    483         }
    484 }
    485 
    486 static void kbd_devs_reclaim(void)
    487 {
    488         /* For each keyboard device */
    489         list_foreach(kbd_devs, kdev_link) {
    490                 kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
    491                     kbd_devs);
    492                
    493                 /* Reclaim port */
    494                 if (kdev->port_ops != NULL)
    495                         (*kdev->port_ops->reclaim)();
    496         }
    497 }
    498 
    499579static int dev_check_new_kbdevs(void)
    500580{
     
    525605               
    526606                /* Determine whether we already know this device. */
    527                 list_foreach(kbd_devs, kdev_link) {
    528                         kbd_dev_t *kdev = list_get_instance(kdev_link,
    529                             kbd_dev_t, kbd_devs);
     607                list_foreach(kbd_devs, link, kbd_dev_t, kdev) {
    530608                        if (kdev->svc_id == svcs[i]) {
    531609                                already_known = true;
     
    578656               
    579657                /* Determine whether we already know this device. */
    580                 list_foreach(mouse_devs, mdev_link) {
    581                         mouse_dev_t *mdev = list_get_instance(mdev_link,
    582                             mouse_dev_t, mouse_devs);
     658                list_foreach(mouse_devs, link, mouse_dev_t, mdev) {
    583659                        if (mdev->svc_id == svcs[i]) {
    584660                                already_known = true;
     
    634710static int input_start_dev_discovery(void)
    635711{
    636         int rc;
    637 
    638         rc = loc_register_cat_change_cb(cat_change_cb);
     712        int rc = loc_register_cat_change_cb(cat_change_cb);
    639713        if (rc != EOK) {
    640714                printf("%s: Failed registering callback for device discovery. "
     
    642716                return rc;
    643717        }
    644 
     718       
    645719        return dev_check_new();
    646720}
     
    662736        sysarg_t obio;
    663737       
     738        list_initialize(&clients);
    664739        list_initialize(&kbd_devs);
    665740        list_initialize(&mouse_devs);
     
    681756       
    682757        /* Register driver */
     758        async_set_client_data_constructor(client_data_create);
     759        async_set_client_data_destructor(client_data_destroy);
    683760        async_set_client_connection(client_connection);
     761       
    684762        int rc = loc_server_register(NAME);
    685763        if (rc != EOK) {
     
    694772                return rc;
    695773        }
     774       
     775        /* Receive kernel notifications */
     776        rc = async_event_subscribe(EVENT_KCONSOLE, kconsole_event_handler, NULL);
     777        if (rc != EOK)
     778                printf("%s: Failed to register kconsole notifications (%s)\n",
     779                    NAME, str_error(rc));
    696780       
    697781        /* Start looking for new input devices */
Note: See TracChangeset for help on using the changeset viewer.