~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/os-support/sco/sco_kbd.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86$ */
 
2
/*
 
3
 * Copyright 2005 by J. Kean Johnston <jkj@sco.com>
 
4
 *
 
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.
 
14
 *
 
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.
 
22
 */
 
23
/* $XConsortium$ */
 
24
 
 
25
/*
 
26
 * Based on sco_io.c which is
 
27
 * (C) Copyright 2003 J. Kean Johnston <jkj@sco.com>
 
28
 *
 
29
 * Based on lnx_kbd.c which is 
 
30
 * Copyright (c) 2002 by The XFree86 Project, Inc.
 
31
 *
 
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>
 
35
 */
 
36
 
 
37
#define NEED_EVENTS
 
38
#include "X.h"
 
39
 
 
40
#include "compiler.h"
 
41
 
 
42
#define _NEED_SYSI86
 
43
#include "xf86.h"
 
44
#include "xf86Priv.h"
 
45
#include "xf86OSpriv.h"
 
46
#include "xf86_OSlib.h"
 
47
 
 
48
#include "xf86Xinput.h"
 
49
#include "xf86OSKbd.h"
 
50
#include "atKeynames.h"
 
51
#include "sco_kbd.h"
 
52
 
 
53
#include <sys/param.h>
 
54
#include <sys/emap.h>
 
55
#include <sys/nmap.h>
 
56
 
 
57
static KbdProtocolRec protocols[] = {
 
58
  { "standard", PROT_STD },
 
59
  { NULL, PROT_UNKNOWN_KBD }
 
60
};
 
61
 
 
62
extern Bool VTSwitchEnabled;
 
63
#ifdef USE_VT_SYSREQ
 
64
extern Bool VTSysreqToggle;
 
65
#endif
 
66
 
 
67
static void
 
68
SoundBell(InputInfoPtr pInfo, int loudness, int pitch, int duration)
 
69
{
 
70
  if (loudness && pitch) {
 
71
    ioctl(pInfo->fd, KIOCSOUND, 1193180 / pitch);
 
72
    usleep(duration * loudness * 20);
 
73
    ioctl(pInfo->fd, KIOCSOUND, 0);
 
74
  }
 
75
}
 
76
 
 
77
static void
 
78
SetKbdLeds(InputInfoPtr pInfo, int leds)
 
79
{
 
80
  int real_leds = 0;
 
81
  static int once = 1;
 
82
 
 
83
  /*
 
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
 
88
   * leave this in here.
 
89
   */
 
90
  if (once) {
 
91
    usleep(100);
 
92
    once = 0;
 
93
  }
 
94
 
 
95
#ifdef LED_CAP
 
96
  if (leds & XLED1)
 
97
    real_leds |= LED_CAP;
 
98
  if (leds & XLED2)
 
99
    real_leds |= LED_NUM;
 
100
  if (leds & XLED3)
 
101
    real_leds |= LED_SCR;
 
102
#ifdef LED_COMP
 
103
  if (leds & XLED4)
 
104
    real_leds |= LED_COMP;
 
105
#else
 
106
  if (leds & XLED4)
 
107
    real_leds |= LED_SCR;
 
108
#endif
 
109
#endif
 
110
  ioctl(pInfo->fd, KDSETLED, real_leds);
 
111
}
 
112
 
 
113
static int
 
114
GetKbdLeds(InputInfoPtr pInfo)
 
115
{
 
116
    int real_leds, leds = 0;
 
117
 
 
118
    ioctl(pInfo->fd, KDGETLED, &real_leds);
 
119
 
 
120
    if (real_leds & LED_CAP) leds |= XLED1;
 
121
    if (real_leds & LED_NUM) leds |= XLED2;
 
122
    if (real_leds & LED_SCR) leds |= XLED3;
 
123
 
 
124
    return(leds);
 
125
}
 
126
 
 
127
/*
 
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.
 
131
 */
 
132
#undef rate
 
133
 
 
134
static void
 
135
SetKbdRepeat(InputInfoPtr pInfo, char rad)
 
136
{
 
137
#if defined(KBIO_SETRATE)
 
138
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
139
  int i;
 
140
  int value = 0x7f;     /* Maximum delay with slowest rate */
 
141
  int delay = 250;      /* Default delay */
 
142
  int rate = 300;       /* Default repeat rate */
 
143
 
 
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,
 
147
                               25, 23, 21, 20 };
 
148
#define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
 
149
 
 
150
  static int valid_delays[] = { 250, 500, 750, 1000 };
 
151
#define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
 
152
 
 
153
  if (pKbd->rate >= 0) 
 
154
    rate = pKbd->rate * 10;
 
155
  if (pKbd->delay >= 0)
 
156
    delay = pKbd->delay;
 
157
 
 
158
  for (i = 0; i < RATE_COUNT; i++)
 
159
    if (rate >= valid_rates[i]) {
 
160
      value &= 0x60;
 
161
      value |= i;
 
162
      break;
 
163
    }
 
164
 
 
165
  for (i = 0; i < DELAY_COUNT; i++)
 
166
    if (delay <= valid_delays[i]) {
 
167
      value &= 0x1f;
 
168
      value |= i << 5;
 
169
      break;
 
170
    }
 
171
 
 
172
  ioctl (pInfo->fd, KBIO_SETRATE, value);
 
173
#endif /* defined(KBIO_SETRATE) */
 
174
}
 
175
 
 
176
static int
 
177
KbdInit(InputInfoPtr pInfo, int what)
 
178
{
 
179
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
180
  ScoKbdPrivPtr priv = (ScoKbdPrivPtr) pKbd->private;
 
181
 
 
182
  if (pKbd->isConsole) {
 
183
    priv->use_tcs = 1;
 
184
    priv->use_kd = 1;
 
185
    priv->no_nmap = 1;
 
186
    priv->no_emap = 1;
 
187
    priv->orig_getsc = 0;
 
188
 
 
189
    if (ioctl (pInfo->fd, TCGETSC, &priv->orig_getsc) < 0)
 
190
      priv->use_tcs = 0;
 
191
    if (ioctl (pInfo->fd, KDGKBMODE, &priv->orig_kbm) < 0)
 
192
      priv->use_kd = 0;
 
193
 
 
194
    if (!priv->use_tcs && !priv->use_kd) {
 
195
      xf86Msg (X_ERROR, "KbdInit: Could not determine keyboard mode\n");
 
196
      return !Success;
 
197
    }
 
198
 
 
199
    /*
 
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.
 
203
     */
 
204
    if (priv->use_tcs && !(priv->orig_getsc & KB_ISSCANCODE)) {
 
205
      xf86Msg (X_ERROR, "KbdInit: Keyboard can not send scancodes\n");
 
206
      return !Success;
 
207
    }
 
208
 
 
209
    /*
 
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.
 
213
     */
 
214
    if (ioctl (pInfo->fd, GIO_KEYMAP, &priv->keymap) < 0) {
 
215
      xf86Msg (X_ERROR, "KbdInit: Failed to get keyboard map (%s)\n",
 
216
        strerror(errno));
 
217
      return !Success;
 
218
    }
 
219
    if (ioctl (pInfo->fd, GIO_KEYMAP, &priv->noledmap) < 0) {
 
220
      xf86Msg (X_ERROR, "KbdInit: Failed to get keyboard map (%s)\n",
 
221
        strerror(errno));
 
222
      return !Success;
 
223
    } else {
 
224
      int i, j;
 
225
 
 
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;
 
233
          }
 
234
        }
 
235
      }
 
236
    }
 
237
 
 
238
    if (ioctl (pInfo->fd, XCGETA, &priv->kbdtty) < 0) {
 
239
      xf86Msg (X_ERROR, "KbdInit: Failed to get terminal modes (%s)\n",
 
240
        strerror(errno));
 
241
      return !Success;
 
242
    }
 
243
 
 
244
    priv->sc_mapbuf = xalloc (10*BSIZE);
 
245
    priv->sc_mapbuf2 = xalloc(10*BSIZE);
 
246
 
 
247
    /* Get the emap */
 
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",
 
251
          strerror (errno));
 
252
        return !Success;
 
253
      }
 
254
      priv->no_emap = 0;
 
255
    }
 
256
 
 
257
    /* Get the nmap */
 
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",
 
261
          strerror (errno));
 
262
        return !Success;
 
263
      }
 
264
      priv->no_nmap = 0;
 
265
    }
 
266
  } /* End of if we are on a console */
 
267
 
 
268
  return Success;
 
269
}
 
270
 
 
271
static int
 
272
KbdOn(InputInfoPtr pInfo, int what)
 
273
{
 
274
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
275
  ScoKbdPrivPtr priv = (ScoKbdPrivPtr) pKbd->private;
 
276
  struct termios newtio;
 
277
 
 
278
  if (pKbd->isConsole) {
 
279
    ioctl (pInfo->fd, LDNMAP); /* Turn e-mapping off */
 
280
    ioctl (pInfo->fd, NMNMAP); /* Turn n-mapping off */
 
281
 
 
282
    newtio = priv->kbdtty;     /* structure copy */
 
283
    newtio.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
 
284
    newtio.c_oflag = 0;
 
285
    newtio.c_cflag = CREAD | CS8 | B9600;
 
286
    newtio.c_lflag = 0;
 
287
    newtio.c_cc[VTIME]=0;
 
288
    newtio.c_cc[VMIN]=1;
 
289
    cfsetispeed(&newtio, 9600);
 
290
    cfsetospeed(&newtio, 9600);
 
291
    ioctl(pInfo->fd, XCSETA, &newtio);
 
292
 
 
293
    /* Now tell the keyboard driver to send us raw scancodes */
 
294
    if (priv->use_tcs) {
 
295
      int nm = priv->orig_getsc;
 
296
      nm &= ~KB_XSCANCODE;
 
297
      ioctl (pInfo->fd, TCSETSC, &nm);
 
298
    }
 
299
 
 
300
    if (priv->use_kd)
 
301
      ioctl (pInfo->fd, KDSKBMODE, K_RAW);
 
302
 
 
303
    ioctl (pInfo->fd, PIO_KEYMAP, &priv->noledmap);
 
304
  }
 
305
 
 
306
  return Success;
 
307
}
 
308
 
 
309
static int
 
310
KbdOff(InputInfoPtr pInfo, int what)
 
311
{
 
312
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
313
  ScoKbdPrivPtr priv = (ScoKbdPrivPtr) pKbd->private;
 
314
 
 
315
  if (pKbd->isConsole) {
 
316
    /* Revert back to original translate scancode mode */
 
317
    if (priv->use_tcs)
 
318
      ioctl (pInfo->fd, TCSETSC, &priv->orig_getsc);
 
319
    if (priv->use_kd)
 
320
      ioctl (pInfo->fd, KDSKBMODE, priv->orig_kbm);
 
321
 
 
322
    ioctl (pInfo->fd, PIO_KEYMAP, &priv->keymap);
 
323
 
 
324
    if (priv->no_emap)
 
325
      ioctl (pInfo->fd, LDSMAP, priv->sc_mapbuf);
 
326
    if (priv->no_nmap)
 
327
      ioctl (pInfo->fd, NMSMAP, priv->sc_mapbuf2);
 
328
 
 
329
    ioctl(pInfo->fd, XCSETA, &priv->kbdtty);
 
330
  }
 
331
 
 
332
  return Success;
 
333
}
 
334
 
 
335
static int
 
336
GetSpecialKey(InputInfoPtr pInfo, int scanCode)
 
337
{
 
338
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
339
  int specialkey = scanCode;
 
340
 
 
341
  if (pKbd->CustomKeycodes) {
 
342
      specialkey = pKbd->specialMap->map[scanCode];
 
343
  }
 
344
  return specialkey;
 
345
}
 
346
 
 
347
#define ModifierSet(k) ((modifiers & (k)) == (k))
 
348
 
 
349
static Bool
 
350
SpecialKey(InputInfoPtr pInfo, int key, Bool down, int modifiers)
 
351
{
 
352
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
353
 
 
354
  if(!pKbd->vtSwitchSupported)
 
355
    return FALSE;
 
356
 
 
357
  if ((!ModifierSet(ShiftMask)) && ((ModifierSet(ControlMask | AltMask)) ||
 
358
      (ModifierSet(ControlMask | AltLangMask)))) {
 
359
    if (VTSwitchEnabled && !xf86Info.vtSysreq) {
 
360
      switch (key) {
 
361
        case KEY_F1:
 
362
        case KEY_F2:
 
363
        case KEY_F3:
 
364
        case KEY_F4:
 
365
        case KEY_F5:
 
366
        case KEY_F6:
 
367
        case KEY_F7:
 
368
        case KEY_F8:
 
369
        case KEY_F9:
 
370
        case KEY_F10:
 
371
          if (down) {
 
372
            int sts = key - KEY_F1;
 
373
            if (sts != xf86Info.vtno) {
 
374
              ioctl(pInfo->fd, VT_ACTIVATE, sts);
 
375
            }
 
376
            return TRUE;
 
377
          }
 
378
        case KEY_F11:
 
379
        case KEY_F12:
 
380
          if (down) {
 
381
            int sts = key - KEY_F11 + 10;
 
382
            if (sts != xf86Info.vtno) {
 
383
              ioctl(pInfo->fd, VT_ACTIVATE, sts);
 
384
            }
 
385
            return TRUE;
 
386
          }
 
387
      }
 
388
    }
 
389
  }
 
390
#ifdef USE_VT_SYSREQ
 
391
  if (VTSwitchEnabled && xf86Info.vtSysreq) {
 
392
    switch (key) {
 
393
      case KEY_F1:
 
394
      case KEY_F2:
 
395
      case KEY_F3:
 
396
      case KEY_F4:
 
397
      case KEY_F5:
 
398
      case KEY_F6:
 
399
      case KEY_F7:
 
400
      case KEY_F8:
 
401
      case KEY_F9:
 
402
      case KEY_F10:
 
403
        if (VTSysreqToggle && down) {
 
404
          ioctl(pInfo->fd, VT_ACTIVATE, key - KEY_F1);
 
405
          VTSysreqToggle = FALSE;
 
406
          return TRUE;
 
407
        }
 
408
        break;
 
409
      case KEY_F11:
 
410
      case KEY_F12:
 
411
        if (VTSysreqToggle && down) {
 
412
          ioctl(pInfo->fd, VT_ACTIVATE, key - KEY_F11 + 10);
 
413
          VTSysreqToggle = FALSE;
 
414
          return TRUE;
 
415
        }
 
416
        break;
 
417
        /* Ignore these keys -- ie don't let them cancel an alt-sysreq */
 
418
      case KEY_Alt:
 
419
      case KEY_AltLang:
 
420
        break;
 
421
      case KEY_SysReqest:
 
422
        if (!(ModifierSet(ShiftMask) || ModifierSet(ControlMask))) {
 
423
          if ((ModifierSet(AltMask) || ModifierSet(AltLangMask)) && down)
 
424
            VTSysreqToggle = TRUE;
 
425
        }
 
426
        break;
 
427
      default:
 
428
        /*
 
429
         * We only land here when Alt-SysReq is followed by a
 
430
         * non-switching key.
 
431
         */
 
432
        if (VTSysreqToggle)
 
433
          VTSysreqToggle = FALSE;
 
434
    }
 
435
  }
 
436
#endif /* USE_VT_SYSREQ */
 
437
  return FALSE;
 
438
 
439
 
 
440
static void
 
441
stdReadInput(InputInfoPtr pInfo)
 
442
{
 
443
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
444
  unsigned char rBuf[64];
 
445
  int nBytes, i;
 
446
 
 
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);
 
450
    }
 
451
  }
 
452
}
 
453
 
 
454
static Bool
 
455
OpenKeyboard(InputInfoPtr pInfo)
 
456
{
 
457
  KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
 
458
  int i;
 
459
  KbdProtocolId prot = PROT_UNKNOWN_KBD;
 
460
  char *s;
 
461
 
 
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;
 
466
      break;
 
467
    }
 
468
  }
 
469
 
 
470
  switch (prot) {
 
471
    case PROT_STD:
 
472
      pInfo->read_input = stdReadInput;
 
473
      break;
 
474
    default:
 
475
      xf86Msg(X_ERROR,"\"%s\" is not a valid keyboard protocol name\n", s);
 
476
      xfree(s);
 
477
      return FALSE;
 
478
  }
 
479
 
 
480
  xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, s);
 
481
  xfree(s);
 
482
 
 
483
  s = xf86SetStrOption(pInfo->options, "Device", NULL);
 
484
  if (s == NULL) {
 
485
    pInfo->fd = xf86Info.consoleFd;
 
486
    pKbd->isConsole = TRUE;
 
487
  } else {
 
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);
 
491
      xfree(s);
 
492
      return FALSE;
 
493
    }
 
494
    pKbd->isConsole = FALSE;
 
495
    xfree(s);
 
496
  }
 
497
 
 
498
  if (pKbd->isConsole)
 
499
    pKbd->vtSwitchSupported = TRUE;
 
500
 
 
501
  return TRUE;
 
502
}
 
503
 
 
504
Bool
 
505
xf86OSKbdPreInit(InputInfoPtr pInfo)
 
506
{
 
507
  KbdDevPtr pKbd = pInfo->private;
 
508
 
 
509
  pKbd->KbdInit           = KbdInit;
 
510
  pKbd->KbdOn             = KbdOn;
 
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;
 
522
 
 
523
  pKbd->private = xcalloc(sizeof(ScoKbdPrivRec), 1);
 
524
  if (pKbd->private == NULL) {
 
525
    xf86Msg(X_ERROR,"can't allocate keyboard OS private data\n");
 
526
    return FALSE;
 
527
  }
 
528
 
 
529
  return TRUE;
 
530
}