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