source: mainline/uspace/srv/hid/kbd/generic/kbd.c@ 79ae36dd

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 79ae36dd was 79ae36dd, checked in by Martin Decky <martin@…>, 15 years ago

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
  • Property mode set to 100644
File size: 6.3 KB
RevLine 
[51d6f80]1/*
[df4ed85]2 * Copyright (c) 2006 Josef Cejka
[51d6f80]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[231a60a]29/**
30 * @addtogroup kbdgen generic
[215abc1]31 * @brief HelenOS generic uspace keyboard handler.
32 * @ingroup kbd
[ce5bcb4]33 * @{
[215abc1]34 */
[ce5bcb4]35/** @file
36 */
37
[7ee6aff]38#include <ipc/services.h>
[e795203]39#include <ipc/kbd.h>
[3e5a814]40#include <sysinfo.h>
[51d6f80]41#include <stdio.h>
42#include <unistd.h>
43#include <stdlib.h>
[37458472]44#include <stdio.h>
[79ae36dd]45#include <ns.h>
46#include <ns_obsolete.h>
[fa09449]47#include <async.h>
[79ae36dd]48#include <async_obsolete.h>
[51d6f80]49#include <errno.h>
[d9c8c81]50#include <adt/fifo.h>
[215abc1]51#include <io/console.h>
52#include <io/keycode.h>
[47a350f]53#include <devmap.h>
[51d6f80]54#include <kbd.h>
[f89979b]55#include <kbd_port.h>
56#include <kbd_ctl.h>
57#include <layout.h>
[51d6f80]58
[79ae36dd]59// FIXME: remove this header
60#include <kernel/ipc/ipc_methods.h>
61
[47a350f]62#define NAME "kbd"
63#define NAMESPACE "hid_in"
[854387b]64
[3f29834]65int client_phone = -1;
[d1eece6]66
67/** Currently active modifiers. */
[90e3d6a]68static unsigned mods = KM_NUM_LOCK;
[085bd54]69
[12b6796]70/** Currently pressed lock keys. We track these to tackle autorepeat. */
71static unsigned lock_keys;
72
[57d129e]73bool irc_service = false;
74int irc_phone = -1;
[3e5a814]75
[0175246]76#define NUM_LAYOUTS 3
77
78static layout_op_t *layout[NUM_LAYOUTS] = {
79 &us_qwerty_op,
80 &us_dvorak_op,
81 &cz_op
82};
83
84static int active_layout = 0;
85
[f89979b]86void kbd_push_scancode(int scancode)
87{
[5ad8661]88/* printf("scancode: 0x%x\n", scancode);*/
[f89979b]89 kbd_ctl_parse_scancode(scancode);
90}
91
[d1eece6]92void kbd_push_ev(int type, unsigned int key)
[085bd54]93{
[79ae36dd]94 kbd_event_t ev;
[d1eece6]95 unsigned mod_mask;
96
97 switch (key) {
98 case KC_LCTRL: mod_mask = KM_LCTRL; break;
99 case KC_RCTRL: mod_mask = KM_RCTRL; break;
100 case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
101 case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
102 case KC_LALT: mod_mask = KM_LALT; break;
103 case KC_RALT: mod_mask = KM_RALT; break;
104 default: mod_mask = 0; break;
105 }
106
107 if (mod_mask != 0) {
[215abc1]108 if (type == KEY_PRESS)
[d1eece6]109 mods = mods | mod_mask;
110 else
111 mods = mods & ~mod_mask;
112 }
113
114 switch (key) {
115 case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
116 case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
117 case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
118 default: mod_mask = 0; break;
119 }
120
[12b6796]121 if (mod_mask != 0) {
[215abc1]122 if (type == KEY_PRESS) {
[12b6796]123 /*
124 * Only change lock state on transition from released
125 * to pressed. This prevents autorepeat from messing
126 * up the lock state.
127 */
128 mods = mods ^ (mod_mask & ~lock_keys);
129 lock_keys = lock_keys | mod_mask;
[c145bc2]130
131 /* Update keyboard lock indicator lights. */
132 kbd_ctl_set_ind(mods);
[12b6796]133 } else {
134 lock_keys = lock_keys & ~mod_mask;
135 }
136 }
[5ad8661]137/*
[f89979b]138 printf("type: %d\n", type);
139 printf("mods: 0x%x\n", mods);
140 printf("keycode: %u\n", key);
[5ad8661]141*/
[215abc1]142 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
[0175246]143 key == KC_F1) {
144 active_layout = 0;
[d15815e2]145 layout[active_layout]->reset();
[0175246]146 return;
147 }
148
[215abc1]149 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
[0175246]150 key == KC_F2) {
151 active_layout = 1;
[d15815e2]152 layout[active_layout]->reset();
[0175246]153 return;
154 }
155
[215abc1]156 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
[0175246]157 key == KC_F3) {
158 active_layout = 2;
[d15815e2]159 layout[active_layout]->reset();
[0175246]160 return;
161 }
162
[f89979b]163 ev.type = type;
164 ev.key = key;
165 ev.mods = mods;
166
[0175246]167 ev.c = layout[active_layout]->parse_ev(&ev);
[f89979b]168
[79ae36dd]169 async_obsolete_msg_4(client_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
[085bd54]170}
171
[3f29834]172static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
[085bd54]173{
174 ipc_callid_t callid;
175 ipc_call_t call;
176 int retval;
177
[ffa2c8ef]178 async_answer_0(iid, EOK);
[085bd54]179
[79ae36dd]180 while (true) {
[085bd54]181 callid = async_get_call(&call);
[79ae36dd]182
183 if (!IPC_GET_IMETHOD(call)) {
[3f29834]184 if (client_phone != -1) {
[79ae36dd]185 async_obsolete_hangup(client_phone);
[3f29834]186 client_phone = -1;
[47a350f]187 }
188
[ffa2c8ef]189 async_answer_0(callid, EOK);
[085bd54]190 return;
[79ae36dd]191 }
192
193 switch (IPC_GET_IMETHOD(call)) {
[085bd54]194 case IPC_M_CONNECT_TO_ME:
[3f29834]195 if (client_phone != -1) {
[085bd54]196 retval = ELIMIT;
197 break;
198 }
[3f29834]199 client_phone = IPC_GET_ARG5(call);
[085bd54]200 retval = 0;
201 break;
[ccd1a14]202 case KBD_YIELD:
203 kbd_port_yield();
204 retval = 0;
205 break;
206 case KBD_RECLAIM:
207 kbd_port_reclaim();
208 retval = 0;
209 break;
[153a209]210 default:
211 retval = EINVAL;
[085bd54]212 }
[ffa2c8ef]213 async_answer_0(callid, retval);
[085bd54]214 }
215}
216
217
[51d6f80]218int main(int argc, char **argv)
219{
[d9fae235]220 printf("%s: HelenOS Keyboard service\n", NAME);
[e00938c]221
[d9fae235]222 sysarg_t fhc;
223 sysarg_t obio;
224
[57d129e]225 if (((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
226 || ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio)))
227 irc_service = true;
[3e5a814]228
[57d129e]229 if (irc_service) {
230 while (irc_phone < 0)
[79ae36dd]231 irc_phone = service_obsolete_connect_blocking(SERVICE_IRC, 0, 0);
[3e5a814]232 }
233
[f89979b]234 /* Initialize port driver. */
[b0b5628]235 if (kbd_port_init() != 0)
236 return -1;
237
238 /* Initialize controller driver. */
239 if (kbd_ctl_init() != 0)
[15039b67]240 return -1;
[d15815e2]241
242 /* Initialize (reset) layout. */
243 layout[active_layout]->reset();
[51d6f80]244
[47a350f]245 /* Register driver */
[3f29834]246 int rc = devmap_driver_register(NAME, client_connection);
[47a350f]247 if (rc < 0) {
[d9fae235]248 printf("%s: Unable to register driver (%d)\n", NAME, rc);
[51d6f80]249 return -1;
[47a350f]250 }
251
252 char kbd[DEVMAP_NAME_MAXLEN + 1];
253 snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
[e00938c]254
[991f645]255 devmap_handle_t devmap_handle;
256 if (devmap_device_register(kbd, &devmap_handle) != EOK) {
[d9fae235]257 printf("%s: Unable to register device %s\n", NAME, kbd);
[47a350f]258 return -1;
259 }
260
[e00938c]261 printf(NAME ": Accepting connections\n");
[085bd54]262 async_manager();
[51c1b003]263
[f89979b]264 /* Not reached. */
[153a209]265 return 0;
[51d6f80]266}
[ce5bcb4]267
268/**
269 * @}
270 */
Note: See TracBrowser for help on using the repository browser.