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