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