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