usb: kbd: simplify coding for arrow keys
[oweals/u-boot.git] / common / usb_kbd.c
index cbb1995de3398431878811f92f6e79551b947965..d177b97d67ed2fdc01a73238412de9f2583ed355 100644 (file)
@@ -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 <common.h>
 #include <console.h>
 #include <dm.h>
+#include <env.h>
 #include <errno.h>
 #include <malloc.h>
 #include <memalign.h>
 #include <stdio_dev.h>
+#include <watchdog.h>
 #include <asm/byteorder.h>
 
 #include <usb.h>
@@ -74,13 +75,8 @@ 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[] = {
+       'C', 'D', 'B', 'A'
 };
 
 /*
@@ -126,7 +122,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 +195,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 +203,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 +230,17 @@ 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;
        }
 
-       return 0;
+       /* 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;
 }
 
 static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up)
@@ -316,11 +316,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 +367,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 +383,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;
@@ -480,8 +481,8 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
        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);
@@ -515,8 +516,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;
@@ -537,7 +538,7 @@ 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)
 {
@@ -566,12 +567,11 @@ int drv_usb_kbd_init(void)
        /* 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;
@@ -582,8 +582,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
@@ -599,16 +599,15 @@ 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);
-       int ret;
 
-       ret = probe_usb_keyboard(udev);
-
-       return ret;
+       return probe_usb_keyboard(udev);
 }
 
 static int usb_kbd_remove(struct udevice *dev)
@@ -628,8 +627,8 @@ static int usb_kbd_remove(struct udevice *dev)
                ret = -EPERM;
                goto err;
        }
-#ifdef CONFIG_CONSOLE_MUX
-       if (iomux_doenv(stdin, getenv("stdin"))) {
+#if CONFIG_IS_ENABLED(CONSOLE_MUX)
+       if (iomux_doenv(stdin, env_get("stdin"))) {
                ret = -ENOLINK;
                goto err;
        }