From patchwork Wed May 13 12:47:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 471855 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id B13E4140663 for ; Wed, 13 May 2015 22:48:06 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5224A4B6F4; Wed, 13 May 2015 14:48:05 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hvG09wxTy-SV; Wed, 13 May 2015 14:48:05 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9C73D4B6DC; Wed, 13 May 2015 14:48:04 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 8AFE84B6DC for ; Wed, 13 May 2015 14:48:02 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dltE9JaYCJya for ; Wed, 13 May 2015 14:48:02 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by theia.denx.de (Postfix) with ESMTPS id 06AE34B6C6 for ; Wed, 13 May 2015 14:47:58 +0200 (CEST) Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t4DClrig004905 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 13 May 2015 08:47:54 -0400 Received: from shalem.localdomain.com (vpn1-6-133.ams2.redhat.com [10.36.6.133]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t4DClqZn008074; Wed, 13 May 2015 08:47:52 -0400 From: Hans de Goede To: Marek Vasut Date: Wed, 13 May 2015 14:47:51 +0200 Message-Id: <1431521271-4493-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2] usb: kbd: Fix key repeat not always using X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The usb-kbd key repeat code assumes that reports get repeated every 40 ms, this is never true when using CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP, and does not always works for CONFIG_SYS_USB_EVENT_POLL and CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE since not all usb keyboards honor the usb_set_idle() command. For CONFIG_SYS_USB_EVENT_POLL we must use usb_set_idle() since we do a blocking wait for the hid report, so if we do not tell the keyboard to send a hid report every 40ms even if nothing changes then we will block u-boot for 1s (the default u-boot usb interrupt packet timeout). Note that in this case on keyboards which do not support usb_set_idle() we loose and we actually get 1s latencies on other u-boot activities. For the other poll-methods this commit stops using usb_set_idle() and instead repeats the last received hid-report every 40 ms as long as no new hid-report is received. This fixes key-repeat not working at all with CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP and fixes it not working with keyboards which do not implement usb_set_idle() when using CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE. Signed-off-by: Hans de Goede --- Changes in v2: -Change last_report type to unsigned long to match the get_timer return type --- common/usb_kbd.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 24a1a56..e8d108c 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -31,7 +31,7 @@ int overwrite_console(void) #endif /* Keyboard sampling rate */ -#define REPEAT_RATE (40 / 4) /* 40msec -> 25cps */ +#define REPEAT_RATE 40 /* 40msec -> 25cps */ #define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */ #define NUM_LOCK 0x53 @@ -103,6 +103,7 @@ struct usb_kbd_pdata { unsigned long intpipe; int intpktsize; int intinterval; + unsigned long last_report; struct int_queue *intq; uint32_t repeat_delay; @@ -318,15 +319,16 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) data->intinterval); usb_kbd_irq_worker(dev); -#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) +#else +# if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) struct usb_interface *iface; struct usb_kbd_pdata *data = dev->privptr; iface = &dev->config.if_desc[0]; usb_get_report(dev, iface->desc.bInterfaceNumber, 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); - if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) + if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) { usb_kbd_irq_worker(dev); -#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) +# elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) struct usb_kbd_pdata *data = dev->privptr; if (poll_int_queue(dev, data->intq)) { usb_kbd_irq_worker(dev); @@ -335,6 +337,13 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) data->intq = create_int_queue(dev, data->intpipe, 1, USB_KBD_BOOT_REPORT_SIZE, data->new, data->intinterval); +# endif + data->last_report = get_timer(0); + /* Repeat last usb hid report every REPEAT_RATE ms for keyrepeat */ + } else if (data->last_report != -1 && + get_timer(data->last_report) > REPEAT_RATE) { + usb_kbd_irq_worker(dev); + data->last_report = get_timer(0); } #endif } @@ -445,12 +454,15 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) data->intpktsize = min(usb_maxpacket(dev, data->intpipe), USB_KBD_BOOT_REPORT_SIZE); data->intinterval = ep->bInterval; + data->last_report = -1; /* We found a USB Keyboard, install it. */ usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); +#ifdef CONFIG_SYS_USB_EVENT_POLL debug("USB KBD: found set idle...\n"); - usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); + usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0); +#endif debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE