184d30d9dStsutsui/* $NetBSD: x68kKbd.c,v 1.5 2020/11/05 16:06:08 tsutsui Exp $ */
2706f2543Smrg/*-------------------------------------------------------------------------
3706f2543Smrg * Copyright (c) 1996 Yasushi Yamasaki
4706f2543Smrg * All rights reserved.
5706f2543Smrg *
6706f2543Smrg * Redistribution and use in source and binary forms, with or without
7706f2543Smrg * modification, are permitted provided that the following conditions
8706f2543Smrg * are met:
9706f2543Smrg * 1. Redistributions of source code must retain the above copyright
10706f2543Smrg *    notice, this list of conditions and the following disclaimer.
11706f2543Smrg * 2. Redistributions in binary form must reproduce the above copyright
12706f2543Smrg *    notice, this list of conditions and the following disclaimer in the
13706f2543Smrg *    documentation and/or other materials provided with the distribution.
14706f2543Smrg *
15706f2543Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16706f2543Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17706f2543Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18706f2543Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19706f2543Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20706f2543Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21706f2543Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22706f2543Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23706f2543Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24706f2543Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25706f2543Smrg *-----------------------------------------------------------------------*/
26706f2543Smrg
27706f2543Smrg/*-
28706f2543Smrg * Copyright (c) 1987 by the Regents of the University of California
29706f2543Smrg *
30706f2543Smrg * Permission to use, copy, modify, and distribute this
31706f2543Smrg * software and its documentation for any purpose and without
32706f2543Smrg * fee is hereby granted, provided that the above copyright
33706f2543Smrg * notice appear in all copies.  The University of California
34706f2543Smrg * makes no representations about the suitability of this
35706f2543Smrg * software for any purpose.  It is provided "as is" without
36706f2543Smrg * express or implied warranty.
37706f2543Smrg */
38706f2543Smrg
39706f2543Smrg/************************************************************
40706f2543SmrgCopyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
41706f2543Smrg
42706f2543Smrg                    All Rights Reserved
43706f2543Smrg
44706f2543SmrgPermission  to  use,  copy,  modify,  and  distribute   this
45706f2543Smrgsoftware  and  its documentation for any purpose and without
46706f2543Smrgfee is hereby granted, provided that the above copyright no-
47706f2543Smrgtice  appear  in all copies and that both that copyright no-
48706f2543Smrgtice and this permission notice appear in  supporting  docu-
49706f2543Smrgmentation,  and  that the names of Sun or X Consortium
50ab290810Stsutsuinot be used in advertising or publicity pertaining to
51ab290810Stsutsuidistribution  of  the software  without specific prior
52ab290810Stsutsuiwritten permission. Sun and X Consortium make no
53ab290810Stsutsuirepresentations about the suitability of this software for
54ab290810Stsutsuiany purpose. It is provided "as is" without any express or
55706f2543Smrgimplied warranty.
56706f2543Smrg
57706f2543SmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
58706f2543SmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
59706f2543SmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
60706f2543SmrgABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
62706f2543SmrgPROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
63706f2543SmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
64706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
65706f2543Smrg
66706f2543Smrg********************************************************/
67706f2543Smrg
68706f2543Smrg#include "x68k.h"
69706f2543Smrg#include "mi.h"
70706f2543Smrg
71706f2543Smrg#include <X11/X.h>
72706f2543Smrg#include <X11/Xproto.h>
73706f2543Smrg#include <X11/keysym.h>
74706f2543Smrg#include "screenint.h"
75706f2543Smrg#include "inputstr.h"
76706f2543Smrg#include "misc.h"
77706f2543Smrg#include "scrnintstr.h"
78706f2543Smrg#include "servermd.h"
79706f2543Smrg
80706f2543Smrg#include <X11/extensions/XKB.h>
81706f2543Smrg#include "xkbsrv.h"
82706f2543Smrg
83706f2543Smrg#define MIN_KEYCODE     7       /* necessary to avoid the mouse buttons */
84706f2543Smrg#define MAX_KEYCODE     255     /* limited by the protocol */
85706f2543Smrg
86706f2543SmrgX68kKbdPriv x68kKbdPriv;
87706f2543SmrgDeviceIntPtr x68kKeyboardDevice = NULL;
88706f2543Smrg
89706f2543Smrgstatic void x68kInitModMap(KeySymsRec *, CARD8 *);
90706f2543Smrgstatic void x68kInitKbdNames(XkbRMLVOSet *, X68kKbdPrivPtr);
91706f2543Smrgstatic void x68kKbdRingBell(DeviceIntPtr, int, int);
92706f2543Smrgstatic void x68kKbdBell(int, DeviceIntPtr, pointer, int);
93706f2543Smrgstatic void x68kKbdCtrl(DeviceIntPtr, KeybdCtrl *);
9484d30d9dStsutsuistatic void x68kSetLeds(X68kKbdPrivPtr, uint8_t);
95706f2543Smrg
96706f2543Smrg/*------------------------------------------------------------------------
97706f2543Smrg * x68kKbdProc --
98706f2543Smrg *	Handle the initialization, etc. of a keyboard.
99706f2543Smrg *
100706f2543Smrg * Results:
101706f2543Smrg *	None.
102706f2543Smrg *
103706f2543Smrg *----------------------------------------------------------------------*/
104706f2543Smrgint
105ab290810Stsutsuix68kKbdProc(DeviceIntPtr pDev,	/* Keyboard to manipulate */
106ab290810Stsutsui            int what)		/* What to do to it */
107706f2543Smrg{
108706f2543Smrg    DevicePtr pKeyboard = &pDev->public;
109706f2543Smrg    CARD8 x68kModMap[MAP_LENGTH];
110706f2543Smrg    int mode;
111706f2543Smrg    XkbRMLVOSet rmlvo;
112ab290810Stsutsui
113706f2543Smrg    switch (what) {
114706f2543Smrg        case DEVICE_INIT:
115706f2543Smrg            pKeyboard->devicePrivate = (pointer)&x68kKbdPriv;
116706f2543Smrg            if( (x68kKbdPriv.fd = open("/dev/kbd", O_RDONLY)) == -1 ) {
117706f2543Smrg                Error("Can't open keyboard device");
118706f2543Smrg                return !Success;
119706f2543Smrg            }
120706f2543Smrg            pKeyboard->on = FALSE;
121706f2543Smrg            x68kInitModMap(x68kKeySyms, x68kModMap);
122706f2543Smrg
123706f2543Smrg            x68kInitKbdNames(&rmlvo, pKeyboard->devicePrivate);
124706f2543Smrg#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
125706f2543Smrg            InitKeyboardDeviceStruct(pDev, &rmlvo,
126706f2543Smrg                                     x68kKbdBell, x68kKbdCtrl);
127706f2543Smrg#else
128706f2543Smrg            InitKeyboardDeviceStruct(pDev, NULL,
129706f2543Smrg                                     x68kKbdBell, x68kKbdCtrl);
130706f2543Smrg	    XkbApplyMappingChange(pDev, x68kKeySyms,
131706f2543Smrg		x68kKeySyms->minKeyCode,
132706f2543Smrg		x68kKeySyms->maxKeyCode - x68kKeySyms->minKeyCode + 1,
133706f2543Smrg		x68kModMap, serverClient);
134706f2543Smrg#endif
135706f2543Smrg            break;
136706f2543Smrg
137706f2543Smrg        case DEVICE_ON:
138706f2543Smrg            mode = 1;
139706f2543Smrg            if ( fcntl(x68kKbdPriv.fd, F_SETOWN, getpid()) == -1 ||
140706f2543Smrg                 fcntl(x68kKbdPriv.fd, F_SETFL, O_NONBLOCK|O_ASYNC) == -1 ||
141706f2543Smrg                 ioctl(x68kKbdPriv.fd, KIOCSDIRECT, &mode) == -1 ) {
142706f2543Smrg                Error("Async keyboard I/O failed");
143706f2543Smrg                return !Success;
144706f2543Smrg            }
14584d30d9dStsutsui	    x68kSetLeds(&x68kKbdPriv, (uint8_t)x68kKbdPriv.leds);
146706f2543Smrg            (void) AddEnabledDevice(x68kKbdPriv.fd);
147706f2543Smrg            pKeyboard->on = TRUE;
148706f2543Smrg            break;
149706f2543Smrg
150706f2543Smrg        case DEVICE_CLOSE:
151706f2543Smrg        case DEVICE_OFF:
152706f2543Smrg            RemoveEnabledDevice(x68kKbdPriv.fd);
153706f2543Smrg            pKeyboard->on = FALSE;
154706f2543Smrg            break;
155706f2543Smrg        default:
156706f2543Smrg            FatalError("Unknown keyboard operation\n");
157706f2543Smrg    }
158706f2543Smrg    return Success;
159706f2543Smrg}
160706f2543Smrg
161706f2543Smrg/*-------------------------------------------------------------------------
162706f2543Smrg * function "x68kInitModMap"
163706f2543Smrg *
164706f2543Smrg *  purpose:  initialize modmap with keysym table
165706f2543Smrg *  argument: (KeySymsRec *)x68kKeySyms : keysym table
166706f2543Smrg *            (CARD8 *)x68kModMap       : result
167706f2543Smrg *  returns:  nothing
168706f2543Smrg *-----------------------------------------------------------------------*/
169706f2543Smrgstatic void
170706f2543Smrgx68kInitModMap(KeySymsRec *KeySyms, CARD8 *x68kModMap)
171706f2543Smrg{
172706f2543Smrg    int i;
173ab290810Stsutsui
174706f2543Smrg    for (i = 0; i < MAP_LENGTH; i++)
175706f2543Smrg        x68kModMap[i] = NoSymbol;
176706f2543Smrg    if (KeySyms->minKeyCode < MIN_KEYCODE) {
177706f2543Smrg        KeySyms->minKeyCode += MIN_KEYCODE;
178706f2543Smrg        KeySyms->maxKeyCode += MIN_KEYCODE;
179706f2543Smrg    }
180706f2543Smrg    if (KeySyms->maxKeyCode > MAX_KEYCODE)
18184d30d9dStsutsui        KeySyms->maxKeyCode = MAX_KEYCODE;
182706f2543Smrg    for (i = KeySyms->minKeyCode;
183706f2543Smrg         i < KeySyms->maxKeyCode; i++) {
184706f2543Smrg        switch (KeySyms->map[(i-KeySyms->minKeyCode)*4]) {
185706f2543Smrg            case XK_Shift_L:
186706f2543Smrg            case XK_Shift_R:
187706f2543Smrg                x68kModMap[i] = ShiftMask;
188706f2543Smrg                break;
189706f2543Smrg            case XK_Control_L:
190706f2543Smrg            case XK_Control_R:
191706f2543Smrg                x68kModMap[i] = ControlMask;
192706f2543Smrg                break;
193706f2543Smrg            case XK_Alt_L:
194706f2543Smrg            case XK_Alt_R:
195706f2543Smrg                x68kModMap[i] = Mod1Mask;
196706f2543Smrg                break;
197706f2543Smrg            case XK_Meta_L:
198706f2543Smrg            case XK_Meta_R:
199706f2543Smrg                x68kModMap[i] = Mod2Mask;
200706f2543Smrg                break;
201706f2543Smrg            case XK_Caps_Lock:
202706f2543Smrg                x68kModMap[i] = LockMask;
203706f2543Smrg                break;
204706f2543Smrg        }
205706f2543Smrg    }
206706f2543Smrg}
207706f2543Smrg
208706f2543Smrg/*-------------------------------------------------------------------------
209706f2543Smrg * function "x68kInitKbdNames"
210706f2543Smrg *
211706f2543Smrg *  purpose:  store xkb database names
212706f2543Smrg *  argument: (XkbRMLVOSet *)rmlvo
213706f2543Smrg *            (X68kKbdPrivPtr)pKbd
214706f2543Smrg *  returns:  nothing
215706f2543Smrg *-----------------------------------------------------------------------*/
216706f2543Smrgstatic void
217706f2543Smrgx68kInitKbdNames(XkbRMLVOSet *rmlvo, X68kKbdPrivPtr pKbd)
218706f2543Smrg{
219706f2543Smrg#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */
220706f2543Smrg    rmlvo->rules = "base";
221706f2543Smrg    rmlvo->model = "x68k";
222706f2543Smrg    switch (pKbd->type) {
223706f2543Smrg    case X68K_KB_STANDARD:
224706f2543Smrg        rmlvo->layout = "jp(standard)";
225706f2543Smrg        break;
226706f2543Smrg    case X68K_KB_ASCII:
227706f2543Smrg        rmlvo->layout = "jp(ascii)";
228706f2543Smrg        break;
229706f2543Smrg    }
230706f2543Smrg    rmlvo->variant = "basic";
231706f2543Smrg    rmlvo->options = "";
232706f2543Smrg#else
233706f2543Smrg    rmlvo->rules = "base";
234706f2543Smrg    rmlvo->model = NULL;
235706f2543Smrg    rmlvo->layout = NULL;
236706f2543Smrg    rmlvo->variant = NULL;
237706f2543Smrg    rmlvo->options = NULL;
238706f2543Smrg#endif
239706f2543Smrg}
240ab290810Stsutsui
241706f2543Smrg/*-
242706f2543Smrg *-----------------------------------------------------------------------
243706f2543Smrg * x68kKbdGetEvents --
244706f2543Smrg *	Return the events waiting in the wings for the given keyboard.
245706f2543Smrg *
246706f2543Smrg * Results:
247706f2543Smrg *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
248706f2543Smrg *	The number of events contained in the array.
249706f2543Smrg *	A boolean as to whether more events might be available.
250706f2543Smrg *
251706f2543Smrg * Side Effects:
252706f2543Smrg *	None.
253706f2543Smrg *-----------------------------------------------------------------------
254706f2543Smrg */
255706f2543SmrgFirm_event *
256706f2543Smrgx68kKbdGetEvents(int fd, int *pNumEvents, Bool *pAgain)
257706f2543Smrg{
258ab290810Stsutsui    int nBytes;		/* number of bytes of events available. */
259ab290810Stsutsui    static Firm_event evBuf[MAXEVENTS];	/* Buffer for Firm_events */
260706f2543Smrg
261706f2543Smrg    if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) {
262706f2543Smrg	if (errno == EWOULDBLOCK) {
263706f2543Smrg	    *pNumEvents = 0;
264706f2543Smrg	    *pAgain = FALSE;
265706f2543Smrg	} else {
266706f2543Smrg	    Error ("Reading keyboard");
267706f2543Smrg	    FatalError ("Could not read the keyboard");
268706f2543Smrg	}
269706f2543Smrg    } else {
270706f2543Smrg	*pNumEvents = nBytes / sizeof (Firm_event);
271706f2543Smrg	*pAgain = (nBytes == sizeof (evBuf));
272706f2543Smrg    }
273706f2543Smrg    return evBuf;
274706f2543Smrg}
275706f2543Smrg
276706f2543Smrg/*-
277706f2543Smrg *-----------------------------------------------------------------------
278706f2543Smrg * x68kKbdEnqueueEvent --
279706f2543Smrg *
280706f2543Smrg *-----------------------------------------------------------------------
281706f2543Smrg */
282706f2543Smrgvoid
283706f2543Smrgx68kKbdEnqueueEvent(DeviceIntPtr pDev, Firm_event *fe)
284706f2543Smrg{
285706f2543Smrg    BYTE		keycode;
286706f2543Smrg    int			type;
287706f2543Smrg    int			i, nevents;
288706f2543Smrg
289706f2543Smrg    GetEventList(&x68kEvents);
290706f2543Smrg    type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
291706f2543Smrg    keycode = (fe->id & 0x7f) + MIN_KEYCODE;
292706f2543Smrg    nevents = GetKeyboardEvents(x68kEvents, pDev, type, keycode);
293706f2543Smrg    for (i = 0; i < nevents; i++)
294706f2543Smrg	mieqEnqueue(pDev, (InternalEvent*)(x68kEvents + i)->event);
295706f2543Smrg}
296706f2543Smrg
297706f2543Smrg/*-
298706f2543Smrg *-----------------------------------------------------------------------
299706f2543Smrg * x68kKbdBell --
300706f2543Smrg *	Ring the terminal/keyboard bell
301706f2543Smrg *
302706f2543Smrg * Results:
303706f2543Smrg *	Ring the keyboard bell for an amount of time proportional to
304706f2543Smrg *	"loudness."
305706f2543Smrg *
306706f2543Smrg * Side Effects:
307706f2543Smrg *	None, really...
308706f2543Smrg *
309706f2543Smrg *-----------------------------------------------------------------------
310706f2543Smrg */
311706f2543Smrg
312706f2543Smrgstatic void
313706f2543Smrgx68kKbdRingBell(DeviceIntPtr pDev, int volume, int duration)
314706f2543Smrg{
315ab290810Stsutsui    int		    kbdCmd;	/* Command to give keyboard */
316706f2543Smrg    X68kKbdPrivPtr  pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
317ab290810Stsutsui
318706f2543Smrg    if (volume == 0)
319ab290810Stsutsui	return;
320706f2543Smrg
321706f2543Smrg    kbdCmd = KBD_CMD_BELL;
322706f2543Smrg    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1) {
323ab290810Stsutsui	Error("Failed to activate bell");
324706f2543Smrg	return;
325706f2543Smrg    }
326706f2543Smrg    usleep (duration * 1000);
327706f2543Smrg    kbdCmd = KBD_CMD_NOBELL;
328706f2543Smrg    if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1)
329706f2543Smrg	Error ("Failed to deactivate bell");
330706f2543Smrg}
331706f2543Smrg
332706f2543Smrgstatic void
333706f2543Smrgx68kKbdBell(int volume, DeviceIntPtr pDev, pointer ctrl, int unused)
334706f2543Smrg{
335706f2543Smrg    KeybdCtrl*      kctrl = (KeybdCtrl*) ctrl;
336ab290810Stsutsui
337706f2543Smrg    if (kctrl->bell == 0)
338ab290810Stsutsui	return;
339706f2543Smrg
340706f2543Smrg    x68kKbdRingBell(pDev, volume, kctrl->bell_duration);
341706f2543Smrg}
342706f2543Smrg
343706f2543Smrgvoid
344706f2543SmrgDDXRingBell(int volume, int pitch, int duration)
345706f2543Smrg{
346706f2543Smrg    DeviceIntPtr	pKeyboard;
347706f2543Smrg
348706f2543Smrg    pKeyboard = x68kKeyboardDevice;
349706f2543Smrg    if (pKeyboard != NULL)
350706f2543Smrg	x68kKbdRingBell(pKeyboard, volume, duration);
351706f2543Smrg}
352706f2543Smrg
353706f2543Smrg/*-
354706f2543Smrg *-----------------------------------------------------------------------
355706f2543Smrg * x68kKbdCtrl --
356706f2543Smrg *	Alter some of the keyboard control parameters
357706f2543Smrg *
358706f2543Smrg * Results:
359706f2543Smrg *	None.
360706f2543Smrg *
361706f2543Smrg * Side Effects:
362706f2543Smrg *	Some...
363706f2543Smrg *
364706f2543Smrg *-----------------------------------------------------------------------
365706f2543Smrg */
366706f2543Smrg#define	XKB_LED_ZENKAKU		0x40
367706f2543Smrg#define	XKB_LED_HIRAGANA	0x20
368706f2543Smrg#define	XKB_LED_INSERT		0x10
369706f2543Smrg#define	XKB_LED_CAPS_LOCK	0x08
370706f2543Smrg#define	XKB_LED_CODE_INPUT	0x04
371706f2543Smrg#define	XKB_LED_ROMAJI		0x02
372706f2543Smrg#define	XKB_LED_KANA_LOCK	0x01
373706f2543Smrg
374706f2543Smrgstatic void
375706f2543Smrgx68kKbdCtrl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
376706f2543Smrg{
377706f2543Smrg    X68kKbdPrivPtr pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate;
378706f2543Smrg
379706f2543Smrg    if (pPriv->leds != ctrl->leds) {
38084d30d9dStsutsui        x68kSetLeds(pPriv, (uint8_t)ctrl->leds);
381706f2543Smrg	pPriv->leds = ctrl->leds;
382706f2543Smrg    }
383706f2543Smrg}
384706f2543Smrg
385706f2543Smrg/*-------------------------------------------------------------------------
386706f2543Smrg * function "x68kSetLeds"
387706f2543Smrg *
388706f2543Smrg *  purpose:  set keyboard leds to specified state
389706f2543Smrg *  argument: (X68kKbdPrivPtr)pPriv
39084d30d9dStsutsui *            (uint8_t)data;
391706f2543Smrg *  returns:  nothing
392706f2543Smrg *-----------------------------------------------------------------------*/
393706f2543Smrgstatic void
39484d30d9dStsutsuix68kSetLeds(X68kKbdPrivPtr pPriv, uint8_t data)
395706f2543Smrg{
396706f2543Smrg    /* bit sequence of led indicator in xkb and hardware are same */
397706f2543Smrg    if (ioctl(pPriv->fd, KIOCSLED, &data) == -1)
398706f2543Smrg        Error("Failed to set keyboard lights");
399ab290810Stsutsui}
400706f2543Smrg
401706f2543SmrgBool
402706f2543SmrgLegalModifier(unsigned int key, DeviceIntPtr pDev)
403706f2543Smrg{
404706f2543Smrg    return TRUE;
405706f2543Smrg}
406706f2543Smrg
407706f2543Smrg/* EOF x68kKbd.c */
408