1b9325ec5Stsutsui/* $Xorg: sunKbd.c,v 1.3 2000/08/17 19:48:30 cpqbld Exp $ */
2b9325ec5Stsutsui/*-
3b9325ec5Stsutsui * Copyright 1987 by the Regents of the University of California
4b9325ec5Stsutsui *
5b9325ec5Stsutsui * Permission to use, copy, modify, and distribute this
6b9325ec5Stsutsui * software and its documentation for any purpose and without
7b9325ec5Stsutsui * fee is hereby granted, provided that the above copyright
8b9325ec5Stsutsui * notice appear in all copies.  The University of California
9b9325ec5Stsutsui * makes no representations about the suitability of this
10b9325ec5Stsutsui * software for any purpose.  It is provided "as is" without
11b9325ec5Stsutsui * express or implied warranty.
12b9325ec5Stsutsui */
13b9325ec5Stsutsui
14b9325ec5Stsutsui/************************************************************
15b9325ec5StsutsuiCopyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
16b9325ec5Stsutsui
17b9325ec5Stsutsui                    All Rights Reserved
18b9325ec5Stsutsui
19b9325ec5StsutsuiPermission  to  use,  copy,  modify,  and  distribute   this
20b9325ec5Stsutsuisoftware  and  its documentation for any purpose and without
21b9325ec5Stsutsuifee is hereby granted, provided that the above copyright no-
22b9325ec5Stsutsuitice  appear  in all copies and that both that copyright no-
23b9325ec5Stsutsuitice and this permission notice appear in  supporting  docu-
24b9325ec5Stsutsuimentation,  and  that the names of Sun or The Open Group
25b9325ec5Stsutsuinot be used in advertising or publicity pertaining to
26b9325ec5Stsutsuidistribution  of  the software  without specific prior
27b9325ec5Stsutsuiwritten permission. Sun and The Open Group make no
28b9325ec5Stsutsuirepresentations about the suitability of this software for
29b9325ec5Stsutsuiany purpose. It is provided "as is" without any express or
30b9325ec5Stsutsuiimplied warranty.
31b9325ec5Stsutsui
32b9325ec5StsutsuiSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
33b9325ec5StsutsuiINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
34b9325ec5StsutsuiNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
35b9325ec5StsutsuiABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
36b9325ec5StsutsuiANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
37b9325ec5StsutsuiPROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
38b9325ec5StsutsuiOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
39b9325ec5StsutsuiTHE USE OR PERFORMANCE OF THIS SOFTWARE.
40b9325ec5Stsutsui
41b9325ec5Stsutsui********************************************************/
42b9325ec5Stsutsui/* $XFree86: xc/programs/Xserver/hw/sun/sunKbd.c,v 1.9 2003/11/17 22:20:36 dawes Exp $ */
43b9325ec5Stsutsui
44b9325ec5Stsutsui#define NEED_EVENTS
45b9325ec5Stsutsui#include "sun.h"
46b9325ec5Stsutsui#include <X11/keysym.h>
47b9325ec5Stsutsui#include <X11/Sunkeysym.h>
48b9325ec5Stsutsui#include "mi.h"
49b9325ec5Stsutsui
50b9325ec5Stsutsui#include <X11/extensions/XKB.h>
51b9325ec5Stsutsui#include "xkbsrv.h"
52b9325ec5Stsutsui#include "xkbstr.h"
53b9325ec5Stsutsui
54cb17d216Stsutsui#ifdef __sun
55b9325ec5Stsutsui#define SUN_LED_MASK	0x0f
56cb17d216Stsutsui#else
57cb17d216Stsutsui#define SUN_LED_MASK	0x07
58cb17d216Stsutsui#endif
59b9325ec5Stsutsui#define MIN_KEYCODE	7	/* necessary to avoid the mouse buttons */
60b9325ec5Stsutsui#define MAX_KEYCODE	255	/* limited by the protocol */
61cb17d216Stsutsui#define NUM_KEYCODES	(MAX_KEYCODE - MIN_KEYCODE + 1)
62b9325ec5Stsutsui#ifndef KB_SUN4
63b9325ec5Stsutsui#define KB_SUN4		4
64b9325ec5Stsutsui#endif
65b9325ec5Stsutsui
66cb17d216Stsutsui#define Meta_Mask	Mod1Mask
67cb17d216Stsutsui#define Mode_switch_Mask Mod2Mask
68cb17d216Stsutsui#define Alt_Mask	Mod3Mask
69cb17d216Stsutsui#define Num_Lock_Mask	Mod4Mask
70cb17d216Stsutsui#define ScrollLockMask	Mod5Mask
71cb17d216Stsutsui
72b9325ec5Stsutsui#define tvminus(tv, tv1, tv2)   /* tv = tv1 - tv2 */ \
73b9325ec5Stsutsui		if ((tv1).tv_usec < (tv2).tv_usec) { \
74b9325ec5Stsutsui		    (tv1).tv_usec += 1000000; \
75b9325ec5Stsutsui		    (tv1).tv_sec -= 1; \
76b9325ec5Stsutsui		} \
77b9325ec5Stsutsui		(tv).tv_usec = (tv1).tv_usec - (tv2).tv_usec; \
78b9325ec5Stsutsui		(tv).tv_sec = (tv1).tv_sec - (tv2).tv_sec;
79b9325ec5Stsutsui
80b9325ec5Stsutsui#define tvplus(tv, tv1, tv2)    /* tv = tv1 + tv2 */ \
81b9325ec5Stsutsui		(tv).tv_sec = (tv1).tv_sec + (tv2).tv_sec; \
82b9325ec5Stsutsui		(tv).tv_usec = (tv1).tv_usec + (tv2).tv_usec; \
83b9325ec5Stsutsui		if ((tv).tv_usec > 1000000) { \
84b9325ec5Stsutsui		    (tv).tv_usec -= 1000000; \
85b9325ec5Stsutsui		    (tv).tv_sec += 1; \
86b9325ec5Stsutsui		}
87b9325ec5Stsutsui
88cb17d216Stsutsuistatic void sunInitModMap(const KeySymsRec *, CARD8 *);
89b9325ec5Stsutsuistatic void SwapLKeys(KeySymsRec *);
90b9325ec5Stsutsuistatic void SetLights(KeybdCtrl *, int);
91b9325ec5Stsutsuistatic KeyCode LookupKeyCode(KeySym, XkbDescPtr, KeySymsPtr);
92b9325ec5Stsutsuistatic void pseudoKey(DeviceIntPtr, Bool, KeyCode);
93b9325ec5Stsutsuistatic void DoLEDs(DeviceIntPtr, KeybdCtrl *, sunKbdPrivPtr);
94b9325ec5Stsutsui
95b9325ec5StsutsuiDeviceIntPtr	sunKeyboardDevice = NULL;
96b9325ec5Stsutsui
97b9325ec5Stsutsuivoid
98b9325ec5StsutsuisunKbdWait(void)
99b9325ec5Stsutsui{
100b9325ec5Stsutsui    static struct timeval lastChngKbdTransTv;
101b9325ec5Stsutsui    struct timeval tv;
102b9325ec5Stsutsui    struct timeval lastChngKbdDeltaTv;
103b9325ec5Stsutsui    unsigned int lastChngKbdDelta;
104b9325ec5Stsutsui
105b9325ec5Stsutsui    X_GETTIMEOFDAY(&tv);
106b9325ec5Stsutsui    if (!lastChngKbdTransTv.tv_sec)
107b9325ec5Stsutsui	lastChngKbdTransTv = tv;
108b9325ec5Stsutsui    tvminus(lastChngKbdDeltaTv, tv, lastChngKbdTransTv);
109b9325ec5Stsutsui    lastChngKbdDelta = TVTOMILLI(lastChngKbdDeltaTv);
110b9325ec5Stsutsui    if (lastChngKbdDelta < 750) {
111b9325ec5Stsutsui	unsigned wait;
112b9325ec5Stsutsui	/*
113b9325ec5Stsutsui         * We need to guarantee at least 750 milliseconds between
114b9325ec5Stsutsui	 * calls to KIOCTRANS. YUCK!
115b9325ec5Stsutsui	 */
116b9325ec5Stsutsui	wait = (750L - lastChngKbdDelta) * 1000L;
117b9325ec5Stsutsui        usleep (wait);
118b9325ec5Stsutsui        X_GETTIMEOFDAY(&tv);
119b9325ec5Stsutsui    }
120b9325ec5Stsutsui    lastChngKbdTransTv = tv;
121b9325ec5Stsutsui}
122b9325ec5Stsutsui
123b9325ec5Stsutsuistatic
124b9325ec5Stsutsuivoid SwapLKeys(KeySymsRec* keysyms)
125b9325ec5Stsutsui{
126b9325ec5Stsutsui    unsigned int i;
127b9325ec5Stsutsui    KeySym k;
128b9325ec5Stsutsui
129b9325ec5Stsutsui    for (i = 2; i < keysyms->maxKeyCode * keysyms->mapWidth; i++)
130b9325ec5Stsutsui	if (keysyms->map[i] == XK_L1 ||
131b9325ec5Stsutsui	    keysyms->map[i] == XK_L2 ||
132b9325ec5Stsutsui	    keysyms->map[i] == XK_L3 ||
133b9325ec5Stsutsui	    keysyms->map[i] == XK_L4 ||
134b9325ec5Stsutsui	    keysyms->map[i] == XK_L5 ||
135b9325ec5Stsutsui	    keysyms->map[i] == XK_L6 ||
136b9325ec5Stsutsui	    keysyms->map[i] == XK_L7 ||
137b9325ec5Stsutsui	    keysyms->map[i] == XK_L8 ||
138b9325ec5Stsutsui	    keysyms->map[i] == XK_L9 ||
139b9325ec5Stsutsui	    keysyms->map[i] == XK_L10) {
140b9325ec5Stsutsui	    /* yes, I could have done a clever two line swap! */
141b9325ec5Stsutsui	    k = keysyms->map[i - 2];
142b9325ec5Stsutsui	    keysyms->map[i - 2] = keysyms->map[i];
143b9325ec5Stsutsui	    keysyms->map[i] = k;
144b9325ec5Stsutsui	}
145b9325ec5Stsutsui}
146b9325ec5Stsutsui
147b9325ec5Stsutsuistatic void
148b9325ec5StsutsuiSetLights(KeybdCtrl* ctrl, int fd)
149b9325ec5Stsutsui{
150b9325ec5Stsutsui#ifdef KIOCSLED
151b9325ec5Stsutsui    static unsigned char led_tab[16] = {
152b9325ec5Stsutsui	0,
153cb17d216Stsutsui#ifdef __sun
154b9325ec5Stsutsui	LED_NUM_LOCK,
155b9325ec5Stsutsui	LED_SCROLL_LOCK,
156b9325ec5Stsutsui	LED_SCROLL_LOCK | LED_NUM_LOCK,
157b9325ec5Stsutsui	LED_COMPOSE,
158b9325ec5Stsutsui	LED_COMPOSE | LED_NUM_LOCK,
159b9325ec5Stsutsui	LED_COMPOSE | LED_SCROLL_LOCK,
160b9325ec5Stsutsui	LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK,
161b9325ec5Stsutsui	LED_CAPS_LOCK,
162b9325ec5Stsutsui	LED_CAPS_LOCK | LED_NUM_LOCK,
163b9325ec5Stsutsui	LED_CAPS_LOCK | LED_SCROLL_LOCK,
164b9325ec5Stsutsui	LED_CAPS_LOCK | LED_SCROLL_LOCK | LED_NUM_LOCK,
165b9325ec5Stsutsui	LED_CAPS_LOCK | LED_COMPOSE,
166b9325ec5Stsutsui	LED_CAPS_LOCK | LED_COMPOSE | LED_NUM_LOCK,
167b9325ec5Stsutsui	LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK,
168b9325ec5Stsutsui	LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK
169cb17d216Stsutsui#else
170cb17d216Stsutsui	LED_CAPS_LOCK,
171cb17d216Stsutsui	LED_NUM_LOCK,
172cb17d216Stsutsui	LED_NUM_LOCK | LED_CAPS_LOCK,
173cb17d216Stsutsui	LED_SCROLL_LOCK,
174cb17d216Stsutsui	LED_SCROLL_LOCK | LED_CAPS_LOCK,
175cb17d216Stsutsui	LED_SCROLL_LOCK | LED_NUM_LOCK,
176cb17d216Stsutsui	LED_SCROLL_LOCK | LED_NUM_LOCK | LED_CAPS_LOCK,
177cb17d216Stsutsui	LED_COMPOSE,
178cb17d216Stsutsui	LED_COMPOSE | LED_CAPS_LOCK,
179cb17d216Stsutsui	LED_COMPOSE | LED_NUM_LOCK,
180cb17d216Stsutsui	LED_COMPOSE | LED_NUM_LOCK | LED_CAPS_LOCK,
181cb17d216Stsutsui	LED_COMPOSE | LED_SCROLL_LOCK,
182cb17d216Stsutsui	LED_COMPOSE | LED_SCROLL_LOCK | LED_CAPS_LOCK,
183cb17d216Stsutsui	LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK,
184cb17d216Stsutsui	LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK | LED_CAPS_LOCK,
185cb17d216Stsutsui#endif
186b9325ec5Stsutsui    };
187cb17d216Stsutsui    if (ioctl (fd, KIOCSLED, (caddr_t)&led_tab[ctrl->leds & SUN_LED_MASK]) == -1)
188cb17d216Stsutsui	ErrorF("Failed to set keyboard lights");
189b9325ec5Stsutsui#endif
190b9325ec5Stsutsui}
191b9325ec5Stsutsui
192b9325ec5Stsutsui
193b9325ec5Stsutsui/*-
194b9325ec5Stsutsui *-----------------------------------------------------------------------
195b9325ec5Stsutsui * sunBell --
196b9325ec5Stsutsui *	Ring the terminal/keyboard bell
197b9325ec5Stsutsui *
198b9325ec5Stsutsui * Results:
199b9325ec5Stsutsui *	Ring the keyboard bell for an amount of time proportional to
200b9325ec5Stsutsui *	"loudness."
201b9325ec5Stsutsui *
202b9325ec5Stsutsui * Side Effects:
203b9325ec5Stsutsui *	None, really...
204b9325ec5Stsutsui *
205b9325ec5Stsutsui *-----------------------------------------------------------------------
206b9325ec5Stsutsui */
207b9325ec5Stsutsui
208b9325ec5Stsutsuistatic void
209b9325ec5Stsutsuibell(int fd, int duration)
210b9325ec5Stsutsui{
211b9325ec5Stsutsui    int		    kbdCmd;   	    /* Command to give keyboard */
212b9325ec5Stsutsui
213b9325ec5Stsutsui    kbdCmd = KBD_CMD_BELL;
214b9325ec5Stsutsui    if (ioctl (fd, KIOCCMD, &kbdCmd) == -1) {
215b9325ec5Stsutsui 	Error("Failed to activate bell");
216b9325ec5Stsutsui	return;
217b9325ec5Stsutsui    }
218b9325ec5Stsutsui    if (duration) usleep (duration);
219b9325ec5Stsutsui    kbdCmd = KBD_CMD_NOBELL;
220b9325ec5Stsutsui    if (ioctl (fd, KIOCCMD, &kbdCmd) == -1)
221b9325ec5Stsutsui	Error ("Failed to deactivate bell");
222b9325ec5Stsutsui}
223b9325ec5Stsutsui
224b9325ec5Stsutsuistatic void
225b9325ec5StsutsuisunBell(int percent, DeviceIntPtr device, pointer ctrl, int unused)
226b9325ec5Stsutsui{
227b9325ec5Stsutsui    KeybdCtrl*      kctrl = (KeybdCtrl*) ctrl;
228b9325ec5Stsutsui    sunKbdPrivPtr   pPriv = (sunKbdPrivPtr) device->public.devicePrivate;
229b9325ec5Stsutsui
230b9325ec5Stsutsui    if (percent == 0 || kctrl->bell == 0)
231b9325ec5Stsutsui 	return;
232b9325ec5Stsutsui
233b9325ec5Stsutsui    bell (pPriv->fd, kctrl->bell_duration * 1000);
234b9325ec5Stsutsui}
235b9325ec5Stsutsui
236b9325ec5Stsutsuivoid
237b9325ec5StsutsuiDDXRingBell(int volume, int pitch, int duration)
238b9325ec5Stsutsui{
239b9325ec5Stsutsui    DeviceIntPtr pKeyboard;
240b9325ec5Stsutsui    sunKbdPrivPtr pPriv;
241b9325ec5Stsutsui
242b9325ec5Stsutsui    pKeyboard = sunKeyboardDevice;
243b9325ec5Stsutsui    if (pKeyboard != NULL) {
244b9325ec5Stsutsui	pPriv = (sunKbdPrivPtr)pKeyboard->public.devicePrivate;
245b9325ec5Stsutsui	bell(pPriv->fd, duration * 1000);
246b9325ec5Stsutsui    }
247b9325ec5Stsutsui}
248b9325ec5Stsutsui
249b9325ec5Stsutsui
250cb17d216Stsutsui#ifdef __sun
251b9325ec5Stsutsui#define XLED_NUM_LOCK    0x1
252b9325ec5Stsutsui#define XLED_COMPOSE     0x4
253b9325ec5Stsutsui#define XLED_SCROLL_LOCK 0x2
254b9325ec5Stsutsui#define XLED_CAPS_LOCK   0x8
255cb17d216Stsutsui#else
256cb17d216Stsutsui#define XLED_NUM_LOCK    0x2
257cb17d216Stsutsui#define XLED_COMPOSE     0x8
258cb17d216Stsutsui#define XLED_SCROLL_LOCK 0x4
259cb17d216Stsutsui#define XLED_CAPS_LOCK   0x1
260cb17d216Stsutsui#endif
261b9325ec5Stsutsui
262b9325ec5Stsutsuistatic KeyCode
263b9325ec5StsutsuiLookupKeyCode(KeySym keysym, XkbDescPtr xkb, KeySymsPtr syms)
264b9325ec5Stsutsui{
265b9325ec5Stsutsui    KeyCode i;
266b9325ec5Stsutsui    int ii, index = 0;
267b9325ec5Stsutsui
268b9325ec5Stsutsui    for (i = xkb->min_key_code; i < xkb->max_key_code; i++)
269b9325ec5Stsutsui	for (ii = 0; ii < syms->mapWidth; ii++)
270b9325ec5Stsutsui	    if (syms->map[index++] == keysym)
271b9325ec5Stsutsui		return i;
272b9325ec5Stsutsui    return 0;
273b9325ec5Stsutsui}
274b9325ec5Stsutsui
275b9325ec5Stsutsuistatic void
276b9325ec5StsutsuipseudoKey(DeviceIntPtr device, Bool down, KeyCode keycode)
277b9325ec5Stsutsui{
278b9325ec5Stsutsui    int bit;
279b9325ec5Stsutsui    CARD8 modifiers;
280b9325ec5Stsutsui    CARD16 mask;
281b9325ec5Stsutsui    BYTE* kptr;
282b9325ec5Stsutsui
283b9325ec5Stsutsui    kptr = &device->key->down[keycode >> 3];
284b9325ec5Stsutsui    bit = 1 << (keycode & 7);
285b9325ec5Stsutsui    modifiers = device->key->xkbInfo->desc->map->modmap[keycode];
286b9325ec5Stsutsui    if (down) {
287b9325ec5Stsutsui	/* fool dix into thinking this key is now "down" */
288b9325ec5Stsutsui	int i;
289b9325ec5Stsutsui	*kptr |= bit;
290b9325ec5Stsutsui	for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
291b9325ec5Stsutsui	    if (mask & modifiers) {
292b9325ec5Stsutsui		device->key->modifierKeyCount[i]++;
293b9325ec5Stsutsui		modifiers &= ~mask;
294b9325ec5Stsutsui	    }
295b9325ec5Stsutsui    } else {
296b9325ec5Stsutsui	/* fool dix into thinking this key is now "up" */
297b9325ec5Stsutsui	if (*kptr & bit) {
298b9325ec5Stsutsui	    int i;
299b9325ec5Stsutsui	    *kptr &= ~bit;
300b9325ec5Stsutsui	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
301b9325ec5Stsutsui		if (mask & modifiers) {
302b9325ec5Stsutsui		    if (--device->key->modifierKeyCount[i] <= 0) {
303b9325ec5Stsutsui			device->key->modifierKeyCount[i] = 0;
304b9325ec5Stsutsui		    }
305b9325ec5Stsutsui		    modifiers &= ~mask;
306b9325ec5Stsutsui		}
307b9325ec5Stsutsui	}
308b9325ec5Stsutsui    }
309b9325ec5Stsutsui}
310b9325ec5Stsutsui
311b9325ec5Stsutsuistatic void
312b9325ec5StsutsuiDoLEDs(
313b9325ec5Stsutsui    DeviceIntPtr    device,	    /* Keyboard to alter */
314b9325ec5Stsutsui    KeybdCtrl* ctrl,
315b9325ec5Stsutsui    sunKbdPrivPtr pPriv
316b9325ec5Stsutsui)
317b9325ec5Stsutsui{
318b9325ec5Stsutsui    XkbDescPtr xkb;
319b9325ec5Stsutsui    KeySymsPtr syms;
320b9325ec5Stsutsui
321b9325ec5Stsutsui    xkb = device->key->xkbInfo->desc;
322b9325ec5Stsutsui    syms = XkbGetCoreMap(device);
323b9325ec5Stsutsui    if (!syms)
324b9325ec5Stsutsui	return;	/* XXX */
325b9325ec5Stsutsui
326b9325ec5Stsutsui    if ((ctrl->leds & XLED_CAPS_LOCK) && !(pPriv->leds & XLED_CAPS_LOCK))
327b9325ec5Stsutsui	    pseudoKey(device, TRUE,
328b9325ec5Stsutsui		LookupKeyCode(XK_Caps_Lock, xkb, syms));
329b9325ec5Stsutsui
330b9325ec5Stsutsui    if (!(ctrl->leds & XLED_CAPS_LOCK) && (pPriv->leds & XLED_CAPS_LOCK))
331b9325ec5Stsutsui	    pseudoKey(device, FALSE,
332b9325ec5Stsutsui		LookupKeyCode(XK_Caps_Lock, xkb, syms));
333b9325ec5Stsutsui
334b9325ec5Stsutsui    if ((ctrl->leds & XLED_NUM_LOCK) && !(pPriv->leds & XLED_NUM_LOCK))
335b9325ec5Stsutsui	    pseudoKey(device, TRUE,
336b9325ec5Stsutsui		LookupKeyCode(XK_Num_Lock, xkb, syms));
337b9325ec5Stsutsui
338b9325ec5Stsutsui    if (!(ctrl->leds & XLED_NUM_LOCK) && (pPriv->leds & XLED_NUM_LOCK))
339b9325ec5Stsutsui	    pseudoKey(device, FALSE,
340b9325ec5Stsutsui		LookupKeyCode(XK_Num_Lock, xkb, syms));
341b9325ec5Stsutsui
342b9325ec5Stsutsui    if ((ctrl->leds & XLED_SCROLL_LOCK) && !(pPriv->leds & XLED_SCROLL_LOCK))
343b9325ec5Stsutsui	    pseudoKey(device, TRUE,
344b9325ec5Stsutsui		LookupKeyCode(XK_Scroll_Lock, xkb, syms));
345b9325ec5Stsutsui
346b9325ec5Stsutsui    if (!(ctrl->leds & XLED_SCROLL_LOCK) && (pPriv->leds & XLED_SCROLL_LOCK))
347b9325ec5Stsutsui	    pseudoKey(device, FALSE,
348b9325ec5Stsutsui		LookupKeyCode(XK_Scroll_Lock, xkb, syms));
349b9325ec5Stsutsui
350b9325ec5Stsutsui    if ((ctrl->leds & XLED_COMPOSE) && !(pPriv->leds & XLED_COMPOSE))
351b9325ec5Stsutsui	    pseudoKey(device, TRUE,
352b9325ec5Stsutsui		LookupKeyCode(SunXK_Compose, xkb, syms));
353b9325ec5Stsutsui
354b9325ec5Stsutsui    if (!(ctrl->leds & XLED_COMPOSE) && (pPriv->leds & XLED_COMPOSE))
355b9325ec5Stsutsui	    pseudoKey(device, FALSE,
356b9325ec5Stsutsui		LookupKeyCode(SunXK_Compose, xkb, syms));
357b9325ec5Stsutsui
358cb17d216Stsutsui    pPriv->leds = ctrl->leds & SUN_LED_MASK;
359b9325ec5Stsutsui    SetLights (ctrl, pPriv->fd);
360b9325ec5Stsutsui    xfree(syms->map);
361b9325ec5Stsutsui    xfree(syms);
362b9325ec5Stsutsui}
363b9325ec5Stsutsui
364b9325ec5Stsutsui/*-
365b9325ec5Stsutsui *-----------------------------------------------------------------------
366b9325ec5Stsutsui * sunKbdCtrl --
367b9325ec5Stsutsui *	Alter some of the keyboard control parameters
368b9325ec5Stsutsui *
369b9325ec5Stsutsui * Results:
370b9325ec5Stsutsui *	None.
371b9325ec5Stsutsui *
372b9325ec5Stsutsui * Side Effects:
373b9325ec5Stsutsui *	Some...
374b9325ec5Stsutsui *
375b9325ec5Stsutsui *-----------------------------------------------------------------------
376b9325ec5Stsutsui */
377b9325ec5Stsutsui
378b9325ec5Stsutsuistatic void
379b9325ec5StsutsuisunKbdCtrl(DeviceIntPtr device, KeybdCtrl* ctrl)
380b9325ec5Stsutsui{
381b9325ec5Stsutsui    sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate;
382b9325ec5Stsutsui
383b9325ec5Stsutsui    if (pPriv->fd < 0) return;
384b9325ec5Stsutsui
385b9325ec5Stsutsui    if (ctrl->click != pPriv->click) {
386b9325ec5Stsutsui    	int kbdClickCmd;
387b9325ec5Stsutsui
388b9325ec5Stsutsui	pPriv->click = ctrl->click;
389b9325ec5Stsutsui	kbdClickCmd = pPriv->click ? KBD_CMD_CLICK : KBD_CMD_NOCLICK;
390b9325ec5Stsutsui    	if (ioctl (pPriv->fd, KIOCCMD, &kbdClickCmd) == -1)
391b9325ec5Stsutsui 	    Error("Failed to set keyclick");
392b9325ec5Stsutsui    }
393cb17d216Stsutsui    if ((pPriv->type == KB_SUN4) && (pPriv->leds != (ctrl->leds & SUN_LED_MASK)))
394b9325ec5Stsutsui	DoLEDs(device, ctrl, pPriv);
395b9325ec5Stsutsui}
396b9325ec5Stsutsui
397b9325ec5Stsutsui/*-
398b9325ec5Stsutsui *-----------------------------------------------------------------------
399b9325ec5Stsutsui * sunInitKbdNames --
400b9325ec5Stsutsui *	Handle the XKB initialization
401b9325ec5Stsutsui *
402b9325ec5Stsutsui * Results:
403b9325ec5Stsutsui *	None.
404b9325ec5Stsutsui *
405b9325ec5Stsutsui * Comments:
406b9325ec5Stsutsui *     This function needs considerable work, in conjunctions with
407b9325ec5Stsutsui *     the need to add geometry descriptions of Sun Keyboards.
408b9325ec5Stsutsui *     It would also be nice to have #defines for all the keyboard
409b9325ec5Stsutsui *     layouts so that we don't have to have these hard-coded
410b9325ec5Stsutsui *     numbers.
411b9325ec5Stsutsui *
412b9325ec5Stsutsui *-----------------------------------------------------------------------
413b9325ec5Stsutsui */
414b9325ec5Stsutsuistatic void
415b9325ec5StsutsuisunInitKbdNames(XkbRMLVOSet *rmlvo, sunKbdPrivPtr pKbd)
416b9325ec5Stsutsui{
417b9325ec5Stsutsui#if 0 /* XXX to be revisited later */
418b9325ec5Stsutsui#ifndef XKBBUFSIZE
419b9325ec5Stsutsui#define XKBBUFSIZE 64
420b9325ec5Stsutsui#endif
421b9325ec5Stsutsui    static char keycodesbuf[XKBBUFSIZE];
422b9325ec5Stsutsui    static char geometrybuf[XKBBUFSIZE];
423b9325ec5Stsutsui    static char  symbolsbuf[XKBBUFSIZE];
424b9325ec5Stsutsui
425b9325ec5Stsutsui    names->keymap = NULL;
426b9325ec5Stsutsui    names->compat = "compat/complete";
427b9325ec5Stsutsui    names->types  = "types/complete";
428b9325ec5Stsutsui    names->keycodes = keycodesbuf;
429b9325ec5Stsutsui    names->geometry = geometrybuf;
430b9325ec5Stsutsui    names->symbols = symbolsbuf;
431b9325ec5Stsutsui    (void) strcpy (keycodesbuf, "keycodes/");
432b9325ec5Stsutsui    (void) strcpy (geometrybuf, "geometry/");
433b9325ec5Stsutsui    (void) strcpy (symbolsbuf, "symbols/");
434b9325ec5Stsutsui
435b9325ec5Stsutsui    /* keycodes & geometry */
436b9325ec5Stsutsui    switch (pKbd->type) {
437b9325ec5Stsutsui    case KB_SUN2:
438b9325ec5Stsutsui	(void) strcat (names->keycodes, "sun(type2)");
439b9325ec5Stsutsui	(void) strcat (names->geometry, "sun(type2)");
440b9325ec5Stsutsui	(void) strcat (names->symbols, "us(sun2)");
441b9325ec5Stsutsui	break;
442b9325ec5Stsutsui    case KB_SUN3:
443b9325ec5Stsutsui	(void) strcat (names->keycodes, "sun(type3)");
444b9325ec5Stsutsui	(void) strcat (names->geometry, "sun(type3)");
445b9325ec5Stsutsui	(void) strcat (names->symbols, "us(sun3)");
446b9325ec5Stsutsui	break;
447b9325ec5Stsutsui    case KB_SUN4:
448b9325ec5Stsutsui	/* First, catch "fully known" models */
449b9325ec5Stsutsui	switch (pKbd->layout) {
450b9325ec5Stsutsui	case 11:		/* type4, Sweden */
451b9325ec5Stsutsui	    (void) strcat (names->geometry, "sun(type4_se)");
452b9325ec5Stsutsui	    (void) strcat (names->keycodes,
453b9325ec5Stsutsui			   "sun(type4_se_swapctl)");
454b9325ec5Stsutsui	    (void) strcat (names->symbols,
455b9325ec5Stsutsui			   "sun/se(sun4)+se(fixdollar)");
456b9325ec5Stsutsui	    return;
457b9325ec5Stsutsui	    break;
458b9325ec5Stsutsui	case 43:		/* type5/5c, Sweden */
459b9325ec5Stsutsui	    (void) strcat (names->geometry, "sun(type5c_se)");
460b9325ec5Stsutsui	    (void) strcat (names->keycodes, "sun(type5_se)");
461b9325ec5Stsutsui	    (void) strcat (names->symbols,
462b9325ec5Stsutsui			   "sun/se(sun5)+se(fixdollar)");
463b9325ec5Stsutsui	    return;
464b9325ec5Stsutsui	    break;
465b9325ec5Stsutsui	case 90:		/* "Compact 1", Sweden (???) */
466b9325ec5Stsutsui	    break;		/* No specific mapping, yet */
467b9325ec5Stsutsui	default:
468b9325ec5Stsutsui	    break;
469b9325ec5Stsutsui	}
470b9325ec5Stsutsui
471b9325ec5Stsutsui	if (pKbd->layout == 19) {
472b9325ec5Stsutsui	    (void) strcat (names->keycodes, "sun(US101A)");
473b9325ec5Stsutsui	    (void) strcat (names->geometry, "pc101-NG"); /* XXX */
474b9325ec5Stsutsui	    (void) strcat (names->symbols, "us(pc101)");
475b9325ec5Stsutsui	} else if (pKbd->layout < 33) {
476b9325ec5Stsutsui	    (void) strcat (names->keycodes, "sun(type4)");
477b9325ec5Stsutsui	    (void) strcat (names->geometry, "sun(type4)");
478b9325ec5Stsutsui	    if (sunSwapLkeys)
479b9325ec5Stsutsui		(void) strcat (names->symbols, "sun/us(sun4ol)");
480b9325ec5Stsutsui	    else
481b9325ec5Stsutsui		(void) strcat (names->symbols, "sun/us(sun4)");
482b9325ec5Stsutsui	} else {
483b9325ec5Stsutsui	    switch (pKbd->layout) {
484b9325ec5Stsutsui	    case 33: case 80: /* U.S. */
485b9325ec5Stsutsui	    case 47: case 94: /* Korea */
486b9325ec5Stsutsui	    case 48: case 95: /* Taiwan */
487b9325ec5Stsutsui	    case 49: case 96: /* Japan */
488b9325ec5Stsutsui		(void) strcat (names->keycodes, "sun(type5)");
489b9325ec5Stsutsui		(void) strcat (names->geometry, "sun(type5)");
490b9325ec5Stsutsui		break;
491b9325ec5Stsutsui	    case 34: case 81: /* U.S. Unix */
492b9325ec5Stsutsui		(void) strcat (names->keycodes, "sun(type5)");
493b9325ec5Stsutsui		(void) strcat (names->geometry, "sun(type5unix)");
494b9325ec5Stsutsui		break;
495b9325ec5Stsutsui	    default:
496b9325ec5Stsutsui		(void) strcat (names->keycodes, "sun(type5_euro)");
497b9325ec5Stsutsui		(void) strcat (names->geometry, "sun(type5euro)");
498b9325ec5Stsutsui	    }
499b9325ec5Stsutsui
500b9325ec5Stsutsui	    if (sunSwapLkeys)
501b9325ec5Stsutsui		(void) strcat (names->symbols, "sun/us(sun5ol)");
502b9325ec5Stsutsui	    else
503b9325ec5Stsutsui		(void) strcat (names->symbols, "sun/us(sun5)");
504b9325ec5Stsutsui	}
505b9325ec5Stsutsui	break;
506b9325ec5Stsutsui    default:
507b9325ec5Stsutsui	names->keycodes = names->geometry = NULL;
508b9325ec5Stsutsui	break;
509b9325ec5Stsutsui    }
510b9325ec5Stsutsui
511b9325ec5Stsutsui    /* extra symbols */
512b9325ec5Stsutsui
513b9325ec5Stsutsui    if (pKbd->type == KB_SUN4) {
514b9325ec5Stsutsui	switch (pKbd->layout) {
515b9325ec5Stsutsui	case  4: case 36: case 83:
516b9325ec5Stsutsui	case  5: case 37: case 84:
517b9325ec5Stsutsui	case  6: case 38: case 85:
518b9325ec5Stsutsui	case  8: case 40: case 87:
519b9325ec5Stsutsui	case  9: case 41: case 88:
520b9325ec5Stsutsui	case 10: case 42: case 89:
521b9325ec5Stsutsui/*	case 11: case 43: case 90: */ /* handled earlier */
522b9325ec5Stsutsui	case 12: case 44: case 91:
523b9325ec5Stsutsui	case 13: case 45: case 92:
524b9325ec5Stsutsui	case 14: case 46: case 93:
525b9325ec5Stsutsui	    (void) strcat (names->symbols, "+iso9995-3(basic)"); break;
526b9325ec5Stsutsui	}
527b9325ec5Stsutsui    }
528b9325ec5Stsutsui
529b9325ec5Stsutsui    if (pKbd->type == KB_SUN4) {
530b9325ec5Stsutsui	switch (pKbd->layout) {
531b9325ec5Stsutsui	case  0: case  1: case 33: case 34: case 80: case 81:
532b9325ec5Stsutsui	    break;
533b9325ec5Stsutsui	case  3:
534b9325ec5Stsutsui	    (void) strcat (names->symbols, "+ca"); break;
535b9325ec5Stsutsui	case  4: case 36: case 83:
536b9325ec5Stsutsui	    (void) strcat (names->symbols, "+dk"); break;
537b9325ec5Stsutsui	case  5: case 37: case 84:
538b9325ec5Stsutsui	    (void) strcat (names->symbols, "+de"); break;
539b9325ec5Stsutsui	case  6: case 38: case 85:
540b9325ec5Stsutsui	    (void) strcat (names->symbols, "+it"); break;
541b9325ec5Stsutsui	case  8: case 40: case 87:
542b9325ec5Stsutsui	    (void) strcat (names->symbols, "+no"); break;
543b9325ec5Stsutsui	case  9: case 41: case 88:
544b9325ec5Stsutsui	    (void) strcat (names->symbols, "+pt"); break;
545b9325ec5Stsutsui	case 10: case 42: case 89:
546b9325ec5Stsutsui	    (void) strcat (names->symbols, "+es"); break;
547b9325ec5Stsutsui	    /* case 11: case 43: */ /* handled earlier */
548b9325ec5Stsutsui	case 90:
549b9325ec5Stsutsui	    (void) strcat (names->symbols, "+se"); break;
550b9325ec5Stsutsui	case 12: case 44: case 91:
551b9325ec5Stsutsui	    (void) strcat (names->symbols, "+fr_CH"); break;
552b9325ec5Stsutsui	case 13: case 45: case 92:
553b9325ec5Stsutsui	    (void) strcat (names->symbols, "+de_CH"); break;
554b9325ec5Stsutsui	case 14: case 46: case 93:
555b9325ec5Stsutsui	    (void) strcat (names->symbols, "+gb"); break; /* s/b en_UK */
556b9325ec5Stsutsui	case 52:
557b9325ec5Stsutsui	    (void) strcat (names->symbols, "+pl"); break;
558b9325ec5Stsutsui	case 53:
559b9325ec5Stsutsui	    (void) strcat (names->symbols, "+cs"); break;
560b9325ec5Stsutsui	case 54:
561b9325ec5Stsutsui	    (void) strcat (names->symbols, "+ru"); break;
562b9325ec5Stsutsui#if 0
563b9325ec5Stsutsui	/* don't have symbols defined for these yet, let them default */
564b9325ec5Stsutsui	case  2:
565b9325ec5Stsutsui	    (void) strcat (names->symbols, "+fr_BE"); break;
566b9325ec5Stsutsui	case  7: case 39: case 86:
567b9325ec5Stsutsui	    (void) strcat (names->symbols, "+nl"); break;
568b9325ec5Stsutsui	case 50: case 97:
569b9325ec5Stsutsui	    (void) strcat (names->symbols, "+fr_CA"); break;
570b9325ec5Stsutsui	case 16: case 47: case 94:
571b9325ec5Stsutsui	    (void) strcat (names->symbols, "+ko"); break;
572b9325ec5Stsutsui	case 17: case 48: case 95:
573b9325ec5Stsutsui	    (void) strcat (names->symbols, "+tw"); break;
574b9325ec5Stsutsui	case 32: case 49: case 96:
575b9325ec5Stsutsui	    (void) strcat (names->symbols, "+jp"); break;
576b9325ec5Stsutsui	case 51:
577b9325ec5Stsutsui	    (void) strcat (names->symbols, "+hu"); break;
578b9325ec5Stsutsui#endif
579b9325ec5Stsutsui	/*
580b9325ec5Stsutsui	 * by setting the symbols to NULL XKB will use the symbols in
581b9325ec5Stsutsui	 * the "default" keymap.
582b9325ec5Stsutsui	 */
583b9325ec5Stsutsui	default:
584b9325ec5Stsutsui	    names->symbols = NULL; return; break;
585b9325ec5Stsutsui	}
586b9325ec5Stsutsui    }
587b9325ec5Stsutsui#else
588b9325ec5Stsutsui    rmlvo->rules = "base";
589cb17d216Stsutsui    rmlvo->model = "empty";
590cb17d216Stsutsui    rmlvo->layout = "empty";
591b9325ec5Stsutsui    rmlvo->variant = NULL;
592b9325ec5Stsutsui    rmlvo->options = NULL;
593b9325ec5Stsutsui#endif
594b9325ec5Stsutsui}
595b9325ec5Stsutsui
596b9325ec5Stsutsui/*-
597b9325ec5Stsutsui *-----------------------------------------------------------------------
598b9325ec5Stsutsui * sunKbdProc --
599b9325ec5Stsutsui *	Handle the initialization, etc. of a keyboard.
600b9325ec5Stsutsui *
601b9325ec5Stsutsui * Results:
602b9325ec5Stsutsui *	None.
603b9325ec5Stsutsui *
604b9325ec5Stsutsui *-----------------------------------------------------------------------
605b9325ec5Stsutsui */
606b9325ec5Stsutsui
607b9325ec5Stsutsuiint
608b9325ec5StsutsuisunKbdProc(DeviceIntPtr device, int what)
609b9325ec5Stsutsui{
61085d6961bStsutsui    DevicePtr pKeyboard = &device->public;
611b9325ec5Stsutsui    sunKbdPrivPtr pPriv;
612b9325ec5Stsutsui    KeybdCtrl*	ctrl = &device->kbdfeed->ctrl;
613b9325ec5Stsutsui    XkbRMLVOSet rmlvo;
614cb17d216Stsutsui    CARD8 workingModMap[MAP_LENGTH];
615b9325ec5Stsutsui
616b9325ec5Stsutsui    static KeySymsRec *workingKeySyms;
617b9325ec5Stsutsui
618b9325ec5Stsutsui    switch (what) {
619b9325ec5Stsutsui    case DEVICE_INIT:
62085d6961bStsutsui	if (pKeyboard != &sunKeyboardDevice->public) {
621b9325ec5Stsutsui	    ErrorF ("Cannot open non-system keyboard\n");
622b9325ec5Stsutsui	    return (!Success);
623b9325ec5Stsutsui	}
624b9325ec5Stsutsui
625b9325ec5Stsutsui	if (!workingKeySyms) {
626b9325ec5Stsutsui	    workingKeySyms = &sunKeySyms[sunKbdPriv.type];
627b9325ec5Stsutsui
628b9325ec5Stsutsui	    if (sunKbdPriv.type == KB_SUN4 && sunSwapLkeys)
629b9325ec5Stsutsui		SwapLKeys(workingKeySyms);
630b9325ec5Stsutsui
631b9325ec5Stsutsui	    if (workingKeySyms->minKeyCode < MIN_KEYCODE) {
632b9325ec5Stsutsui		workingKeySyms->minKeyCode += MIN_KEYCODE;
633b9325ec5Stsutsui		workingKeySyms->maxKeyCode += MIN_KEYCODE;
634b9325ec5Stsutsui	    }
635b9325ec5Stsutsui	    if (workingKeySyms->maxKeyCode > MAX_KEYCODE)
636b9325ec5Stsutsui		workingKeySyms->maxKeyCode = MAX_KEYCODE;
637b9325ec5Stsutsui
638cb17d216Stsutsui	    sunInitModMap(workingKeySyms, workingModMap);
639b9325ec5Stsutsui	}
640b9325ec5Stsutsui
641b9325ec5Stsutsui	pKeyboard->devicePrivate = (pointer)&sunKbdPriv;
642b9325ec5Stsutsui	pKeyboard->on = FALSE;
643b9325ec5Stsutsui
644b9325ec5Stsutsui	sunInitKbdNames(&rmlvo, pKeyboard->devicePrivate);
645b9325ec5Stsutsui#if 0 /* XXX needs more work for Xorg xkb */
646cb17d216Stsutsui	InitKeyboardDeviceStruct(device, &rmlvo,
647b9325ec5Stsutsui				 sunBell, sunKbdCtrl);
648b9325ec5Stsutsui#else
649cb17d216Stsutsui	XkbSetRulesDflts(&rmlvo);
650b9325ec5Stsutsui	InitKeyboardDeviceStruct(device, NULL,
651b9325ec5Stsutsui				 sunBell, sunKbdCtrl);
652b9325ec5Stsutsui	XkbApplyMappingChange(device, workingKeySyms,
653b9325ec5Stsutsui			      workingKeySyms->minKeyCode,
654b9325ec5Stsutsui			      workingKeySyms->maxKeyCode -
655b9325ec5Stsutsui			      workingKeySyms->minKeyCode + 1,
656b9325ec5Stsutsui			      workingModMap, serverClient);
657b9325ec5Stsutsui#endif
658b9325ec5Stsutsui	break;
659b9325ec5Stsutsui
660b9325ec5Stsutsui    case DEVICE_ON:
661b9325ec5Stsutsui	pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate;
662b9325ec5Stsutsui	/*
663b9325ec5Stsutsui	 * Set the keyboard into "direct" mode and turn on
664b9325ec5Stsutsui	 * event translation.
665b9325ec5Stsutsui	 */
666b9325ec5Stsutsui	if (sunChangeKbdTranslation(pPriv->fd,TRUE) == -1)
667b9325ec5Stsutsui	    FatalError("Can't set keyboard translation\n");
668b9325ec5Stsutsui	AddEnabledDevice(pPriv->fd);
669b9325ec5Stsutsui	pKeyboard->on = TRUE;
670b9325ec5Stsutsui	break;
671b9325ec5Stsutsui
672b9325ec5Stsutsui    case DEVICE_CLOSE:
673b9325ec5Stsutsui    case DEVICE_OFF:
674b9325ec5Stsutsui	pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate;
675b9325ec5Stsutsui	if (pPriv->type == KB_SUN4) {
676b9325ec5Stsutsui	    /* dumb bug in Sun's keyboard! Turn off LEDS before resetting */
677b9325ec5Stsutsui	    pPriv->leds = 0;
678b9325ec5Stsutsui	    ctrl->leds = 0;
679b9325ec5Stsutsui	    SetLights(ctrl, pPriv->fd);
680b9325ec5Stsutsui	}
681b9325ec5Stsutsui	/*
682b9325ec5Stsutsui	 * Restore original keyboard directness and translation.
683b9325ec5Stsutsui	 */
684b9325ec5Stsutsui	if (sunChangeKbdTranslation(pPriv->fd,FALSE) == -1)
685b9325ec5Stsutsui	    FatalError("Can't reset keyboard translation\n");
686b9325ec5Stsutsui	RemoveEnabledDevice(pPriv->fd);
687b9325ec5Stsutsui	pKeyboard->on = FALSE;
688b9325ec5Stsutsui	break;
689b9325ec5Stsutsui    default:
690b9325ec5Stsutsui	FatalError("Unknown keyboard operation\n");
691b9325ec5Stsutsui    }
692b9325ec5Stsutsui    return Success;
693b9325ec5Stsutsui}
694b9325ec5Stsutsui
695cb17d216Stsutsui/*-------------------------------------------------------------------------
696cb17d216Stsutsui * sunInitModMap --
697cb17d216Stsutsui *	Initialize ModMap per specified KeyMap table.
698cb17d216Stsutsui *
699cb17d216Stsutsui * Results:
700cb17d216Stsutsui * 	None.
701cb17d216Stsutsui *
702cb17d216Stsutsui * Side Effects:
703cb17d216Stsutsui *	None.
704cb17d216Stsutsui *-----------------------------------------------------------------------*/
705cb17d216Stsutsuistatic void
706cb17d216StsutsuisunInitModMap(
707cb17d216Stsutsui    const KeySymsRec *KeySyms,	/* KeyMap data to set ModMap */
708cb17d216Stsutsui    CARD8 *ModMap		/* ModMap to be initialized */
709cb17d216Stsutsui)
710cb17d216Stsutsui{
711cb17d216Stsutsui    KeySym *k;
712cb17d216Stsutsui    int i, min, max, width;
713cb17d216Stsutsui
714cb17d216Stsutsui    for (i = 0; i < MAP_LENGTH; i++)
715cb17d216Stsutsui        ModMap[i] = NoSymbol;
716cb17d216Stsutsui
717cb17d216Stsutsui    min   = KeySyms->minKeyCode;
718cb17d216Stsutsui    max   = KeySyms->maxKeyCode;
719cb17d216Stsutsui    width = KeySyms->mapWidth;
720cb17d216Stsutsui    for (i = min, k = KeySyms->map; i < max; i++, k += width) {
721cb17d216Stsutsui	switch (*k) {
722cb17d216Stsutsui
723cb17d216Stsutsui	case XK_Shift_L:
724cb17d216Stsutsui	case XK_Shift_R:
725cb17d216Stsutsui	    ModMap[i] = ShiftMask;
726cb17d216Stsutsui	    break;
727cb17d216Stsutsui
728cb17d216Stsutsui	case XK_Control_L:
729cb17d216Stsutsui	case XK_Control_R:
730cb17d216Stsutsui	    ModMap[i] = ControlMask;
731cb17d216Stsutsui	    break;
732cb17d216Stsutsui
733cb17d216Stsutsui	case XK_Caps_Lock:
734cb17d216Stsutsui	    ModMap[i] = LockMask;
735cb17d216Stsutsui	    break;
736cb17d216Stsutsui
737cb17d216Stsutsui	case XK_Alt_L:
738cb17d216Stsutsui	case XK_Alt_R:
739cb17d216Stsutsui	    ModMap[i] = Alt_Mask;
740cb17d216Stsutsui	    break;
741cb17d216Stsutsui
742cb17d216Stsutsui	case XK_Num_Lock:
743cb17d216Stsutsui	    ModMap[i] = Num_Lock_Mask;
744cb17d216Stsutsui	    break;
745cb17d216Stsutsui
746cb17d216Stsutsui	case XK_Scroll_Lock:
747cb17d216Stsutsui	    ModMap[i] = ScrollLockMask;
748cb17d216Stsutsui	    break;
749cb17d216Stsutsui
750cb17d216Stsutsui	case XK_Meta_L:
751cb17d216Stsutsui	case XK_Meta_R:
752cb17d216Stsutsui	    ModMap[i] = Meta_Mask;
753cb17d216Stsutsui	    break;
754cb17d216Stsutsui
755cb17d216Stsutsui	case SunXK_AltGraph:
756cb17d216Stsutsui	    ModMap[i] = Mode_switch_Mask;
757cb17d216Stsutsui	    break;
758cb17d216Stsutsui        }
759cb17d216Stsutsui    }
760cb17d216Stsutsui}
761cb17d216Stsutsui
762b9325ec5Stsutsui/*-
763b9325ec5Stsutsui *-----------------------------------------------------------------------
764b9325ec5Stsutsui * sunKbdGetEvents --
765b9325ec5Stsutsui *	Return the events waiting in the wings for the given keyboard.
766b9325ec5Stsutsui *
767b9325ec5Stsutsui * Results:
768b9325ec5Stsutsui *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
769b9325ec5Stsutsui *	The number of events contained in the array.
770b9325ec5Stsutsui *	A boolean as to whether more events might be available.
771b9325ec5Stsutsui *
772b9325ec5Stsutsui * Side Effects:
773b9325ec5Stsutsui *	None.
774b9325ec5Stsutsui *-----------------------------------------------------------------------
775b9325ec5Stsutsui */
776b9325ec5Stsutsui
777b9325ec5StsutsuiFirm_event *
778b9325ec5StsutsuisunKbdGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain)
779b9325ec5Stsutsui{
780b9325ec5Stsutsui    int	    	  nBytes;	    /* number of bytes of events available. */
781b9325ec5Stsutsui    static Firm_event	evBuf[MAXEVENTS];   /* Buffer for Firm_events */
782b9325ec5Stsutsui
783b9325ec5Stsutsui    if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) {
784b9325ec5Stsutsui	if (errno == EWOULDBLOCK) {
785b9325ec5Stsutsui	    *pNumEvents = 0;
786b9325ec5Stsutsui	    *pAgain = FALSE;
787b9325ec5Stsutsui	} else {
788b9325ec5Stsutsui	    Error ("Reading keyboard");
789b9325ec5Stsutsui	    FatalError ("Could not read the keyboard");
790b9325ec5Stsutsui	}
791b9325ec5Stsutsui    } else {
792b9325ec5Stsutsui	if (on) {
793b9325ec5Stsutsui	    *pNumEvents = nBytes / sizeof (Firm_event);
794b9325ec5Stsutsui	    *pAgain = (nBytes == sizeof (evBuf));
795b9325ec5Stsutsui	} else {
796b9325ec5Stsutsui	    *pNumEvents = 0;
797b9325ec5Stsutsui	    *pAgain = FALSE;
798b9325ec5Stsutsui	}
799b9325ec5Stsutsui    }
800b9325ec5Stsutsui    return evBuf;
801b9325ec5Stsutsui}
802b9325ec5Stsutsui
803b9325ec5Stsutsui/*-
804b9325ec5Stsutsui *-----------------------------------------------------------------------
805b9325ec5Stsutsui * sunKbdEnqueueEvent --
806b9325ec5Stsutsui *
807b9325ec5Stsutsui *-----------------------------------------------------------------------
808b9325ec5Stsutsui */
809b9325ec5Stsutsui
810b9325ec5Stsutsuivoid
811b9325ec5StsutsuisunKbdEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
812b9325ec5Stsutsui{
813b9325ec5Stsutsui    BYTE		keycode;
814b9325ec5Stsutsui    int			type;
815b9325ec5Stsutsui    int			i, nevents;
816b9325ec5Stsutsui
817b9325ec5Stsutsui    GetEventList(&sunEvents);
818b9325ec5Stsutsui    keycode = (fe->id & 0x7f) + MIN_KEYCODE;
819b9325ec5Stsutsui
820b9325ec5Stsutsui    type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
821b9325ec5Stsutsui    nevents = GetKeyboardEvents(sunEvents, device, type, keycode);
822b9325ec5Stsutsui    for (i = 0; i < nevents; i++)
823b9325ec5Stsutsui	mieqEnqueue(device, (InternalEvent *)(sunEvents + i)->event);
824b9325ec5Stsutsui}
825b9325ec5Stsutsui
826b9325ec5Stsutsui
827b9325ec5Stsutsui/*-
828b9325ec5Stsutsui *-----------------------------------------------------------------------
829b9325ec5Stsutsui * sunChangeKbdTranslation
830b9325ec5Stsutsui *	Makes operating system calls to set keyboard translation
831b9325ec5Stsutsui *	and direction on or off.
832b9325ec5Stsutsui *
833b9325ec5Stsutsui * Results:
834b9325ec5Stsutsui *	-1 if failure, else 0.
835b9325ec5Stsutsui *
836b9325ec5Stsutsui * Side Effects:
837b9325ec5Stsutsui * 	Changes kernel management of keyboard.
838b9325ec5Stsutsui *
839b9325ec5Stsutsui *-----------------------------------------------------------------------
840b9325ec5Stsutsui */
841b9325ec5Stsutsuiint
842b9325ec5StsutsuisunChangeKbdTranslation(int fd, Bool makeTranslated)
843b9325ec5Stsutsui{
844b9325ec5Stsutsui    int 	tmp;
845b9325ec5Stsutsui#ifndef i386 /* { */
846b9325ec5Stsutsui    sigset_t	hold_mask, old_mask;
847b9325ec5Stsutsui#else /* }{ */
848b9325ec5Stsutsui    int		old_mask;
849b9325ec5Stsutsui#endif /* } */
850b9325ec5Stsutsui    int		toread;
851b9325ec5Stsutsui    char	junk[8192];
852b9325ec5Stsutsui
853b9325ec5Stsutsui#ifndef i386 /* { */
854b9325ec5Stsutsui    (void) sigfillset(&hold_mask);
855b9325ec5Stsutsui    (void) sigprocmask(SIG_BLOCK, &hold_mask, &old_mask);
856b9325ec5Stsutsui#else /* }{ */
857b9325ec5Stsutsui    old_mask = sigblock (~0);
858b9325ec5Stsutsui#endif /* } */
859b9325ec5Stsutsui    sunKbdWait();
860b9325ec5Stsutsui    if (makeTranslated) {
861b9325ec5Stsutsui        /*
862b9325ec5Stsutsui         * Next set the keyboard into "direct" mode and turn on
863b9325ec5Stsutsui         * event translation. If either of these fails, we can't go
864b9325ec5Stsutsui         * on.
865b9325ec5Stsutsui         */
866b9325ec5Stsutsui	tmp = 1;
867b9325ec5Stsutsui	if (ioctl (fd, KIOCSDIRECT, &tmp) == -1) {
868b9325ec5Stsutsui	    Error ("Setting keyboard direct mode");
869b9325ec5Stsutsui	    return -1;
870b9325ec5Stsutsui	}
871b9325ec5Stsutsui	tmp = TR_UNTRANS_EVENT;
872b9325ec5Stsutsui	if (ioctl (fd, KIOCTRANS, &tmp) == -1) {
873b9325ec5Stsutsui	    Error ("Setting keyboard translation");
874b9325ec5Stsutsui	    ErrorF ("sunChangeKbdTranslation: kbdFd=%d\n", fd);
875b9325ec5Stsutsui	    return -1;
876b9325ec5Stsutsui	}
877b9325ec5Stsutsui    } else {
878b9325ec5Stsutsui        /*
879b9325ec5Stsutsui         * Next set the keyboard into "indirect" mode and turn off
880b9325ec5Stsutsui         * event translation.
881b9325ec5Stsutsui         */
882b9325ec5Stsutsui	tmp = 0;
883b9325ec5Stsutsui	(void)ioctl (fd, KIOCSDIRECT, &tmp);
884b9325ec5Stsutsui	tmp = TR_ASCII;
885b9325ec5Stsutsui	(void)ioctl (fd, KIOCTRANS, &tmp);
886b9325ec5Stsutsui    }
887b9325ec5Stsutsui    if (ioctl (fd, FIONREAD, &toread) != -1 && toread > 0) {
888b9325ec5Stsutsui	while (toread) {
889b9325ec5Stsutsui	    tmp = toread;
890b9325ec5Stsutsui	    if (toread > sizeof (junk))
891b9325ec5Stsutsui		tmp = sizeof (junk);
892b9325ec5Stsutsui	    (void) read (fd, junk, tmp);
893b9325ec5Stsutsui	    toread -= tmp;
894b9325ec5Stsutsui	}
895b9325ec5Stsutsui    }
896b9325ec5Stsutsui#ifndef i386 /* { */
897b9325ec5Stsutsui    (void) sigprocmask(SIG_SETMASK, &old_mask, (sigset_t *)NULL);
898b9325ec5Stsutsui#else /* }{ */
899b9325ec5Stsutsui    sigsetmask (old_mask);
900b9325ec5Stsutsui#endif /* } */
901b9325ec5Stsutsui    return 0;
902b9325ec5Stsutsui}
903b9325ec5Stsutsui
904b9325ec5Stsutsui/*ARGSUSED*/
905b9325ec5StsutsuiBool
906b9325ec5StsutsuiLegalModifier(unsigned int key, DeviceIntPtr pDev)
907b9325ec5Stsutsui{
908b9325ec5Stsutsui    return TRUE;
909b9325ec5Stsutsui}
910