Subject: kern/30927: no way to flush input queue on uhid devices
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: seebs <seebs@vash.cel.plethora.net>
List: netbsd-bugs
Date: 08/06/2005 19:08:00
>Number:         30927
>Category:       kern
>Synopsis:       no way to flush input queue on uhid devices
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Aug 06 19:08:00 +0000 2005
>Originator:     seebs
>Release:        NetBSD 3.99.7
>Organization:
	
>Environment:
System: NetBSD vash.cel.plethora.net 3.99.7 NetBSD 3.99.7 (VASH) #2: Sat Aug 6 13:37:44 CDT 2005 seebs@vash.cel.plethora.net:/usr/src/sys/arch/i386/compile/VASH i386
Architecture: i386
Machine: i386
>Description:
	USB devices can be actively polled, using USB_GET_REPORT, or may
	deliver data of their own accord, handled by uhid_intr.

	Data received with interrupts gets attached to a queue, sc->sc_q.
	Unless the UHID_IMMED flag is set, this queue is then used to satisfy
	read requests.

	There is no way for the user application to request a flush of the
	queue, and it is unclear that anything would ever flush it once
	immediate mode has been set.

	I am the proud and mostly-happy owner of a USB widget that does not
	support USB_GET_REPORT requests, and delivers data fairly actively,
	based on the presumption that the Windows USB buffer is small enough
	that you'll get the fresh data "soon enough".

	In this case, the most reasonable thing to do is flush the queue
	right before trying a read.  Rather than invent a new ioctl, I
	propose attaching this to the SET_IMMED ioctl.  The rationale is that,
	since that queue will never be seen when SET_IMMED works, it does no
	harm to flush it, and furthermore, this makes USB_SET_IMMED useful
	even on devices incapable of really supporting immediate mode,
	providing semantically similar behavior.

>How-To-Repeat:
	Get a HWLV "matrix" bill validator and spend a day or so pondering the
	Windows documentation.

>Fix:
	This patch works wonders.

Index: uhid.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhid.c,v
retrieving revision 1.64
diff -c -r1.64 uhid.c
*** uhid.c	21 Jun 2005 14:01:12 -0000	1.64
--- uhid.c	6 Aug 2005 18:59:56 -0000
***************
*** 467,472 ****
--- 467,473 ----
  
  	case USB_SET_IMMED:
  		if (*(int *)addr) {
+ 			ndflush(&sc->sc_q, 1024);
  			extra = sc->sc_hdev.sc_report_id != 0;
  			err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
  						buffer, sc->sc_isize + extra);