3
* Copyright 2005 by J. Kean Johnston <jkj@sco.com>
5
* Permission to use, copy, modify, distribute, and sell this software and its
6
* documentation for any purpose is hereby granted without fee, provided that
7
* the above copyright notice appear in all copies and that both that
8
* copyright notice and this permission notice appear in supporting
9
* documentation, and that the name J. Kean Johnston not be used in
10
* advertising or publicity pertaining to distribution of the software without
11
* specific, written prior permission. J. Kean Johnston makes no
12
* representations about the suitability of this software for any purpose.
13
* It is provided "as is" without express or implied warranty.
15
* J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17
* EVENT SHALL J. KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21
* PERFORMANCE OF THIS SOFTWARE.
26
* Based on sco_io.c which is
27
* (C) Copyright 2003 J. Kean Johnston <jkj@sco.com>
29
* Based on lnx_kbd.c which is
30
* Copyright (c) 2002 by The XFree86 Project, Inc.
32
* Based on the code from lnx_io.c which is
33
* Copyright 1992 by Orest Zborowski <obz@Kodak.com>
34
* Copyright 1993 by David Dawes <dawes@xfree86.org>
45
#include "xf86OSpriv.h"
46
#include "xf86_OSlib.h"
48
#include "xf86Xinput.h"
49
#include "xf86OSKbd.h"
50
#include "atKeynames.h"
53
#include <sys/param.h>
57
static KbdProtocolRec protocols[] = {
58
{ "standard", PROT_STD },
59
{ NULL, PROT_UNKNOWN_KBD }
62
extern Bool VTSwitchEnabled;
64
extern Bool VTSysreqToggle;
68
SoundBell(InputInfoPtr pInfo, int loudness, int pitch, int duration)
70
if (loudness && pitch) {
71
ioctl(pInfo->fd, KIOCSOUND, 1193180 / pitch);
72
usleep(duration * loudness * 20);
73
ioctl(pInfo->fd, KIOCSOUND, 0);
78
SetKbdLeds(InputInfoPtr pInfo, int leds)
84
* sleep the first time through under SCO. There appears to be a
85
* timing problem in the driver which causes the keyboard to be lost.
86
* This usleep stops it from occurring. NOTE: this was in the old code.
87
* I am not convinced it is true any longer, but it doesn't hurt to
101
real_leds |= LED_SCR;
104
real_leds |= LED_COMP;
107
real_leds |= LED_SCR;
110
ioctl(pInfo->fd, KDSETLED, real_leds);
114
GetKbdLeds(InputInfoPtr pInfo)
116
int real_leds, leds = 0;
118
ioctl(pInfo->fd, KDGETLED, &real_leds);
120
if (real_leds & LED_CAP) leds |= XLED1;
121
if (real_leds & LED_NUM) leds |= XLED2;
122
if (real_leds & LED_SCR) leds |= XLED3;
128
* NOTE: Only OpenServer Release 5.0.6 with Release Supplement 5.0.6A
129
* and later have the required ioctl. 5.0.6A or higher is HIGHLY
130
* recommended. The console driver is quite a different beast on that OS.
135
SetKbdRepeat(InputInfoPtr pInfo, char rad)
137
#if defined(KBIO_SETRATE)
138
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
140
int value = 0x7f; /* Maximum delay with slowest rate */
141
int delay = 250; /* Default delay */
142
int rate = 300; /* Default repeat rate */
144
static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
145
133, 120, 109, 100, 92, 86, 80, 75, 67,
146
60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
148
#define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
150
static int valid_delays[] = { 250, 500, 750, 1000 };
151
#define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
154
rate = pKbd->rate * 10;
155
if (pKbd->delay >= 0)
158
for (i = 0; i < RATE_COUNT; i++)
159
if (rate >= valid_rates[i]) {
165
for (i = 0; i < DELAY_COUNT; i++)
166
if (delay <= valid_delays[i]) {
172
ioctl (pInfo->fd, KBIO_SETRATE, value);
173
#endif /* defined(KBIO_SETRATE) */
177
KbdInit(InputInfoPtr pInfo, int what)
179
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
180
ScoKbdPrivPtr priv = (ScoKbdPrivPtr) pKbd->private;
182
if (pKbd->isConsole) {
187
priv->orig_getsc = 0;
189
if (ioctl (pInfo->fd, TCGETSC, &priv->orig_getsc) < 0)
191
if (ioctl (pInfo->fd, KDGKBMODE, &priv->orig_kbm) < 0)
194
if (!priv->use_tcs && !priv->use_kd) {
195
xf86Msg (X_ERROR, "KbdInit: Could not determine keyboard mode\n");
200
* One day this should be fixed to translate normal ASCII characters
201
* back into scancodes or into events that XFree86 wants, but not
202
* now. For the time being, we only support scancode mode screens.
204
if (priv->use_tcs && !(priv->orig_getsc & KB_ISSCANCODE)) {
205
xf86Msg (X_ERROR, "KbdInit: Keyboard can not send scancodes\n");
210
* We need to get the original keyboard map and NUL out the lock
211
* modifiers. This prevents the scancode API from messing with
212
* the keyboard LED's. We restore the original map when we exit.
214
if (ioctl (pInfo->fd, GIO_KEYMAP, &priv->keymap) < 0) {
215
xf86Msg (X_ERROR, "KbdInit: Failed to get keyboard map (%s)\n",
219
if (ioctl (pInfo->fd, GIO_KEYMAP, &priv->noledmap) < 0) {
220
xf86Msg (X_ERROR, "KbdInit: Failed to get keyboard map (%s)\n",
226
for (i = 0; i < priv->noledmap.n_keys; i++) {
227
for (j = 0; j < NUM_STATES; j++) {
228
if (IS_SPECIAL(priv->noledmap, i, j) &&
229
((priv->noledmap.key[i].map[j] == K_CLK) ||
230
(priv->noledmap.key[i].map[j] == K_NLK) ||
231
(priv->noledmap.key[i].map[j] == K_SLK))) {
232
priv->noledmap.key[i].map[j] = K_NOP;
238
if (ioctl (pInfo->fd, XCGETA, &priv->kbdtty) < 0) {
239
xf86Msg (X_ERROR, "KbdInit: Failed to get terminal modes (%s)\n",
244
priv->sc_mapbuf = xalloc (10*BSIZE);
245
priv->sc_mapbuf2 = xalloc(10*BSIZE);
248
if (ioctl (pInfo->fd, LDGMAP, priv->sc_mapbuf) < 0) {
249
if (errno != ENAVAIL) {
250
xf86Msg (X_ERROR, "KbdInit: Failed to retrieve e-map (%s)\n",
258
if (ioctl (pInfo->fd, NMGMAP, priv->sc_mapbuf2) < 0) {
259
if (errno != ENAVAIL) {
260
xf86Msg (X_ERROR, "KbdInit: Failed to retrieve n-map (%s)\n",
266
} /* End of if we are on a console */
272
KbdOn(InputInfoPtr pInfo, int what)
274
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
275
ScoKbdPrivPtr priv = (ScoKbdPrivPtr) pKbd->private;
276
struct termios newtio;
278
if (pKbd->isConsole) {
279
ioctl (pInfo->fd, LDNMAP); /* Turn e-mapping off */
280
ioctl (pInfo->fd, NMNMAP); /* Turn n-mapping off */
282
newtio = priv->kbdtty; /* structure copy */
283
newtio.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
285
newtio.c_cflag = CREAD | CS8 | B9600;
287
newtio.c_cc[VTIME]=0;
289
cfsetispeed(&newtio, 9600);
290
cfsetospeed(&newtio, 9600);
291
ioctl(pInfo->fd, XCSETA, &newtio);
293
/* Now tell the keyboard driver to send us raw scancodes */
295
int nm = priv->orig_getsc;
297
ioctl (pInfo->fd, TCSETSC, &nm);
301
ioctl (pInfo->fd, KDSKBMODE, K_RAW);
303
ioctl (pInfo->fd, PIO_KEYMAP, &priv->noledmap);
310
KbdOff(InputInfoPtr pInfo, int what)
312
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
313
ScoKbdPrivPtr priv = (ScoKbdPrivPtr) pKbd->private;
315
if (pKbd->isConsole) {
316
/* Revert back to original translate scancode mode */
318
ioctl (pInfo->fd, TCSETSC, &priv->orig_getsc);
320
ioctl (pInfo->fd, KDSKBMODE, priv->orig_kbm);
322
ioctl (pInfo->fd, PIO_KEYMAP, &priv->keymap);
325
ioctl (pInfo->fd, LDSMAP, priv->sc_mapbuf);
327
ioctl (pInfo->fd, NMSMAP, priv->sc_mapbuf2);
329
ioctl(pInfo->fd, XCSETA, &priv->kbdtty);
336
GetSpecialKey(InputInfoPtr pInfo, int scanCode)
338
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
339
int specialkey = scanCode;
341
if (pKbd->CustomKeycodes) {
342
specialkey = pKbd->specialMap->map[scanCode];
347
#define ModifierSet(k) ((modifiers & (k)) == (k))
350
SpecialKey(InputInfoPtr pInfo, int key, Bool down, int modifiers)
352
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
354
if(!pKbd->vtSwitchSupported)
357
if ((!ModifierSet(ShiftMask)) && ((ModifierSet(ControlMask | AltMask)) ||
358
(ModifierSet(ControlMask | AltLangMask)))) {
359
if (VTSwitchEnabled && !xf86Info.vtSysreq) {
372
int sts = key - KEY_F1;
373
if (sts != xf86Info.vtno) {
374
ioctl(pInfo->fd, VT_ACTIVATE, sts);
381
int sts = key - KEY_F11 + 10;
382
if (sts != xf86Info.vtno) {
383
ioctl(pInfo->fd, VT_ACTIVATE, sts);
391
if (VTSwitchEnabled && xf86Info.vtSysreq) {
403
if (VTSysreqToggle && down) {
404
ioctl(pInfo->fd, VT_ACTIVATE, key - KEY_F1);
405
VTSysreqToggle = FALSE;
411
if (VTSysreqToggle && down) {
412
ioctl(pInfo->fd, VT_ACTIVATE, key - KEY_F11 + 10);
413
VTSysreqToggle = FALSE;
417
/* Ignore these keys -- ie don't let them cancel an alt-sysreq */
422
if (!(ModifierSet(ShiftMask) || ModifierSet(ControlMask))) {
423
if ((ModifierSet(AltMask) || ModifierSet(AltLangMask)) && down)
424
VTSysreqToggle = TRUE;
429
* We only land here when Alt-SysReq is followed by a
433
VTSysreqToggle = FALSE;
436
#endif /* USE_VT_SYSREQ */
441
stdReadInput(InputInfoPtr pInfo)
443
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
444
unsigned char rBuf[64];
447
if ((nBytes = read( pInfo->fd, (char *)rBuf, sizeof(rBuf))) > 0) {
448
for (i = 0; i < nBytes; i++) {
449
pKbd->PostEvent(pInfo, rBuf[i] & 0x7f, rBuf[i] & 0x80 ? FALSE : TRUE);
455
OpenKeyboard(InputInfoPtr pInfo)
457
KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
459
KbdProtocolId prot = PROT_UNKNOWN_KBD;
462
s = xf86SetStrOption(pInfo->options, "Protocol", NULL);
463
for (i = 0; protocols[i].name; i++) {
464
if (xf86NameCmp(s, protocols[i].name) == 0) {
465
prot = protocols[i].id;
472
pInfo->read_input = stdReadInput;
475
xf86Msg(X_ERROR,"\"%s\" is not a valid keyboard protocol name\n", s);
480
xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, s);
483
s = xf86SetStrOption(pInfo->options, "Device", NULL);
485
pInfo->fd = xf86Info.consoleFd;
486
pKbd->isConsole = TRUE;
488
pInfo->fd = open(s, O_RDONLY | O_NONBLOCK | O_EXCL);
489
if (pInfo->fd == -1) {
490
xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", pInfo->name, s);
494
pKbd->isConsole = FALSE;
499
pKbd->vtSwitchSupported = TRUE;
505
xf86OSKbdPreInit(InputInfoPtr pInfo)
507
KbdDevPtr pKbd = pInfo->private;
509
pKbd->KbdInit = KbdInit;
511
pKbd->KbdOff = KbdOff;
512
pKbd->Bell = SoundBell;
513
pKbd->SetLeds = SetKbdLeds;
514
pKbd->GetLeds = GetKbdLeds;
515
pKbd->SetKbdRepeat = SetKbdRepeat;
516
pKbd->KbdGetMapping = KbdGetMapping;
517
pKbd->SpecialKey = SpecialKey;
518
pKbd->GetSpecialKey = GetSpecialKey;
519
pKbd->OpenKeyboard = OpenKeyboard;
520
pKbd->RemapScanCode = ATScancode;
521
pKbd->vtSwitchSupported = FALSE;
523
pKbd->private = xcalloc(sizeof(ScoKbdPrivRec), 1);
524
if (pKbd->private == NULL) {
525
xf86Msg(X_ERROR,"can't allocate keyboard OS private data\n");