Changeset 15d0046 in mainline for uspace/srv/hid/input/input.c


Ignore:
Timestamp:
2014-09-12T13:22:33Z (10 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9b20126
Parents:
8db09e4 (diff), 105d8d6 (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 changes

File:
1 edited

Legend:

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

    r8db09e4 r15d0046  
    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
     65bool irc_service = false;
     66async_sess_t *irc_sess = NULL;
     67
    6468#define NUM_LAYOUTS  4
    6569
     
    7175};
    7276
    73 static void kbd_devs_yield(void);
    74 static void kbd_devs_reclaim(void);
    75 
    76 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;
    7791
    7892/** List of keyboard devices */
     
    8296static list_t mouse_devs;
    8397
    84 bool irc_service = false;
    85 async_sess_t *irc_sess = NULL;
    86 
    8798static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
     99
     100static void *client_data_create(void)
     101{
     102        client_t *client = (client_t *) calloc(1, sizeof(client_t));
     103        if (client == NULL)
     104                return NULL;
     105       
     106        link_initialize(&client->link);
     107        client->active = false;
     108        client->sess = NULL;
     109       
     110        list_append(&client->link, &clients);
     111       
     112        return client;
     113}
     114
     115static void client_data_destroy(void *data)
     116{
     117        client_t *client = (client_t *) data;
     118       
     119        list_remove(&client->link);
     120        free(client);
     121}
    88122
    89123void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
     
    103137       
    104138        switch (key) {
    105         case KC_LCTRL: mod_mask = KM_LCTRL; break;
    106         case KC_RCTRL: mod_mask = KM_RCTRL; break;
    107         case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
    108         case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
    109         case KC_LALT: mod_mask = KM_LALT; break;
    110         case KC_RALT: mod_mask = KM_RALT; break;
    111         default: mod_mask = 0; break;
     139        case KC_LCTRL:
     140                mod_mask = KM_LCTRL;
     141                break;
     142        case KC_RCTRL:
     143                mod_mask = KM_RCTRL;
     144                break;
     145        case KC_LSHIFT:
     146                mod_mask = KM_LSHIFT;
     147                break;
     148        case KC_RSHIFT:
     149                mod_mask = KM_RSHIFT;
     150                break;
     151        case KC_LALT:
     152                mod_mask = KM_LALT;
     153                break;
     154        case KC_RALT:
     155                mod_mask = KM_RALT;
     156                break;
     157        default:
     158                mod_mask = 0;
    112159        }
    113160       
     
    120167       
    121168        switch (key) {
    122         case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
    123         case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
    124         case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
    125         default: mod_mask = 0; break;
     169        case KC_CAPS_LOCK:
     170                mod_mask = KM_CAPS_LOCK;
     171                break;
     172        case KC_NUM_LOCK:
     173                mod_mask = KM_NUM_LOCK;
     174                break;
     175        case KC_SCROLL_LOCK:
     176                mod_mask = KM_SCROLL_LOCK;
     177                break;
     178        default:
     179                mod_mask = 0;
    126180        }
    127181       
     
    143197        }
    144198       
    145         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    146             key == KC_F1) {
     199        // TODO: More elegant layout switching
     200       
     201        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     202            (key == KC_F1)) {
    147203                layout_destroy(kdev->active_layout);
    148204                kdev->active_layout = layout_create(layout[0]);
     
    150206        }
    151207       
    152         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    153             key == KC_F2) {
     208        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     209            (key == KC_F2)) {
    154210                layout_destroy(kdev->active_layout);
    155211                kdev->active_layout = layout_create(layout[1]);
     
    157213        }
    158214       
    159         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    160             key == KC_F3) {
     215        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     216            (key == KC_F3)) {
    161217                layout_destroy(kdev->active_layout);
    162218                kdev->active_layout = layout_create(layout[2]);
     
    164220        }
    165221       
    166         if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
    167             key == KC_F4) {
     222        if ((type == KEY_PRESS) && (kdev->mods & KM_LCTRL) &&
     223            (key == KC_F4)) {
    168224                layout_destroy(kdev->active_layout);
    169225                kdev->active_layout = layout_create(layout[3]);
     
    177233        ev.c = layout_parse_ev(kdev->active_layout, &ev);
    178234       
    179         async_exch_t *exch = async_exchange_begin(client_sess);
    180         async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
    181         async_exchange_end(exch);
    182 }
    183 
    184 /** Mouse pointer has moved. */
     235        list_foreach(clients, link, client_t, client) {
     236                if (client->active) {
     237                        async_exch_t *exch = async_exchange_begin(client->sess);
     238                        async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
     239                        async_exchange_end(exch);
     240                }
     241        }
     242}
     243
     244/** Mouse pointer has moved (relative mode). */
    185245void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz)
    186246{
    187         async_exch_t *exch = async_exchange_begin(client_sess);
    188         if (dx || dy)
    189                 async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
    190         if (dz) {
    191                 // TODO: Implement proper wheel support
    192                 keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
    193                 for (int i = 0; i < 3; ++i) {
    194                         async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
    195                 }
    196                 async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
    197         }
    198         async_exchange_end(exch);
    199 }
    200 
    201 /** Mouse pointer has moved in absolute mode. */
     247        list_foreach(clients, link, client_t, client) {
     248                if (client->active) {
     249                        async_exch_t *exch = async_exchange_begin(client->sess);
     250                       
     251                        if ((dx) || (dy))
     252                                async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
     253                       
     254                        if (dz) {
     255                                // TODO: Implement proper wheel support
     256                                keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
     257                               
     258                                for (unsigned int i = 0; i < 3; i++)
     259                                        async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
     260                               
     261                                async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
     262                        }
     263                       
     264                        async_exchange_end(exch);
     265                }
     266        }
     267}
     268
     269/** Mouse pointer has moved (absolute mode). */
    202270void mouse_push_event_abs_move(mouse_dev_t *mdev, unsigned int x, unsigned int y,
    203271    unsigned int max_x, unsigned int max_y)
    204272{
    205         if (max_x && max_y) {
    206                 async_exch_t *exch = async_exchange_begin(client_sess);
    207                 async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
    208                 async_exchange_end(exch);
     273        list_foreach(clients, link, client_t, client) {
     274                if (client->active) {
     275                        if ((max_x) && (max_y)) {
     276                                async_exch_t *exch = async_exchange_begin(client->sess);
     277                                async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
     278                                async_exchange_end(exch);
     279                        }
     280                }
    209281        }
    210282}
     
    213285void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
    214286{
    215         async_exch_t *exch = async_exchange_begin(client_sess);
    216         async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
    217         async_exchange_end(exch);
    218 }
    219 
     287        list_foreach(clients, link, client_t, client) {
     288                if (client->active) {
     289                        async_exch_t *exch = async_exchange_begin(client->sess);
     290                        async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
     291                        async_exchange_end(exch);
     292                }
     293        }
     294}
     295
     296/** Arbitrate client actiovation */
     297static void client_arbitration(client_t *req)
     298{
     299        /* Mutual exclusion of active clients */
     300        list_foreach(clients, link, client_t, client)
     301                client->active = (client == req);
     302       
     303        /* Notify clients about the arbitration */
     304        list_foreach(clients, link, client_t, client) {
     305                async_exch_t *exch = async_exchange_begin(client->sess);
     306                async_msg_0(exch, client->active ?
     307                    INPUT_EVENT_ACTIVE : INPUT_EVENT_DEACTIVE);
     308                async_exchange_end(exch);
     309        }
     310}
     311
     312/** New client connection */
    220313static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    221314{
     315        client_t *client = (client_t *) async_get_client_data();
     316        if (client == NULL) {
     317                async_answer_0(iid, ENOMEM);
     318                return;
     319        }
     320       
    222321        async_answer_0(iid, EOK);
    223322       
     
    227326               
    228327                if (!IPC_GET_IMETHOD(call)) {
    229                         if (client_sess != NULL) {
    230                                 async_hangup(client_sess);
    231                                 client_sess = NULL;
     328                        if (client->sess != NULL) {
     329                                async_hangup(client->sess);
     330                                client->sess = NULL;
    232331                        }
    233332                       
     
    239338                    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
    240339                if (sess != NULL) {
    241                         if (client_sess == NULL) {
    242                                 client_sess = sess;
     340                        if (client->sess == NULL) {
     341                                client->sess = sess;
    243342                                async_answer_0(callid, EOK);
    244343                        } else
     
    246345                } else {
    247346                        switch (IPC_GET_IMETHOD(call)) {
    248                         case INPUT_YIELD:
    249                                 kbd_devs_yield();
    250                                 async_answer_0(callid, EOK);
    251                                 break;
    252                         case INPUT_RECLAIM:
    253                                 kbd_devs_reclaim();
     347                        case INPUT_ACTIVATE:
     348                                active_client = client;
     349                                client_arbitration(client);
    254350                                async_answer_0(callid, EOK);
    255351                                break;
     
    261357}
    262358
     359static void kconsole_event_handler(ipc_callid_t callid, ipc_call_t *call,
     360    void *arg)
     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
    263371static kbd_dev_t *kbd_dev_new(void)
    264372{
     
    270378        }
    271379       
    272         link_initialize(&kdev->kbd_devs);
     380        link_initialize(&kdev->link);
    273381       
    274382        kdev->mods = KM_NUM_LOCK;
     
    288396        }
    289397       
    290         link_initialize(&mdev->mouse_devs);
     398        link_initialize(&mdev->link);
    291399       
    292400        return mdev;
     
    314422        }
    315423       
    316         list_append(&kdev->kbd_devs, &kbd_devs);
     424        list_append(&kdev->link, &kbd_devs);
    317425        return;
    318426       
     
    342450        }
    343451       
    344         list_append(&mdev->mouse_devs, &mouse_devs);
     452        list_append(&mdev->link, &mouse_devs);
    345453        return;
    346454       
     
    351459/** Add new kbdev device.
    352460 *
    353  * @param service_id    Service ID of the keyboard device
     461 * @param service_id Service ID of the keyboard device
    354462 *
    355463 */
     
    375483        }
    376484       
    377         list_append(&kdev->kbd_devs, &kbd_devs);
     485        list_append(&kdev->link, &kbd_devs);
    378486        *kdevp = kdev;
    379487        return EOK;
     
    388496/** Add new mousedev device.
    389497 *
    390  * @param service_id    Service ID of the mouse device
     498 * @param service_id Service ID of the mouse device
    391499 *
    392500 */
     
    412520        }
    413521       
    414         list_append(&mdev->mouse_devs, &mouse_devs);
     522        list_append(&mdev->link, &mouse_devs);
    415523        *mdevp = mdev;
    416524        return EOK;
     
    430538#if defined(UARCH_arm32) && defined(MACHINE_gta02)
    431539        kbd_add_dev(&chardev_port, &stty_ctl);
    432 #endif
    433 #if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
    434         kbd_add_dev(&pl050_port, &pc_ctl);
    435540#endif
    436541#if defined(MACHINE_ski)
     
    467572}
    468573
    469 static void kbd_devs_yield(void)
    470 {
    471         /* For each keyboard device */
    472         list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
    473                 /* Yield port */
    474                 if (kdev->port_ops != NULL)
    475                         (*kdev->port_ops->yield)();
    476         }
    477 }
    478 
    479 static void kbd_devs_reclaim(void)
    480 {
    481         /* For each keyboard device */
    482         list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
    483                 /* Reclaim port */
    484                 if (kdev->port_ops != NULL)
    485                         (*kdev->port_ops->reclaim)();
    486         }
    487 }
    488 
    489574static int dev_check_new_kbdevs(void)
    490575{
     
    515600               
    516601                /* Determine whether we already know this device. */
    517                 list_foreach(kbd_devs, kbd_devs, kbd_dev_t, kdev) {
     602                list_foreach(kbd_devs, link, kbd_dev_t, kdev) {
    518603                        if (kdev->svc_id == svcs[i]) {
    519604                                already_known = true;
     
    566651               
    567652                /* Determine whether we already know this device. */
    568                 list_foreach(mouse_devs, mouse_devs, mouse_dev_t, mdev) {
     653                list_foreach(mouse_devs, link, mouse_dev_t, mdev) {
    569654                        if (mdev->svc_id == svcs[i]) {
    570655                                already_known = true;
     
    620705static int input_start_dev_discovery(void)
    621706{
    622         int rc;
    623 
    624         rc = loc_register_cat_change_cb(cat_change_cb);
     707        int rc = loc_register_cat_change_cb(cat_change_cb);
    625708        if (rc != EOK) {
    626709                printf("%s: Failed registering callback for device discovery. "
     
    628711                return rc;
    629712        }
    630 
     713       
    631714        return dev_check_new();
    632715}
     
    648731        sysarg_t obio;
    649732       
     733        list_initialize(&clients);
    650734        list_initialize(&kbd_devs);
    651735        list_initialize(&mouse_devs);
     
    667751       
    668752        /* Register driver */
     753        async_set_client_data_constructor(client_data_create);
     754        async_set_client_data_destructor(client_data_destroy);
    669755        async_set_client_connection(client_connection);
     756       
    670757        int rc = loc_server_register(NAME);
    671758        if (rc != EOK) {
     
    680767                return rc;
    681768        }
     769       
     770        /* Receive kernel notifications */
     771        rc = async_event_subscribe(EVENT_KCONSOLE, kconsole_event_handler, NULL);
     772        if (rc != EOK)
     773                printf("%s: Failed to register kconsole notifications (%s)\n",
     774                    NAME, str_error(rc));
    682775       
    683776        /* Start looking for new input devices */
Note: See TracChangeset for help on using the changeset viewer.