summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut@gmail.com>2011-09-25 21:00:37 +0200
committerGerrit <chrome-bot@google.com>2011-12-06 18:05:57 -0800
commit131aee9ae75672816571d579f6a46c404b54f291 (patch)
tree6a7eacd2b3352c335d977904c5c0b09995b766bd /common
parent194928175871a0ef6dda9e36fe704b9539487e6e (diff)
UPSTREAM: USB: Add functionality to poll the USB keyboard via control EP
This allows the keyboard to avoid requests via Interrupt Endpoint altogether and run all requests via Control Endpoint. This uses the Get_Report request. Signed-off-by: Marek Vasut <marek.vasut@gmail.com> Cc: Remy Bohmer <linux@bohmer.net> (cherry picked from u-boot-usb.git commit 24e626cafd0793843c3e38439237c4031cef7ebf) BUG=chrome-os-partner:5752 TEST=on Lumpy, use USB keyboard to enter commands on U-Boot command line. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Change-Id: I55a47a6193ff3c7ce55510ebea922e5223cfc29c Reviewed-on: https://gerrit.chromium.org/gerrit/12511 Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Stefan Reinauer <reinauer@chromium.org> Reviewed-by: Simon Glass <sjg@chromium.org> Commit-Ready: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/usb_kbd.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 9957dcc323..503d175a75 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -96,6 +96,26 @@ static unsigned char usb_kbd_numkey_shifted[] = {
'+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'
};
+static int usb_kbd_irq_worker(struct usb_device *dev);
+
+/******************************************************************
+ * Interrupt polling
+ ******************************************************************/
+static inline void usb_kbd_poll_for_event(struct usb_device *dev)
+{
+#if defined(CONFIG_SYS_USB_EVENT_POLL)
+ usb_event_poll();
+ usb_kbd_irq_worker(dev);
+#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
+ struct usb_interface *iface;
+ iface = &dev->config.if_desc[0];
+ usb_get_report(dev, iface->desc.bInterfaceNumber,
+ 1, 1, new, sizeof(new));
+ if (memcmp(old, new, sizeof(new)))
+ usb_kbd_irq_worker(dev);
+#endif
+}
+
/******************************************************************
* Queue handling
******************************************************************/
@@ -120,9 +140,14 @@ static void usb_kbd_put_queue(char data)
/* test if a character is in the queue */
static int usb_kbd_testc(void)
{
-#ifdef CONFIG_SYS_USB_EVENT_POLL
- usb_event_poll();
-#endif
+ struct stdio_dev *dev;
+ struct usb_device *usb_kbd_dev;
+
+ dev = stdio_get_by_name("usbkbd");
+ usb_kbd_dev = (struct usb_device *)dev->priv;
+
+ usb_kbd_poll_for_event(usb_kbd_dev);
+
if(usb_in_pointer==usb_out_pointer)
return(0); /* no data */
else
@@ -132,11 +157,16 @@ static int usb_kbd_testc(void)
static int usb_kbd_getc(void)
{
char c;
- while(usb_in_pointer==usb_out_pointer) {
-#ifdef CONFIG_SYS_USB_EVENT_POLL
- usb_event_poll();
-#endif
- }
+
+ struct stdio_dev *dev;
+ struct usb_device *usb_kbd_dev;
+
+ dev = stdio_get_by_name("usbkbd");
+ usb_kbd_dev = (struct usb_device *)dev->priv;
+
+ while(usb_in_pointer==usb_out_pointer)
+ usb_kbd_poll_for_event(usb_kbd_dev);
+
if((usb_out_pointer+1)==USB_KBD_BUFFER_LEN)
usb_out_pointer=0;
else
@@ -308,15 +338,10 @@ static int usb_kbd_translate(unsigned char scancode,unsigned char modifier,int p
}
/* Interrupt service routine */
-static int usb_kbd_irq(struct usb_device *dev)
+static int usb_kbd_irq_worker(struct usb_device *dev)
{
int i,res;
- if((dev->irq_status!=0)||(dev->irq_act_len!=8))
- {
- USB_KBD_PRINTF("usb_keyboard Error %lX, len %d\n",dev->irq_status,dev->irq_act_len);
- return 1;
- }
res=0;
switch (new[0]) {
@@ -345,6 +370,17 @@ static int usb_kbd_irq(struct usb_device *dev)
return 1; /* install IRQ Handler again */
}
+static int usb_kbd_irq(struct usb_device *dev)
+{
+ if ((dev->irq_status != 0) || (dev->irq_act_len != 8))
+ {
+ USB_KBD_PRINTF("usb_keyboard Error %lX, len %d\n",dev->irq_status,dev->irq_act_len);
+ return 1;
+ }
+
+ return usb_kbd_irq_worker(dev);
+}
+
/* probes the USB device dev for keyboard type */
static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
{