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