x68kKbd.c revision 80c54d45
1/* $NetBSD: x68kKbd.c,v 1.4 2020/04/10 16:49:36 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 "eventstr.h"
77#include "misc.h"
78#include "scrnintstr.h"
79#include "servermd.h"
80
81#include <X11/extensions/XKB.h>
82#include "xkbsrv.h"
83
84#define MIN_KEYCODE     7       /* necessary to avoid the mouse buttons */
85#define MAX_KEYCODE     255     /* limited by the protocol */
86
87X68kKbdPriv x68kKbdPriv;
88DeviceIntPtr x68kKeyboardDevice = NULL;
89
90static void x68kInitModMap(KeySymsRec *, CARD8 *);
91static void x68kInitKbdNames(XkbRMLVOSet *, X68kKbdPrivPtr);
92static void x68kKbdRingBell(DeviceIntPtr, int, int);
93static void x68kKbdBell(int, DeviceIntPtr, pointer, int);
94static void x68kKbdCtrl(DeviceIntPtr, KeybdCtrl *);
95static void x68kSetLeds(X68kKbdPrivPtr, u_char);
96
97/*------------------------------------------------------------------------
98 * x68kKbdProc --
99 *	Handle the initialization, etc. of a keyboard.
100 *
101 * Results:
102 *	None.
103 *
104 *----------------------------------------------------------------------*/
105int
106x68kKbdProc(DeviceIntPtr pDev, 	/* Keyboard to manipulate */
107            int what)	    	/* What to do to it */
108{
109    DevicePtr pKeyboard = &pDev->public;
110    CARD8 x68kModMap[MAP_LENGTH];
111    int mode;
112    XkbRMLVOSet rmlvo;
113
114    switch (what) {
115        case DEVICE_INIT:
116            pKeyboard->devicePrivate = (pointer)&x68kKbdPriv;
117            if( (x68kKbdPriv.fd = open("/dev/kbd", O_RDONLY)) == -1 ) {
118                ErrorF("Can't open keyboard device");
119                return !Success;
120            }
121            pKeyboard->on = FALSE;
122            x68kInitModMap(x68kKeySyms, x68kModMap);
123
124            x68kInitKbdNames(&rmlvo, pKeyboard->devicePrivate);
125#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
126            InitKeyboardDeviceStruct(pDev, &rmlvo,
127                                     x68kKbdBell, x68kKbdCtrl);
128#else
129            InitKeyboardDeviceStruct(pDev, NULL,
130                                     x68kKbdBell, x68kKbdCtrl);
131	    XkbApplyMappingChange(pDev, x68kKeySyms,
132		x68kKeySyms->minKeyCode,
133		x68kKeySyms->maxKeyCode - x68kKeySyms->minKeyCode + 1,
134		x68kModMap, serverClient);
135#endif
136            break;
137
138        case DEVICE_ON:
139            mode = 1;
140            if ( fcntl(x68kKbdPriv.fd, F_SETOWN, getpid()) == -1 ||
141                 fcntl(x68kKbdPriv.fd, F_SETFL, O_NONBLOCK|O_ASYNC) == -1 ||
142                 ioctl(x68kKbdPriv.fd, KIOCSDIRECT, &mode) == -1 ) {
143                ErrorF("Async keyboard I/O failed");
144                return !Success;
145            }
146	    x68kSetLeds(&x68kKbdPriv, (u_char)x68kKbdPriv.leds);
147            (void) AddEnabledDevice(x68kKbdPriv.fd);
148            pKeyboard->on = TRUE;
149            break;
150
151        case DEVICE_CLOSE:
152        case DEVICE_OFF:
153            RemoveEnabledDevice(x68kKbdPriv.fd);
154            pKeyboard->on = FALSE;
155            break;
156        default:
157            FatalError("Unknown keyboard operation\n");
158    }
159    return Success;
160}
161
162/*-------------------------------------------------------------------------
163 * function "x68kInitModMap"
164 *
165 *  purpose:  initialize modmap with keysym table
166 *  argument: (KeySymsRec *)x68kKeySyms : keysym table
167 *            (CARD8 *)x68kModMap       : result
168 *  returns:  nothing
169 *-----------------------------------------------------------------------*/
170static void
171x68kInitModMap(KeySymsRec *KeySyms, CARD8 *x68kModMap)
172{
173    int i;
174
175    for (i = 0; i < MAP_LENGTH; i++)
176        x68kModMap[i] = NoSymbol;
177    if (KeySyms->minKeyCode < MIN_KEYCODE) {
178        KeySyms->minKeyCode += MIN_KEYCODE;
179        KeySyms->maxKeyCode += MIN_KEYCODE;
180    }
181#if 0
182    if (KeySyms->maxKeyCode > MAX_KEYCODE)
183        KeySyms->maxKeyCode += MAX_KEYCODE;
184#endif
185    for (i = KeySyms->minKeyCode;
186         i < KeySyms->maxKeyCode; i++) {
187        switch (KeySyms->map[(i-KeySyms->minKeyCode)*4]) {
188            case XK_Shift_L:
189            case XK_Shift_R:
190                x68kModMap[i] = ShiftMask;
191                break;
192            case XK_Control_L:
193            case XK_Control_R:
194                x68kModMap[i] = ControlMask;
195                break;
196            case XK_Alt_L:
197            case XK_Alt_R:
198                x68kModMap[i] = Mod1Mask;
199                break;
200            case XK_Meta_L:
201            case XK_Meta_R:
202                x68kModMap[i] = Mod2Mask;
203                break;
204            case XK_Caps_Lock:
205                x68kModMap[i] = LockMask;
206                break;
207        }
208    }
209}
210
211/*-------------------------------------------------------------------------
212 * function "x68kInitKbdNames"
213 *
214 *  purpose:  store xkb database names
215 *  argument: (XkbRMLVOSet *)rmlvo
216 *            (X68kKbdPrivPtr)pKbd
217 *  returns:  nothing
218 *-----------------------------------------------------------------------*/
219static void
220x68kInitKbdNames(XkbRMLVOSet *rmlvo, X68kKbdPrivPtr pKbd)
221{
222#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
223    rmlvo->rules = "base";
224    rmlvo->model = "x68k";
225    switch (pKbd->type) {
226    case X68K_KB_STANDARD:
227        rmlvo->layout = "jp(standard)";
228        break;
229    case X68K_KB_ASCII:
230        rmlvo->layout = "jp(ascii)";
231        break;
232    }
233    rmlvo->variant = "basic";
234    rmlvo->options = "";
235#else
236    rmlvo->rules = "base";
237    rmlvo->model = NULL;
238    rmlvo->layout = NULL;
239    rmlvo->variant = NULL;
240    rmlvo->options = NULL;
241#endif
242}
243
244/*-
245 *-----------------------------------------------------------------------
246 * x68kKbdGetEvents --
247 *	Return the events waiting in the wings for the given keyboard.
248 *
249 * Results:
250 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
251 *	The number of events contained in the array.
252 *	A boolean as to whether more events might be available.
253 *
254 * Side Effects:
255 *	None.
256 *-----------------------------------------------------------------------
257 */
258Firm_event *
259x68kKbdGetEvents(int fd, int *pNumEvents, Bool *pAgain)
260{
261    int nBytes; 	    /* number of bytes of events available. */
262    static Firm_event evBuf[X68K_MAXEVENTS];   /* Buffer for Firm_events */
263
264    if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) {
265	if (errno == EWOULDBLOCK) {
266	    *pNumEvents = 0;
267	    *pAgain = FALSE;
268	} else {
269	    ErrorF("Reading keyboard");
270	    FatalError ("Could not read the keyboard");
271	}
272    } else {
273	*pNumEvents = nBytes / sizeof (Firm_event);
274	*pAgain = (nBytes == sizeof (evBuf));
275    }
276    return evBuf;
277}
278
279/*-
280 *-----------------------------------------------------------------------
281 * x68kKbdEnqueueEvent --
282 *
283 *-----------------------------------------------------------------------
284 */
285void
286x68kKbdEnqueueEvent(DeviceIntPtr pDev, Firm_event *fe)
287{
288    BYTE		keycode;
289    int			type;
290
291    type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
292    keycode = (fe->id & 0x7f) + MIN_KEYCODE;
293    QueueKeyboardEvents(pDev, type, keycode);
294}
295
296/*-
297 *-----------------------------------------------------------------------
298 * x68kKbdBell --
299 *	Ring the terminal/keyboard bell
300 *
301 * Results:
302 *	Ring the keyboard bell for an amount of time proportional to
303 *	"loudness."
304 *
305 * Side Effects:
306 *	None, really...
307 *
308 *-----------------------------------------------------------------------
309 */
310
311static void
312x68kKbdRingBell(DeviceIntPtr pDev, int volume, int duration)
313{
314    int		    kbdCmd;   	    /* Command to give keyboard */
315    X68kKbdPrivPtr  pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
316
317    if (volume == 0)
318 	return;
319
320    kbdCmd = KBD_CMD_BELL;
321    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1) {
322 	ErrorF("Failed to activate bell");
323	return;
324    }
325    usleep (duration * 1000);
326    kbdCmd = KBD_CMD_NOBELL;
327    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1)
328	ErrorF("Failed to deactivate bell");
329}
330
331static void
332x68kKbdBell(int volume, DeviceIntPtr pDev, pointer ctrl, int unused)
333{
334    KeybdCtrl*      kctrl = (KeybdCtrl*) ctrl;
335
336    if (kctrl->bell == 0)
337 	return;
338
339    x68kKbdRingBell(pDev, volume, kctrl->bell_duration);
340}
341
342void
343DDXRingBell(int volume, int pitch, int duration)
344{
345    DeviceIntPtr	pKeyboard;
346
347    pKeyboard = x68kKeyboardDevice;
348    if (pKeyboard != NULL)
349	x68kKbdRingBell(pKeyboard, volume, duration);
350}
351
352/*-
353 *-----------------------------------------------------------------------
354 * x68kKbdCtrl --
355 *	Alter some of the keyboard control parameters
356 *
357 * Results:
358 *	None.
359 *
360 * Side Effects:
361 *	Some...
362 *
363 *-----------------------------------------------------------------------
364 */
365#define	XKB_LED_ZENKAKU		0x40
366#define	XKB_LED_HIRAGANA	0x20
367#define	XKB_LED_INSERT		0x10
368#define	XKB_LED_CAPS_LOCK	0x08
369#define	XKB_LED_CODE_INPUT	0x04
370#define	XKB_LED_ROMAJI		0x02
371#define	XKB_LED_KANA_LOCK	0x01
372
373static void
374x68kKbdCtrl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
375{
376    X68kKbdPrivPtr pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
377
378#ifdef XKB
379    if (pPriv->leds != ctrl->leds) {
380        x68kSetLeds(pPriv, (u_char)ctrl->leds);
381	pPriv->leds = ctrl->leds;
382    }
383#endif
384}
385
386/*-------------------------------------------------------------------------
387 * function "x68kSetLeds"
388 *
389 *  purpose:  set keyboard leds to specified state
390 *  argument: (X68kKbdPrivPtr)pPriv
391 *            (u_char)data;
392 *  returns:  nothing
393 *-----------------------------------------------------------------------*/
394static void
395x68kSetLeds(X68kKbdPrivPtr pPriv, u_char data)
396{
397    /* bit sequence of led indicator in xkb and hardware are same */
398    if (ioctl(pPriv->fd, KIOCSLED, &data) == -1)
399        ErrorF("Failed to set keyboard lights");
400}
401
402Bool
403LegalModifier(unsigned int key, DeviceIntPtr pDev)
404{
405    return TRUE;
406}
407
408/* EOF x68kKbd.c */
409