diff options
| author | Marek Vasut <marek.vasut@gmail.com> | 2011-10-10 16:34:26 +0100 | 
|---|---|---|
| committer | Remy Bohmer <linux@bohmer.net> | 2011-12-11 14:40:38 +0100 | 
| commit | 9a8c72a6c42471d503d573988510e8ec71edddaa (patch) | |
| tree | a09a9c3fdc14af7d747ff229639e25213025c30b /common/usb_kbd.c | |
| parent | 48c8073ec957b4b472835f4c7b6447f7e518e2f5 (diff) | |
| download | olio-uboot-2014.01-9a8c72a6c42471d503d573988510e8ec71edddaa.tar.xz olio-uboot-2014.01-9a8c72a6c42471d503d573988510e8ec71edddaa.zip | |
USB: Rework usb_kbd.c
* Support dynamic allocation of devices
* Passing data via usb device privptr
* Reorder functions to avoid forward declarations
* Introduce generic polling mechanism to fix musb and ehci-hcd breakage
  due to using "extern new;" to access keyboard driver data!
Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Acked-by: Mike Frysinger <vapier@gentoo.org>
Cc: Remy Bohmer <linux@bohmer.net>
Cc: Wolfgang Denk <wd@denx.de>
Diffstat (limited to 'common/usb_kbd.c')
| -rw-r--r-- | common/usb_kbd.c | 583 | 
1 files changed, 323 insertions, 260 deletions
| diff --git a/common/usb_kbd.c b/common/usb_kbd.c index ef440e472..2d788314c 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -25,12 +25,18 @@   *   */  #include <common.h> +#include <malloc.h>  #include <stdio_dev.h>  #include <asm/byteorder.h>  #include <usb.h> -#undef USB_KBD_DEBUG +#ifdef	USB_KBD_DEBUG +#define USB_KBD_PRINTF(fmt, args...)	printf(fmt, ##args) +#else +#define USB_KBD_PRINTF(fmt, args...) +#endif +  /*   * If overwrite_console returns 1, the stdin, stderr and stdout   * are switched to the serial port, else the settings in the @@ -45,352 +51,257 @@ int overwrite_console(void)  }  #endif -#ifdef USB_KBD_DEBUG -#define USB_KBD_PRINTF(fmt, args...)	printf(fmt, ##args) -#else -#define USB_KBD_PRINTF(fmt, args...) -#endif - - -#define REPEAT_RATE	(40/4)	/* 40msec -> 25cps */ -#define REPEAT_DELAY	10	/* 10 x REPEAT_RATE = 400msec */ +/* Keyboard sampling rate */ +#define REPEAT_RATE	(40 / 4)	/* 40msec -> 25cps */ +#define REPEAT_DELAY	10		/* 10 x REPEAT_RATE = 400msec */  #define NUM_LOCK	0x53  #define CAPS_LOCK	0x39  #define SCROLL_LOCK	0x47 -  /* Modifier bits */ -#define LEFT_CNTR		0 -#define LEFT_SHIFT		1 -#define LEFT_ALT		2 -#define LEFT_GUI		3 -#define RIGHT_CNTR		4 -#define RIGHT_SHIFT		5 -#define RIGHT_ALT		6 -#define RIGHT_GUI		7 - -#define USB_KBD_BUFFER_LEN	0x20	/* size of the keyboardbuffer */ +#define LEFT_CNTR	(1 << 0) +#define LEFT_SHIFT	(1 << 1) +#define LEFT_ALT	(1 << 2) +#define LEFT_GUI	(1 << 3) +#define RIGHT_CNTR	(1 << 4) +#define RIGHT_SHIFT	(1 << 5) +#define RIGHT_ALT	(1 << 6) +#define RIGHT_GUI	(1 << 7) -static char usb_kbd_buffer[USB_KBD_BUFFER_LEN]; -static int usb_in_pointer; -static int usb_out_pointer; +/* Size of the keyboard buffer */ +#define USB_KBD_BUFFER_LEN	0x20 -unsigned char new[8]; -unsigned char old[8]; -int repeat_delay; +/* Device name */  #define DEVNAME			"usbkbd" -static unsigned char num_lock; -static unsigned char caps_lock; -static unsigned char scroll_lock; -static unsigned char ctrl; -static unsigned char leds __attribute__((aligned(0x4))); - -static unsigned char usb_kbd_numkey[] = { +/* Keyboard maps */ +static const unsigned char usb_kbd_numkey[] = {  	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',  	'\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']',  	'\\', '#', ';', '\'', '`', ',', '.', '/'  }; -static unsigned char usb_kbd_numkey_shifted[] = { +static const unsigned char usb_kbd_numkey_shifted[] = {  	'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',  	'\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}',  	'|', '~', ':', '"', '~', '<', '>', '?'  }; -static int usb_kbd_irq_worker(struct usb_device *dev); +/* + * NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this + *       order. See usb_kbd_setled() function! + */ +#define USB_KBD_NUMLOCK		(1 << 0) +#define USB_KBD_CAPSLOCK	(1 << 1) +#define USB_KBD_SCROLLLOCK	(1 << 2) +#define USB_KBD_CTRL		(1 << 3) -/****************************************************************** - * 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 -} +#define USB_KBD_LEDMASK		\ +	(USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) -/****************************************************************** - * Queue handling - ******************************************************************/ -/* puts character in the queue and sets up the in and out pointer */ -static void usb_kbd_put_queue(char data) -{ -	if ((usb_in_pointer+1) == USB_KBD_BUFFER_LEN) { -		if (usb_out_pointer == 0) -			return; /* buffer full */ -		else -			usb_in_pointer = 0; -	} else { -		if ((usb_in_pointer+1) == usb_out_pointer) -			return; /* buffer full */ -		usb_in_pointer++; -	} -	usb_kbd_buffer[usb_in_pointer] = data; -	return; -} +struct usb_kbd_pdata { +	uint32_t	repeat_delay; -/* test if a character is in the queue */ -static int usb_kbd_testc(void) -{ -	struct stdio_dev *dev; -	struct usb_device *usb_kbd_dev; +	uint32_t	usb_in_pointer; +	uint32_t	usb_out_pointer; +	uint8_t		usb_kbd_buffer[USB_KBD_BUFFER_LEN]; -	dev = stdio_get_by_name("usbkbd"); -	usb_kbd_dev = (struct usb_device *)dev->priv; +	uint8_t		new[8]; +	uint8_t		old[8]; -	usb_kbd_poll_for_event(usb_kbd_dev); +	uint8_t		flags; +}; -	if (usb_in_pointer == usb_out_pointer) -		return 0; /* no data */ -	else -		return 1; -} -/* gets the character from the queue */ -static int usb_kbd_getc(void) +/* Generic keyboard event polling. */ +void usb_kbd_generic_poll(void)  { -	char c; -  	struct stdio_dev *dev;  	struct usb_device *usb_kbd_dev; +	struct usb_kbd_pdata *data; +	struct usb_interface *iface; +	struct usb_endpoint_descriptor *ep; +	int pipe; +	int maxp; -	dev = stdio_get_by_name("usbkbd"); +	/* Get the pointer to USB Keyboard device pointer */ +	dev = stdio_get_by_name(DEVNAME);  	usb_kbd_dev = (struct usb_device *)dev->priv; +	data = usb_kbd_dev->privptr; +	iface = &usb_kbd_dev->config.if_desc[0]; +	ep = &iface->ep_desc[0]; +	pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress); -	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 -		usb_out_pointer++; -	c = usb_kbd_buffer[usb_out_pointer]; -	return (int)c; - +	/* Submit a interrupt transfer request */ +	maxp = usb_maxpacket(usb_kbd_dev, pipe); +	usb_submit_int_msg(usb_kbd_dev, pipe, data->new, +			maxp > 8 ? 8 : maxp, ep->bInterval);  } -/* forward decleration */ -static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum); - -/* search for keyboard and register it if found */ -int drv_usb_kbd_init(void) +/* 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)  { -	int error, i; -	struct stdio_dev usb_kbd_dev, *old_dev; -	struct usb_device *dev; -	char *stdinname = getenv("stdin"); +	if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { +		/* Check for buffer full. */ +		if (data->usb_out_pointer == 0) +			return; -	usb_in_pointer = 0; -	usb_out_pointer = 0; -	/* scan all USB Devices */ -	for (i = 0 ; i < USB_MAX_DEVICE ; i++) { -		dev = usb_get_dev_index(i); /* get device */ -		if (dev == NULL) -			return -1; -		if (dev->devnum != -1) { -			/* Ok, we found a keyboard */ -			if (usb_kbd_probe(dev, 0) == 1) { -				/* check, if it is already registered */ -				USB_KBD_PRINTF("USB KBD found set up " -						"device.\n"); -				old_dev = stdio_get_by_name(DEVNAME); -				if (old_dev) { -					/* already registered, just return ok */ -					USB_KBD_PRINTF("USB KBD is already " -							"registered.\n"); -					return 1; -				} -				/* register the keyboard */ -				USB_KBD_PRINTF("USB KBD register.\n"); -				memset(&usb_kbd_dev, 0, -						sizeof(struct stdio_dev)); -				strcpy(usb_kbd_dev.name, DEVNAME); -				usb_kbd_dev.flags =  DEV_FLAGS_INPUT | -							DEV_FLAGS_SYSTEM; -				usb_kbd_dev.putc = NULL; -				usb_kbd_dev.puts = NULL; -				usb_kbd_dev.getc = usb_kbd_getc; -				usb_kbd_dev.tstc = usb_kbd_testc; -				usb_kbd_dev.priv = (void *)dev; -				error = stdio_register(&usb_kbd_dev); -				if (error == 0) { -					/* -					 * check if this is the standard -					 * input device -					 */ -					if (strcmp(stdinname, DEVNAME) == 0) { -						/* reassign the console */ -						if (overwrite_console()) -							return 1; -						error = console_assign(stdin, -								DEVNAME); -						if (error == 0) -							return 1; -						else -							return error; -					} -					return 1; -				} -				return error; -			} -		} -	} -	/* no USB Keyboard found */ -	return -1; -} +		data->usb_in_pointer = 0; +	} else { +		/* Check for buffer full. */ +		if (data->usb_in_pointer == data->usb_out_pointer - 1) +			return; +		data->usb_in_pointer++; +	} -/* deregistering the keyboard */ -int usb_kbd_deregister(void) -{ -#ifdef CONFIG_SYS_STDIO_DEREGISTER -	return stdio_deregister(DEVNAME); -#else -	return 1; -#endif +	data->usb_kbd_buffer[data->usb_in_pointer] = c;  } -/************************************************************************** - * Low Level drivers +/* + * Set the LEDs. Since this is used in the irq routine, the control job is + * issued with a timeout of 0. This means, that the job is queued without + * waiting for job completion.   */ - -/* set the LEDs. Since this is used in the irq routine, the control job -   is issued with a timeout of 0. This means, that the job is queued without -   waiting for job completion */ -  static void usb_kbd_setled(struct usb_device *dev)  { -	struct usb_interface *iface; -	iface = &dev->config.if_desc[0]; -	leds = 0; -	if (scroll_lock != 0) -		leds |= 1; -	leds <<= 1; -	if (caps_lock != 0) -		leds |= 1; -	leds <<= 1; -	if (num_lock != 0) -		leds |= 1; +	struct usb_interface *iface = &dev->config.if_desc[0]; +	struct usb_kbd_pdata *data = dev->privptr; +	uint32_t leds = data->flags & USB_KBD_LEDMASK; +  	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  		USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,  		0x200, iface->desc.bInterfaceNumber, (void *)&leds, 1, 0); -  } - -#define CAPITAL_MASK 0x20 +#define CAPITAL_MASK	0x20  /* Translate the scancode in ASCII */ -static int usb_kbd_translate(unsigned char scancode, unsigned char modifier, -				int pressed) +static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, +				unsigned char modifier, int pressed)  { -	unsigned char keycode; +	uint8_t keycode = 0; +	/* Key released */  	if (pressed == 0) { -		/* key released */ -		repeat_delay = 0; +		data->repeat_delay = 0;  		return 0;  	} +  	if (pressed == 2) { -		repeat_delay++; -		if (repeat_delay < REPEAT_DELAY) +		data->repeat_delay++; +		if (data->repeat_delay < REPEAT_DELAY)  			return 0; -		repeat_delay = REPEAT_DELAY; + +		data->repeat_delay = REPEAT_DELAY;  	} -	keycode = 0; -	if ((scancode > 3) && (scancode <= 0x1d)) { /* alpha numeric values */ -		keycode = scancode - 4 + 0x61; -		if (caps_lock) -			/* switch to capital Letters */ + +	/* Alphanumeric values */ +	if ((scancode > 3) && (scancode <= 0x1d)) { +		keycode = scancode - 4 + 'a'; + +		if (data->flags & USB_KBD_CAPSLOCK)  			keycode &= ~CAPITAL_MASK; -		if (((modifier&(1 << LEFT_SHIFT)) != 0) || -			((modifier&(1 << RIGHT_SHIFT)) != 0)) { + +		if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) { +			/* Handle CAPSLock + Shift pressed simultaneously */  			if (keycode & CAPITAL_MASK) -				/* switch to capital Letters */  				keycode &= ~CAPITAL_MASK;  			else -				/* switch to non capital Letters */  				keycode |= CAPITAL_MASK;  		}  	} -	if ((scancode > 0x1d) && (scancode < 0x3A)) { -		if (((modifier&(1 << LEFT_SHIFT)) != 0) || -			((modifier&(1 << RIGHT_SHIFT)) != 0))  /* shifted */ -			keycode = usb_kbd_numkey_shifted[scancode-0x1e]; -		else /* non shifted */ -			keycode = usb_kbd_numkey[scancode-0x1e]; + +	if ((scancode > 0x1d) && (scancode < 0x3a)) { +		/* Shift pressed */ +		if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) +			keycode = usb_kbd_numkey_shifted[scancode - 0x1e]; +		else +			keycode = usb_kbd_numkey[scancode - 0x1e];  	} -	if (ctrl) +	if (data->flags & USB_KBD_CTRL)  		keycode = scancode - 0x3;  	if (pressed == 1) {  		if (scancode == NUM_LOCK) { -			num_lock = ~num_lock; +			data->flags ^= USB_KBD_NUMLOCK;  			return 1;  		} +  		if (scancode == CAPS_LOCK) { -			caps_lock = ~caps_lock; +			data->flags ^= USB_KBD_CAPSLOCK;  			return 1;  		}  		if (scancode == SCROLL_LOCK) { -			scroll_lock = ~scroll_lock; +			data->flags ^= USB_KBD_SCROLLLOCK;  			return 1;  		}  	} -	if (keycode != 0) { + +	/* Report keycode if any */ +	if (keycode) {  		USB_KBD_PRINTF("%c", keycode); -		usb_kbd_put_queue(keycode); +		usb_kbd_put_queue(data, keycode);  	} +  	return 0;  } +static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up) +{ +	uint32_t res = 0; +	struct usb_kbd_pdata *data = dev->privptr; +	uint8_t *new; +	uint8_t *old; + +	if (up) { +		new = data->old; +		old = data->new; +	} else { +		new = data->new; +		old = data->old; +	} + +	if ((old[i] > 3) && (memscan(new + 2, old[i], 6) == new + 8)) +		res |= usb_kbd_translate(data, old[i], data->new[0], up); + +	return res; +} +  /* Interrupt service routine */  static int usb_kbd_irq_worker(struct usb_device *dev)  { -	int i, res; +	struct usb_kbd_pdata *data = dev->privptr; +	int i, res = 0; -	res = 0; - -	switch (new[0]) { -	case 0x0:	/* No combo key pressed */ -		ctrl = 0; -		break; -	case 0x01:	/* Left Ctrl pressed */ -	case 0x10:	/* Right Ctrl pressed */ -		ctrl = 1; -		break; -	} +	/* No combo key pressed */ +	if (data->new[0] == 0x00) +		data->flags &= ~USB_KBD_CTRL; +	/* Left or Right Ctrl pressed */ +	else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR)) +		data->flags |= USB_KBD_CTRL;  	for (i = 2; i < 8; i++) { -		if (old[i] > 3 && memscan(&new[2], old[i], 6) == &new[8]) -			res |= usb_kbd_translate(old[i], new[0], 0); - -		if (new[i] > 3 && memscan(&old[2], new[i], 6) == &old[8]) -			res |= usb_kbd_translate(new[i], new[0], 1); +		res |= usb_kbd_service_key(dev, i, 0); +		res |= usb_kbd_service_key(dev, i, 1);  	} -	if ((new[2] > 3) && (old[2] == new[2])) /* still pressed */ -		res |= usb_kbd_translate(new[2], new[0], 2); +	/* Key is still pressed */ +	if ((data->new[2] > 3) && (data->old[2] == data->new[2])) +		res |= usb_kbd_translate(data, data->new[2], data->new[0], 2); +  	if (res == 1)  		usb_kbd_setled(dev); -	memcpy(&old[0], &new[0], 8); +	memcpy(data->old, data->new, 8); -	return 1; /* install IRQ Handler again */ +	return 1;  } +/* Keyboard interrupt handler */  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", +		USB_KBD_PRINTF("USB KBD: Error %lX, len %d\n",  				dev->irq_status, dev->irq_act_len);  		return 1;  	} @@ -398,50 +309,202 @@ static int usb_kbd_irq(struct usb_device *dev)  	return usb_kbd_irq_worker(dev);  } -/* probes the USB device dev for keyboard type */ +/* 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; +	struct usb_kbd_pdata *data = dev->privptr; +	iface = &dev->config.if_desc[0]; +	usb_get_report(dev, iface->desc.bInterfaceNumber, +			1, 1, data->new, sizeof(data->new)); +	if (memcmp(data->old, data->new, sizeof(data->new))) +		usb_kbd_irq_worker(dev); +#endif +} + +/* test if a character is in the queue */ +static int usb_kbd_testc(void) +{ +	struct stdio_dev *dev; +	struct usb_device *usb_kbd_dev; +	struct usb_kbd_pdata *data; + +	dev = stdio_get_by_name(DEVNAME); +	usb_kbd_dev = (struct usb_device *)dev->priv; +	data = usb_kbd_dev->privptr; + +	usb_kbd_poll_for_event(usb_kbd_dev); + +	return !(data->usb_in_pointer == data->usb_out_pointer); +} + +/* gets the character from the queue */ +static int usb_kbd_getc(void) +{ +	struct stdio_dev *dev; +	struct usb_device *usb_kbd_dev; +	struct usb_kbd_pdata *data; + +	dev = stdio_get_by_name(DEVNAME); +	usb_kbd_dev = (struct usb_device *)dev->priv; +	data = usb_kbd_dev->privptr; + +	while (data->usb_in_pointer == data->usb_out_pointer) +		usb_kbd_poll_for_event(usb_kbd_dev); + +	if (data->usb_out_pointer == USB_KBD_BUFFER_LEN - 1) +		data->usb_out_pointer = 0; +	else +		data->usb_out_pointer++; + +	return data->usb_kbd_buffer[data->usb_out_pointer]; +} + +/* probes the USB device dev for keyboard type. */  static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)  {  	struct usb_interface *iface;  	struct usb_endpoint_descriptor *ep; +	struct usb_kbd_pdata *data;  	int pipe, maxp;  	if (dev->descriptor.bNumConfigurations != 1)  		return 0; +  	iface = &dev->config.if_desc[ifnum];  	if (iface->desc.bInterfaceClass != 3)  		return 0; +  	if (iface->desc.bInterfaceSubClass != 1)  		return 0; +  	if (iface->desc.bInterfaceProtocol != 1)  		return 0; +  	if (iface->desc.bNumEndpoints != 1)  		return 0;  	ep = &iface->ep_desc[0]; +	/* Check if endpoint 1 is interrupt endpoint */  	if (!(ep->bEndpointAddress & 0x80))  		return 0; +  	if ((ep->bmAttributes & 3) != 3)  		return 0; -	USB_KBD_PRINTF("USB KBD found set protocol...\n"); -	/* ok, we found a USB Keyboard, install it */ -	/* usb_kbd_get_hid_desc(dev); */ -	usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); -	USB_KBD_PRINTF("USB KBD found set idle...\n"); -	usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); -	memset(&new[0], 0, 8); -	memset(&old[0], 0, 8); -	repeat_delay = 0; + +	USB_KBD_PRINTF("USB KBD: found set protocol...\n"); + +	data = malloc(sizeof(struct usb_kbd_pdata)); +	if (!data) { +		printf("USB KBD: Error allocating private data\n"); +		return 0; +	} + +	/* Clear private data */ +	memset(data, 0, sizeof(struct usb_kbd_pdata)); + +	/* Insert private data into USB device structure */ +	dev->privptr = data; + +	/* Set IRQ handler */ +	dev->irq_handle = usb_kbd_irq; +  	pipe = usb_rcvintpipe(dev, ep->bEndpointAddress);  	maxp = usb_maxpacket(dev, pipe); -	dev->irq_handle = usb_kbd_irq; -	USB_KBD_PRINTF("USB KBD enable interrupt pipe...\n"); -	usb_submit_int_msg(dev, pipe, &new[0], maxp > 8 ? 8 : maxp, + +	/* We found a USB Keyboard, install it. */ +	usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); + +	USB_KBD_PRINTF("USB KBD: found set idle...\n"); +	usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); + +	USB_KBD_PRINTF("USB KBD: enable interrupt pipe...\n"); +	usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp,  				ep->bInterval); + +	/* Success. */  	return 1;  } +/* Search for keyboard and register it if found. */ +int drv_usb_kbd_init(void) +{ +	struct stdio_dev usb_kbd_dev, *old_dev; +	struct usb_device *dev; +	char *stdinname = getenv("stdin"); +	int error, i; + +	/* Scan all USB Devices */ +	for (i = 0; i < USB_MAX_DEVICE; i++) { +		/* Get USB device. */ +		dev = usb_get_dev_index(i); +		if (!dev) +			return -1; + +		if (dev->devnum == -1) +			continue; + +		/* Try probing the keyboard */ +		if (usb_kbd_probe(dev, 0) != 1) +			continue; + +		/* We found a keyboard, check if it is already registered. */ +		USB_KBD_PRINTF("USB KBD: found set up device.\n"); +		old_dev = stdio_get_by_name(DEVNAME); +		if (old_dev) { +			/* Already registered, just return ok. */ +			USB_KBD_PRINTF("USB KBD: is already registered.\n"); +			return 1; +		} + +		/* Register the keyboard */ +		USB_KBD_PRINTF("USB KBD: register.\n"); +		memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); +		strcpy(usb_kbd_dev.name, DEVNAME); +		usb_kbd_dev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; +		usb_kbd_dev.putc = NULL; +		usb_kbd_dev.puts = NULL; +		usb_kbd_dev.getc = usb_kbd_getc; +		usb_kbd_dev.tstc = usb_kbd_testc; +		usb_kbd_dev.priv = (void *)dev; +		error = stdio_register(&usb_kbd_dev); +		if (error) +			return error; + +		/* Check if this is the standard input device. */ +		if (strcmp(stdinname, DEVNAME)) +			return 1; + +		/* Reassign the console */ +		if (overwrite_console()) +			return 1; + +		error = console_assign(stdin, DEVNAME); +		if (error) +			return error; + +		return 1; +	} + +	/* No USB Keyboard found */ +	return -1; +} + +/* Deregister the keyboard. */ +int usb_kbd_deregister(void) +{ +#ifdef CONFIG_SYS_STDIO_DEREGISTER +	return stdio_deregister(DEVNAME); +#else +	return 1; +#endif +}  #if 0  struct usb_hid_descriptor { |