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

lfn serial ticket/834-toolchain-update 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
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
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
29/**
30 * @addtogroup kbdgen generic
31 * @brief HelenOS generic uspace keyboard handler.
32 * @ingroup kbd
33 * @{
34 */
35/** @file
36 */
37
38#include <ipc/services.h>
39#include <ipc/kbd.h>
40#include <sysinfo.h>
41#include <stdio.h>
42#include <unistd.h>
43#include <stdlib.h>
44#include <stdio.h>
45#include <ns.h>
46#include <ns_obsolete.h>
47#include <async.h>
48#include <async_obsolete.h>
49#include <errno.h>
50#include <adt/fifo.h>
51#include <io/console.h>
52#include <io/keycode.h>
53#include <devmap.h>
54#include <kbd.h>
55#include <kbd_port.h>
56#include <kbd_ctl.h>
57#include <layout.h>
58
59// FIXME: remove this header
60#include <kernel/ipc/ipc_methods.h>
61
62#define NAME "kbd"
63#define NAMESPACE "hid_in"
64
65int client_phone = -1;
66
67/** Currently active modifiers. */
68static unsigned mods = KM_NUM_LOCK;
69
70/** Currently pressed lock keys. We track these to tackle autorepeat. */
71static unsigned lock_keys;
72
73bool irc_service = false;
74int irc_phone = -1;
75
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
86void kbd_push_scancode(int scancode)
87{
88/* printf("scancode: 0x%x\n", scancode);*/
89 kbd_ctl_parse_scancode(scancode);
90}
91
92void kbd_push_ev(int type, unsigned int key)
93{
94 kbd_event_t ev;
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) {
108 if (type == KEY_PRESS)
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
121 if (mod_mask != 0) {
122 if (type == KEY_PRESS) {
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;
130
131 /* Update keyboard lock indicator lights. */
132 kbd_ctl_set_ind(mods);
133 } else {
134 lock_keys = lock_keys & ~mod_mask;
135 }
136 }
137/*
138 printf("type: %d\n", type);
139 printf("mods: 0x%x\n", mods);
140 printf("keycode: %u\n", key);
141*/
142 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
143 key == KC_F1) {
144 active_layout = 0;
145 layout[active_layout]->reset();
146 return;
147 }
148
149 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
150 key == KC_F2) {
151 active_layout = 1;
152 layout[active_layout]->reset();
153 return;
154 }
155
156 if (type == KEY_PRESS && (mods & KM_LCTRL) &&
157 key == KC_F3) {
158 active_layout = 2;
159 layout[active_layout]->reset();
160 return;
161 }
162
163 ev.type = type;
164 ev.key = key;
165 ev.mods = mods;
166
167 ev.c = layout[active_layout]->parse_ev(&ev);
168
169 async_obsolete_msg_4(client_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
170}
171
172static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
173{
174 ipc_callid_t callid;
175 ipc_call_t call;
176 int retval;
177
178 async_answer_0(iid, EOK);
179
180 while (true) {
181 callid = async_get_call(&call);
182
183 if (!IPC_GET_IMETHOD(call)) {
184 if (client_phone != -1) {
185 async_obsolete_hangup(client_phone);
186 client_phone = -1;
187 }
188
189 async_answer_0(callid, EOK);
190 return;
191 }
192
193 switch (IPC_GET_IMETHOD(call)) {
194 case IPC_M_CONNECT_TO_ME:
195 if (client_phone != -1) {
196 retval = ELIMIT;
197 break;
198 }
199 client_phone = IPC_GET_ARG5(call);
200 retval = 0;
201 break;
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;
210 default:
211 retval = EINVAL;
212 }
213 async_answer_0(callid, retval);
214 }
215}
216
217
218int main(int argc, char **argv)
219{
220 printf("%s: HelenOS Keyboard service\n", NAME);
221
222 sysarg_t fhc;
223 sysarg_t obio;
224
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;
228
229 if (irc_service) {
230 while (irc_phone < 0)
231 irc_phone = service_obsolete_connect_blocking(SERVICE_IRC, 0, 0);
232 }
233
234 /* Initialize port driver. */
235 if (kbd_port_init() != 0)
236 return -1;
237
238 /* Initialize controller driver. */
239 if (kbd_ctl_init() != 0)
240 return -1;
241
242 /* Initialize (reset) layout. */
243 layout[active_layout]->reset();
244
245 /* Register driver */
246 int rc = devmap_driver_register(NAME, client_connection);
247 if (rc < 0) {
248 printf("%s: Unable to register driver (%d)\n", NAME, rc);
249 return -1;
250 }
251
252 char kbd[DEVMAP_NAME_MAXLEN + 1];
253 snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
254
255 devmap_handle_t devmap_handle;
256 if (devmap_device_register(kbd, &devmap_handle) != EOK) {
257 printf("%s: Unable to register device %s\n", NAME, kbd);
258 return -1;
259 }
260
261 printf(NAME ": Accepting connections\n");
262 async_manager();
263
264 /* Not reached. */
265 return 0;
266}
267
268/**
269 * @}
270 */
Note: See TracBrowser for help on using the repository browser.