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; 733e72ca8cSmrg uchar_t setleds = (uchar_t) (leds & 0xFF); 74ee3138f1Smrg 753e72ca8cSmrg SYSCALL(i = ioctl(pInfo->fd, KIOCSLED, &setleds)); 76ee3138f1Smrg if (i < 0) { 77ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to set keyboard LED's: %s\n", 78ee3138f1Smrg pInfo->name, strerror(errno)); 79ee3138f1Smrg } 80ee3138f1Smrg} 81ee3138f1Smrg 82ee3138f1Smrg 83ee3138f1Smrgstatic int 84ee3138f1SmrgsunKbdGetLeds(InputInfoPtr pInfo) 85ee3138f1Smrg{ 863e72ca8cSmrg int i; 873e72ca8cSmrg uchar_t leds = 0; 88ee3138f1Smrg 89ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCGLED, &leds)); 90ee3138f1Smrg if (i < 0) { 91ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to get keyboard LED's: %s\n", 92ee3138f1Smrg pInfo->name, strerror(errno)); 93ee3138f1Smrg } 943e72ca8cSmrg return (int) leds; 95ee3138f1Smrg} 96ee3138f1Smrg 97ee3138f1Smrg 98ee3138f1Smrg/* 99ee3138f1Smrg * Save initial keyboard state. This is called at the start of each server 100ee3138f1Smrg * generation. 101ee3138f1Smrg */ 102ee3138f1Smrgstatic int 103ee3138f1SmrgKbdInit(InputInfoPtr pInfo, int what) 104ee3138f1Smrg{ 105ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 106ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 107ee3138f1Smrg pointer options = pInfo->options; 108ee3138f1Smrg 109ee3138f1Smrg int ktype, klayout, i; 110ee3138f1Smrg const char *ktype_name; 111ee3138f1Smrg 11234977a2fSmrg priv->kbdActive = FALSE; 113ee3138f1Smrg priv->otranslation = -1; 114ee3138f1Smrg priv->odirect = -1; 115ee3138f1Smrg 116ee3138f1Smrg if (options != NULL) { 117ee3138f1Smrg priv->strmod = xf86SetStrOption(options, "StreamsModule", NULL); 118ee3138f1Smrg } else { 119ee3138f1Smrg priv->strmod = NULL; 120ee3138f1Smrg } 121ee3138f1Smrg 12234977a2fSmrg i = KbdOn(pInfo, DEVICE_INIT); 12334977a2fSmrg if (i != Success) { 12434977a2fSmrg return i; 125ee3138f1Smrg } 12634977a2fSmrg 127ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCTYPE, &ktype)); 128ee3138f1Smrg if (i < 0) { 129ee3138f1Smrg xf86Msg(X_ERROR, "%s: Unable to determine keyboard type: %s\n", 130ee3138f1Smrg pInfo->name, strerror(errno)); 131ee3138f1Smrg return BadImplementation; 132ee3138f1Smrg } 133ee3138f1Smrg 134ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCLAYOUT, &klayout)); 135ee3138f1Smrg if (i < 0) { 136ee3138f1Smrg xf86Msg(X_ERROR, "%s: Unable to determine keyboard layout: %s\n", 137ee3138f1Smrg pInfo->name, strerror(errno)); 138ee3138f1Smrg return BadImplementation; 139ee3138f1Smrg } 140ee3138f1Smrg 141ee3138f1Smrg switch (ktype) { 142ee3138f1Smrg case KB_SUN3: 143ee3138f1Smrg ktype_name = "Sun Type 3"; break; 144ee3138f1Smrg case KB_SUN4: 145ee3138f1Smrg ktype_name = "Sun Type 4/5/6"; break; 146ee3138f1Smrg case KB_USB: 147ee3138f1Smrg ktype_name = "USB"; break; 148ee3138f1Smrg case KB_PC: 149ee3138f1Smrg ktype_name = "PC"; break; 150ee3138f1Smrg default: 151ee3138f1Smrg ktype_name = "Unknown"; break; 152ee3138f1Smrg } 153ee3138f1Smrg 154ee3138f1Smrg xf86Msg(X_PROBED, "%s: Keyboard type: %s (%d)\n", 155ee3138f1Smrg pInfo->name, ktype_name, ktype); 156ee3138f1Smrg xf86Msg(X_PROBED, "%s: Keyboard layout: %d\n", pInfo->name, klayout); 157ee3138f1Smrg 158ee3138f1Smrg priv->ktype = ktype; 159ee3138f1Smrg 160ee3138f1Smrg return Success; 161ee3138f1Smrg} 162ee3138f1Smrg 163ee3138f1Smrg 164ee3138f1Smrgstatic int 165ee3138f1SmrgKbdOn(InputInfoPtr pInfo, int what) 166ee3138f1Smrg{ 167ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 168ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 169ee3138f1Smrg 170ee3138f1Smrg int ktrans, kdirect, i; 17134977a2fSmrg int io_get_direct = KIOCGDIRECT; 17234977a2fSmrg int io_set_direct = KIOCSDIRECT; 17334977a2fSmrg 17434977a2fSmrg if (priv->kbdActive) { 17534977a2fSmrg return Success; 17634977a2fSmrg } 177ee3138f1Smrg 17834977a2fSmrg if (pInfo->fd == -1) { 17934977a2fSmrg if (!OpenKeyboard(pInfo)) { 18034977a2fSmrg return BadImplementation; 18134977a2fSmrg } 18234977a2fSmrg } 18334977a2fSmrg 18434977a2fSmrg if (priv->strmod) { 18534977a2fSmrg /* Check to see if module is already pushed */ 18634977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, priv->strmod)); 18734977a2fSmrg 18834977a2fSmrg if (i == 0) { /* Not already pushed */ 18934977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, priv->strmod)); 19034977a2fSmrg if (i < 0) { 19134977a2fSmrg xf86Msg(X_ERROR, "%s: cannot push module '%s' onto " 19234977a2fSmrg "keyboard device: %s\n", 19334977a2fSmrg pInfo->name, priv->strmod, strerror(errno)); 19434977a2fSmrg } 19534977a2fSmrg } 19634977a2fSmrg 19734977a2fSmrg#ifdef HIDIOCKMSDIRECT 19834977a2fSmrg if (strcmp(priv->strmod, "usbkbm") == 0) { 19934977a2fSmrg io_get_direct = HIDIOCKMGDIRECT; 20034977a2fSmrg io_set_direct = HIDIOCKMSDIRECT; 20134977a2fSmrg } 20234977a2fSmrg#endif 20334977a2fSmrg } 20434977a2fSmrg 20534977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, io_get_direct, &kdirect)); 206ee3138f1Smrg if (i < 0) { 207ee3138f1Smrg xf86Msg(X_ERROR, 208ee3138f1Smrg "%s: Unable to determine keyboard direct setting: %s\n", 209ee3138f1Smrg pInfo->name, strerror(errno)); 210ee3138f1Smrg return BadImplementation; 211ee3138f1Smrg } 212ee3138f1Smrg 213ee3138f1Smrg priv->odirect = kdirect; 214ee3138f1Smrg kdirect = 1; 215ee3138f1Smrg 21634977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, io_set_direct, &kdirect)); 217ee3138f1Smrg if (i < 0) { 218ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed turning keyboard direct mode on: %s\n", 219ee3138f1Smrg pInfo->name, strerror(errno)); 220ee3138f1Smrg return BadImplementation; 221ee3138f1Smrg } 222ee3138f1Smrg 223ee3138f1Smrg /* Setup translation */ 224ee3138f1Smrg 225ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCGTRANS, &ktrans)); 226ee3138f1Smrg if (i < 0) { 227ee3138f1Smrg xf86Msg(X_ERROR, 228ee3138f1Smrg "%s: Unable to determine keyboard translation mode: %s\n", 229ee3138f1Smrg pInfo->name, strerror(errno)); 230ee3138f1Smrg return BadImplementation; 231ee3138f1Smrg } 232ee3138f1Smrg 233ee3138f1Smrg priv->otranslation = ktrans; 234ee3138f1Smrg ktrans = TR_UNTRANS_EVENT; 235ee3138f1Smrg 236ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCTRANS, &ktrans)); 237ee3138f1Smrg if (i < 0) { 238ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed setting keyboard translation mode: %s\n", 239ee3138f1Smrg pInfo->name, strerror(errno)); 240ee3138f1Smrg return BadImplementation; 241ee3138f1Smrg } 242ee3138f1Smrg 24334977a2fSmrg priv->oleds = sunKbdGetLeds(pInfo); 24434977a2fSmrg 24534977a2fSmrg /* Allocate here so we don't alloc in ReadInput which may be called 24634977a2fSmrg from SIGIO handler. */ 24734977a2fSmrg priv->remove_timer = TimerSet(priv->remove_timer, 0, 0, NULL, NULL); 24834977a2fSmrg 24934977a2fSmrg priv->kbdActive = TRUE; 250ee3138f1Smrg return Success; 251ee3138f1Smrg} 252ee3138f1Smrg 253ee3138f1Smrgstatic int 254ee3138f1SmrgKbdOff(InputInfoPtr pInfo, int what) 255ee3138f1Smrg{ 256ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 257ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 258ee3138f1Smrg 259ee3138f1Smrg int i; 26034977a2fSmrg int io_set_direct, kdirect; 26134977a2fSmrg 26234977a2fSmrg if (priv->remove_timer) { 26334977a2fSmrg TimerFree(priv->remove_timer); 26434977a2fSmrg priv->remove_timer = NULL; 26534977a2fSmrg } 26634977a2fSmrg 26734977a2fSmrg if (!priv->kbdActive) { 26834977a2fSmrg return Success; 26934977a2fSmrg } 27034977a2fSmrg 27134977a2fSmrg if (pInfo->fd == -1) { 27234977a2fSmrg priv->kbdActive = FALSE; 27334977a2fSmrg return Success; 27434977a2fSmrg } 275ee3138f1Smrg 276ee3138f1Smrg /* restore original state */ 27779a8a9c6Smrg 27879a8a9c6Smrg if (priv->oleds != -1) { 27979a8a9c6Smrg sunKbdSetLeds(pInfo, priv->oleds); 28079a8a9c6Smrg priv->oleds = -1; 28179a8a9c6Smrg } 282ee3138f1Smrg 283ee3138f1Smrg if (priv->otranslation != -1) { 284ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, KIOCTRANS, &priv->otranslation)); 285ee3138f1Smrg if (i < 0) { 286ee3138f1Smrg xf86Msg(X_ERROR, 287ee3138f1Smrg "%s: Unable to restore keyboard translation mode: %s\n", 288ee3138f1Smrg pInfo->name, strerror(errno)); 289ee3138f1Smrg return BadImplementation; 290ee3138f1Smrg } 291ee3138f1Smrg priv->otranslation = -1; 292ee3138f1Smrg } 293ee3138f1Smrg 29434977a2fSmrg io_set_direct = KIOCSDIRECT; 29534977a2fSmrg kdirect = priv->odirect; 29634977a2fSmrg 29734977a2fSmrg#ifdef HIDIOCKMSDIRECT 29834977a2fSmrg if ((priv->strmod != NULL) && (strcmp(priv->strmod, "usbkbm") == 0)) { 29934977a2fSmrg io_set_direct = HIDIOCKMSDIRECT; 30034977a2fSmrg kdirect = 0; 30134977a2fSmrg } 30234977a2fSmrg#endif 30334977a2fSmrg 30434977a2fSmrg if (kdirect != -1) { 30534977a2fSmrg SYSCALL(i = ioctl(pInfo->fd, io_set_direct, &kdirect)); 306ee3138f1Smrg if (i < 0) { 307ee3138f1Smrg xf86Msg(X_ERROR, 308ee3138f1Smrg "%s: Unable to restore keyboard direct setting: %s\n", 309ee3138f1Smrg pInfo->name, strerror(errno)); 310ee3138f1Smrg return BadImplementation; 311ee3138f1Smrg } 312ee3138f1Smrg priv->odirect = -1; 313ee3138f1Smrg } 314ee3138f1Smrg 315ee3138f1Smrg if (priv->strmod) { 316ee3138f1Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, priv->strmod)); 317ee3138f1Smrg if (i < 0) { 318ee3138f1Smrg xf86Msg(X_WARNING, 319ee3138f1Smrg "%s: cannot pop module '%s' off keyboard device: %s\n", 320ee3138f1Smrg pInfo->name, priv->strmod, strerror(errno)); 321ee3138f1Smrg } 322ee3138f1Smrg } 323ee3138f1Smrg 32434977a2fSmrg CloseKeyboard(pInfo); 325ee3138f1Smrg return Success; 326ee3138f1Smrg} 327ee3138f1Smrg 328ee3138f1Smrg 329ee3138f1Smrgstatic void 330ee3138f1SmrgSoundKbdBell(InputInfoPtr pInfo, int loudness, int pitch, int duration) 331ee3138f1Smrg{ 332ee3138f1Smrg int kbdCmd, i; 333ee3138f1Smrg#ifdef KIOCMKTONE 334ee3138f1Smrg int cycles; 335ee3138f1Smrg int mktonevalue; 336ee3138f1Smrg#endif 337ee3138f1Smrg 338ee3138f1Smrg if (loudness && pitch) 339ee3138f1Smrg { 340ee3138f1Smrg#ifdef KIOCMKTONE 341ee3138f1Smrg if (pitch == 0) 342ee3138f1Smrg cycles = UINT16_MAX; 343ee3138f1Smrg else if (pitch >= UINT16_MAX) 344ee3138f1Smrg cycles = 0; 345ee3138f1Smrg else { 346ee3138f1Smrg cycles = (PIT_HZ + pitch / 2) / pitch; 347ee3138f1Smrg if (cycles > UINT16_MAX) 348ee3138f1Smrg cycles = UINT16_MAX; 349ee3138f1Smrg } 350ee3138f1Smrg 351ee3138f1Smrg mktonevalue = cycles | (((duration * loudness * 20) / 1000) << 16); 352ee3138f1Smrg 353ee3138f1Smrg errno = 0; 354ee3138f1Smrg SYSCALL(i = ioctl (pInfo->fd, KIOCMKTONE, mktonevalue)); 355ee3138f1Smrg if (i == 0) 356ee3138f1Smrg return; 357ee3138f1Smrg 358ee3138f1Smrg if (errno != EINVAL) { 359ee3138f1Smrg if (errno != EAGAIN) 360ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to activate bell: %s\n", 361ee3138f1Smrg pInfo->name, strerror(errno)); 362ee3138f1Smrg return; 363ee3138f1Smrg } 364ee3138f1Smrg#endif 365ee3138f1Smrg 366ee3138f1Smrg kbdCmd = KBD_CMD_BELL; 367ee3138f1Smrg 368ee3138f1Smrg SYSCALL(i = ioctl (pInfo->fd, KIOCCMD, &kbdCmd)); 369ee3138f1Smrg if (i < 0) { 370ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to activate bell: %s\n", 371ee3138f1Smrg pInfo->name, strerror(errno)); 372ee3138f1Smrg } 373ee3138f1Smrg 374ee3138f1Smrg usleep(duration * loudness * 20); 375ee3138f1Smrg 376ee3138f1Smrg kbdCmd = KBD_CMD_NOBELL; 377ee3138f1Smrg SYSCALL(i = ioctl (pInfo->fd, KIOCCMD, &kbdCmd)); 378ee3138f1Smrg if (i < 0) { 379ee3138f1Smrg xf86Msg(X_ERROR, "%s: Failed to deactivate bell: %s\n", 380ee3138f1Smrg pInfo->name, strerror(errno)); 381ee3138f1Smrg } 382ee3138f1Smrg } 383ee3138f1Smrg} 384ee3138f1Smrg 385ee3138f1Smrgstatic void 386ee3138f1SmrgSetKbdLeds(InputInfoPtr pInfo, int leds) 387ee3138f1Smrg{ 388ee3138f1Smrg int real_leds = sunKbdGetLeds(pInfo); 389ee3138f1Smrg 390ee3138f1Smrg real_leds &= ~(LED_CAPS_LOCK | LED_NUM_LOCK | LED_SCROLL_LOCK | LED_COMPOSE); 391ee3138f1Smrg 392ee3138f1Smrg if (leds & XLED1) real_leds |= LED_CAPS_LOCK; 393ee3138f1Smrg if (leds & XLED2) real_leds |= LED_NUM_LOCK; 394ee3138f1Smrg if (leds & XLED3) real_leds |= LED_SCROLL_LOCK; 395ee3138f1Smrg if (leds & XLED4) real_leds |= LED_COMPOSE; 396ee3138f1Smrg 397ee3138f1Smrg sunKbdSetLeds(pInfo, real_leds); 398ee3138f1Smrg} 399ee3138f1Smrg 400ee3138f1Smrgstatic int 401ee3138f1SmrgGetKbdLeds(InputInfoPtr pInfo) 402ee3138f1Smrg{ 403ee3138f1Smrg int leds = 0; 404ee3138f1Smrg int real_leds = sunKbdGetLeds(pInfo); 405ee3138f1Smrg 406ee3138f1Smrg if (real_leds & LED_CAPS_LOCK) leds |= XLED1; 407ee3138f1Smrg if (real_leds & LED_NUM_LOCK) leds |= XLED2; 408ee3138f1Smrg if (real_leds & LED_SCROLL_LOCK) leds |= XLED3; 409ee3138f1Smrg if (real_leds & LED_COMPOSE) leds |= XLED4; 410ee3138f1Smrg 411ee3138f1Smrg return leds; 412ee3138f1Smrg} 413ee3138f1Smrg 41434977a2fSmrgstatic void 41534977a2fSmrgCloseKeyboard(InputInfoPtr pInfo) 41634977a2fSmrg{ 41734977a2fSmrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 41834977a2fSmrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 41934977a2fSmrg 42034977a2fSmrg close(pInfo->fd); 42134977a2fSmrg pInfo->fd = -1; 42234977a2fSmrg priv->kbdActive = FALSE; 42334977a2fSmrg} 42434977a2fSmrg 42534977a2fSmrg/* Called from OsTimer callback, since removing a device from the device 42634977a2fSmrg list or changing pInfo->fd while xf86Wakeup is looping through the list 42734977a2fSmrg causes server crashes */ 42834977a2fSmrgstatic CARD32 42934977a2fSmrgRemoveKeyboard(OsTimerPtr timer, CARD32 time, pointer arg) 43034977a2fSmrg{ 43134977a2fSmrg InputInfoPtr pInfo = (InputInfoPtr) arg; 43234977a2fSmrg 43334977a2fSmrg CloseKeyboard(pInfo); 43434977a2fSmrg xf86DisableDevice(pInfo->dev, TRUE); 43534977a2fSmrg 43634977a2fSmrg return 0; /* All done, don't set to run again */ 43734977a2fSmrg} 43834977a2fSmrg 439ee3138f1Smrgstatic void 440ee3138f1SmrgReadInput(InputInfoPtr pInfo) 441ee3138f1Smrg{ 442ee3138f1Smrg KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; 44334977a2fSmrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 444ee3138f1Smrg Firm_event event[64]; 445ee3138f1Smrg int nBytes, i; 446ee3138f1Smrg 44734977a2fSmrg while (TRUE) { 44834977a2fSmrg /* I certainly hope it's not possible to read partial events */ 44934977a2fSmrg nBytes = read(pInfo->fd, (char *)event, sizeof(event)); 45034977a2fSmrg if (nBytes > 0) { 45134977a2fSmrg for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) { 45234977a2fSmrg pKbd->PostEvent(pInfo, event[i].id & 0xFF, 45334977a2fSmrg event[i].value == VKEY_DOWN ? TRUE : FALSE); 45434977a2fSmrg } 45534977a2fSmrg } else if (nBytes == -1) { 45634977a2fSmrg switch (errno) { 45734977a2fSmrg case EAGAIN: /* Nothing to read now */ 45834977a2fSmrg return; 45934977a2fSmrg case EINTR: /* Interrupted, try again */ 46034977a2fSmrg break; 46134977a2fSmrg case ENODEV: /* May happen when USB kbd is unplugged */ 4623e72ca8cSmrg /* We use X_NONE here because it didn't alloc since we 4633e72ca8cSmrg may be called from SIGIO handler. No longer true for 4643e72ca8cSmrg sigsafe logging, but matters for older servers */ 4653e72ca8cSmrg LogMessageVerbSigSafe(X_NONE, 0, 4663e72ca8cSmrg "%s: Device no longer present - removing.\n", 4673e72ca8cSmrg pInfo->name); 46834977a2fSmrg xf86RemoveEnabledDevice(pInfo); 46934977a2fSmrg priv->remove_timer = TimerSet(priv->remove_timer, 0, 1, 47034977a2fSmrg RemoveKeyboard, pInfo); 47134977a2fSmrg return; 47234977a2fSmrg default: /* All other errors */ 4733e72ca8cSmrg /* We use X_NONE here because it didn't alloc since we 4743e72ca8cSmrg may be called from SIGIO handler. No longer true for 4753e72ca8cSmrg sigsafe logging, but matters for older servers */ 4763e72ca8cSmrg LogMessageVerbSigSafe(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, 4773e72ca8cSmrg strerror(errno)); 47834977a2fSmrg return; 47934977a2fSmrg } 48034977a2fSmrg } else { /* nBytes == 0, so nothing more to read */ 48134977a2fSmrg return; 482ee3138f1Smrg } 483ee3138f1Smrg } 484ee3138f1Smrg} 485ee3138f1Smrg 486ee3138f1Smrgstatic Bool 487ee3138f1SmrgOpenKeyboard(InputInfoPtr pInfo) 488ee3138f1Smrg{ 489a1ed278cSmrg char *kbdPath = xf86SetStrOption(pInfo->options, "Device", "/dev/kbd"); 490a1ed278cSmrg Bool ret; 491ee3138f1Smrg 492ee3138f1Smrg pInfo->fd = open(kbdPath, O_RDONLY | O_NONBLOCK); 493ee3138f1Smrg 494ee3138f1Smrg if (pInfo->fd == -1) { 495a1ed278cSmrg xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", pInfo->name, kbdPath); 496a1ed278cSmrg ret = FALSE; 497ee3138f1Smrg } else { 498ee3138f1Smrg xf86MsgVerb(X_INFO, 3, "%s: Opened device \"%s\"\n", pInfo->name, 499ee3138f1Smrg kbdPath); 500ee3138f1Smrg pInfo->read_input = ReadInput; 501a1ed278cSmrg ret = TRUE; 5023e72ca8cSmrg /* in case it wasn't set and we fell back to default */ 5033e72ca8cSmrg xf86ReplaceStrOption(pInfo->options, "Device", kbdPath); 504ee3138f1Smrg } 505a1ed278cSmrg 506a1ed278cSmrg free(kbdPath); 507a1ed278cSmrg return ret; 508ee3138f1Smrg} 509ee3138f1Smrg 510ee3138f1Smrg_X_EXPORT Bool 511ee3138f1Smrgxf86OSKbdPreInit(InputInfoPtr pInfo) 512ee3138f1Smrg{ 513ee3138f1Smrg KbdDevPtr pKbd = pInfo->private; 514ee3138f1Smrg 515ee3138f1Smrg pKbd->KbdInit = KbdInit; 516ee3138f1Smrg pKbd->KbdOn = KbdOn; 517ee3138f1Smrg pKbd->KbdOff = KbdOff; 518ee3138f1Smrg pKbd->Bell = SoundKbdBell; 519ee3138f1Smrg pKbd->SetLeds = SetKbdLeds; 520ee3138f1Smrg pKbd->GetLeds = GetKbdLeds; 521ee3138f1Smrg pKbd->KbdGetMapping = KbdGetMapping; 522ee3138f1Smrg 523ee3138f1Smrg pKbd->RemapScanCode = NULL; 524ee3138f1Smrg 525ee3138f1Smrg pKbd->OpenKeyboard = OpenKeyboard; 526ee3138f1Smrg 527a1ed278cSmrg pKbd->private = calloc(sizeof(sunKbdPrivRec), 1); 528ee3138f1Smrg if (pKbd->private == NULL) { 529ee3138f1Smrg xf86Msg(X_ERROR,"can't allocate keyboard OS private data\n"); 530ee3138f1Smrg return FALSE; 531ee3138f1Smrg } else { 532ee3138f1Smrg sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private; 533ee3138f1Smrg priv->otranslation = -1; 534ee3138f1Smrg priv->odirect = -1; 535ee3138f1Smrg } 536ee3138f1Smrg 537ee3138f1Smrg return TRUE; 538ee3138f1Smrg} 539