sun_kbd.c revision a1ed278c
1ee3138f1Smrg/* 2ee3138f1Smrg * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany 3ee3138f1Smrg * Copyright 1993 by David Dawes <dawes@XFree86.org> 4ee3138f1Smrg * Copyright 1999 by David Holland <davidh@iquest.net) 5ee3138f1Smrg * 6ee3138f1Smrg * Permission to use, copy, modify, distribute, and sell this software and its 7ee3138f1Smrg * documentation for any purpose is hereby granted without fee, provided that 8ee3138f1Smrg * the above copyright notice appear in all copies and that both that copyright 9ee3138f1Smrg * notice and this permission notice appear in supporting documentation, and 10ee3138f1Smrg * that the names of Thomas Roell, David Dawes, and David Holland not be used 11ee3138f1Smrg * in advertising or publicity pertaining to distribution of the software 12ee3138f1Smrg * without specific, written prior permission. Thomas Roell, David Dawes, and 13ee3138f1Smrg * David Holland make no representations about the suitability of this software 14ee3138f1Smrg * for any purpose. It is provided "as is" without express or implied 15ee3138f1Smrg * warranty. 16ee3138f1Smrg * 17ee3138f1Smrg * THOMAS ROELL, DAVID DAWES, AND DAVID HOLLAND DISCLAIM ALL WARRANTIES WITH 18ee3138f1Smrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19ee3138f1Smrg * AND FITNESS. IN NO EVENT SHALL THOMAS ROELL, DAVID DAWES, OR DAVID HOLLAND 20ee3138f1Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 21ee3138f1Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 22ee3138f1Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23ee3138f1Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24ee3138f1Smrg */ 25b425557eSmrg/* 26b425557eSmrg * Copyright (c) 2004-2009, Oracle and/or its affiliates. All rights reserved. 27ee3138f1Smrg * 28ee3138f1Smrg * Permission is hereby granted, free of charge, to any person obtaining a 29b425557eSmrg * copy of this software and associated documentation files (the "Software"), 30b425557eSmrg * to deal in the Software without restriction, including without limitation 31b425557eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 32b425557eSmrg * and/or sell copies of the Software, and to permit persons to whom the 33b425557eSmrg * Software is furnished to do so, subject to the following conditions: 34b425557eSmrg * 35b425557eSmrg * The above copyright notice and this permission notice (including the next 36b425557eSmrg * paragraph) shall be included in all copies or substantial portions of the 37b425557eSmrg * Software. 38b425557eSmrg * 39b425557eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40b425557eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41b425557eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 42b425557eSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43b425557eSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 44b425557eSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 45b425557eSmrg * DEALINGS IN THE SOFTWARE. 46ee3138f1Smrg */ 47ee3138f1Smrg 48ee3138f1Smrg#ifdef HAVE_CONFIG_H 49ee3138f1Smrg#include "config.h" 50ee3138f1Smrg#endif 51ee3138f1Smrg 52b425557eSmrg#include <xorg-server.h> 53ee3138f1Smrg#include "xf86.h" 54ee3138f1Smrg#include "xf86Priv.h" 55ee3138f1Smrg#include "xf86_OSlib.h" 56ee3138f1Smrg#include "xf86OSKbd.h" 57ee3138f1Smrg#include "sun_kbd.h" 58ee3138f1Smrg 59ee3138f1Smrg#include <sys/stropts.h> 60ee3138f1Smrg#include <sys/vuid_event.h> 61ee3138f1Smrg#include <sys/kbd.h> 6234977a2fSmrg#include <sys/note.h> /* needed before including older versions of hid.h */ 6334977a2fSmrg#include <sys/usb/clients/hid/hid.h> 6434977a2fSmrg 6534977a2fSmrgstatic int KbdOn(InputInfoPtr pInfo, int what); 6634977a2fSmrgstatic Bool OpenKeyboard(InputInfoPtr pInfo); 6734977a2fSmrgstatic void CloseKeyboard(InputInfoPtr pInfo); 68ee3138f1Smrg 69ee3138f1Smrgstatic void 70ee3138f1SmrgsunKbdSetLeds(InputInfoPtr pInfo, int leds) 71ee3138f1Smrg{ 72ee3138f1Smrg int i; 73ee3138f1Smrg 74ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCSLED, &leds)); 75ee3138f1Smrg if (i < 0) { 76ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to set keyboard LED's: %s\n", 77ee3138f1Smrg pInfo->name, strerror(errno)); 78ee3138f1Smrg } 79ee3138f1Smrg} 80ee3138f1Smrg 81ee3138f1Smrg 82ee3138f1Smrgstatic int 83ee3138f1SmrgsunKbdGetLeds(InputInfoPtr pInfo) 84ee3138f1Smrg{ 85ee3138f1Smrg int i, leds = 0; 86ee3138f1Smrg 87ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCGLED, &leds)); 88ee3138f1Smrg if (i < 0) { 89ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to get keyboard LED's: %s\n", 90ee3138f1Smrg pInfo->name, strerror(errno)); 91ee3138f1Smrg } 92ee3138f1Smrg return leds; 93ee3138f1Smrg} 94ee3138f1Smrg 95ee3138f1Smrg 96ee3138f1Smrg/* 97ee3138f1Smrg * Save initial keyboard state. This is called at the start of each server 98ee3138f1Smrg * generation. 99ee3138f1Smrg */ 100ee3138f1Smrgstatic int 101ee3138f1SmrgKbdInit(InputInfoPtr pInfo, int what) 102ee3138f1Smrg{ 103ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 104ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 105ee3138f1Smrg pointer options = pInfo->options; 106ee3138f1Smrg 107ee3138f1Smrg int ktype, klayout, i; 108ee3138f1Smrg const char *ktype_name; 109ee3138f1Smrg 11034977a2fSmrg priv->kbdActive = FALSE; 111ee3138f1Smrg priv->otranslation = -1; 112ee3138f1Smrg priv->odirect = -1; 113ee3138f1Smrg 114ee3138f1Smrg if (options != NULL) { 115ee3138f1Smrg priv->strmod = xf86SetStrOption(options, "StreamsModule", NULL); 116ee3138f1Smrg } else { 117ee3138f1Smrg priv->strmod = NULL; 118ee3138f1Smrg } 119ee3138f1Smrg 12034977a2fSmrg i = KbdOn(pInfo, DEVICE_INIT); 12134977a2fSmrg if (i != Success) { 12234977a2fSmrg return i; 123ee3138f1Smrg } 12434977a2fSmrg 125ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCTYPE, &ktype)); 126ee3138f1Smrg if (i < 0) { 127ee3138f1Smrg xf86Msg(X_ERROR, "%s: Unable to determine keyboard type: %s\n", 128ee3138f1Smrg pInfo->name, strerror(errno)); 129ee3138f1Smrg return BadImplementation; 130ee3138f1Smrg } 131ee3138f1Smrg 132ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCLAYOUT, &klayout)); 133ee3138f1Smrg if (i < 0) { 134ee3138f1Smrg xf86Msg(X_ERROR, "%s: Unable to determine keyboard layout: %s\n", 135ee3138f1Smrg pInfo->name, strerror(errno)); 136ee3138f1Smrg return BadImplementation; 137ee3138f1Smrg } 138ee3138f1Smrg 139ee3138f1Smrg switch (ktype) { 140ee3138f1Smrg case KB_SUN3: 141ee3138f1Smrg ktype_name = "Sun Type 3"; break; 142ee3138f1Smrg case KB_SUN4: 143ee3138f1Smrg ktype_name = "Sun Type 4/5/6"; break; 144ee3138f1Smrg case KB_USB: 145ee3138f1Smrg ktype_name = "USB"; break; 146ee3138f1Smrg case KB_PC: 147ee3138f1Smrg ktype_name = "PC"; break; 148ee3138f1Smrg default: 149ee3138f1Smrg ktype_name = "Unknown"; break; 150ee3138f1Smrg } 151ee3138f1Smrg 152ee3138f1Smrg xf86Msg(X_PROBED, "%s: Keyboard type: %s (%d)\n", 153ee3138f1Smrg pInfo->name, ktype_name, ktype); 154ee3138f1Smrg xf86Msg(X_PROBED, "%s: Keyboard layout: %d\n", pInfo->name, klayout); 155ee3138f1Smrg 156ee3138f1Smrg priv->ktype = ktype; 157ee3138f1Smrg 158ee3138f1Smrg return Success; 159ee3138f1Smrg} 160ee3138f1Smrg 161ee3138f1Smrg 162ee3138f1Smrgstatic int 163ee3138f1SmrgKbdOn(InputInfoPtr pInfo, int what) 164ee3138f1Smrg{ 165ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 166ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 167ee3138f1Smrg 168ee3138f1Smrg int ktrans, kdirect, i; 16934977a2fSmrg int io_get_direct = KIOCGDIRECT; 17034977a2fSmrg int io_set_direct = KIOCSDIRECT; 17134977a2fSmrg 17234977a2fSmrg if (priv->kbdActive) { 17334977a2fSmrg return Success; 17434977a2fSmrg } 175ee3138f1Smrg 17634977a2fSmrg if (pInfo->fd == -1) { 17734977a2fSmrg if (!OpenKeyboard(pInfo)) { 17834977a2fSmrg return BadImplementation; 17934977a2fSmrg } 18034977a2fSmrg } 18134977a2fSmrg 18234977a2fSmrg if (priv->strmod) { 18334977a2fSmrg /* Check to see if module is already pushed */ 18434977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, priv->strmod)); 18534977a2fSmrg 18634977a2fSmrg if (i == 0) { /* Not already pushed */ 18734977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, priv->strmod)); 18834977a2fSmrg if (i < 0) { 18934977a2fSmrg xf86Msg(X_ERROR, "%s: cannot push module '%s' onto " 19034977a2fSmrg "keyboard device: %s\n", 19134977a2fSmrg pInfo->name, priv->strmod, strerror(errno)); 19234977a2fSmrg } 19334977a2fSmrg } 19434977a2fSmrg 19534977a2fSmrg#ifdef HIDIOCKMSDIRECT 19634977a2fSmrg if (strcmp(priv->strmod, "usbkbm") == 0) { 19734977a2fSmrg io_get_direct = HIDIOCKMGDIRECT; 19834977a2fSmrg io_set_direct = HIDIOCKMSDIRECT; 19934977a2fSmrg } 20034977a2fSmrg#endif 20134977a2fSmrg } 20234977a2fSmrg 20334977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, io_get_direct, &kdirect)); 204ee3138f1Smrg if (i < 0) { 205ee3138f1Smrg xf86Msg(X_ERROR, 206ee3138f1Smrg "%s: Unable to determine keyboard direct setting: %s\n", 207ee3138f1Smrg pInfo->name, strerror(errno)); 208ee3138f1Smrg return BadImplementation; 209ee3138f1Smrg } 210ee3138f1Smrg 211ee3138f1Smrg priv->odirect = kdirect; 212ee3138f1Smrg kdirect = 1; 213ee3138f1Smrg 21434977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, io_set_direct, &kdirect)); 215ee3138f1Smrg if (i < 0) { 216ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed turning keyboard direct mode on: %s\n", 217ee3138f1Smrg pInfo->name, strerror(errno)); 218ee3138f1Smrg return BadImplementation; 219ee3138f1Smrg } 220ee3138f1Smrg 221ee3138f1Smrg /* Setup translation */ 222ee3138f1Smrg 223ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCGTRANS, &ktrans)); 224ee3138f1Smrg if (i < 0) { 225ee3138f1Smrg xf86Msg(X_ERROR, 226ee3138f1Smrg "%s: Unable to determine keyboard translation mode: %s\n", 227ee3138f1Smrg pInfo->name, strerror(errno)); 228ee3138f1Smrg return BadImplementation; 229ee3138f1Smrg } 230ee3138f1Smrg 231ee3138f1Smrg priv->otranslation = ktrans; 232ee3138f1Smrg ktrans = TR_UNTRANS_EVENT; 233ee3138f1Smrg 234ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCTRANS, &ktrans)); 235ee3138f1Smrg if (i < 0) { 236ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed setting keyboard translation mode: %s\n", 237ee3138f1Smrg pInfo->name, strerror(errno)); 238ee3138f1Smrg return BadImplementation; 239ee3138f1Smrg } 240ee3138f1Smrg 24134977a2fSmrg priv->oleds = sunKbdGetLeds(pInfo); 24234977a2fSmrg 24334977a2fSmrg /* Allocate here so we don't alloc in ReadInput which may be called 24434977a2fSmrg from SIGIO handler. */ 24534977a2fSmrg priv->remove_timer = TimerSet(priv->remove_timer, 0, 0, NULL, NULL); 24634977a2fSmrg 24734977a2fSmrg priv->kbdActive = TRUE; 248ee3138f1Smrg return Success; 249ee3138f1Smrg} 250ee3138f1Smrg 251ee3138f1Smrgstatic int 252ee3138f1SmrgKbdOff(InputInfoPtr pInfo, int what) 253ee3138f1Smrg{ 254ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 255ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 256ee3138f1Smrg 257ee3138f1Smrg int i; 25834977a2fSmrg int io_set_direct, kdirect; 25934977a2fSmrg 26034977a2fSmrg if (priv->remove_timer) { 26134977a2fSmrg TimerFree(priv->remove_timer); 26234977a2fSmrg priv->remove_timer = NULL; 26334977a2fSmrg } 26434977a2fSmrg 26534977a2fSmrg if (!priv->kbdActive) { 26634977a2fSmrg return Success; 26734977a2fSmrg } 26834977a2fSmrg 26934977a2fSmrg if (pInfo->fd == -1) { 27034977a2fSmrg priv->kbdActive = FALSE; 27134977a2fSmrg return Success; 27234977a2fSmrg } 273ee3138f1Smrg 274ee3138f1Smrg /* restore original state */ 27579a8a9c6Smrg 27679a8a9c6Smrg if (priv->oleds != -1) { 27779a8a9c6Smrg sunKbdSetLeds(pInfo, priv->oleds); 27879a8a9c6Smrg priv->oleds = -1; 27979a8a9c6Smrg } 280ee3138f1Smrg 281ee3138f1Smrg if (priv->otranslation != -1) { 282ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCTRANS, &priv->otranslation)); 283ee3138f1Smrg if (i < 0) { 284ee3138f1Smrg xf86Msg(X_ERROR, 285ee3138f1Smrg "%s: Unable to restore keyboard translation mode: %s\n", 286ee3138f1Smrg pInfo->name, strerror(errno)); 287ee3138f1Smrg return BadImplementation; 288ee3138f1Smrg } 289ee3138f1Smrg priv->otranslation = -1; 290ee3138f1Smrg } 291ee3138f1Smrg 29234977a2fSmrg io_set_direct = KIOCSDIRECT; 29334977a2fSmrg kdirect = priv->odirect; 29434977a2fSmrg 29534977a2fSmrg#ifdef HIDIOCKMSDIRECT 29634977a2fSmrg if ((priv->strmod != NULL) && (strcmp(priv->strmod, "usbkbm") == 0)) { 29734977a2fSmrg io_set_direct = HIDIOCKMSDIRECT; 29834977a2fSmrg kdirect = 0; 29934977a2fSmrg } 30034977a2fSmrg#endif 30134977a2fSmrg 30234977a2fSmrg if (kdirect != -1) { 30334977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, io_set_direct, &kdirect)); 304ee3138f1Smrg if (i < 0) { 305ee3138f1Smrg xf86Msg(X_ERROR, 306ee3138f1Smrg "%s: Unable to restore keyboard direct setting: %s\n", 307ee3138f1Smrg pInfo->name, strerror(errno)); 308ee3138f1Smrg return BadImplementation; 309ee3138f1Smrg } 310ee3138f1Smrg priv->odirect = -1; 311ee3138f1Smrg } 312ee3138f1Smrg 313ee3138f1Smrg if (priv->strmod) { 314ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, priv->strmod)); 315ee3138f1Smrg if (i < 0) { 316ee3138f1Smrg xf86Msg(X_WARNING, 317ee3138f1Smrg "%s: cannot pop module '%s' off keyboard device: %s\n", 318ee3138f1Smrg pInfo->name, priv->strmod, strerror(errno)); 319ee3138f1Smrg } 320ee3138f1Smrg } 321ee3138f1Smrg 32234977a2fSmrg CloseKeyboard(pInfo); 323ee3138f1Smrg return Success; 324ee3138f1Smrg} 325ee3138f1Smrg 326ee3138f1Smrg 327ee3138f1Smrgstatic void 328ee3138f1SmrgSoundKbdBell(InputInfoPtr pInfo, int loudness, int pitch, int duration) 329ee3138f1Smrg{ 330ee3138f1Smrg int kbdCmd, i; 331ee3138f1Smrg#ifdef KIOCMKTONE 332ee3138f1Smrg int cycles; 333ee3138f1Smrg int mktonevalue; 334ee3138f1Smrg#endif 335ee3138f1Smrg 336ee3138f1Smrg if (loudness && pitch) 337ee3138f1Smrg { 338ee3138f1Smrg#ifdef KIOCMKTONE 339ee3138f1Smrg if (pitch == 0) 340ee3138f1Smrg cycles = UINT16_MAX; 341ee3138f1Smrg else if (pitch >= UINT16_MAX) 342ee3138f1Smrg cycles = 0; 343ee3138f1Smrg else { 344ee3138f1Smrg cycles = (PIT_HZ + pitch / 2) / pitch; 345ee3138f1Smrg if (cycles > UINT16_MAX) 346ee3138f1Smrg cycles = UINT16_MAX; 347ee3138f1Smrg } 348ee3138f1Smrg 349ee3138f1Smrg mktonevalue = cycles | (((duration * loudness * 20) / 1000) << 16); 350ee3138f1Smrg 351ee3138f1Smrg errno = 0; 352ee3138f1Smrg SYSCALL(i = ioctl (pInfo->fd, KIOCMKTONE, mktonevalue)); 353ee3138f1Smrg if (i == 0) 354ee3138f1Smrg return; 355ee3138f1Smrg 356ee3138f1Smrg if (errno != EINVAL) { 357ee3138f1Smrg if (errno != EAGAIN) 358ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to activate bell: %s\n", 359ee3138f1Smrg pInfo->name, strerror(errno)); 360ee3138f1Smrg return; 361ee3138f1Smrg } 362ee3138f1Smrg#endif 363ee3138f1Smrg 364ee3138f1Smrg kbdCmd = KBD_CMD_BELL; 365ee3138f1Smrg 366ee3138f1Smrg SYSCALL(i = ioctl (pInfo->fd, KIOCCMD, &kbdCmd)); 367ee3138f1Smrg if (i < 0) { 368ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to activate bell: %s\n", 369ee3138f1Smrg pInfo->name, strerror(errno)); 370ee3138f1Smrg } 371ee3138f1Smrg 372ee3138f1Smrg usleep(duration * loudness * 20); 373ee3138f1Smrg 374ee3138f1Smrg kbdCmd = KBD_CMD_NOBELL; 375ee3138f1Smrg SYSCALL(i = ioctl (pInfo->fd, KIOCCMD, &kbdCmd)); 376ee3138f1Smrg if (i < 0) { 377ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to deactivate bell: %s\n", 378ee3138f1Smrg pInfo->name, strerror(errno)); 379ee3138f1Smrg } 380ee3138f1Smrg } 381ee3138f1Smrg} 382ee3138f1Smrg 383ee3138f1Smrgstatic void 384ee3138f1SmrgSetKbdLeds(InputInfoPtr pInfo, int leds) 385ee3138f1Smrg{ 386ee3138f1Smrg int real_leds = sunKbdGetLeds(pInfo); 387ee3138f1Smrg 388ee3138f1Smrg real_leds &= ~(LED_CAPS_LOCK | LED_NUM_LOCK | LED_SCROLL_LOCK | LED_COMPOSE); 389ee3138f1Smrg 390ee3138f1Smrg if (leds & XLED1) real_leds |= LED_CAPS_LOCK; 391ee3138f1Smrg if (leds & XLED2) real_leds |= LED_NUM_LOCK; 392ee3138f1Smrg if (leds & XLED3) real_leds |= LED_SCROLL_LOCK; 393ee3138f1Smrg if (leds & XLED4) real_leds |= LED_COMPOSE; 394ee3138f1Smrg 395ee3138f1Smrg sunKbdSetLeds(pInfo, real_leds); 396ee3138f1Smrg} 397ee3138f1Smrg 398ee3138f1Smrgstatic int 399ee3138f1SmrgGetKbdLeds(InputInfoPtr pInfo) 400ee3138f1Smrg{ 401ee3138f1Smrg int leds = 0; 402ee3138f1Smrg int real_leds = sunKbdGetLeds(pInfo); 403ee3138f1Smrg 404ee3138f1Smrg if (real_leds & LED_CAPS_LOCK) leds |= XLED1; 405ee3138f1Smrg if (real_leds & LED_NUM_LOCK) leds |= XLED2; 406ee3138f1Smrg if (real_leds & LED_SCROLL_LOCK) leds |= XLED3; 407ee3138f1Smrg if (real_leds & LED_COMPOSE) leds |= XLED4; 408ee3138f1Smrg 409ee3138f1Smrg return leds; 410ee3138f1Smrg} 411ee3138f1Smrg 41234977a2fSmrgstatic void 41334977a2fSmrgCloseKeyboard(InputInfoPtr pInfo) 41434977a2fSmrg{ 41534977a2fSmrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 41634977a2fSmrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 41734977a2fSmrg 41834977a2fSmrg close(pInfo->fd); 41934977a2fSmrg pInfo->fd = -1; 42034977a2fSmrg priv->kbdActive = FALSE; 42134977a2fSmrg} 42234977a2fSmrg 42334977a2fSmrg/* Called from OsTimer callback, since removing a device from the device 42434977a2fSmrg list or changing pInfo->fd while xf86Wakeup is looping through the list 42534977a2fSmrg causes server crashes */ 42634977a2fSmrgstatic CARD32 42734977a2fSmrgRemoveKeyboard(OsTimerPtr timer, CARD32 time, pointer arg) 42834977a2fSmrg{ 42934977a2fSmrg InputInfoPtr pInfo = (InputInfoPtr) arg; 43034977a2fSmrg 43134977a2fSmrg CloseKeyboard(pInfo); 43234977a2fSmrg xf86DisableDevice(pInfo->dev, TRUE); 43334977a2fSmrg 43434977a2fSmrg return 0; /* All done, don't set to run again */ 43534977a2fSmrg} 43634977a2fSmrg 437ee3138f1Smrgstatic void 438ee3138f1SmrgReadInput(InputInfoPtr pInfo) 439ee3138f1Smrg{ 440ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 44134977a2fSmrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 442ee3138f1Smrg Firm_event event[64]; 443ee3138f1Smrg int nBytes, i; 444ee3138f1Smrg 44534977a2fSmrg while (TRUE) { 44634977a2fSmrg /* I certainly hope it's not possible to read partial events */ 44734977a2fSmrg nBytes = read(pInfo->fd, (char *)event, sizeof(event)); 44834977a2fSmrg if (nBytes > 0) { 44934977a2fSmrg for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) { 45034977a2fSmrg pKbd->PostEvent(pInfo, event[i].id & 0xFF, 45134977a2fSmrg event[i].value == VKEY_DOWN ? TRUE : FALSE); 45234977a2fSmrg } 45334977a2fSmrg } else if (nBytes == -1) { 45434977a2fSmrg switch (errno) { 45534977a2fSmrg case EAGAIN: /* Nothing to read now */ 45634977a2fSmrg return; 45734977a2fSmrg case EINTR: /* Interrupted, try again */ 45834977a2fSmrg break; 45934977a2fSmrg case ENODEV: /* May happen when USB kbd is unplugged */ 46034977a2fSmrg /* We use X_NONE here because it doesn't alloc since we 46134977a2fSmrg may be called from SIGIO handler */ 46234977a2fSmrg xf86MsgVerb(X_NONE, 0, 46334977a2fSmrg "%s: Device no longer present - removing.\n", 46434977a2fSmrg pInfo->name); 46534977a2fSmrg xf86RemoveEnabledDevice(pInfo); 46634977a2fSmrg priv->remove_timer = TimerSet(priv->remove_timer, 0, 1, 46734977a2fSmrg RemoveKeyboard, pInfo); 46834977a2fSmrg return; 46934977a2fSmrg default: /* All other errors */ 47034977a2fSmrg /* We use X_NONE here because it doesn't alloc since we 47134977a2fSmrg may be called from SIGIO handler */ 47234977a2fSmrg xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, 47334977a2fSmrg strerror(errno)); 47434977a2fSmrg return; 47534977a2fSmrg } 47634977a2fSmrg } else { /* nBytes == 0, so nothing more to read */ 47734977a2fSmrg return; 478ee3138f1Smrg } 479ee3138f1Smrg } 480ee3138f1Smrg} 481ee3138f1Smrg 482ee3138f1Smrgstatic Bool 483ee3138f1SmrgOpenKeyboard(InputInfoPtr pInfo) 484ee3138f1Smrg{ 485a1ed278cSmrg char *kbdPath = xf86SetStrOption(pInfo->options, "Device", "/dev/kbd"); 486a1ed278cSmrg Bool ret; 487ee3138f1Smrg 488ee3138f1Smrg pInfo->fd = open(kbdPath, O_RDONLY | O_NONBLOCK); 489ee3138f1Smrg 490ee3138f1Smrg if (pInfo->fd == -1) { 491a1ed278cSmrg xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", pInfo->name, kbdPath); 492a1ed278cSmrg ret = FALSE; 493ee3138f1Smrg } else { 494ee3138f1Smrg xf86MsgVerb(X_INFO, 3, "%s: Opened device \"%s\"\n", pInfo->name, 495ee3138f1Smrg kbdPath); 496ee3138f1Smrg pInfo->read_input = ReadInput; 497a1ed278cSmrg ret = TRUE; 498ee3138f1Smrg } 499a1ed278cSmrg 500a1ed278cSmrg free(kbdPath); 501a1ed278cSmrg return ret; 502ee3138f1Smrg} 503ee3138f1Smrg 504ee3138f1Smrg_X_EXPORT Bool 505ee3138f1Smrgxf86OSKbdPreInit(InputInfoPtr pInfo) 506ee3138f1Smrg{ 507ee3138f1Smrg KbdDevPtr pKbd = pInfo->private; 508ee3138f1Smrg 509ee3138f1Smrg pKbd->KbdInit = KbdInit; 510ee3138f1Smrg pKbd->KbdOn = KbdOn; 511ee3138f1Smrg pKbd->KbdOff = KbdOff; 512ee3138f1Smrg pKbd->Bell = SoundKbdBell; 513ee3138f1Smrg pKbd->SetLeds = SetKbdLeds; 514ee3138f1Smrg pKbd->GetLeds = GetKbdLeds; 515ee3138f1Smrg pKbd->KbdGetMapping = KbdGetMapping; 516ee3138f1Smrg 517ee3138f1Smrg pKbd->RemapScanCode = NULL; 518ee3138f1Smrg 519ee3138f1Smrg pKbd->OpenKeyboard = OpenKeyboard; 520ee3138f1Smrg 521a1ed278cSmrg pKbd->private = calloc(sizeof(sunKbdPrivRec), 1); 522ee3138f1Smrg if (pKbd->private == NULL) { 523ee3138f1Smrg xf86Msg(X_ERROR,"can't allocate keyboard OS private data\n"); 524ee3138f1Smrg return FALSE; 525ee3138f1Smrg } else { 526ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 527ee3138f1Smrg priv->otranslation = -1; 528ee3138f1Smrg priv->odirect = -1; 529ee3138f1Smrg } 530ee3138f1Smrg 531ee3138f1Smrg return TRUE; 532ee3138f1Smrg} 533