Patchwork [U-Boot] USB: Add functionality to poll the USB keyboard via control EP

login
register
mail settings
Submitter Marek Vasut
Date Sept. 25, 2011, 6:45 p.m.
Message ID <1316976340-31467-1-git-send-email-marek.vasut@gmail.com>
Download mbox | patch
Permalink /patch/116316/
State Accepted
Delegated to: Marek Vasut
Headers show

Comments

Marek Vasut - Sept. 25, 2011, 6:45 p.m.
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>
---
 common/usb_kbd.c |   63 ++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 49 insertions(+), 14 deletions(-)

Patch

diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 9957dcc..870d3f7 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -96,6 +96,25 @@  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));
+	usb_kbd_irq_worker(dev);
+#endif
+}
+
 /******************************************************************
  * Queue handling
  ******************************************************************/
@@ -120,9 +139,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 +156,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 +337,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 +369,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)
 {