Subject: kern/33452: ugen: timeout does not work in function ugen_do_read (interrupt mode)
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <NevilTh@nat.com.au>
List: netbsd-bugs
Date: 05/10/2006 10:19:47
>Number:         33452
>Category:       kern
>Synopsis:       ugen:  timeout does not work in function ugen_do_read  (interrupt mode)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed May 10 10:19:47 +0000 2006
>Originator:     Nevil Thatcher
>Release:        netBSD 3.0 amd64
>Organization:
>Environment:
NetBSD lamborghini.nat.com.au 3.0.0_STABLE NetBSD 3.0.0_STABLE (lamborghini) #9: Sat Mar 11 11:10:07 EST 2006  nevil@lamborghini.nat.com.au:/usr/src/sys/arch/amd64/compile/lamborghini amd64
>Description:
This has come about whilst trying to get nut (ups monitoring) software operational under netBSD. Nut uses libusb as the layer to access usb devices(/dev/ugen), the device I am using being a MGE Nova 1100 UPS.

 

Software versions are:
  netBSD 3.0_STABLE (amd64)
  libusb 0.1.12
  nut 2.0.3

Libusb offers a function usb_interrupt_read, the function looks like
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)

A call to this should return with *char buffer filled with data from usb device OR timeout after int timeout seconds.

Note: timeout is set within usb_interrup_read with the following call 
ret = ioctl(fd, USB_SET_TIMEOUT, &timeout);

The problem seems to be that the dev/ugen code ugen_do_read does not respect this timeout and will not return until such time as data is returned from the usb device.

End result is that when libusb usb_interrupt_read is called it won’t return until data is received from the usb device and the buffer filled, so effectively hangs.


>How-To-Repeat:
Install 

libusb 0.1.12
nut 2.0.3 (after installation move to work directory and do 
make usb 
make installusb 
to get usb support)

Remove uhid from kernel config , recompile and install

Connect UPS 

Run /usr/local/libexec/nut/newhidups -u root -DDDDD /dev/ugen0 to run in debug mode.

Following output is observed..

--cut

process_status_info: !shutdownimm
entering string_to_path()
Looking up UPS
Looking up PowerSummary
Looking up PresentStatus
Looking up BelowRemainingCapacityLimit
Report : (8 bytes) => 02 23 00 01 00 80 FF FF
hu_find_infoval: searching for value = 0

hu_find_infoval: found !lowbatt (value: 0)

process_status_info: !lowbatt
new connection on fd 7
upsdrv_updateinfo...
Waiting for notifications...

And here it sits indefinitly.

Debugging has identified that at this point it is sitting in ugen_do_read waiting for data from device.
>Fix:
ugen_do_read should respect timeout set by 
ioctl(fd, USB_SET_TIMEOUT, &timeout)