diff options
author | Hans de Goede <hdegoede@redhat.com> | 2014-09-20 16:54:35 +0200 |
---|---|---|
committer | Marek Vasut <marex@denx.de> | 2014-10-06 14:50:43 +0200 |
commit | 6e78c74f62ebfa378d1a2f9b83423b23545c28bf (patch) | |
tree | a1822c0772256b3b6b14ac55a08839b4c5bc40be | |
parent | 0ea09dfe873657df47d83d5d4e0090bbf05c6abb (diff) |
usb: kbd: On a "usb reset" call usb_kbd_deregister() before calling usb_stop()
We need to call usb_kbd_deregister() before calling usb_stop().
usbkbd's stdio_dev->priv points to the usb_device, and usb_kbd_testc
dereferences usb_device->privptr.
usb_stop zeros usb_device, leaving usb_device->privptr NULL, causing
bad things (tm) to happen once control returns to the main loop and
usb_kbd_testc gets called.
Calling usb_kbd_deregister() avoids this. Note that we do not allow
the "usb reset" to continue when the deregister fails. This will be fixed
in a later patch.
For the same reasons always fail "usb stop" if the usb_kbd_deregister() fails,
even in the force path. This can happen when CONFIG_SYS_STDIO_DEREGISTER is
not set.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | common/cmd_usb.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 2519497dad..b2aa44c2a7 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -430,6 +430,16 @@ static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif /* CONFIG_USB_STORAGE */ +static int do_usb_stop_keyboard(void) +{ +#ifdef CONFIG_USB_KEYBOARD + if (usb_kbd_deregister() != 0) { + printf("USB not stopped: usbkbd still using USB\n"); + return 1; + } +#endif + return 0; +} /****************************************************************************** * usb command intepreter @@ -450,6 +460,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if ((strncmp(argv[1], "reset", 5) == 0) || (strncmp(argv[1], "start", 5) == 0)) { bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start"); + if (do_usb_stop_keyboard() != 0) + return 1; usb_stop(); printf("(Re)start USB...\n"); if (usb_init() >= 0) { @@ -468,19 +480,10 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "stop", 4) == 0) { -#ifdef CONFIG_USB_KEYBOARD - if (argc == 2) { - if (usb_kbd_deregister() != 0) { - printf("USB not stopped: usbkbd still" - " using USB\n"); - return 1; - } - } else { - /* forced stop, switch console in to serial */ + if (argc != 2) console_assign(stdin, "serial"); - usb_kbd_deregister(); - } -#endif + if (do_usb_stop_keyboard() != 0) + return 1; printf("stopping USB..\n"); usb_stop(); return 0; |