/* Support for the HID Boot Protocol. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
*
* 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/keyboard_layouts.h>
GRUB_MOD_LICENSE ("GPLv3+");
enum
{
};
enum
{
};
/* Valid values for bRequest. See HID definition version 1.11 section 7.2. */
struct grub_usb_keyboard_data
{
int interfno;
int dead;
int last_key;
int index;
int max_index;
};
{
.next = 0
};
static int
{
int mods = 0;
/* Check Shift, Control, and Alt status. */
if (data0 & GRUB_USB_KEYBOARD_LEFT_CTRL)
if (data0 & GRUB_USB_KEYBOARD_LEFT_ALT)
if (data0 & GRUB_USB_KEYBOARD_RIGHT_ALT)
return mods;
}
static void
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++)
{
if (!data)
continue;
continue;
grub_usb_keyboards[i].data = 0;
}
}
static int
{
unsigned curnum;
int j;
break;
return 0;
return 0;
return 0;
j++)
{
break;
}
return 0;
if (!data)
{
grub_print_error ();
return 0;
}
/* Configure device */
/* Place the device in boot mode. */
USB_HID_SET_PROTOCOL, 0, interfno, 0, 0);
/* Reports every time an event occurs and not more often than that. */
sizeof (grub_usb_keyboards[curnum]));
{
grub_print_error ();
return 0;
}
/* Test showed that getting report may make the keyboard go nuts.
Moreover since we're reattaching keyboard it usually sends
an initial message on interrupt pipe and so we retrieve
the same keystatus.
*/
#if 0
{
if (err)
else
}
#else
#endif
{
grub_print_error ();
return 0;
}
return 1;
}
static void
{
report[0] = 0;
report[0] |= LED_CAPS_LOCK;
report[0] |= LED_NUM_LOCK;
}
static int
{
int i, keycode;
/* Sanity check */
if (index < 2)
index = 2;
{
if (keycode == KEY_NO_KEY
|| keycode == KEY_ERR_BUFFER
|| keycode == KEY_ERR_POST
|| keycode == KEY_ERR_UNDEF)
{
/* Don't parse (rest of) this report */
if (keycode != KEY_NO_KEY)
/* Don't replace last report with current faulty report
* in future ! */
return GRUB_TERM_NO_KEY;
}
/* Try to find current keycode in last report. */
for (i = 2; i < 8; i++)
break;
if (i < 8)
/* Keycode is in last report, it means it was not released,
* ignore it. */
continue;
if (keycode == KEY_CAPS_LOCK)
{
continue;
}
if (keycode == KEY_NUM_LOCK)
{
continue;
}
index++;
else
}
/* All keycodes parsed */
return GRUB_TERM_NO_KEY;
}
static int
{
return GRUB_TERM_NO_KEY;
if (keycode != GRUB_TERM_NO_KEY)
return keycode;
/* Poll interrupt pipe. */
if (err == GRUB_USB_ERR_WAIT)
{
{
}
return GRUB_TERM_NO_KEY;
}
{
}
grub_dprintf ("usb_keyboard",
"err = %d, actual = %" PRIuGRUB_SIZE
" report: 0x%02x 0x%02x 0x%02x 0x%02x"
" 0x%02x 0x%02x 0x%02x 0x%02x\n",
return GRUB_TERM_NO_KEY;
if (actual < 3)
return GRUB_TERM_NO_KEY;
return parse_keycode (termdata);
}
static int
{
}
{
};
{
}
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++)
if (grub_usb_keyboards[i].data)
{
if (!data)
continue;
grub_usb_keyboards[i].data = 0;
}
}