1 /* Support for the HID Boot Protocol. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008, 2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/term.h>
21 #include <grub/machine/machine.h>
22 #include <grub/machine/console.h>
23 #include <grub/time.h>
24 #include <grub/cpu/io.h>
25 #include <grub/misc.h>
26 #include <grub/term.h>
29 #include <grub/time.h>
32 static char keyboard_map
[128] =
34 '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd',
35 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
36 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
37 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
38 '3', '4', '5', '6', '7', '8', '9', '0',
39 '\n', GRUB_TERM_ESC
, GRUB_TERM_BACKSPACE
, GRUB_TERM_TAB
, ' ', '-', '=', '[',
40 ']', '\\', '#', ';', '\'', '`', ',', '.',
41 '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
42 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
43 '\0', '\0', GRUB_TERM_HOME
, GRUB_TERM_PPAGE
, GRUB_TERM_DC
, GRUB_TERM_END
, GRUB_TERM_NPAGE
, GRUB_TERM_RIGHT
,
44 GRUB_TERM_LEFT
, GRUB_TERM_DOWN
, GRUB_TERM_UP
47 static char keyboard_map_shift
[128] =
49 '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D',
50 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
51 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
52 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
53 '#', '$', '%', '^', '&', '*', '(', ')',
54 '\n', '\0', '\0', '\0', ' ', '_', '+', '{',
55 '}', '|', '#', ':', '"', '`', '<', '>',
59 static grub_usb_device_t usbdev
;
64 struct grub_usb_desc_device
*descdev
;
66 auto int usb_iterate (grub_usb_device_t dev
);
67 int usb_iterate (grub_usb_device_t dev
)
69 descdev
= &dev
->descdev
;
71 grub_dprintf ("usb_keyboard", "%x %x %x\n",
72 descdev
->class, descdev
->subclass
, descdev
->protocol
);
75 if (descdev
->class != 0x09
76 || descdev
->subclass
== 0x01
77 || descdev
->protocol
!= 0x02)
81 if (descdev
->class != 0 || descdev
->subclass
!= 0 || descdev
->protocol
!= 0)
84 grub_printf ("HID found!\n");
90 grub_usb_iterate (usb_iterate
);
92 /* Place the device in boot mode. */
93 grub_usb_control_msg (usbdev
, 0x21, 0x0B, 0, 0, 0, 0);
95 /* Reports every time an event occurs and not more often than that. */
96 grub_usb_control_msg (usbdev
, 0x21, 0x0A, 0<<8, 0, 0, 0);
100 grub_usb_keyboard_getreport (grub_usb_device_t dev
, unsigned char *report
)
102 return grub_usb_control_msg (dev
, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
109 grub_usb_keyboard_checkkey (void)
111 unsigned char data
[8];
117 for (i
= 0; i
< 50; i
++)
120 err
= grub_usb_keyboard_getreport (usbdev
, data
);
122 if (! err
&& data
[2])
129 grub_dprintf ("usb_keyboard",
130 "report: 0x%02x 0x%02x 0x%02x 0x%02x"
131 " 0x%02x 0x%02x 0x%02x 0x%02x\n",
132 data
[0], data
[1], data
[2], data
[3],
133 data
[4], data
[5], data
[6], data
[7]);
135 /* Check if the Control or Shift key was pressed. */
136 if (data
[0] & 0x01 || data
[0] & 0x10)
137 key
= keyboard_map
[data
[2]] - 'a' + 1;
138 else if (data
[0] & 0x02 || data
[0] & 0x20)
139 key
= keyboard_map_shift
[data
[2]];
141 key
= keyboard_map
[data
[2]];
144 grub_printf ("Unknown key 0x%x detected\n", data
[2]);
147 /* Wait until the key is released. */
148 while (!err
&& data
[2])
150 err
= grub_usb_control_msg (usbdev
, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
151 sizeof (data
), (char *) data
);
152 grub_dprintf ("usb_keyboard",
153 "report2: 0x%02x 0x%02x 0x%02x 0x%02x"
154 " 0x%02x 0x%02x 0x%02x 0x%02x\n",
155 data
[0], data
[1], data
[2], data
[3],
156 data
[4], data
[5], data
[6], data
[7]);
160 grub_errno
= GRUB_ERR_NONE
;
167 GRUB_HIDBOOT_REPEAT_NONE
,
168 GRUB_HIDBOOT_REPEAT_FIRST
,
170 } grub_usb_keyboard_repeat_t
;
173 grub_usb_keyboard_getkey (void)
177 unsigned char data
[8];
178 grub_uint64_t currtime
;
180 static grub_usb_keyboard_repeat_t repeat
= GRUB_HIDBOOT_REPEAT_NONE
;
186 key
= grub_usb_keyboard_checkkey ();
189 data
[2] = !0; /* Or whatever. */
194 case GRUB_HIDBOOT_REPEAT_FIRST
:
197 case GRUB_HIDBOOT_REPEAT
:
205 /* Wait until the key is released. */
206 currtime
= grub_get_time_ms ();
207 while (!err
&& data
[2])
209 /* Implement a timeout. */
210 if (grub_get_time_ms () > currtime
+ timeout
)
217 grub_errno
= GRUB_ERR_NONE
;
221 err
= grub_usb_keyboard_getreport (usbdev
, data
);
232 grub_errno
= GRUB_ERR_NONE
;
237 static struct grub_term_input grub_usb_keyboard_term
=
239 .name
= "usb_keyboard",
240 .checkkey
= grub_usb_keyboard_checkkey
,
241 .getkey
= grub_usb_keyboard_getkey
,
245 GRUB_MOD_INIT(usb_keyboard
)
248 grub_term_register_input ("usb_keyboard", &grub_usb_keyboard_term
);
251 GRUB_MOD_FINI(usb_keyboard
)
253 grub_term_unregister_input (&grub_usb_keyboard_term
);