--- /dev/null
- #include <grub/gzio.h>
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/term.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/time.h>
+#include <grub/dl.h>
+#include <grub/keyboard_layouts.h>
+#include <grub/command.h>
- file = grub_gzfile_open (filename, 1);
+#include <grub/i18n.h>
++#include <grub/file.h>
+
+static struct grub_keyboard_layout layout_us = {
+ .keyboard_map = {
+ /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',
+ /* 0x08 */ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,
+ /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+ /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's',
+ /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+ /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
+ /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*',
+ /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1,
+ /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3,
+ /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
+ /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7,
+ /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
+ /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME,
+ /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT,
+ /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT,
+ /* 0x4e */ '+', GRUB_TERM_KEY_END,
+ /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE,
+ /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC,
+ /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11,
+ /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ /* 0x60 */ '\0', '\0', '\0', '\0',
+ /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT,
+ /* 0x68 */ GRUB_TERM_KEY_RIGHT
+ },
+ .keyboard_map_shift = {
+ '\0', '\0', '!', '@', '#', '$', '%', '^',
+ '&', '*', '(', ')', '_', '+', '\0', '\0',
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+ 'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+ '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
+ 'B', 'N', 'M', '<', '>', '?',
+ [0x56] = '|'
+ }
+};
+
+static struct grub_keyboard_layout *grub_current_layout = &layout_us;
+
+static int
+map_key_core (int code, int status, int *alt_gr_consumed)
+{
+ *alt_gr_consumed = 0;
+
+ if (status & GRUB_TERM_STATUS_RALT)
+ {
+ if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT))
+ {
+ if (grub_current_layout->keyboard_map_shift_l3[code])
+ {
+ *alt_gr_consumed = 1;
+ return grub_current_layout->keyboard_map_shift_l3[code];
+ }
+ else if (grub_current_layout->keyboard_map_shift[code])
+ {
+ *alt_gr_consumed = 1;
+ return grub_current_layout->keyboard_map_l3[code]
+ | GRUB_TERM_SHIFT;
+ }
+ }
+ else if (grub_current_layout->keyboard_map_shift[code])
+ {
+ *alt_gr_consumed = 1;
+ return grub_current_layout->keyboard_map_l3[code];
+ }
+ }
+ if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT))
+ {
+ if (grub_current_layout->keyboard_map_shift[code])
+ return grub_current_layout->keyboard_map_shift[code];
+ else
+ return grub_current_layout->keyboard_map[code] | GRUB_TERM_SHIFT;
+ }
+ else
+ return grub_current_layout->keyboard_map[code];
+}
+
+unsigned
+grub_term_map_key (int code, int status)
+{
+ int alt_gr_consumed;
+ int key;
+
+ key = map_key_core (code, status, &alt_gr_consumed);
+
+ if (key == 0 || key == GRUB_TERM_SHIFT)
+ grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code);
+
+ if (status & GRUB_TERM_STATUS_CAPS)
+ {
+ if ((key >= 'a') && (key <= 'z'))
+ key += 'A' - 'a';
+ else if ((key >= 'A') && (key <= 'Z'))
+ key += 'a' - 'A';
+ }
+
+ if ((status & GRUB_TERM_STATUS_LALT) ||
+ ((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed))
+ key |= GRUB_TERM_ALT;
+ if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL))
+ key |= GRUB_TERM_CTRL;
+
+ return key;
+}
+
+static grub_err_t
+grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ char *filename;
+ grub_file_t file;
+ grub_uint32_t version;
+ grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE];
+ struct grub_keyboard_layout *newmap = NULL;
+ unsigned i;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "file or layout name required");
+ if (argv[0][0] != '(' && argv[0][0] != '/' && argv[0][0] != '+')
+ {
+ const char *prefix = grub_env_get ("prefix");
+ if (!prefix)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set");
+ filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]);
+ if (!filename)
+ return grub_errno;
+ }
+ else
+ filename = argv[0];
+
++ file = grub_file_open (filename);
+ if (! file)
+ goto fail;
+
+ if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic))
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
+ goto fail;
+ }
+
+ if (grub_memcmp (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC,
+ GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE) != 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid magic");
+ goto fail;
+ }
+
+ if (grub_file_read (file, &version, sizeof (version)) != sizeof (version))
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
+ goto fail;
+ }
+
+ if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version");
+ goto fail;
+ }
+
+ newmap = grub_malloc (sizeof (*newmap));
+ if (!newmap)
+ goto fail;
+
+ if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap))
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
+ goto fail;
+ }
+
+ for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map); i++)
+ newmap->keyboard_map[i] = grub_le_to_cpu32(newmap->keyboard_map[i]);
+
+ for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift); i++)
+ newmap->keyboard_map_shift[i]
+ = grub_le_to_cpu32(newmap->keyboard_map_shift[i]);
+
+ for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_l3); i++)
+ newmap->keyboard_map_l3[i]
+ = grub_le_to_cpu32(newmap->keyboard_map_l3[i]);
+
+ for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift_l3); i++)
+ newmap->keyboard_map_shift_l3[i]
+ = grub_le_to_cpu32(newmap->keyboard_map_shift_l3[i]);
+
+ grub_current_layout = newmap;
+
+ return GRUB_ERR_NONE;
+
+ fail:
+ if (filename != argv[0])
+ grub_free (filename);
+ grub_free (newmap);
+ if (file)
+ grub_file_close (file);
+ return grub_errno;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(keylayouts)
+{
+ cmd = grub_register_command ("keymap", grub_cmd_keymap,
+ 0, N_("Load a keyboard layout."));
+}
+
+GRUB_MOD_FINI(keylayouts)
+{
+ grub_unregister_command (cmd);
+}
#include <grub/usb.h>
#include <grub/dl.h>
#include <grub/time.h>
+#include <grub/keyboard_layouts.h>
\f
-static char keyboard_map[128] =
- {
- '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
- '3', '4', '5', '6', '7', '8', '9', '0',
- '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[',
- ']', '\\', '#', ';', '\'', '`', ',', '.',
- '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
- '\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT,
- GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP
- };
-static char keyboard_map_shift[128] =
- {
- '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D',
- 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
- '#', '$', '%', '^', '&', '*', '(', ')',
- '\n', '\0', '\0', '\0', ' ', '_', '+', '{',
- '}', '|', '#', ':', '"', '`', '<', '>',
- '?'
- };
+static grub_uint8_t usb_to_at_map[128] =
+{
+ /* 0x00 */ 0x00, 0x00,
+ /* 0x02 */ 0x00, 0x00,
+ /* 0x04 */ 0x1e /* a */, 0x30 /* b */,
+ /* 0x06 */ 0x2e /* c */, 0x20 /* d */,
+ /* 0x08 */ 0x12 /* e */, 0x21 /* f */,
+ /* 0x0a */ 0x22 /* g */, 0x23 /* h */,
+ /* 0x0c */ 0x17 /* i */, 0x24 /* j */,
+ /* 0x0e */ 0x25 /* k */, 0x26 /* l */,
+ /* 0x10 */ 0x32 /* m */, 0x31 /* n */,
+ /* 0x12 */ 0x18 /* o */, 0x19 /* p */,
+ /* 0x14 */ 0x10 /* q */, 0x13 /* r */,
+ /* 0x16 */ 0x1f /* s */, 0x14 /* t */,
+ /* 0x18 */ 0x16 /* u */, 0x2f /* v */,
+ /* 0x1a */ 0x11 /* w */, 0x2d /* x */,
+ /* 0x1c */ 0x15 /* y */, 0x2c /* z */,
+ /* 0x1e */ 0x02 /* 1 */, 0x03 /* 2 */,
+ /* 0x20 */ 0x04 /* 3 */, 0x05 /* 4 */,
+ /* 0x22 */ 0x06 /* 5 */, 0x07 /* 6 */,
+ /* 0x24 */ 0x08 /* 7 */, 0x09 /* 8 */,
+ /* 0x26 */ 0x0a /* 9 */, 0x0b /* 0 */,
+ /* 0x28 */ 0x1c /* Enter */, 0x01 /* Escape */,
+ /* 0x2a */ 0x0e /* \b */, 0x0f /* \t */,
+ /* 0x2c */ 0x39 /* Space */, 0x0c /* - */,
+ /* 0x2e */ 0x0d /* = */, 0x1a /* [ */,
+ /* 0x30 */ 0x1b /* ] */, 0x2b /* \ */,
+ /* 0x32 */ 0x00, 0x27 /* ; */,
+ /* 0x34 */ 0x28 /* " */, 0x29 /* ` */,
+ /* 0x36 */ 0x33 /* , */, 0x34 /* . */,
+ /* 0x38 */ 0x35 /* / */, 0x00,
+ /* 0x3a */ 0x3b /* F1 */, 0x3c /* F2 */,
+ /* 0x3c */ 0x3d /* F3 */, 0x3e /* F4 */,
+ /* 0x3e */ 0x3f /* F5 */, 0x40 /* F6 */,
+ /* 0x40 */ 0x41 /* F7 */, 0x42 /* F8 */,
+ /* 0x42 */ 0x43 /* F9 */, 0x44 /* F10 */,
+ /* 0x44 */ 0x57 /* F11 */, 0x58 /* F12 */,
+ /* 0x46 */ 0x00, 0x00,
+ /* 0x48 */ 0x00, 0x00,
+ /* 0x4a */ 0x47 /* HOME */, 0x51 /* PPAGE */,
+ /* 0x4c */ 0x53 /* DC */, 0x4f /* END */,
+ /* 0x4e */ 0x49 /* NPAGE */, 0x4d /* RIGHT */,
+ /* 0x50 */ 0x4b /* LEFT */, 0x50 /* DOWN */,
+ /* 0x52 */ 0x48 /* UP */, 0x00,
+ /* 0x54 */ 0x00, 0x00,
+ /* 0x56 */ 0x00, 0x00,
+ /* 0x58 */ 0x00, 0x00,
+ /* 0x5a */ 0x00, 0x00,
+ /* 0x5c */ 0x00, 0x00,
+ /* 0x5e */ 0x00, 0x00,
+ /* 0x60 */ 0x00, 0x00,
+ /* 0x62 */ 0x00, 0x00,
+ /* 0x64 */ 0x56 /* 102nd key. */, 0x00,
+ /* 0x66 */ 0x00, 0x00,
+ /* 0x68 */ 0x00, 0x00,
+ /* 0x6a */ 0x00, 0x00,
+ /* 0x6c */ 0x00, 0x00,
+ /* 0x6e */ 0x00, 0x00,
+ /* 0x70 */ 0x00, 0x00,
+ /* 0x72 */ 0x00, 0x00,
+ /* 0x74 */ 0x00, 0x00,
+ /* 0x76 */ 0x00, 0x00,
+ /* 0x78 */ 0x00, 0x00,
+ /* 0x7a */ 0x00, 0x00,
+ /* 0x7c */ 0x00, 0x00,
+ /* 0x7e */ 0x00, 0x00,
+};
- static grub_usb_device_t usbdev;
-
- /* Valid values for bmRequestType. See HID definition version 1.11 section
- 7.2. */
- #define USB_HID_HOST_TO_DEVICE 0x21
- #define USB_HID_DEVICE_TO_HOST 0xA1
/* Valid values for bRequest. See HID definition version 1.11 section 7.2. */
#define USB_HID_GET_REPORT 0x01
#define USB_HID_SET_IDLE 0x0A
#define USB_HID_SET_PROTOCOL 0x0B
-struct grub_usb_keyboard_data
+ #define USB_HID_BOOT_SUBCLASS 0x01
+ #define USB_HID_KBD_PROTOCOL 0x01
+
+#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01
+#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02
+#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04
+#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10
+#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20
+#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40
+
++struct grub_usb_keyboard_data
++{
++ grub_usb_device_t usbdev;
++ grub_uint8_t status;
++ int key;
++ struct grub_usb_desc_endp *endp;
++};
++
++static struct grub_term_input grub_usb_keyboards[16];
++
+ static int grub_usb_keyboard_checkkey (struct grub_term_input *term);
+ static int grub_usb_keyboard_getkey (struct grub_term_input *term);
+ static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term);
+
+ static struct grub_term_input grub_usb_keyboard_term =
+ {
+ .checkkey = grub_usb_keyboard_checkkey,
+ .getkey = grub_usb_keyboard_getkey,
+ .getkeystatus = grub_usb_keyboard_getkeystatus,
+ .next = 0
+ };
+
+static int
+interpret_status (grub_uint8_t data0)
{
- grub_usb_device_t usbdev;
- grub_uint8_t status;
- int key;
- struct grub_usb_desc_endp *endp;
-};
+ int mods = 0;
-static struct grub_term_input grub_usb_keyboards[16];
+ /* Check Shift, Control, and Alt status. */
+ if (data0 & GRUB_USB_KEYBOARD_LEFT_SHIFT)
+ mods |= GRUB_TERM_STATUS_LSHIFT;
+ if (data0 & GRUB_USB_KEYBOARD_RIGHT_SHIFT)
+ mods |= GRUB_TERM_STATUS_RSHIFT;
+ if (data0 & GRUB_USB_KEYBOARD_LEFT_CTRL)
+ mods |= GRUB_TERM_STATUS_LCTRL;
+ if (data0 & GRUB_USB_KEYBOARD_RIGHT_CTRL)
+ mods |= GRUB_TERM_STATUS_RCTRL;
+ if (data0 & GRUB_USB_KEYBOARD_LEFT_ALT)
+ mods |= GRUB_TERM_STATUS_LALT;
+ if (data0 & GRUB_USB_KEYBOARD_RIGHT_ALT)
+ mods |= GRUB_TERM_STATUS_RALT;
+
+ return mods;
+}
static void
- grub_usb_hid (void)
+ grub_usb_keyboard_detach (grub_usb_device_t usbdev,
+ int config __attribute__ ((unused)),
+ int interface __attribute__ ((unused)))
{
- struct grub_usb_desc_device *descdev;
-
- auto int usb_iterate (grub_usb_device_t dev);
- int usb_iterate (grub_usb_device_t dev)
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++)
{
- descdev = &dev->descdev;
+ struct grub_usb_keyboard_data *data = grub_usb_keyboards[i].data;
+
+ if (!data)
+ continue;
+
+ if (data->usbdev != usbdev)
+ continue;
+
+ grub_term_unregister_input (&grub_usb_keyboards[i]);
+ grub_free ((char *) grub_usb_keyboards[i].name);
+ grub_usb_keyboards[i].name = NULL;
+ grub_free (grub_usb_keyboards[i].data);
+ grub_usb_keyboards[i].data = 0;
+ }
+ }
+
+ static int
+ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
+ {
+ unsigned curnum;
+ struct grub_usb_keyboard_data *data;
+ struct grub_usb_desc_endp *endp = NULL;
+ int j;
+
+ grub_dprintf ("usb_keyboard", "%x %x %x %d %d\n",
+ usbdev->descdev.class, usbdev->descdev.subclass,
+ usbdev->descdev.protocol, configno, interfno);
+
+ for (curnum = 0; curnum < ARRAY_SIZE (grub_usb_keyboards); curnum++)
+ if (!grub_usb_keyboards[curnum].data)
+ break;
+
+ if (curnum == ARRAY_SIZE (grub_usb_keyboards))
+ return 0;
- grub_dprintf ("usb_keyboard", "%x %x %x\n",
- descdev->class, descdev->subclass, descdev->protocol);
+ if (usbdev->descdev.class != 0
+ || usbdev->descdev.subclass != 0 || usbdev->descdev.protocol != 0)
+ return 0;
- #if 0
- if (descdev->class != 0x09
- || descdev->subclass == 0x01
- || descdev->protocol != 0x02)
- return 0;
- #endif
+ if (usbdev->config[configno].interf[interfno].descif->subclass
+ != USB_HID_BOOT_SUBCLASS
+ || usbdev->config[configno].interf[interfno].descif->protocol
+ != USB_HID_KBD_PROTOCOL)
+ return 0;
- if (descdev->class != 0 || descdev->subclass != 0 || descdev->protocol != 0)
- return 0;
+ for (j = 0; j < usbdev->config[configno].interf[interfno].descif->endpointcnt;
+ j++)
+ {
+ endp = &usbdev->config[configno].interf[interfno].descendp[j];
- grub_printf ("HID found!\n");
+ if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
+ == GRUB_USB_EP_INTERRUPT)
+ break;
+ }
+ if (j == usbdev->config[configno].interf[interfno].descif->endpointcnt)
+ return 0;
- usbdev = dev;
+ grub_dprintf ("usb_keyboard", "HID found!\n");
- return 1;
+ data = grub_malloc (sizeof (*data));
+ if (!data)
+ {
+ grub_print_error ();
+ return 0;
}
- grub_usb_iterate (usb_iterate);
+
+ data->usbdev = usbdev;
+ data->endp = endp;
/* Place the device in boot mode. */
- grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_PROTOCOL,
- 0, 0, 0, 0);
+ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT,
+ USB_HID_SET_PROTOCOL, 0, 0, 0, 0);
/* Reports every time an event occurs and not more often than that. */
- grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE,
- 0<<8, 0, 0, 0);
- }
+ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT,
+ USB_HID_SET_IDLE, 0<<8, 0, 0, 0);
+
+ grub_memcpy (&grub_usb_keyboards[curnum], &grub_usb_keyboard_term,
+ sizeof (grub_usb_keyboards[curnum]));
+ grub_usb_keyboards[curnum].data = data;
+ usbdev->config[configno].interf[interfno].detach_hook
+ = grub_usb_keyboard_detach;
+ grub_usb_keyboards[curnum].name = grub_xasprintf ("usb_keyboard%d", curnum);
+ if (!grub_usb_keyboards[curnum].name)
+ {
+ grub_print_error ();
+ return 0;
+ }
- static grub_err_t
- grub_usb_keyboard_getreport (grub_usb_device_t dev, grub_uint8_t *report)
- {
- return grub_usb_control_msg (dev, USB_HID_DEVICE_TO_HOST, USB_HID_GET_REPORT,
- 0, 0, 8, (char *) report);
+ {
+ grub_uint8_t report[8];
+ grub_usb_err_t err;
+ grub_memset (report, 0, sizeof (report));
+ err = grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_IN,
+ USB_HID_GET_REPORT, 0x0000, interfno,
+ sizeof (report), (char *) report);
+ if (err)
+ {
+ data->status = 0;
+ data->key = -1;
+ }
+ else
+ {
+ data->status = report[0];
+ data->key = report[2] ? : -1;
+ }
+ }
+
+ grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]);
+
+ return 1;
}
\f
data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7]);
- /* Check if the Control or Shift key was pressed. */
- if (data[0] & 0x01 || data[0] & 0x10)
- termdata->key = keyboard_map[data[2]] - 'a' + 1;
- else if (data[0] & 0x02 || data[0] & 0x20)
- termdata->key = keyboard_map_shift[data[2]];
- else
- termdata->key = keyboard_map[data[2]];
-
- if (termdata->key == 0)
+ if (usb_to_at_map[data[2]] == 0)
grub_printf ("Unknown key 0x%x detected\n", data[2]);
- key = grub_term_map_key (usb_to_at_map[data[2]], interpret_status (data[0]));
+
+ else
++ termdata->key = grub_term_map_key (usb_to_at_map[data[2]],
++ interpret_status (data[0]));
+
grub_errno = GRUB_ERR_NONE;
- return key;
-
- #if 0
- /* Wait until the key is released. */
- while (!err && data[2])
- {
- err = grub_usb_control_msg (usbdev, USB_HID_DEVICE_TO_HOST,
- USB_HID_GET_REPORT, 0, 0,
- sizeof (data), (char *) data);
- grub_dprintf ("usb_keyboard",
- "report2: 0x%02x 0x%02x 0x%02x 0x%02x"
- " 0x%02x 0x%02x 0x%02x 0x%02x\n",
- data[0], data[1], data[2], data[3],
- data[4], data[5], data[6], data[7]);
- }
- #endif
-
- return key;
+ return termdata->key;
}
- typedef enum
- {
- GRUB_HIDBOOT_REPEAT_NONE,
- GRUB_HIDBOOT_REPEAT_FIRST,
- GRUB_HIDBOOT_REPEAT
- } grub_usb_keyboard_repeat_t;
-
static int
grub_usb_keyboard_getkey (struct grub_term_input *term)
{
}
static int
- grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unused)))
+ grub_usb_keyboard_getkeystatus (struct grub_term_input *term)
{
- grub_uint8_t data[8];
- grub_err_t err;
- grub_uint64_t currtime;
- int timeout = 50;
-
- /* Set idle time to the minimum offered by the spec (4 milliseconds) so
- that we can find out the current state. */
- grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE,
- 0<<8, 0, 0, 0);
-
- currtime = grub_get_time_ms ();
- do
- {
- /* Get_Report. */
- err = grub_usb_keyboard_getreport (usbdev, data);
-
- /* Implement a timeout. */
- if (grub_get_time_ms () > currtime + timeout)
- break;
- }
- while (err || !data[0]);
-
- /* Go back to reporting every time an event occurs and not more often than
- that. */
- grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE,
- 0<<8, 0, 0, 0);
-
- /* We allowed a while for modifiers to show up in the report, but it is
- not an error if they never did. */
- if (err)
- return -1;
-
- grub_dprintf ("usb_keyboard",
- "report: 0x%02x 0x%02x 0x%02x 0x%02x"
- " 0x%02x 0x%02x 0x%02x 0x%02x\n",
- data[0], data[1], data[2], data[3],
- data[4], data[5], data[6], data[7]);
-
- grub_errno = GRUB_ERR_NONE;
+ struct grub_usb_keyboard_data *termdata = term->data;
- int mods = 0;
-
- /* Check Shift, Control, and Alt status. */
- if (termdata->status & 0x02 || termdata->status & 0x20)
- mods |= GRUB_TERM_STATUS_SHIFT;
- if (termdata->status & 0x01 || termdata->status & 0x10)
- mods |= GRUB_TERM_STATUS_CTRL;
- if (termdata->status & 0x04 || termdata->status & 0x40)
- mods |= GRUB_TERM_STATUS_ALT;
- return interpret_status (data[0]);
- return mods;
++ return interpret_status (termdata->status);
}
- static struct grub_term_input grub_usb_keyboard_term =
- {
- .name = "usb_keyboard",
- .checkkey = grub_usb_keyboard_checkkey,
- .getkey = grub_usb_keyboard_getkey,
- .getkeystatus = grub_usb_keyboard_getkeystatus,
- .next = 0
- };
+ struct grub_usb_attach_desc attach_hook =
+ {
+ .class = GRUB_USB_CLASS_HID,
+ .hook = grub_usb_keyboard_attach
+ };
GRUB_MOD_INIT(usb_keyboard)
{