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