Add a "usbinit" boot option to handle various buggy USB devices.

This replaces the "keyboard=buggy-usb" option, and adds a second
workaround to handle the problem seen in issue #107.
This commit is contained in:
Martin Whitaker 2022-07-11 22:37:06 +01:00
parent 81ffdeb4a0
commit fc40ce6236
4 changed files with 24 additions and 10 deletions

View File

@ -132,7 +132,13 @@ recognised:
* where *type* is one of
* legacy
* usb
* buggy-usb
* usbdebug
* pauses after probing for USB keyboards
* usbinit=*mode*
* where *mode* is one of
* 1 = use the two-step init sequence for high speed devices
* 2 = add a second USB reset in the init sequence
* 3 = the combination of modes 1 and 2
* console=ttyS*x*,*y*
* activate serial/tty console output, where *x* is one of the following IO port
* 0 = 0x3F8
@ -152,9 +158,7 @@ recognised:
Memtest86+ supports both the legacy keyboard interface (using I/O ports 0x60
and 0x64) and USB keyboards (using its own USB device drivers). One or the
other can be selected via the boot command line, If neither is selected, the
default is to use both. An additional option on the boot command line is
`buggy-usb` which enables the longer initialisation sequence required by some
older USB devices.
default is to use both.
Older BIOSs usually support USB legacy keyboard emulation, which makes USB
keyboards act like legacy keyboards connected to ports 0x60 and 0x64. This
@ -170,6 +174,10 @@ emulation and add `keyboard=legacy` on the boot command line.
you enable the Compatibility System Module (CSM) in the BIOS setup. Others
only support it when actually booting in legacy mode.
Many USB devices don't fully conform to the USB specification. If the USB
keyboard probe hangs or fails to detect your keyboard, try the various
workarounds provided by the "usbinit" boot option.
**NOTE**: Memtest86+'s USB device drivers are work in progress. Not all USB
devices are supported yet, and there may be problems on some hardware.

View File

@ -175,9 +175,6 @@ static void parse_option(const char *option, const char *params)
keyboard_types = KT_LEGACY;
} else if (strncmp(params, "usb", 4) == 0) {
keyboard_types = KT_USB;
} else if (strncmp(params, "buggy-usb", 10) == 0) {
keyboard_types = KT_USB;
usb_init_options |= USB_EXTRA_RESET;
}
} else if (strncmp(option, "powersave", 10) == 0) {
if (strncmp(params, "off", 4) == 0) {
@ -201,6 +198,14 @@ static void parse_option(const char *option, const char *params)
enable_trace = true;
} else if (strncmp(option, "usbdebug", 9) == 0) {
usb_init_options |= USB_DEBUG;
} else if (strncmp(option, "usbinit", 8) == 0) {
if (strncmp(params, "1", 2) == 0) {
usb_init_options |= USB_2_STEP_INIT;
} else if (strncmp(params, "2", 2) == 0) {
usb_init_options |= USB_EXTRA_RESET;
} else if (strncmp(params, "3", 2) == 0) {
usb_init_options |= USB_2_STEP_INIT|USB_EXTRA_RESET;
}
} else if (strncmp(option, "nosm", 5) == 0) {
enable_sm = false;
}

View File

@ -543,12 +543,12 @@ bool assign_usb_address(const usb_hcd_t *hcd, const usb_hub_t *hub, int port_num
ep0->max_packet_size = default_max_packet_size(device_speed);
ep0->interval = 0;
// The device should currently be in Default state. For loww and full speed devices, We first fetch the first
// The device should currently be in Default state. For low and full speed devices, we first fetch the first
// 8 bytes of the device descriptor to discover the maximum packet size for the control endpoint. We then set
// the device address, which moves the device into Address state, and fetch the full device descriptor.
size_t fetch_length = sizeof(usb_device_desc_t);
if (device_speed < USB_SPEED_HIGH) {
if (device_speed < USB_SPEED_HIGH || usb_init_options & USB_2_STEP_INIT) {
fetch_length = 8;
goto fetch_descriptor;
}

View File

@ -121,7 +121,8 @@ typedef enum {
USB_DEFAULT_INIT = 0,
USB_EXTRA_RESET = 1 << 0,
USB_IGNORE_EHCI = 1 << 1,
USB_DEBUG = 1 << 2
USB_2_STEP_INIT = 1 << 2,
USB_DEBUG = 1 << 3
} usb_init_options_t;
/**