Subject: kern/29558: USB keyboards don't provide autorepeat on netbsd/i386
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Matthias Pfaller <leo@dachau.marco.de>
List: netbsd-bugs
Date: 02/28/2005 16:40:00
>Number:         29558
>Category:       kern
>Synopsis:       USB keyboards don't provide autorepeat on netbsd/i386
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 28 16:40:00 +0000 2005
>Originator:     Matthias Pfaller
>Release:        NetBSD 2.99.14
>Organization:
Matthias Pfaller                            Software Entwicklung
marco Systemanalyse und Entwicklung GmbH    Tel   +49 8131 5161-41
Hans-B=F6ckler-Str. 2, D 85221 Dachau         Fax   +49 8131 5161-66
http://www.marco.de/                        Email leo@dachau.marco.de
>Environment:
System: NetBSD joghurt 2.99.14 NetBSD 2.99.14 (SIN) #24: Mon Jan 17 10:21:1=
7 CET 2005 leo@joghurt:/usr/src/sys/arch/i386/compile/SIN i386
Architecture: i386
Machine: i386
>Description:
	When using usb keyboards with XF86 (secondary keyboard, RAW mode is
	not enabled), autorepeat is not working.
	How does this work with architectures that use USB keyboards only?
	Should this be fixed in the kernel (as I did it) or should this be
	fixed in the xserver?
>How-To-Repeat:
	Connect an usb keyboard and change XF86Config to use this keyboard
	instead of the console keyboard.
>Fix:
RCS file: /cvsroot/src/sys/dev/usb/ukbd.c,v
retrieving revision 1.85
diff -u -u -r1.85 ukbd.c
--- ukbd.c	11 Mar 2003 16:44:00 -0000	1.85
+++ ukbd.c	28 Feb 2005 16:34:04 -0000
@@ -172,6 +172,8 @@
 	struct hid_location sc_capsloc;
 	struct hid_location sc_scroloc;
 	int sc_leds;
+	usb_callout_t sc_repeat_ch;
+	int sc_rep_char;
 #if defined(__NetBSD__)
 	usb_callout_t sc_rawrepeat_ch;
=20
@@ -250,6 +252,7 @@
 #ifdef WSDISPLAY_COMPAT_RAWKBD
 Static void	ukbd_rawrepeat(void *v);
 #endif
+Static void	ukbd_repeat(void *v);
=20
 const struct wskbd_accessops ukbd_accessops =3D {
 	ukbd_enable,
@@ -631,14 +634,20 @@
 		return;
 	}
 #endif
-
 	s =3D spltty();
+	key =3D 0; /* shutup gcc */
 	for (i =3D 0; i < nkeys; i++) {
 		key =3D ibuf[i];
 		wskbd_input(sc->sc_wskbddev,
 		    key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
 		    key&CODEMASK);
 	}
+	usb_uncallout(sc->sc_repeat_ch, ukbd_repeat, sc);
+	if ((key & RELEASE) =3D=3D 0) {
+		sc->sc_rep_char =3D key;
+		usb_callout(sc->sc_repeat_ch,
+			    hz * REP_DELAY1 / 1000, ukbd_repeat, sc);
+	}
 	splx(s);
 }
=20
@@ -683,6 +692,22 @@
 }
 #endif
=20
+void
+ukbd_repeat(void *v)
+{
+	struct ukbd_softc *sc =3D v;
+	int s;
+
+	s =3D spltty();
+	wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_UP,
+		sc->sc_rep_char & CODEMASK);
+	wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN,
+		sc->sc_rep_char & CODEMASK);
+	splx(s);
+	usb_callout(sc->sc_repeat_ch, hz * REP_DELAYN / 1000,
+		ukbd_repeat, sc);
+}
+
 int
 ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
 {