~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to term/i386/pc/at_keyboard.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Millan
  • Date: 2007-11-01 13:18:51 UTC
  • mto: (17.3.1 squeeze) (1.9.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: james.westby@ubuntu.com-20071101131851-63uqsb4dax2h1cbm
Tags: upstream-1.95+20071101
ImportĀ upstreamĀ versionĀ 1.95+20071101

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2007  Free Software Foundation, Inc.
 
4
 *
 
5
 *  GRUB is free software: you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation, either version 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  GRUB is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <grub/machine/console.h>
 
20
#include <grub/cpu/io.h>
 
21
#include <grub/misc.h>
 
22
 
 
23
#define SHIFT_L         0x2a
 
24
#define SHIFT_R         0x36
 
25
#define CTRL            0x1d
 
26
#define ALT             0x38
 
27
#define CAPS_LOCK       0x3a
 
28
 
 
29
#define KEYBOARD_STATUS_SHIFT_L         (1 << 0)
 
30
#define KEYBOARD_STATUS_SHIFT_R         (1 << 1)
 
31
#define KEYBOARD_STATUS_ALT_L           (1 << 2)
 
32
#define KEYBOARD_STATUS_ALT_R           (1 << 3)
 
33
#define KEYBOARD_STATUS_CTRL_L          (1 << 4)
 
34
#define KEYBOARD_STATUS_CTRL_R          (1 << 5)
 
35
#define KEYBOARD_STATUS_CAPS_LOCK       (1 << 6)
 
36
 
 
37
#define KEYBOARD_REG_DATA       0x60
 
38
#define KEYBOARD_REG_STATUS     0x64
 
39
 
 
40
#define KEYBOARD_ISMAKE(x)      !((x) & 0x80)
 
41
#define KEYBOARD_ISREADY(x)     (((x) & 0x01) == 0)
 
42
#define KEYBOARD_SCANCODE(x)    ((x) & 0x7f)
 
43
 
 
44
static short at_keyboard_status = 0;
 
45
 
 
46
static char keyboard_map[128] =
 
47
{
 
48
  '\0', '\0', '1', '2', '3', '4', '5', '6',
 
49
  '7', '8', '9', '0', '-', '=', '\b', '\t',
 
50
  'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
 
51
  'o', 'p', '[', ']', '\n', '\0', 'a', 's',
 
52
  'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
 
53
  '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
 
54
  'b', 'n', 'm', ',', '.', '/', '\0', '*',
 
55
  '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
 
56
  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7',
 
57
  '8', '9', '-', '4', '5', '6', '+', '1',
 
58
  '2', '3',
 
59
};
 
60
 
 
61
static char keyboard_map_shift[128] =
 
62
{
 
63
  '\0', '\0', '!', '@', '#', '$', '%', '^',
 
64
  '&', '*', '(', ')', '_', '+', '\b', '\t',
 
65
  'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
 
66
  'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
 
67
  'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
 
68
  '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
 
69
  'B', 'N', 'M', '<', '>', '?', '\0', '*',
 
70
  '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
 
71
  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7',
 
72
  '8', '9', '-', '4', '5', '6', '+', '1',
 
73
  '2', '3',
 
74
};
 
75
 
 
76
/* FIXME: This should become an interrupt service routine.  For now
 
77
   it's just used to catch events from control keys.  */
 
78
static void
 
79
grub_keyboard_isr (char key)
 
80
{
 
81
  char is_make = KEYBOARD_ISMAKE (key);
 
82
  key = KEYBOARD_SCANCODE (key);
 
83
  if (is_make)
 
84
    switch (key)
 
85
      {
 
86
        case SHIFT_L:
 
87
          at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L;
 
88
          break;
 
89
        case SHIFT_R:
 
90
          at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R;
 
91
          break;
 
92
        case CTRL:
 
93
          at_keyboard_status |= KEYBOARD_STATUS_CTRL_L;
 
94
          break;
 
95
        case ALT:
 
96
          at_keyboard_status |= KEYBOARD_STATUS_ALT_L;
 
97
          break;
 
98
        default:
 
99
          /* Skip grub_dprintf.  */
 
100
          return;
 
101
      }
 
102
  else
 
103
    switch (key)
 
104
      {
 
105
        case SHIFT_L:
 
106
          at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L;
 
107
          break;
 
108
        case SHIFT_R:
 
109
          at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R;
 
110
          break;
 
111
        case CTRL:
 
112
          at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L;
 
113
          break;
 
114
        case ALT:
 
115
          at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L;
 
116
          break;
 
117
        default:
 
118
          /* Skip grub_dprintf.  */
 
119
          return;
 
120
      }
 
121
  grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed");
 
122
}
 
123
 
 
124
/* If there is a raw key pending, return it; otherwise return -1.  */
 
125
static int
 
126
grub_keyboard_getkey ()
 
127
{
 
128
  grub_uint8_t key;
 
129
  if (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
 
130
    return -1;
 
131
  key = grub_inb (KEYBOARD_REG_DATA);
 
132
  /* FIXME */ grub_keyboard_isr (key);
 
133
  if (! KEYBOARD_ISMAKE (key))
 
134
    return -1;
 
135
  return (KEYBOARD_SCANCODE (key));
 
136
}
 
137
 
 
138
/* If there is a character pending, return it; otherwise return -1.  */
 
139
int
 
140
grub_console_checkkey ()
 
141
{
 
142
  int key;
 
143
  key = grub_keyboard_getkey ();
 
144
  if (key == -1)
 
145
    return -1;
 
146
  grub_dprintf ("atkeyb", "Detected key 0x%x\n", key);
 
147
  switch (key)
 
148
    {
 
149
      case CAPS_LOCK:
 
150
        if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)
 
151
          at_keyboard_status &= ~KEYBOARD_STATUS_CAPS_LOCK;
 
152
        else
 
153
          at_keyboard_status |= KEYBOARD_STATUS_CAPS_LOCK;
 
154
        grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK));
 
155
        key = -1;
 
156
        break;
 
157
      default:
 
158
        if (at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R))
 
159
          key = keyboard_map_shift[key];
 
160
        else
 
161
          key = keyboard_map[key];
 
162
        if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)
 
163
          {
 
164
            if ((key >= 'a') && (key <= 'z'))
 
165
              key += 'A' - 'a';
 
166
            else if ((key >= 'A') && (key <= 'Z'))
 
167
              key += 'a' - 'A';
 
168
          }
 
169
    }
 
170
  return (int) key;
 
171
}
 
172
 
 
173
int
 
174
grub_console_getkey ()
 
175
{
 
176
  int key;
 
177
  do
 
178
    {
 
179
      key = grub_console_checkkey ();
 
180
    } while (key == -1);
 
181
  return key;
 
182
}