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