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