x68kKbd.c revision 706f2543
1/* $NetBSD: x68kKbd.c,v 1.1.1.1 2016/06/09 09:07:59 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 "misc.h" 82#include "scrnintstr.h" 83#include "servermd.h" 84 85#include <X11/extensions/XKB.h> 86#include "xkbsrv.h" 87 88#define MIN_KEYCODE 7 /* necessary to avoid the mouse buttons */ 89#define MAX_KEYCODE 255 /* limited by the protocol */ 90 91X68kKbdPriv x68kKbdPriv; 92DeviceIntPtr x68kKeyboardDevice = NULL; 93 94static void x68kInitModMap(KeySymsRec *, CARD8 *); 95static void x68kInitKbdNames(XkbRMLVOSet *, X68kKbdPrivPtr); 96static void x68kKbdRingBell(DeviceIntPtr, int, int); 97static void x68kKbdBell(int, DeviceIntPtr, pointer, int); 98static void x68kKbdCtrl(DeviceIntPtr, KeybdCtrl *); 99static void x68kSetLeds(X68kKbdPrivPtr, u_char); 100 101/*------------------------------------------------------------------------ 102 * x68kKbdProc -- 103 * Handle the initialization, etc. of a keyboard. 104 * 105 * Results: 106 * None. 107 * 108 *----------------------------------------------------------------------*/ 109int 110x68kKbdProc(DeviceIntPtr pDev, /* Keyboard to manipulate */ 111 int what) /* What to do to it */ 112{ 113 DevicePtr pKeyboard = &pDev->public; 114 CARD8 x68kModMap[MAP_LENGTH]; 115 int mode; 116 XkbRMLVOSet rmlvo; 117 118 switch (what) { 119 case DEVICE_INIT: 120 pKeyboard->devicePrivate = (pointer)&x68kKbdPriv; 121 if( (x68kKbdPriv.fd = open("/dev/kbd", O_RDONLY)) == -1 ) { 122 Error("Can't open keyboard device"); 123 return !Success; 124 } 125 pKeyboard->on = FALSE; 126 x68kInitModMap(x68kKeySyms, x68kModMap); 127 128 x68kInitKbdNames(&rmlvo, pKeyboard->devicePrivate); 129#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */ 130 InitKeyboardDeviceStruct(pDev, &rmlvo, 131 x68kKbdBell, x68kKbdCtrl); 132#else 133 InitKeyboardDeviceStruct(pDev, NULL, 134 x68kKbdBell, x68kKbdCtrl); 135 XkbApplyMappingChange(pDev, x68kKeySyms, 136 x68kKeySyms->minKeyCode, 137 x68kKeySyms->maxKeyCode - x68kKeySyms->minKeyCode + 1, 138 x68kModMap, serverClient); 139#endif 140 break; 141 142 case DEVICE_ON: 143 mode = 1; 144 if ( fcntl(x68kKbdPriv.fd, F_SETOWN, getpid()) == -1 || 145 fcntl(x68kKbdPriv.fd, F_SETFL, O_NONBLOCK|O_ASYNC) == -1 || 146 ioctl(x68kKbdPriv.fd, KIOCSDIRECT, &mode) == -1 ) { 147 Error("Async keyboard I/O failed"); 148 return !Success; 149 } 150 x68kSetLeds(&x68kKbdPriv, (u_char)x68kKbdPriv.leds); 151 (void) AddEnabledDevice(x68kKbdPriv.fd); 152 pKeyboard->on = TRUE; 153 break; 154 155 case DEVICE_CLOSE: 156 case DEVICE_OFF: 157 RemoveEnabledDevice(x68kKbdPriv.fd); 158 pKeyboard->on = FALSE; 159 break; 160 default: 161 FatalError("Unknown keyboard operation\n"); 162 } 163 return Success; 164} 165 166/*------------------------------------------------------------------------- 167 * function "x68kInitModMap" 168 * 169 * purpose: initialize modmap with keysym table 170 * argument: (KeySymsRec *)x68kKeySyms : keysym table 171 * (CARD8 *)x68kModMap : result 172 * returns: nothing 173 *-----------------------------------------------------------------------*/ 174static void 175x68kInitModMap(KeySymsRec *KeySyms, CARD8 *x68kModMap) 176{ 177 int i; 178 179 for (i = 0; i < MAP_LENGTH; i++) 180 x68kModMap[i] = NoSymbol; 181 if (KeySyms->minKeyCode < MIN_KEYCODE) { 182 KeySyms->minKeyCode += MIN_KEYCODE; 183 KeySyms->maxKeyCode += MIN_KEYCODE; 184 } 185#if 0 186 if (KeySyms->maxKeyCode > MAX_KEYCODE) 187 KeySyms->maxKeyCode += MAX_KEYCODE; 188#endif 189 for (i = KeySyms->minKeyCode; 190 i < KeySyms->maxKeyCode; i++) { 191 switch (KeySyms->map[(i-KeySyms->minKeyCode)*4]) { 192 case XK_Shift_L: 193 case XK_Shift_R: 194 x68kModMap[i] = ShiftMask; 195 break; 196 case XK_Control_L: 197 case XK_Control_R: 198 x68kModMap[i] = ControlMask; 199 break; 200 case XK_Alt_L: 201 case XK_Alt_R: 202 x68kModMap[i] = Mod1Mask; 203 break; 204 case XK_Meta_L: 205 case XK_Meta_R: 206 x68kModMap[i] = Mod2Mask; 207 break; 208 case XK_Caps_Lock: 209 x68kModMap[i] = LockMask; 210 break; 211 } 212 } 213} 214 215/*------------------------------------------------------------------------- 216 * function "x68kInitKbdNames" 217 * 218 * purpose: store xkb database names 219 * argument: (XkbRMLVOSet *)rmlvo 220 * (X68kKbdPrivPtr)pKbd 221 * returns: nothing 222 *-----------------------------------------------------------------------*/ 223static void 224x68kInitKbdNames(XkbRMLVOSet *rmlvo, X68kKbdPrivPtr pKbd) 225{ 226#if 0 /* XXX How should we setup XKB maps for non PS/2 keyboard!? */ 227 rmlvo->rules = "base"; 228 rmlvo->model = "x68k"; 229 switch (pKbd->type) { 230 case X68K_KB_STANDARD: 231 rmlvo->layout = "jp(standard)"; 232 break; 233 case X68K_KB_ASCII: 234 rmlvo->layout = "jp(ascii)"; 235 break; 236 } 237 rmlvo->variant = "basic"; 238 rmlvo->options = ""; 239#else 240 rmlvo->rules = "base"; 241 rmlvo->model = NULL; 242 rmlvo->layout = NULL; 243 rmlvo->variant = NULL; 244 rmlvo->options = NULL; 245#endif 246} 247 248/*- 249 *----------------------------------------------------------------------- 250 * x68kKbdGetEvents -- 251 * Return the events waiting in the wings for the given keyboard. 252 * 253 * Results: 254 * A pointer to an array of Firm_events or (Firm_event *)0 if no events 255 * The number of events contained in the array. 256 * A boolean as to whether more events might be available. 257 * 258 * Side Effects: 259 * None. 260 *----------------------------------------------------------------------- 261 */ 262Firm_event * 263x68kKbdGetEvents(int fd, int *pNumEvents, Bool *pAgain) 264{ 265 int nBytes; /* number of bytes of events available. */ 266 static Firm_event evBuf[MAXEVENTS]; /* Buffer for Firm_events */ 267 268 if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) { 269 if (errno == EWOULDBLOCK) { 270 *pNumEvents = 0; 271 *pAgain = FALSE; 272 } else { 273 Error ("Reading keyboard"); 274 FatalError ("Could not read the keyboard"); 275 } 276 } else { 277 *pNumEvents = nBytes / sizeof (Firm_event); 278 *pAgain = (nBytes == sizeof (evBuf)); 279 } 280 return evBuf; 281} 282 283/*- 284 *----------------------------------------------------------------------- 285 * x68kKbdEnqueueEvent -- 286 * 287 *----------------------------------------------------------------------- 288 */ 289void 290x68kKbdEnqueueEvent(DeviceIntPtr pDev, Firm_event *fe) 291{ 292 BYTE keycode; 293 int type; 294 int i, nevents; 295 296 GetEventList(&x68kEvents); 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, (InternalEvent*)(x68kEvents + i)->event); 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 Error("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 Error ("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 Error("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