x68kKbd.c revision ab290810
1/* $NetBSD: x68kKbd.c,v 1.4 2020/08/01 20:09:03 tsutsui Exp $ */
2/*-------------------------------------------------------------------------
3 * Copyright (c) 1996 Yasushi Yamasaki
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *-----------------------------------------------------------------------*/
26
27/*-
28 * Copyright (c) 1987 by the Regents of the University of California
29 *
30 * Permission to use, copy, modify, and distribute this
31 * software and its documentation for any purpose and without
32 * fee is hereby granted, provided that the above copyright
33 * notice appear in all copies.  The University of California
34 * makes no representations about the suitability of this
35 * software for any purpose.  It is provided "as is" without
36 * express or implied warranty.
37 */
38
39/************************************************************
40Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
41
42                    All Rights Reserved
43
44Permission  to  use,  copy,  modify,  and  distribute   this
45software  and  its documentation for any purpose and without
46fee is hereby granted, provided that the above copyright no-
47tice  appear  in all copies and that both that copyright no-
48tice and this permission notice appear in  supporting  docu-
49mentation,  and  that the names of Sun or X Consortium
50not be used in advertising or publicity pertaining to
51distribution  of  the software  without specific prior
52written permission. Sun and X Consortium make no
53representations about the suitability of this software for
54any purpose. It is provided "as is" without any express or
55implied warranty.
56
57SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
58INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
59NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
60ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
62PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
63OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
64THE USE OR PERFORMANCE OF THIS SOFTWARE.
65
66********************************************************/
67
68#include "x68k.h"
69#include "mi.h"
70
71#include <X11/X.h>
72#include <X11/Xproto.h>
73#include <X11/keysym.h>
74#include "screenint.h"
75#include "inputstr.h"
76#include "misc.h"
77#include "scrnintstr.h"
78#include "servermd.h"
79
80#include <X11/extensions/XKB.h>
81#include "xkbsrv.h"
82
83#define MIN_KEYCODE     7       /* necessary to avoid the mouse buttons */
84#define MAX_KEYCODE     255     /* limited by the protocol */
85
86X68kKbdPriv x68kKbdPriv;
87DeviceIntPtr x68kKeyboardDevice = NULL;
88
89static void x68kInitModMap(KeySymsRec *, CARD8 *);
90static void x68kInitKbdNames(XkbRMLVOSet *, X68kKbdPrivPtr);
91static void x68kKbdRingBell(DeviceIntPtr, int, int);
92static void x68kKbdBell(int, DeviceIntPtr, pointer, int);
93static void x68kKbdCtrl(DeviceIntPtr, KeybdCtrl *);
94static void x68kSetLeds(X68kKbdPrivPtr, u_char);
95
96/*------------------------------------------------------------------------
97 * x68kKbdProc --
98 *	Handle the initialization, etc. of a keyboard.
99 *
100 * Results:
101 *	None.
102 *
103 *----------------------------------------------------------------------*/
104int
105x68kKbdProc(DeviceIntPtr pDev,	/* Keyboard to manipulate */
106            int what)		/* What to do to it */
107{
108    DevicePtr pKeyboard = &pDev->public;
109    CARD8 x68kModMap[MAP_LENGTH];
110    int mode;
111    XkbRMLVOSet rmlvo;
112
113    switch (what) {
114        case DEVICE_INIT:
115            pKeyboard->devicePrivate = (pointer)&x68kKbdPriv;
116            if( (x68kKbdPriv.fd = open("/dev/kbd", O_RDONLY)) == -1 ) {
117                Error("Can't open keyboard device");
118                return !Success;
119            }
120            pKeyboard->on = FALSE;
121            x68kInitModMap(x68kKeySyms, x68kModMap);
122
123            x68kInitKbdNames(&rmlvo, pKeyboard->devicePrivate);
124#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
125            InitKeyboardDeviceStruct(pDev, &rmlvo,
126                                     x68kKbdBell, x68kKbdCtrl);
127#else
128            InitKeyboardDeviceStruct(pDev, NULL,
129                                     x68kKbdBell, x68kKbdCtrl);
130	    XkbApplyMappingChange(pDev, x68kKeySyms,
131		x68kKeySyms->minKeyCode,
132		x68kKeySyms->maxKeyCode - x68kKeySyms->minKeyCode + 1,
133		x68kModMap, serverClient);
134#endif
135            break;
136
137        case DEVICE_ON:
138            mode = 1;
139            if ( fcntl(x68kKbdPriv.fd, F_SETOWN, getpid()) == -1 ||
140                 fcntl(x68kKbdPriv.fd, F_SETFL, O_NONBLOCK|O_ASYNC) == -1 ||
141                 ioctl(x68kKbdPriv.fd, KIOCSDIRECT, &mode) == -1 ) {
142                Error("Async keyboard I/O failed");
143                return !Success;
144            }
145	    x68kSetLeds(&x68kKbdPriv, (u_char)x68kKbdPriv.leds);
146            (void) AddEnabledDevice(x68kKbdPriv.fd);
147            pKeyboard->on = TRUE;
148            break;
149
150        case DEVICE_CLOSE:
151        case DEVICE_OFF:
152            RemoveEnabledDevice(x68kKbdPriv.fd);
153            pKeyboard->on = FALSE;
154            break;
155        default:
156            FatalError("Unknown keyboard operation\n");
157    }
158    return Success;
159}
160
161/*-------------------------------------------------------------------------
162 * function "x68kInitModMap"
163 *
164 *  purpose:  initialize modmap with keysym table
165 *  argument: (KeySymsRec *)x68kKeySyms : keysym table
166 *            (CARD8 *)x68kModMap       : result
167 *  returns:  nothing
168 *-----------------------------------------------------------------------*/
169static void
170x68kInitModMap(KeySymsRec *KeySyms, CARD8 *x68kModMap)
171{
172    int i;
173
174    for (i = 0; i < MAP_LENGTH; i++)
175        x68kModMap[i] = NoSymbol;
176    if (KeySyms->minKeyCode < MIN_KEYCODE) {
177        KeySyms->minKeyCode += MIN_KEYCODE;
178        KeySyms->maxKeyCode += MIN_KEYCODE;
179    }
180#if 0
181    if (KeySyms->maxKeyCode > MAX_KEYCODE)
182        KeySyms->maxKeyCode += MAX_KEYCODE;
183#endif
184    for (i = KeySyms->minKeyCode;
185         i < KeySyms->maxKeyCode; i++) {
186        switch (KeySyms->map[(i-KeySyms->minKeyCode)*4]) {
187            case XK_Shift_L:
188            case XK_Shift_R:
189                x68kModMap[i] = ShiftMask;
190                break;
191            case XK_Control_L:
192            case XK_Control_R:
193                x68kModMap[i] = ControlMask;
194                break;
195            case XK_Alt_L:
196            case XK_Alt_R:
197                x68kModMap[i] = Mod1Mask;
198                break;
199            case XK_Meta_L:
200            case XK_Meta_R:
201                x68kModMap[i] = Mod2Mask;
202                break;
203            case XK_Caps_Lock:
204                x68kModMap[i] = LockMask;
205                break;
206        }
207    }
208}
209
210/*-------------------------------------------------------------------------
211 * function "x68kInitKbdNames"
212 *
213 *  purpose:  store xkb database names
214 *  argument: (XkbRMLVOSet *)rmlvo
215 *            (X68kKbdPrivPtr)pKbd
216 *  returns:  nothing
217 *-----------------------------------------------------------------------*/
218static void
219x68kInitKbdNames(XkbRMLVOSet *rmlvo, X68kKbdPrivPtr pKbd)
220{
221#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
222    rmlvo->rules = "base";
223    rmlvo->model = "x68k";
224    switch (pKbd->type) {
225    case X68K_KB_STANDARD:
226        rmlvo->layout = "jp(standard)";
227        break;
228    case X68K_KB_ASCII:
229        rmlvo->layout = "jp(ascii)";
230        break;
231    }
232    rmlvo->variant = "basic";
233    rmlvo->options = "";
234#else
235    rmlvo->rules = "base";
236    rmlvo->model = NULL;
237    rmlvo->layout = NULL;
238    rmlvo->variant = NULL;
239    rmlvo->options = NULL;
240#endif
241}
242
243/*-
244 *-----------------------------------------------------------------------
245 * x68kKbdGetEvents --
246 *	Return the events waiting in the wings for the given keyboard.
247 *
248 * Results:
249 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
250 *	The number of events contained in the array.
251 *	A boolean as to whether more events might be available.
252 *
253 * Side Effects:
254 *	None.
255 *-----------------------------------------------------------------------
256 */
257Firm_event *
258x68kKbdGetEvents(int fd, int *pNumEvents, Bool *pAgain)
259{
260    int nBytes;		/* number of bytes of events available. */
261    static Firm_event evBuf[MAXEVENTS];	/* Buffer for Firm_events */
262
263    if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) {
264	if (errno == EWOULDBLOCK) {
265	    *pNumEvents = 0;
266	    *pAgain = FALSE;
267	} else {
268	    Error ("Reading keyboard");
269	    FatalError ("Could not read the keyboard");
270	}
271    } else {
272	*pNumEvents = nBytes / sizeof (Firm_event);
273	*pAgain = (nBytes == sizeof (evBuf));
274    }
275    return evBuf;
276}
277
278/*-
279 *-----------------------------------------------------------------------
280 * x68kKbdEnqueueEvent --
281 *
282 *-----------------------------------------------------------------------
283 */
284void
285x68kKbdEnqueueEvent(DeviceIntPtr pDev, Firm_event *fe)
286{
287    BYTE		keycode;
288    int			type;
289    int			i, nevents;
290
291    GetEventList(&x68kEvents);
292    type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
293    keycode = (fe->id & 0x7f) + MIN_KEYCODE;
294    nevents = GetKeyboardEvents(x68kEvents, pDev, type, keycode);
295    for (i = 0; i < nevents; i++)
296	mieqEnqueue(pDev, (InternalEvent*)(x68kEvents + i)->event);
297}
298
299/*-
300 *-----------------------------------------------------------------------
301 * x68kKbdBell --
302 *	Ring the terminal/keyboard bell
303 *
304 * Results:
305 *	Ring the keyboard bell for an amount of time proportional to
306 *	"loudness."
307 *
308 * Side Effects:
309 *	None, really...
310 *
311 *-----------------------------------------------------------------------
312 */
313
314static void
315x68kKbdRingBell(DeviceIntPtr pDev, int volume, int duration)
316{
317    int		    kbdCmd;	/* Command to give keyboard */
318    X68kKbdPrivPtr  pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
319
320    if (volume == 0)
321	return;
322
323    kbdCmd = KBD_CMD_BELL;
324    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1) {
325	Error("Failed to activate bell");
326	return;
327    }
328    usleep (duration * 1000);
329    kbdCmd = KBD_CMD_NOBELL;
330    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1)
331	Error ("Failed to deactivate bell");
332}
333
334static void
335x68kKbdBell(int volume, DeviceIntPtr pDev, pointer ctrl, int unused)
336{
337    KeybdCtrl*      kctrl = (KeybdCtrl*) ctrl;
338
339    if (kctrl->bell == 0)
340	return;
341
342    x68kKbdRingBell(pDev, volume, kctrl->bell_duration);
343}
344
345void
346DDXRingBell(int volume, int pitch, int duration)
347{
348    DeviceIntPtr	pKeyboard;
349
350    pKeyboard = x68kKeyboardDevice;
351    if (pKeyboard != NULL)
352	x68kKbdRingBell(pKeyboard, volume, duration);
353}
354
355/*-
356 *-----------------------------------------------------------------------
357 * x68kKbdCtrl --
358 *	Alter some of the keyboard control parameters
359 *
360 * Results:
361 *	None.
362 *
363 * Side Effects:
364 *	Some...
365 *
366 *-----------------------------------------------------------------------
367 */
368#define	XKB_LED_ZENKAKU		0x40
369#define	XKB_LED_HIRAGANA	0x20
370#define	XKB_LED_INSERT		0x10
371#define	XKB_LED_CAPS_LOCK	0x08
372#define	XKB_LED_CODE_INPUT	0x04
373#define	XKB_LED_ROMAJI		0x02
374#define	XKB_LED_KANA_LOCK	0x01
375
376static void
377x68kKbdCtrl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
378{
379    X68kKbdPrivPtr pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
380
381    if (pPriv->leds != ctrl->leds) {
382        x68kSetLeds(pPriv, (u_char)ctrl->leds);
383	pPriv->leds = ctrl->leds;
384    }
385}
386
387/*-------------------------------------------------------------------------
388 * function "x68kSetLeds"
389 *
390 *  purpose:  set keyboard leds to specified state
391 *  argument: (X68kKbdPrivPtr)pPriv
392 *            (u_char)data;
393 *  returns:  nothing
394 *-----------------------------------------------------------------------*/
395static void
396x68kSetLeds(X68kKbdPrivPtr pPriv, u_char data)
397{
398    /* bit sequence of led indicator in xkb and hardware are same */
399    if (ioctl(pPriv->fd, KIOCSLED, &data) == -1)
400        Error("Failed to set keyboard lights");
401}
402
403Bool
404LegalModifier(unsigned int key, DeviceIntPtr pDev)
405{
406    return TRUE;
407}
408
409/* EOF x68kKbd.c */
410