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