Detect usb keyboard properly, support keyboard hotpluanad multiple keyboards
This commit is contained in:
parent
b92c6ff67f
commit
3a25376967
1 changed files with 82 additions and 34 deletions
|
@ -54,7 +54,6 @@ static char keyboard_map_shift[128] =
|
|||
'?'
|
||||
};
|
||||
|
||||
static grub_usb_device_t usbdev;
|
||||
|
||||
/* Valid values for bmRequestType. See HID definition version 1.11 section
|
||||
7.2. */
|
||||
|
@ -69,36 +68,64 @@ static grub_usb_device_t usbdev;
|
|||
#define USB_HID_SET_IDLE 0x0A
|
||||
#define USB_HID_SET_PROTOCOL 0x0B
|
||||
|
||||
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 struct grub_term_input grub_usb_keyboards[16];
|
||||
|
||||
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;
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++)
|
||||
if (grub_usb_keyboards[i].data && grub_usb_keyboards[i].data == usbdev)
|
||||
{
|
||||
grub_term_unregister_input (&grub_usb_keyboards[i]);
|
||||
grub_free ((char *) grub_usb_keyboards[i].name);
|
||||
grub_usb_keyboards[i].name = NULL;
|
||||
grub_usb_keyboards[i].data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
auto int usb_iterate (grub_usb_device_t dev);
|
||||
int usb_iterate (grub_usb_device_t dev)
|
||||
{
|
||||
descdev = &dev->descdev;
|
||||
static int
|
||||
grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
||||
{
|
||||
unsigned curnum;
|
||||
|
||||
grub_dprintf ("usb_keyboard", "%x %x %x\n",
|
||||
descdev->class, descdev->subclass, descdev->protocol);
|
||||
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;
|
||||
|
||||
#if 0
|
||||
if (descdev->class != 0x09
|
||||
|| descdev->subclass == 0x01
|
||||
|| descdev->protocol != 0x02)
|
||||
if (descdev->class != 0x09
|
||||
|| descdev->subclass == 0x01
|
||||
|| descdev->protocol != 0x02)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (descdev->class != 0 || descdev->subclass != 0 || descdev->protocol != 0)
|
||||
return 0;
|
||||
if (usbdev->descdev.class != 0
|
||||
|| usbdev->descdev.subclass != 0 || usbdev->descdev.protocol != 0)
|
||||
return 0;
|
||||
|
||||
grub_printf ("HID found!\n");
|
||||
|
||||
usbdev = dev;
|
||||
|
||||
return 1;
|
||||
}
|
||||
grub_usb_iterate (usb_iterate);
|
||||
grub_printf ("HID found!\n");
|
||||
|
||||
/* Place the device in boot mode. */
|
||||
grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_PROTOCOL,
|
||||
|
@ -107,6 +134,19 @@ grub_usb_hid (void)
|
|||
/* 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_memcpy (&grub_usb_keyboards[curnum], &grub_usb_keyboard_term,
|
||||
sizeof (grub_usb_keyboards[curnum]));
|
||||
grub_usb_keyboards[curnum].data = usbdev;
|
||||
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)
|
||||
return 0;
|
||||
grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -119,13 +159,14 @@ grub_usb_keyboard_getreport (grub_usb_device_t dev, grub_uint8_t *report)
|
|||
|
||||
|
||||
static int
|
||||
grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
grub_usb_keyboard_checkkey (struct grub_term_input *term)
|
||||
{
|
||||
grub_uint8_t data[8];
|
||||
int key;
|
||||
grub_err_t err;
|
||||
grub_uint64_t currtime;
|
||||
int timeout = 50;
|
||||
grub_usb_device_t usbdev = term->data;
|
||||
|
||||
data[2] = 0;
|
||||
currtime = grub_get_time_ms ();
|
||||
|
@ -196,6 +237,7 @@ grub_usb_keyboard_getkey (struct grub_term_input *term)
|
|||
grub_uint64_t currtime;
|
||||
int timeout;
|
||||
static grub_usb_keyboard_repeat_t repeat = GRUB_HIDBOOT_REPEAT_NONE;
|
||||
grub_usb_device_t usbdev = term->data;
|
||||
|
||||
again:
|
||||
|
||||
|
@ -253,13 +295,14 @@ 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];
|
||||
int mods = 0;
|
||||
grub_err_t err;
|
||||
grub_uint64_t currtime;
|
||||
int timeout = 50;
|
||||
grub_usb_device_t usbdev = term->data;
|
||||
|
||||
/* Set idle time to the minimum offered by the spec (4 milliseconds) so
|
||||
that we can find out the current state. */
|
||||
|
@ -307,22 +350,27 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unu
|
|||
return mods;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
grub_usb_hid ();
|
||||
grub_term_register_input ("usb_keyboard", &grub_usb_keyboard_term);
|
||||
grub_usb_register_attach_hook_class (&attach_hook);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(usb_keyboard)
|
||||
{
|
||||
grub_term_unregister_input (&grub_usb_keyboard_term);
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++)
|
||||
if (grub_usb_keyboards[i].data)
|
||||
{
|
||||
grub_term_unregister_input (&grub_usb_keyboards[i]);
|
||||
grub_free ((char *) grub_usb_keyboards[i].name);
|
||||
grub_usb_keyboards[i].name = NULL;
|
||||
grub_usb_keyboards[i].data = 0;
|
||||
}
|
||||
grub_usb_unregister_attach_hook_class (&attach_hook);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue