x68kKbd.c revision 909daefd
1/* $NetBSD: x68kKbd.c,v 1.2 2016/08/30 07:50:55 mrg 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 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Yasushi Yamasaki 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 *-----------------------------------------------------------------------*/ 31 32/*- 33 * Copyright (c) 1987 by the Regents of the University of California 34 * 35 * Permission to use, copy, modify, and distribute this 36 * software and its documentation for any purpose and without 37 * fee is hereby granted, provided that the above copyright 38 * notice appear in all copies. The University of California 39 * makes no representations about the suitability of this 40 * software for any purpose. It is provided "as is" without 41 * express or implied warranty. 42 */ 43 44/************************************************************ 45Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. 46 47 All Rights Reserved 48 49Permission to use, copy, modify, and distribute this 50software and its documentation for any purpose and without 51fee is hereby granted, provided that the above copyright no- 52tice appear in all copies and that both that copyright no- 53tice and this permission notice appear in supporting docu- 54mentation, and that the names of Sun or X Consortium 55not be used in advertising or publicity pertaining to 56distribution of the software without specific prior 57written permission. Sun and X Consortium make no 58representations about the suitability of this software for 59any purpose. It is provided "as is" without any express or 60implied warranty. 61 62SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 63INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 64NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 65ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 66ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 67PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 68OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 69THE USE OR PERFORMANCE OF THIS SOFTWARE. 70 71********************************************************/ 72 73#include "x68k.h" 74#include "mi.h" 75 76#include <X11/X.h> 77#include <X11/Xproto.h> 78#include <X11/keysym.h> 79#include "screenint.h" 80#include "inputstr.h" 81#include "eventstr.h" 82#include "misc.h" 83#include "scrnintstr.h" 84#include "servermd.h" 85 86#include <X11/extensions/XKB.h> 87#include "xkbsrv.h" 88 89#define MIN_KEYCODE 7 /* necessary to avoid the mouse buttons */ 90#define MAX_KEYCODE 255 /* limited by the protocol */ 91 92X68kKbdPriv x68kKbdPriv; 93DeviceIntPtr x68kKeyboardDevice = NULL; 94 95static void x68kInitModMap(KeySymsRec *, CARD8 *); 96static void x68kInitKbdNames(XkbRMLVOSet *, X68kKbdPrivPtr); 97static void x68kKbdRingBell(DeviceIntPtr, int, int); 98static void x68kKbdBell(int, DeviceIntPtr, pointer, int); 99static void x68kKbdCtrl(DeviceIntPtr, KeybdCtrl *); 100static void x68kSetLeds(X68kKbdPrivPtr, u_char); 101 102/*------------------------------------------------------------------------ 103 * x68kKbdProc -- 104 * Handle the initialization, etc. of a keyboard. 105 * 106 * Results: 107 * None. 108 * 109 *----------------------------------------------------------------------*/ 110int 111x68kKbdProc(DeviceIntPtr pDev, /* Keyboard to manipulate */ 112 int what) /* What to do to it */ 113{ 114 DevicePtr pKeyboard = &pDev->public; 115 CARD8 x68kModMap[MAP_LENGTH]; 116 int mode; 117 XkbRMLVOSet rmlvo; 118 119 switch (what) { 120 case DEVICE_INIT: 121 pKeyboard->devicePrivate = (pointer)&x68kKbdPriv; 122 if( (x68kKbdPriv.fd = open("/dev/kbd", O_RDONLY)) == -1 ) { 123 ErrorF("Can't open keyboard device"); 124 return !Success; 125 } 126 pKeyboard->on = FALSE; 127 x68kInitModMap(x68kKeySyms, x68kModMap); 128 129 x68kInitKbdNames(&rmlvo, pKeyboard->devicePrivate); 130#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */ 131 InitKeyboardDeviceStruct(pDev, &rmlvo, 132 x68kKbdBell, x68kKbdCtrl); 133#else 134 InitKeyboardDeviceStruct(pDev, NULL, 135 x68kKbdBell, x68kKbdCtrl); 136 XkbApplyMappingChange(pDev, x68kKeySyms, 137 x68kKeySyms->minKeyCode, 138 x68kKeySyms->maxKeyCode - x68kKeySyms->minKeyCode + 1, 139 x68kModMap, serverClient); 140#endif 141 break; 142 143 case DEVICE_ON: 144 mode = 1; 145 if ( fcntl(x68kKbdPriv.fd, F_SETOWN, getpid()) == -1 || 146 fcntl(x68kKbdPriv.fd, F_SETFL, O_NONBLOCK|O_ASYNC) == -1 || 147 ioctl(x68kKbdPriv.fd, KIOCSDIRECT, &mode) == -1 ) { 148 ErrorF("Async keyboard I/O failed"); 149 return !Success; 150 } 151 x68kSetLeds(&x68kKbdPriv, (u_char)x68kKbdPriv.leds); 152 (void) AddEnabledDevice(x68kKbdPriv.fd); 153 pKeyboard->on = TRUE; 154 break; 155 156 case DEVICE_CLOSE: 157 case DEVICE_OFF: 158 RemoveEnabledDevice(x68kKbdPriv.fd); 159 pKeyboard->on = FALSE; 160 break; 161 default: 162 FatalError("Unknown keyboard operation\n"); 163 } 164 return Success; 165} 166 167/*------------------------------------------------------------------------- 168 * function "x68kInitModMap" 169 * 170 * purpose: initialize modmap with keysym table 171 * argument: (KeySymsRec *)x68kKeySyms : keysym table 172 * (CARD8 *)x68kModMap : result 173 * returns: nothing 174 *-----------------------------------------------------------------------*/ 175static void 176x68kInitModMap(KeySymsRec *KeySyms, CARD8 *x68kModMap) 177{ 178 int i; 179 180 for (i = 0; i < MAP_LENGTH; i++) 181 x68kModMap[i] = NoSymbol; 182 if (KeySyms->minKeyCode < MIN_KEYCODE) { 183 KeySyms->minKeyCode += MIN_KEYCODE; 184 KeySyms->maxKeyCode += MIN_KEYCODE; 185 } 186#if 0 187 if (KeySyms->maxKeyCode > MAX_KEYCODE) 188 KeySyms->maxKeyCode += MAX_KEYCODE; 189#endif 190 for (i = KeySyms->minKeyCode; 191 i < KeySyms->maxKeyCode; i++) { 192 switch (KeySyms->map[(i-KeySyms->minKeyCode)*4]) { 193 case XK_Shift_L: 194 case XK_Shift_R: 195 x68kModMap[i] = ShiftMask; 196 break; 197 case XK_Control_L: 198 case XK_Control_R: 199 x68kModMap[i] = ControlMask; 200 break; 201 case XK_Alt_L: 202 case XK_Alt_R: 203 x68kModMap[i] = Mod1Mask; 204 break; 205 case XK_Meta_L: 206 case XK_Meta_R: 207 x68kModMap[i] = Mod2Mask; 208 break; 209 case XK_Caps_Lock: 210 x68kModMap[i] = LockMask; 211 break; 212 } 213 } 214} 215 216/*------------------------------------------------------------------------- 217 * function "x68kInitKbdNames" 218 * 219 * purpose: store xkb database names 220 * argument: (XkbRMLVOSet *)rmlvo 221 * (X68kKbdPrivPtr)pKbd 222 * returns: nothing 223 *-----------------------------------------------------------------------*/ 224static void 225x68kInitKbdNames(XkbRMLVOSet *rmlvo, X68kKbdPrivPtr pKbd) 226{ 227#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */ 228 rmlvo->rules = "base"; 229 rmlvo->model = "x68k"; 230 switch (pKbd->type) { 231 case X68K_KB_STANDARD: 232 rmlvo->layout = "jp(standard)"; 233 break; 234 case X68K_KB_ASCII: 235 rmlvo->layout = "jp(ascii)"; 236 break; 237 } 238 rmlvo->variant = "basic"; 239 rmlvo->options = ""; 240#else 241 rmlvo->rules = "base"; 242 rmlvo->model = NULL; 243 rmlvo->layout = NULL; 244 rmlvo->variant = NULL; 245 rmlvo->options = NULL; 246#endif 247} 248 249/*- 250 *----------------------------------------------------------------------- 251 * x68kKbdGetEvents -- 252 * Return the events waiting in the wings for the given keyboard. 253 * 254 * Results: 255 * A pointer to an array of Firm_events or (Firm_event *)0 if no events 256 * The number of events contained in the array. 257 * A boolean as to whether more events might be available. 258 * 259 * Side Effects: 260 * None. 261 *----------------------------------------------------------------------- 262 */ 263Firm_event * 264x68kKbdGetEvents(int fd, int *pNumEvents, Bool *pAgain) 265{ 266 int nBytes; /* number of bytes of events available. */ 267 static Firm_event evBuf[X68K_MAXEVENTS]; /* Buffer for Firm_events */ 268 269 if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) { 270 if (errno == EWOULDBLOCK) { 271 *pNumEvents = 0; 272 *pAgain = FALSE; 273 } else { 274 ErrorF("Reading keyboard"); 275 FatalError ("Could not read the keyboard"); 276 } 277 } else { 278 *pNumEvents = nBytes / sizeof (Firm_event); 279 *pAgain = (nBytes == sizeof (evBuf)); 280 } 281 return evBuf; 282} 283 284/*- 285 *----------------------------------------------------------------------- 286 * x68kKbdEnqueueEvent -- 287 * 288 *----------------------------------------------------------------------- 289 */ 290void 291x68kKbdEnqueueEvent(DeviceIntPtr pDev, Firm_event *fe) 292{ 293 BYTE keycode; 294 int type; 295 int i, nevents; 296 297 type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress); 298 keycode = (fe->id & 0x7f) + MIN_KEYCODE; 299 nevents = GetKeyboardEvents(x68kEvents, pDev, type, keycode); 300 for (i = 0; i < nevents; i++) 301 mieqEnqueue(pDev, &x68kEvents[i]); 302} 303 304/*- 305 *----------------------------------------------------------------------- 306 * x68kKbdBell -- 307 * Ring the terminal/keyboard bell 308 * 309 * Results: 310 * Ring the keyboard bell for an amount of time proportional to 311 * "loudness." 312 * 313 * Side Effects: 314 * None, really... 315 * 316 *----------------------------------------------------------------------- 317 */ 318 319static void 320x68kKbdRingBell(DeviceIntPtr pDev, int volume, int duration) 321{ 322 int kbdCmd; /* Command to give keyboard */ 323 X68kKbdPrivPtr pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate; 324 325 if (volume == 0) 326 return; 327 328 kbdCmd = KBD_CMD_BELL; 329 if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1) { 330 ErrorF("Failed to activate bell"); 331 return; 332 } 333 usleep (duration * 1000); 334 kbdCmd = KBD_CMD_NOBELL; 335 if (ioctl (pPriv->fd, KIOCCMD, &kbdCmd) == -1) 336 ErrorF("Failed to deactivate bell"); 337} 338 339static void 340x68kKbdBell(int volume, DeviceIntPtr pDev, pointer ctrl, int unused) 341{ 342 KeybdCtrl* kctrl = (KeybdCtrl*) ctrl; 343 344 if (kctrl->bell == 0) 345 return; 346 347 x68kKbdRingBell(pDev, volume, kctrl->bell_duration); 348} 349 350void 351DDXRingBell(int volume, int pitch, int duration) 352{ 353 DeviceIntPtr pKeyboard; 354 355 pKeyboard = x68kKeyboardDevice; 356 if (pKeyboard != NULL) 357 x68kKbdRingBell(pKeyboard, volume, duration); 358} 359 360/*- 361 *----------------------------------------------------------------------- 362 * x68kKbdCtrl -- 363 * Alter some of the keyboard control parameters 364 * 365 * Results: 366 * None. 367 * 368 * Side Effects: 369 * Some... 370 * 371 *----------------------------------------------------------------------- 372 */ 373#define XKB_LED_ZENKAKU 0x40 374#define XKB_LED_HIRAGANA 0x20 375#define XKB_LED_INSERT 0x10 376#define XKB_LED_CAPS_LOCK 0x08 377#define XKB_LED_CODE_INPUT 0x04 378#define XKB_LED_ROMAJI 0x02 379#define XKB_LED_KANA_LOCK 0x01 380 381static void 382x68kKbdCtrl(DeviceIntPtr pDev, KeybdCtrl *ctrl) 383{ 384 X68kKbdPrivPtr pPriv = (X68kKbdPrivPtr)pDev->public.devicePrivate; 385 386#ifdef XKB 387 if (pPriv->leds != ctrl->leds) { 388 x68kSetLeds(pPriv, (u_char)ctrl->leds); 389 pPriv->leds = ctrl->leds; 390 } 391#endif 392} 393 394/*------------------------------------------------------------------------- 395 * function "x68kSetLeds" 396 * 397 * purpose: set keyboard leds to specified state 398 * argument: (X68kKbdPrivPtr)pPriv 399 * (u_char)data; 400 * returns: nothing 401 *-----------------------------------------------------------------------*/ 402static void 403x68kSetLeds(X68kKbdPrivPtr pPriv, u_char data) 404{ 405 /* bit sequence of led indicator in xkb and hardware are same */ 406 if (ioctl(pPriv->fd, KIOCSLED, &data) == -1) 407 ErrorF("Failed to set keyboard lights"); 408} 409 410Bool 411LegalModifier(unsigned int key, DeviceIntPtr pDev) 412{ 413 return TRUE; 414} 415 416/* EOF x68kKbd.c */ 417