x68kKbd.c revision 2aa2a51f
1/* $NetBSD: x68kKbd.c,v 1.12 2021/03/17 15:02:27 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, uint8_t);
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\n");
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\n");
150                return !Success;
151            }
152	    x68kSetLeds(&x68kKbdPriv, (uint8_t)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
164        case DEVICE_ABORT:
165            break;
166    }
167    return Success;
168}
169
170/*-------------------------------------------------------------------------
171 * function "x68kInitModMap"
172 *
173 *  purpose:  initialize modmap with keysym table
174 *  argument: (KeySymsRec *)x68kKeySyms : keysym table
175 *            (CARD8 *)x68kModMap       : result
176 *  returns:  nothing
177 *-----------------------------------------------------------------------*/
178static void
179x68kInitModMap(KeySymsRec *KeySyms, CARD8 *x68kModMap)
180{
181    int i;
182
183    for (i = 0; i < MAP_LENGTH; i++)
184        x68kModMap[i] = NoSymbol;
185    if (KeySyms->minKeyCode < MIN_KEYCODE) {
186        KeySyms->minKeyCode += MIN_KEYCODE;
187        KeySyms->maxKeyCode += MIN_KEYCODE;
188    }
189    if (KeySyms->maxKeyCode > MAX_KEYCODE)
190        KeySyms->maxKeyCode = MAX_KEYCODE;
191    for (i = KeySyms->minKeyCode;
192         i < KeySyms->maxKeyCode; i++) {
193        switch (KeySyms->map[(i-KeySyms->minKeyCode)*4]) {
194            case XK_Shift_L:
195            case XK_Shift_R:
196                x68kModMap[i] = ShiftMask;
197                break;
198            case XK_Control_L:
199            case XK_Control_R:
200                x68kModMap[i] = ControlMask;
201                break;
202            case XK_Alt_L:
203            case XK_Alt_R:
204                x68kModMap[i] = Mod1Mask;
205                break;
206            case XK_Meta_L:
207            case XK_Meta_R:
208                x68kModMap[i] = Mod2Mask;
209                break;
210            case XK_Caps_Lock:
211                x68kModMap[i] = LockMask;
212                break;
213        }
214    }
215}
216
217/*-------------------------------------------------------------------------
218 * function "x68kInitKbdNames"
219 *
220 *  purpose:  store xkb database names
221 *  argument: (XkbRMLVOSet *)rmlvo
222 *            (X68kKbdPrivPtr)pKbd
223 *  returns:  nothing
224 *-----------------------------------------------------------------------*/
225static void
226x68kInitKbdNames(XkbRMLVOSet *rmlvo, X68kKbdPrivPtr pKbd)
227{
228#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
229    rmlvo->rules = "base";
230    rmlvo->model = "x68k";
231    switch (pKbd->type) {
232    case X68K_KB_STANDARD:
233        rmlvo->layout = "jp(standard)";
234        break;
235    case X68K_KB_ASCII:
236        rmlvo->layout = "jp(ascii)";
237        break;
238    }
239    rmlvo->variant = "basic";
240    rmlvo->options = "";
241#else
242    rmlvo->rules = "base";
243    rmlvo->model = NULL;
244    rmlvo->layout = NULL;
245    rmlvo->variant = NULL;
246    rmlvo->options = NULL;
247#endif
248}
249
250/*-
251 *-----------------------------------------------------------------------
252 * x68kKbdGetEvents --
253 *	Return the events waiting in the wings for the given keyboard.
254 *
255 * Results:
256 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
257 *	The number of events contained in the array.
258 *	A boolean as to whether more events might be available.
259 *
260 * Side Effects:
261 *	None.
262 *-----------------------------------------------------------------------
263 */
264Firm_event *
265x68kKbdGetEvents(int fd, int *pNumEvents, Bool *pAgain)
266{
267    int nBytes;		/* number of bytes of events available. */
268    static Firm_event evBuf[X68K_MAXEVENTS];	/* Buffer for Firm_events */
269
270    if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) {
271	if (errno == EWOULDBLOCK) {
272	    *pNumEvents = 0;
273	    *pAgain = FALSE;
274	} else {
275	    ErrorF("Reading keyboard\n");
276	    FatalError ("Could not read the keyboard");
277	}
278    } else {
279	*pNumEvents = nBytes / sizeof (Firm_event);
280	*pAgain = (nBytes == sizeof (evBuf));
281    }
282    return evBuf;
283}
284
285/*-
286 *-----------------------------------------------------------------------
287 * x68kKbdEnqueueEvent --
288 *
289 *-----------------------------------------------------------------------
290 */
291void
292x68kKbdEnqueueEvent(DeviceIntPtr pDev, Firm_event *fe)
293{
294    BYTE		keycode;
295    int			type;
296
297    type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
298    keycode = (fe->id & 0x7f) + MIN_KEYCODE;
299    QueueKeyboardEvents(pDev, type, keycode);
300}
301
302/*-
303 *-----------------------------------------------------------------------
304 * x68kKbdBell --
305 *	Ring the terminal/keyboard bell
306 *
307 * Results:
308 *	Ring the keyboard bell for an amount of time proportional to
309 *	"loudness."
310 *
311 * Side Effects:
312 *	None, really...
313 *
314 *-----------------------------------------------------------------------
315 */
316
317static void
318x68kKbdRingBell(DeviceIntPtr pDev, int volume, int duration)
319{
320    int		    kbdCmd;	/* Command to give keyboard */
321    X68kKbdPrivPtr  pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
322
323    if (volume == 0)
324	return;
325
326    kbdCmd = KBD_CMD_BELL;
327    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1) {
328	ErrorF("Failed to activate bell\n");
329	return;
330    }
331    usleep (duration * 1000);
332    kbdCmd = KBD_CMD_NOBELL;
333    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1)
334	ErrorF("Failed to deactivate bell\n");
335}
336
337static void
338x68kKbdBell(int volume, DeviceIntPtr pDev, void *ctrl, int unused)
339{
340    KeybdCtrl*      kctrl = (KeybdCtrl*) ctrl;
341
342    if (kctrl->bell == 0)
343	return;
344
345    x68kKbdRingBell(pDev, volume, kctrl->bell_duration);
346}
347
348void
349DDXRingBell(int volume, int pitch, int duration)
350{
351    DeviceIntPtr	pKeyboard;
352
353    pKeyboard = x68kKeyboardDevice;
354    if (pKeyboard != NULL)
355	x68kKbdRingBell(pKeyboard, volume, duration);
356}
357
358/*-
359 *-----------------------------------------------------------------------
360 * x68kKbdCtrl --
361 *	Alter some of the keyboard control parameters
362 *
363 * Results:
364 *	None.
365 *
366 * Side Effects:
367 *	Some...
368 *
369 *-----------------------------------------------------------------------
370 */
371#define	XKB_LED_ZENKAKU		0x40
372#define	XKB_LED_HIRAGANA	0x20
373#define	XKB_LED_INSERT		0x10
374#define	XKB_LED_CAPS_LOCK	0x08
375#define	XKB_LED_CODE_INPUT	0x04
376#define	XKB_LED_ROMAJI		0x02
377#define	XKB_LED_KANA_LOCK	0x01
378
379static void
380x68kKbdCtrl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
381{
382    X68kKbdPrivPtr pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
383
384    if (pPriv->leds != ctrl->leds) {
385        x68kSetLeds(pPriv, (uint8_t)ctrl->leds);
386	pPriv->leds = ctrl->leds;
387    }
388}
389
390/*-------------------------------------------------------------------------
391 * function "x68kSetLeds"
392 *
393 *  purpose:  set keyboard leds to specified state
394 *  argument: (X68kKbdPrivPtr)pPriv
395 *            (uint8_t)data;
396 *  returns:  nothing
397 *-----------------------------------------------------------------------*/
398static void
399x68kSetLeds(X68kKbdPrivPtr pPriv, uint8_t data)
400{
401    /* bit sequence of led indicator in xkb and hardware are same */
402    if (ioctl(pPriv->fd, KIOCSLED, &data) == -1)
403        ErrorF("Failed to set keyboard lights\n");
404}
405
406Bool
407LegalModifier(unsigned int key, DeviceIntPtr pDev)
408{
409    return TRUE;
410}
411
412/* EOF x68kKbd.c */
413