#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;
+ grub_uint16_t mods;
+ int key;
+ int interfno;
+ struct grub_usb_desc_endp *endp;
++ grub_usb_transfer_t transfer;
++ grub_uint8_t report[8];
++ int dead;
+};
+
+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);
.next = 0
};
-struct grub_usb_keyboard_data
++static struct grub_term_input grub_usb_keyboards[16];
++
+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;
- grub_usb_transfer_t transfer;
- grub_uint8_t report[8];
- int dead;
-};
+ 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_keyboard_detach (grub_usb_device_t usbdev,
data->key = report[2] ? : -1;
}
}
+ #else
+ data->status = 0;
+ data->key = -1;
+ #endif
+
+ data->transfer = grub_usb_bulk_read_background (usbdev,
+ data->endp->endp_addr,
+ sizeof (data->report),
+ (char *) data->report);
+ if (!data->transfer)
+ {
+ grub_print_error ();
+ return 0;
+ }
+ data->mods = 0;
+
grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]);
+ data->dead = 0;
+
return 1;
}
if (termdata->key != -1)
return termdata->key;
- data[2] = 0;
+ if (termdata->dead)
+ return -1;
+
/* Poll interrupt pipe. */
- err = grub_usb_bulk_read_extended (termdata->usbdev,
- termdata->endp->endp_addr, sizeof (data),
- (char *) data, 10, &actual);
+ err = grub_usb_check_transfer (termdata->transfer, &actual);
+
+ if (err == GRUB_USB_ERR_WAIT)
+ return -1;
+
+ grub_memcpy (data, termdata->report, sizeof (data));
+
- grub_dprintf ("usb_keyboard",
- "err = %d, actual = %d report: 0x%02x 0x%02x 0x%02x 0x%02x"
- " 0x%02x 0x%02x 0x%02x 0x%02x\n",
- err, actual,
- data[0], data[1], data[2], data[3],
- data[4], data[5], data[6], data[7]);
-
+ termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev,
+ termdata->endp->endp_addr,
+ sizeof (termdata->report),
+ (char *) termdata->report);
+ if (!termdata->transfer)
+ {
+ grub_printf ("%s failed. Stopped\n", term->name);
+ termdata->dead = 1;
+ }
+
++
++ grub_dprintf ("usb_keyboard",
++ "err = %d, actual = %d report: 0x%02x 0x%02x 0x%02x 0x%02x"
++ " 0x%02x 0x%02x 0x%02x 0x%02x\n",
++ err, actual,
++ data[0], data[1], data[2], data[3],
++ data[4], data[5], data[6], data[7]);
++
if (err || actual < 1)
return -1;
if (actual < 3 || !data[2])
return -1;
- /* 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 (data[2] == CAPS_LOCK)
+ {
+ termdata->mods ^= GRUB_TERM_STATUS_CAPS;
+ send_leds (termdata);
+ 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]);
-
- if (termdata->key == 0)
+ if (usb_to_at_map[data[2]] == 0)
grub_printf ("Unknown key 0x%x detected\n", data[2]);
-
+ else
+ termdata->key = grub_term_map_key (usb_to_at_map[data[2]],
+ interpret_status (data[0])
+ | termdata->mods);
grub_errno = GRUB_ERR_NONE;
grub_usb_keyboard_getkeystatus (struct grub_term_input *term)
{
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 mods;
+ grub_usb_keyboard_checkkey (term);
+
+ return interpret_status (termdata->status) | termdata->mods;
}
struct grub_usb_attach_desc attach_hook =