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

« back to all changes in this revision

Viewing changes to term/at_keyboard.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  GRUB  --  GRand Unified Bootloader
3
 
 *  Copyright (C) 2007,2008,2009  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/dl.h>
20
 
#include <grub/at_keyboard.h>
21
 
#include <grub/cpu/at_keyboard.h>
22
 
#include <grub/cpu/io.h>
23
 
#include <grub/misc.h>
24
 
#include <grub/term.h>
25
 
 
26
 
static short at_keyboard_status = 0;
27
 
static int pending_key = -1;
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
 
#define KEYBOARD_STATUS_NUM_LOCK        (1 << 7)
37
 
 
38
 
static grub_uint8_t led_status;
39
 
 
40
 
#define KEYBOARD_LED_SCROLL             (1 << 0)
41
 
#define KEYBOARD_LED_NUM                (1 << 1)
42
 
#define KEYBOARD_LED_CAPS               (1 << 2)
43
 
 
44
 
static char keyboard_map[128] =
45
 
{
46
 
  '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',
47
 
  '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,
48
 
  'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
49
 
  'o', 'p', '[', ']', '\n', '\0', 'a', 's',
50
 
  'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
51
 
  '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
52
 
  'b', 'n', 'm', ',', '.', '/', '\0', '*',
53
 
  '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
54
 
  '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_HOME,
55
 
  GRUB_TERM_UP, GRUB_TERM_NPAGE, '-', GRUB_TERM_LEFT, '\0', GRUB_TERM_RIGHT, '+', GRUB_TERM_END,
56
 
  GRUB_TERM_DOWN, GRUB_TERM_PPAGE, '\0', GRUB_TERM_DC, '\0', '\0', '\0', '\0',
57
 
  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
58
 
  '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT,
59
 
  OLPC_RIGHT
60
 
};
61
 
 
62
 
static char keyboard_map_shift[128] =
63
 
{
64
 
  '\0', '\0', '!', '@', '#', '$', '%', '^',
65
 
  '&', '*', '(', ')', '_', '+', '\0', '\0',
66
 
  'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
67
 
  'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
68
 
  'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
69
 
  '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
70
 
  'B', 'N', 'M', '<', '>', '?'
71
 
};
72
 
 
73
 
static grub_uint8_t grub_keyboard_controller_orig;
74
 
 
75
 
static void
76
 
keyboard_controller_wait_until_ready (void)
77
 
{
78
 
  while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
79
 
}
80
 
 
81
 
static void
82
 
grub_keyboard_controller_write (grub_uint8_t c)
83
 
{
84
 
  keyboard_controller_wait_until_ready ();
85
 
  grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS);
86
 
  grub_outb (c, KEYBOARD_REG_DATA);
87
 
}
88
 
 
89
 
static grub_uint8_t
90
 
grub_keyboard_controller_read (void)
91
 
{
92
 
  keyboard_controller_wait_until_ready ();
93
 
  grub_outb (KEYBOARD_COMMAND_READ, KEYBOARD_REG_STATUS);
94
 
  return grub_inb (KEYBOARD_REG_DATA);
95
 
}
96
 
 
97
 
static void
98
 
keyboard_controller_led (grub_uint8_t leds)
99
 
{
100
 
  keyboard_controller_wait_until_ready ();
101
 
  grub_outb (0xed, KEYBOARD_REG_DATA);
102
 
  keyboard_controller_wait_until_ready ();
103
 
  grub_outb (leds & 0x7, KEYBOARD_REG_DATA);
104
 
}
105
 
 
106
 
/* FIXME: This should become an interrupt service routine.  For now
107
 
   it's just used to catch events from control keys.  */
108
 
static void
109
 
grub_keyboard_isr (char key)
110
 
{
111
 
  char is_make = KEYBOARD_ISMAKE (key);
112
 
  key = KEYBOARD_SCANCODE (key);
113
 
  if (is_make)
114
 
    switch (key)
115
 
      {
116
 
        case SHIFT_L:
117
 
          at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L;
118
 
          break;
119
 
        case SHIFT_R:
120
 
          at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R;
121
 
          break;
122
 
        case CTRL:
123
 
          at_keyboard_status |= KEYBOARD_STATUS_CTRL_L;
124
 
          break;
125
 
        case ALT:
126
 
          at_keyboard_status |= KEYBOARD_STATUS_ALT_L;
127
 
          break;
128
 
        default:
129
 
          /* Skip grub_dprintf.  */
130
 
          return;
131
 
      }
132
 
  else
133
 
    switch (key)
134
 
      {
135
 
        case SHIFT_L:
136
 
          at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L;
137
 
          break;
138
 
        case SHIFT_R:
139
 
          at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R;
140
 
          break;
141
 
        case CTRL:
142
 
          at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L;
143
 
          break;
144
 
        case ALT:
145
 
          at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L;
146
 
          break;
147
 
        default:
148
 
          /* Skip grub_dprintf.  */
149
 
          return;
150
 
      }
151
 
#ifdef DEBUG_AT_KEYBOARD
152
 
  grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed");
153
 
#endif
154
 
}
155
 
 
156
 
/* If there is a raw key pending, return it; otherwise return -1.  */
157
 
static int
158
 
grub_keyboard_getkey (void)
159
 
{
160
 
  grub_uint8_t key;
161
 
  if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
162
 
    return -1;
163
 
  key = grub_inb (KEYBOARD_REG_DATA);
164
 
  /* FIXME */ grub_keyboard_isr (key);
165
 
  if (! KEYBOARD_ISMAKE (key))
166
 
    return -1;
167
 
  return (KEYBOARD_SCANCODE (key));
168
 
}
169
 
 
170
 
/* If there is a character pending, return it; otherwise return -1.  */
171
 
static int
172
 
grub_at_keyboard_getkey_noblock (void)
173
 
{
174
 
  int code, key;
175
 
  code = grub_keyboard_getkey ();
176
 
  if (code == -1)
177
 
    return -1;
178
 
#ifdef DEBUG_AT_KEYBOARD
179
 
  grub_dprintf ("atkeyb", "Detected key 0x%x\n", key);
180
 
#endif
181
 
  switch (code)
182
 
    {
183
 
      case CAPS_LOCK:
184
 
        /* Caps lock sends scan code twice.  Get the second one and discard it.  */
185
 
        while (grub_keyboard_getkey () == -1);
186
 
 
187
 
        at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK;
188
 
        led_status ^= KEYBOARD_LED_CAPS;
189
 
        keyboard_controller_led (led_status);
190
 
 
191
 
#ifdef DEBUG_AT_KEYBOARD
192
 
        grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK));
193
 
#endif
194
 
        key = -1;
195
 
        break;
196
 
      case NUM_LOCK:
197
 
        /* Num lock sends scan code twice.  Get the second one and discard it.  */
198
 
        while (grub_keyboard_getkey () == -1);
199
 
 
200
 
        at_keyboard_status ^= KEYBOARD_STATUS_NUM_LOCK;
201
 
        led_status ^= KEYBOARD_LED_NUM;
202
 
        keyboard_controller_led (led_status);
203
 
 
204
 
#ifdef DEBUG_AT_KEYBOARD
205
 
        grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK));
206
 
#endif
207
 
        key = -1;
208
 
        break;
209
 
      case SCROLL_LOCK:
210
 
        /* For scroll lock we don't keep track of status.  Only update its led.  */
211
 
        led_status ^= KEYBOARD_LED_SCROLL;
212
 
        keyboard_controller_led (led_status);
213
 
        key = -1;
214
 
        break;
215
 
      default:
216
 
        if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R))
217
 
          key = keyboard_map[code] - 'a' + 1;
218
 
        else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R))
219
 
            && keyboard_map_shift[code])
220
 
          key = keyboard_map_shift[code];
221
 
        else
222
 
          key = keyboard_map[code];
223
 
 
224
 
        if (key == 0)
225
 
          grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code);
226
 
 
227
 
        if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)
228
 
          {
229
 
            if ((key >= 'a') && (key <= 'z'))
230
 
              key += 'A' - 'a';
231
 
            else if ((key >= 'A') && (key <= 'Z'))
232
 
              key += 'a' - 'A';
233
 
          }
234
 
    }
235
 
  return key;
236
 
}
237
 
 
238
 
static int
239
 
grub_at_keyboard_checkkey (void)
240
 
{
241
 
  if (pending_key != -1)
242
 
    return 1;
243
 
 
244
 
  pending_key = grub_at_keyboard_getkey_noblock ();
245
 
 
246
 
  if (pending_key != -1)
247
 
    return 1;
248
 
 
249
 
  return -1;
250
 
}
251
 
 
252
 
static int
253
 
grub_at_keyboard_getkey (void)
254
 
{
255
 
  int key;
256
 
  if (pending_key != -1)
257
 
    {
258
 
      key = pending_key;
259
 
      pending_key = -1;
260
 
      return key;
261
 
    }
262
 
  do
263
 
    {
264
 
      key = grub_at_keyboard_getkey_noblock ();
265
 
    } while (key == -1);
266
 
  return key;
267
 
}
268
 
 
269
 
static grub_err_t
270
 
grub_keyboard_controller_init (void)
271
 
{
272
 
  pending_key = -1;
273
 
  at_keyboard_status = 0;
274
 
  grub_keyboard_controller_orig = grub_keyboard_controller_read ();
275
 
  grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1);
276
 
  return GRUB_ERR_NONE;
277
 
}
278
 
 
279
 
static grub_err_t
280
 
grub_keyboard_controller_fini (void)
281
 
{
282
 
  grub_keyboard_controller_write (grub_keyboard_controller_orig);
283
 
  return GRUB_ERR_NONE;
284
 
}
285
 
 
286
 
static struct grub_term_input grub_at_keyboard_term =
287
 
  {
288
 
    .name = "at_keyboard",
289
 
    .init = grub_keyboard_controller_init,
290
 
    .fini = grub_keyboard_controller_fini,
291
 
    .checkkey = grub_at_keyboard_checkkey,
292
 
    .getkey = grub_at_keyboard_getkey,
293
 
  };
294
 
 
295
 
GRUB_MOD_INIT(at_keyboard)
296
 
{
297
 
  grub_term_register_input ("at_keyboard", &grub_at_keyboard_term);
298
 
}
299
 
 
300
 
GRUB_MOD_FINI(at_keyboard)
301
 
{
302
 
  grub_term_unregister_input (&grub_at_keyboard_term);
303
 
}