3516. Jumbo Tiny-X patch with Itsy support (#3527, Keith Packard).
[gstreamer-omap:xserver.git] / hw / kdrive / keyboard.c
1 /*
2  * $Id$
3  *
4  * Copyright © 1999 Keith Packard
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Keith Packard not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  Keith Packard makes no
13  * representations about the suitability of this software for any purpose.  It
14  * is provided "as is" without express or implied warranty.
15  *
16  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24 /* $XFree86: $ */
25
26 #include "kdrive.h"
27 #include "kkeymap.h"
28 #include <linux/keyboard.h>
29 #include <linux/kd.h>
30 #include <X11/keysym.h>
31 #include <termios.h>
32
33 extern int  LinuxConsoleFd;
34
35 static KeySym linux_to_x[256] = {
36         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
37         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
38         XK_BackSpace,   XK_Tab,         XK_Linefeed,    NoSymbol,
39         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
40         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
41         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
42         NoSymbol,       NoSymbol,       NoSymbol,       XK_Escape,
43         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
44         XK_space,       XK_exclam,      XK_quotedbl,    XK_numbersign,
45         XK_dollar,      XK_percent,     XK_ampersand,   XK_apostrophe,
46         XK_parenleft,   XK_parenright,  XK_asterisk,    XK_plus,
47         XK_comma,       XK_minus,       XK_period,      XK_slash,
48         XK_0,           XK_1,           XK_2,           XK_3,
49         XK_4,           XK_5,           XK_6,           XK_7,
50         XK_8,           XK_9,           XK_colon,       XK_semicolon,
51         XK_less,        XK_equal,       XK_greater,     XK_question,
52         XK_at,          XK_A,           XK_B,           XK_C,
53         XK_D,           XK_E,           XK_F,           XK_G,
54         XK_H,           XK_I,           XK_J,           XK_K,
55         XK_L,           XK_M,           XK_N,           XK_O,
56         XK_P,           XK_Q,           XK_R,           XK_S,
57         XK_T,           XK_U,           XK_V,           XK_W,
58         XK_X,           XK_Y,           XK_Z,           XK_bracketleft,
59         XK_backslash,   XK_bracketright,XK_asciicircum, XK_underscore,
60         XK_grave,       XK_a,           XK_b,           XK_c,
61         XK_d,           XK_e,           XK_f,           XK_g,
62         XK_h,           XK_i,           XK_j,           XK_k,
63         XK_l,           XK_m,           XK_n,           XK_o,
64         XK_p,           XK_q,           XK_r,           XK_s,
65         XK_t,           XK_u,           XK_v,           XK_w,
66         XK_x,           XK_y,           XK_z,           XK_braceleft,
67         XK_bar,         XK_braceright,  XK_asciitilde,  XK_Delete,
68         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
69         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
70         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
71         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
72         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
73         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
74         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
75         NoSymbol,       NoSymbol,       NoSymbol,       NoSymbol,
76         XK_nobreakspace,XK_exclamdown,  XK_cent,        XK_sterling,
77         XK_currency,    XK_yen,         XK_brokenbar,   XK_section,
78         XK_diaeresis,   XK_copyright,   XK_ordfeminine, XK_guillemotleft,
79         XK_notsign,     XK_hyphen,      XK_registered,  XK_macron,
80         XK_degree,      XK_plusminus,   XK_twosuperior, XK_threesuperior,
81         XK_acute,       XK_mu,          XK_paragraph,   XK_periodcentered,
82         XK_cedilla,     XK_onesuperior, XK_masculine,   XK_guillemotright,
83         XK_onequarter,  XK_onehalf,     XK_threequarters,XK_questiondown,
84         XK_Agrave,      XK_Aacute,      XK_Acircumflex, XK_Atilde,
85         XK_Adiaeresis,  XK_Aring,       XK_AE,          XK_Ccedilla,
86         XK_Egrave,      XK_Eacute,      XK_Ecircumflex, XK_Ediaeresis,
87         XK_Igrave,      XK_Iacute,      XK_Icircumflex, XK_Idiaeresis,
88         XK_ETH,         XK_Ntilde,      XK_Ograve,      XK_Oacute,
89         XK_Ocircumflex, XK_Otilde,      XK_Odiaeresis,  XK_multiply,
90         XK_Ooblique,    XK_Ugrave,      XK_Uacute,      XK_Ucircumflex,
91         XK_Udiaeresis,  XK_Yacute,      XK_THORN,       XK_ssharp,
92         XK_agrave,      XK_aacute,      XK_acircumflex, XK_atilde,
93         XK_adiaeresis,  XK_aring,       XK_ae,          XK_ccedilla,
94         XK_egrave,      XK_eacute,      XK_ecircumflex, XK_ediaeresis,
95         XK_igrave,      XK_iacute,      XK_icircumflex, XK_idiaeresis,
96         XK_eth,         XK_ntilde,      XK_ograve,      XK_oacute,
97         XK_ocircumflex, XK_otilde,      XK_odiaeresis,  XK_division,
98         XK_oslash,      XK_ugrave,      XK_uacute,      XK_ucircumflex,
99         XK_udiaeresis,  XK_yacute,      XK_thorn,       XK_ydiaeresis
100 };
101
102 static unsigned char tbl[KD_MAX_WIDTH] = 
103 {
104     0,
105     1 << KG_SHIFT,
106     (1 << KG_ALT),
107     (1 << KG_ALT) | (1 << KG_SHIFT)
108 };
109
110 static void
111 readKernelMapping()
112 {
113     KeySym          *k;
114     int             i, j;
115     struct kbentry  kbe;
116     int             minKeyCode, maxKeyCode;
117
118     minKeyCode = NR_KEYS;
119     maxKeyCode = 0;
120     k = kdKeymap;
121     for (i = 0; 
122          i < NR_KEYS && (maxKeyCode - minKeyCode + 1) < KD_MAX_LENGTH; 
123          ++i)
124     {
125         kbe.kb_index = i;
126
127         for (j = 0; j < KD_MAX_WIDTH; ++j)
128         {
129             unsigned short kval;
130
131             k[j] = NoSymbol;
132
133             kbe.kb_table = tbl[j];
134             if (ioctl(LinuxConsoleFd, KDGKBENT, &kbe))
135                 continue;
136
137             kval = KVAL(kbe.kb_value);
138             switch (KTYP(kbe.kb_value))
139             {
140             case KT_LATIN:
141             case KT_LETTER:
142                 k[j] = linux_to_x[kval];
143                 break;
144
145             case KT_FN:
146                 if (kval <= 19)
147                     k[j] = XK_F1 + kval;
148                 else switch (kbe.kb_value)
149                 {
150                 case K_FIND:
151                     k[j] = XK_Home; /* or XK_Find */
152                     break;
153                 case K_INSERT:
154                     k[j] = XK_Insert;
155                     break;
156                 case K_REMOVE:
157                     k[j] = XK_Delete;
158                     break;
159                 case K_SELECT:
160                     k[j] = XK_End; /* or XK_Select */
161                     break;
162                 case K_PGUP:
163                     k[j] = XK_Prior;
164                     break;
165                 case K_PGDN:
166                     k[j] = XK_Next;
167                     break;
168                 case K_HELP:
169                     k[j] = XK_Help;
170                     break;
171                 case K_DO:
172                     k[j] = XK_Execute;
173                     break;
174                 case K_PAUSE:
175                     k[j] = XK_Pause;
176                     break;
177                 case K_MACRO:
178                     k[j] = XK_Menu;
179                     break;
180                 default:
181                     break;
182                 }
183                 break;
184
185             case KT_SPEC:
186                 switch (kbe.kb_value)
187                 {
188                 case K_ENTER:
189                     k[j] = XK_Return;
190                     break;
191                 case K_BREAK:
192                     k[j] = XK_Break;
193                     break;
194                 case K_CAPS:
195                     k[j] = XK_Caps_Lock;
196                     break;
197                 case K_NUM:
198                     k[j] = XK_Num_Lock;
199                     break;
200                 case K_HOLD:
201                     k[j] = XK_Scroll_Lock;
202                     break;
203                 case K_COMPOSE:
204                     k[j] = XK_Multi_key;
205                     break;
206                 default:
207                     break;
208                 }
209                 break;
210
211             case KT_PAD:
212                 switch (kbe.kb_value)
213                 {
214                 case K_PPLUS:
215                     k[j] = XK_KP_Add;
216                     break;
217                 case K_PMINUS:
218                     k[j] = XK_KP_Subtract;
219                     break;
220                 case K_PSTAR:
221                     k[j] = XK_KP_Multiply;
222                     break;
223                 case K_PSLASH:
224                     k[j] = XK_KP_Divide;
225                     break;
226                 case K_PENTER:
227                     k[j] = XK_KP_Enter;
228                     break;
229                 case K_PCOMMA:
230                     k[j] = XK_KP_Separator;
231                     break;
232                 case K_PDOT:
233                     k[j] = XK_KP_Decimal;
234                     break;
235                 case K_PPLUSMINUS:
236                     k[j] = XK_KP_Subtract;
237                     break;
238                 default:
239                     if (kval <= 9)
240                         k[j] = XK_KP_0 + kval;
241                     break;
242                 }
243                 break;
244
245                 /*
246                  * KT_DEAD keys are for accelerated diacritical creation.
247                  */
248             case KT_DEAD:
249                 switch (kbe.kb_value)
250                 {
251                 case K_DGRAVE:
252                     k[j] = XK_dead_grave;
253                     break;
254                 case K_DACUTE:
255                     k[j] = XK_dead_acute;
256                     break;
257                 case K_DCIRCM:
258                     k[j] = XK_dead_circumflex;
259                     break;
260                 case K_DTILDE:
261                     k[j] = XK_dead_tilde;
262                     break;
263                 case K_DDIERE:
264                     k[j] = XK_dead_diaeresis;
265                     break;
266                 }
267                 break;
268
269             case KT_CUR:
270                 switch (kbe.kb_value)
271                 {
272                 case K_DOWN:
273                     k[j] = XK_Down;
274                     break;
275                 case K_LEFT:
276                     k[j] = XK_Left;
277                     break;
278                 case K_RIGHT:
279                     k[j] = XK_Right;
280                     break;
281                 case K_UP:
282                     k[j] = XK_Up;
283                     break;
284                 }
285                 break;
286
287             case KT_SHIFT:
288                 switch (kbe.kb_value)
289                 {
290                 case K_ALTGR:
291                     k[j] = XK_Alt_R;
292                     break;
293                 case K_ALT:
294                     k[j] = (kbe.kb_index == 0x64 ?
295                           XK_Alt_R : XK_Alt_L);
296                     break;
297                 case K_CTRL:
298                     k[j] = (kbe.kb_index == 0x61 ?
299                           XK_Control_R : XK_Control_L);
300                     break;
301                 case K_CTRLL:
302                     k[j] = XK_Control_L;
303                     break;
304                 case K_CTRLR:
305                     k[j] = XK_Control_R;
306                     break;
307                 case K_SHIFT:
308                     k[j] = (kbe.kb_index == 0x36 ?
309                           XK_Shift_R : XK_Shift_L);
310                     break;
311                 case K_SHIFTL:
312                     k[j] = XK_Shift_L;
313                     break;
314                 case K_SHIFTR:
315                     k[j] = XK_Shift_R;
316                     break;
317                 default:
318                     break;
319                 }
320                 break;
321
322                 /*
323                  * KT_ASCII keys accumulate a 3 digit decimal number that gets
324                  * emitted when the shift state changes. We can't emulate that.
325                  */
326             case KT_ASCII:
327                 break;
328
329             case KT_LOCK:
330                 if (kbe.kb_value == K_SHIFTLOCK)
331                     k[j] = XK_Shift_Lock;
332                 break;
333
334             default:
335                 break;
336             }
337             if (i < minKeyCode)
338                 minKeyCode = i;
339             if (i > maxKeyCode)
340                 maxKeyCode = i;
341         }
342
343         if (minKeyCode == NR_KEYS)
344             continue;
345         
346         if (k[3] == k[2]) k[3] = NoSymbol;
347         if (k[2] == k[1]) k[2] = NoSymbol;
348         if (k[1] == k[0]) k[1] = NoSymbol;
349         if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
350         if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol;
351
352         k += KD_MAX_WIDTH;
353     }
354     kdMinScanCode = minKeyCode;
355     kdMaxScanCode = maxKeyCode;
356 }
357
358 void
359 LinuxKeyboardLoad (void)
360 {
361     readKernelMapping ();
362 }
363
364 static int              LinuxKbdTrans;
365 static struct termios   LinuxTermios;
366
367 int
368 LinuxKeyboardInit (void)
369 {
370     struct termios nTty;
371
372     ioctl (LinuxConsoleFd, KDGKBMODE, &LinuxKbdTrans);
373     tcgetattr (LinuxConsoleFd, &LinuxTermios);
374     
375     ioctl(LinuxConsoleFd, KDSKBMODE, K_MEDIUMRAW);
376     nTty = LinuxTermios;
377     nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
378     nTty.c_oflag = 0;
379     nTty.c_cflag = CREAD | CS8;
380     nTty.c_lflag = 0;
381     nTty.c_cc[VTIME]=0;
382     nTty.c_cc[VMIN]=1;
383     cfsetispeed(&nTty, 9600);
384     cfsetospeed(&nTty, 9600);
385     tcsetattr(LinuxConsoleFd, TCSANOW, &nTty);
386     return LinuxConsoleFd;
387 }
388
389 void
390 LinuxKeyboardFini (int fd)
391 {
392     ioctl(LinuxConsoleFd, KDSKBMODE, LinuxKbdTrans);
393     tcsetattr(LinuxConsoleFd, TCSANOW, &LinuxTermios);
394 }
395
396 void
397 LinuxKeyboardRead (int fd)
398 {
399     unsigned char   buf[256], *b;
400     int             n;
401
402     while ((n = read (fd, buf, sizeof (buf))) > 0)
403     {
404         b = buf;
405         while (n--)
406         {
407             KdEnqueueKeyboardEvent (b[0] & 0x7f, b[0] & 0x80);
408             b++;
409         }
410     }
411 }
412
413 void
414 LinuxKeyboardLeds (int leds)
415 {
416     ioctl (LinuxConsoleFd, KDSETLED, leds & 7);
417 }
418
419 void
420 LinuxKeyboardBell (int volume, int pitch, int duration)
421 {
422     if (volume && pitch)
423     {
424         ioctl(LinuxConsoleFd, KDMKTONE,
425               ((1193190 / pitch) & 0xffff) |
426               (((unsigned long)duration *
427                 volume / 50) << 16));
428
429     }
430 }
431
432 KdKeyboardFuncs LinuxKeyboardFuncs = {
433     LinuxKeyboardLoad,
434     LinuxKeyboardInit,
435     LinuxKeyboardRead,
436     LinuxKeyboardLeds,
437     LinuxKeyboardBell,
438     LinuxKeyboardFini,
439     3,
440 };