X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fusb_kbd.c;h=a6221ef71647c20ddef7d68b50346ab6c126d60c;hb=515f613253cf0a892c3a321770ab927fa3d925cf;hp=5a90f843f2a83149448957b51371529678b9ce16;hpb=24b852a7a2b8eca71789100983bdb5104cc00696;p=oweals%2Fu-boot.git diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 5a90f843f2..a6221ef716 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -1,19 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2001 * Denis Peter, MPL AG Switzerland * * Part of this source has been derived from the Linux USB * project. - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include +#include #include #include #include #include +#include #include #include @@ -74,13 +75,12 @@ static const unsigned char usb_kbd_num_keypad[] = { '.', 0, 0, 0, '=' }; -/* - * map arrow keys to ^F/^B ^N/^P, can't really use the proper - * ANSI sequence for arrow keys because the queuing code breaks - * when a single keypress expands to 3 queue elements - */ -static const unsigned char usb_kbd_arrow[] = { - 0x6, 0x2, 0xe, 0x10 +static const u8 usb_special_keys[] = { +#ifdef CONFIG_USB_KEYBOARD_FN_KEYS + '2', 'H', '5', '3', 'F', '6', 'C', 'D', 'B', 'A' +#else + 'C', 'D', 'B', 'A' +#endif }; /* @@ -95,12 +95,6 @@ static const unsigned char usb_kbd_arrow[] = { #define USB_KBD_LEDMASK \ (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) -/* - * USB Keyboard reports are 8 bytes in boot protocol. - * Appendix B of HID Device Class Definition 1.11 - */ -#define USB_KBD_BOOT_REPORT_SIZE 8 - struct usb_kbd_pdata { unsigned long intpipe; int intpktsize; @@ -126,7 +120,7 @@ extern int __maybe_unused net_busy_flag; static unsigned long __maybe_unused kbd_testc_tms; /* Puts character in the queue and sets up the in and out pointer. */ -static void usb_kbd_put_queue(struct usb_kbd_pdata *data, char c) +static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) { if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { /* Check for buffer full. */ @@ -199,7 +193,7 @@ static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, } } - if ((scancode > 0x1d) && (scancode < 0x3a)) { + if ((scancode > 0x1d) && (scancode < 0x39)) { /* Shift pressed */ if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) keycode = usb_kbd_numkey_shifted[scancode - 0x1e]; @@ -207,10 +201,6 @@ static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, keycode = usb_kbd_numkey[scancode - 0x1e]; } - /* Arrow keys */ - if ((scancode >= 0x4f) && (scancode <= 0x52)) - keycode = usb_kbd_arrow[scancode - 0x4f]; - /* Numeric keypad */ if ((scancode >= 0x54) && (scancode <= 0x67)) keycode = usb_kbd_num_keypad[scancode - 0x54]; @@ -238,9 +228,55 @@ static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, if (keycode) { debug("%c", keycode); usb_kbd_put_queue(data, keycode); + return 0; } +#ifdef CONFIG_USB_KEYBOARD_FN_KEYS + if (scancode < 0x3a || scancode > 0x52 || + scancode == 0x46 || scancode == 0x47) + return 1; + + usb_kbd_put_queue(data, 0x1b); + if (scancode < 0x3e) { + /* F1 - F4 */ + usb_kbd_put_queue(data, 0x4f); + usb_kbd_put_queue(data, scancode - 0x3a + 'P'); + return 0; + } + usb_kbd_put_queue(data, '['); + if (scancode < 0x42) { + /* F5 - F8 */ + usb_kbd_put_queue(data, '1'); + if (scancode == 0x3e) + --scancode; + keycode = scancode - 0x3f + '7'; + } else if (scancode < 0x49) { + /* F9 - F12 */ + usb_kbd_put_queue(data, '2'); + if (scancode > 0x43) + ++scancode; + keycode = scancode - 0x42 + '0'; + } else { + /* + * INSERT, HOME, PAGE UP, DELETE, END, PAGE DOWN, + * RIGHT, LEFT, DOWN, UP + */ + keycode = usb_special_keys[scancode - 0x49]; + } + usb_kbd_put_queue(data, keycode); + if (scancode < 0x4f && scancode != 0x4a && scancode != 0x4d) + usb_kbd_put_queue(data, '~'); return 0; +#else + /* Left, Right, Up, Down */ + if (scancode > 0x4e && scancode < 0x53) { + usb_kbd_put_queue(data, 0x1b); + usb_kbd_put_queue(data, '['); + usb_kbd_put_queue(data, usb_special_keys[scancode - 0x4f]); + return 0; + } + return 1; +#endif /* CONFIG_USB_KEYBOARD_FN_KEYS */ } static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up) @@ -316,11 +352,10 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) #if defined(CONFIG_SYS_USB_EVENT_POLL) struct usb_kbd_pdata *data = dev->privptr; - /* Submit a interrupt transfer request */ - usb_submit_int_msg(dev, data->intpipe, &data->new[0], data->intpktsize, - data->intinterval); - - usb_kbd_irq_worker(dev); + /* Submit an interrupt transfer request */ + if (usb_int_msg(dev, data->intpipe, &data->new[0], + data->intpktsize, data->intinterval, true) >= 0) + usb_kbd_irq_worker(dev); #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) || \ defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) #if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) @@ -368,7 +403,7 @@ static int usb_kbd_testc(struct stdio_dev *sdev) return 0; kbd_testc_tms = get_timer(0); #endif - dev = stdio_get_by_name(DEVNAME); + dev = stdio_get_by_name(sdev->name); usb_kbd_dev = (struct usb_device *)dev->priv; data = usb_kbd_dev->privptr; @@ -384,12 +419,14 @@ static int usb_kbd_getc(struct stdio_dev *sdev) struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; - dev = stdio_get_by_name(DEVNAME); + dev = stdio_get_by_name(sdev->name); usb_kbd_dev = (struct usb_device *)dev->priv; data = usb_kbd_dev->privptr; - while (data->usb_in_pointer == data->usb_out_pointer) + while (data->usb_in_pointer == data->usb_out_pointer) { + WATCHDOG_RESET(); usb_kbd_poll_for_event(usb_kbd_dev); + } if (data->usb_out_pointer == USB_KBD_BUFFER_LEN - 1) data->usb_out_pointer = 0; @@ -411,13 +448,13 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) iface = &dev->config.if_desc[ifnum]; - if (iface->desc.bInterfaceClass != 3) + if (iface->desc.bInterfaceClass != USB_CLASS_HID) return 0; - if (iface->desc.bInterfaceSubClass != 1) + if (iface->desc.bInterfaceSubClass != USB_SUB_HID_BOOT) return 0; - if (iface->desc.bInterfaceProtocol != 1) + if (iface->desc.bInterfaceProtocol != USB_PROT_HID_KEYBOARD) return 0; if (iface->desc.bNumEndpoints != 1) @@ -476,9 +513,12 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) USB_KBD_BOOT_REPORT_SIZE, data->new, data->intinterval); if (!data->intq) { +#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) + if (usb_get_report(dev, iface->desc.bInterfaceNumber, + 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE) < 0) { #else - if (usb_submit_int_msg(dev, data->intpipe, data->new, data->intpktsize, - data->intinterval) < 0) { + if (usb_int_msg(dev, data->intpipe, data->new, data->intpktsize, + data->intinterval, false) < 0) { #endif printf("Failed to get keyboard state from device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); @@ -512,8 +552,8 @@ static int probe_usb_keyboard(struct usb_device *dev) if (error) return error; - stdinname = getenv("stdin"); -#ifdef CONFIG_CONSOLE_MUX + stdinname = env_get("stdin"); +#if CONFIG_IS_ENABLED(CONSOLE_MUX) error = iomux_doenv(stdin, stdinname); if (error) return error; @@ -534,42 +574,13 @@ static int probe_usb_keyboard(struct usb_device *dev) return 0; } -#ifndef CONFIG_DM_USB +#if !CONFIG_IS_ENABLED(DM_USB) /* Search for keyboard and register it if found. */ int drv_usb_kbd_init(void) { int error, i; debug("%s: Probing for keyboard\n", __func__); -#ifdef CONFIG_DM_USB - /* - * TODO: We should add U_BOOT_USB_DEVICE() declarations to each USB - * keyboard driver and then most of this file can be removed. - */ - struct udevice *bus; - struct uclass *uc; - int ret; - - ret = uclass_get(UCLASS_USB, &uc); - if (ret) - return ret; - uclass_foreach_dev(bus, uc) { - for (i = 0; i < USB_MAX_DEVICE; i++) { - struct usb_device *dev; - - dev = usb_get_dev_index(bus, i); /* get device */ - debug("i=%d, %p\n", i, dev); - if (!dev) - break; /* no more devices available */ - - error = probe_usb_keyboard(dev); - if (!error) - return 1; - if (error && error != -ENOENT) - return error; - } /* for */ - } -#else /* Scan all USB Devices */ for (i = 0; i < USB_MAX_DEVICE; i++) { struct usb_device *dev; @@ -588,17 +599,15 @@ int drv_usb_kbd_init(void) if (error && error != -ENOENT) return error; } -#endif /* No USB Keyboard found */ return -1; } -#endif /* Deregister the keyboard. */ int usb_kbd_deregister(int force) { -#ifdef CONFIG_SYS_STDIO_DEREGISTER +#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; @@ -609,8 +618,8 @@ int usb_kbd_deregister(int force) data = usb_kbd_dev->privptr; if (stdio_deregister_dev(dev, force) != 0) return 1; -#ifdef CONFIG_CONSOLE_MUX - if (iomux_doenv(stdin, getenv("stdin")) != 0) +#if CONFIG_IS_ENABLED(CONSOLE_MUX) + if (iomux_doenv(stdin, env_get("stdin")) != 0) return 1; #endif #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE @@ -626,15 +635,49 @@ int usb_kbd_deregister(int force) #endif } -#ifdef CONFIG_DM_USB +#endif + +#if CONFIG_IS_ENABLED(DM_USB) static int usb_kbd_probe(struct udevice *dev) { struct usb_device *udev = dev_get_parent_priv(dev); + + return probe_usb_keyboard(udev); +} + +static int usb_kbd_remove(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct usb_kbd_pdata *data; + struct stdio_dev *sdev; int ret; - ret = probe_usb_keyboard(udev); + sdev = stdio_get_by_name(DEVNAME); + if (!sdev) { + ret = -ENXIO; + goto err; + } + data = udev->privptr; + if (stdio_deregister_dev(sdev, true)) { + ret = -EPERM; + goto err; + } +#if CONFIG_IS_ENABLED(CONSOLE_MUX) + if (iomux_doenv(stdin, env_get("stdin"))) { + ret = -ENOLINK; + goto err; + } +#endif +#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE + destroy_int_queue(udev, data->intq); +#endif + free(data->new); + free(data); + return 0; +err: + printf("%s: warning, ret=%d", __func__, ret); return ret; } @@ -648,6 +691,7 @@ U_BOOT_DRIVER(usb_kbd) = { .id = UCLASS_KEYBOARD, .of_match = usb_kbd_ids, .probe = usb_kbd_probe, + .remove = usb_kbd_remove, }; static const struct usb_device_id kbd_id_table[] = { @@ -656,8 +700,8 @@ static const struct usb_device_id kbd_id_table[] = { USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL, .bInterfaceClass = USB_CLASS_HID, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, + .bInterfaceSubClass = USB_SUB_HID_BOOT, + .bInterfaceProtocol = USB_PROT_HID_KEYBOARD, }, { } /* Terminating entry */ };