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