Subject: kern/28613: usb UPS's aren't uhids
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <wolfgang@wsrcc.com>
List: netbsd-bugs
Date: 12/12/2004 00:03:00
>Number: 28613
>Category: kern
>Synopsis: usb UPS's aren't uhids
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Dec 12 00:03:00 +0000 2004
>Originator: Wolfgang S. Rupprecht
>Release: NetBSD 2.99.11
>Organization:
W S Rupprecht Computer Consulting, Fremont CA
>Environment:
System: NetBSD capsicum.wsrcc.com 2.99.11 NetBSD 2.99.11 (WSRCC_ATHLON) #23: Sat Dec 11 14:14:27 PST 2004 wolfgang@capsicum.wsrcc.com:/var/obj/netbsd/sys/arch/i386/compile/WSRCC_ATHLON i386
Architecture: i386
Machine: i386
>Description:
usb UPS's show up as usb uhid devices. Apcupsd needs to see
it as a ugen. The simplest choice seems to be either this
rude quirk-like hack.
>How-To-Repeat:
compile and try to run:
http://www.wsrcc.com/wolfgang/private/apcupsd-3.10.16-test2-wsr.tar.gz
>Fix:
The uhidev.c fix is absolutely needed.
The usbdi.c fixes are hail-mary's that looked wrong to me, but had no
effect on fixing a hang I saw when running apcupsd on VIA uhci's.
Index: uhidev.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.22
diff -u -r1.22 uhidev.c
--- uhidev.c 13 Sep 2004 12:55:49 -0000 1.22
+++ uhidev.c 11 Dec 2004 23:39:55 -0000
@@ -97,6 +97,11 @@
id = usbd_get_interface_descriptor(uaa->iface);
if (id == NULL || id->bInterfaceClass != UICLASS_HID)
return (UMATCH_NONE);
+
+ /* don't match APC products (all of them are UPS's) -wsr 2004/11/16 */
+ if (uaa->vendor == USB_VENDOR_APC)
+ return (UMATCH_NONE);
+
if (uaa->matchlvl)
return (uaa->matchlvl);
return (UMATCH_IFACECLASS_GENERIC);
Index: usbdi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usbdi.c,v
retrieving revision 1.106
diff -u -r1.106 usbdi.c
--- usbdi.c 24 Oct 2004 12:52:40 -0000 1.106
+++ usbdi.c 11 Dec 2004 23:39:55 -0000
@@ -285,7 +285,7 @@
usb_dma_t *dmap = &xfer->dmabuf;
usbd_status err;
u_int size;
- int s;
+ int s, sync;
DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
xfer, xfer->flags, pipe, pipe->running));
@@ -318,6 +318,10 @@
!usbd_xfer_isread(xfer))
memcpy(KERNADDR(dmap, 0), xfer->buffer, size);
+ /* If the transfer is not synchronous, xfer may have been freed in a
+ * callback before transfer returns, so check for synchronous now. */
+ sync = xfer->flags & USBD_SYNCHRONOUS ? 1 : 0;
+
err = pipe->methods->transfer(xfer);
if (err != USBD_IN_PROGRESS && err) {
@@ -330,7 +334,7 @@
}
}
- if (!(xfer->flags & USBD_SYNCHRONOUS))
+ if (!sync)
return (err);
/* Sync transfer, wait for completion. */
@@ -340,7 +344,9 @@
if (!xfer->done) {
if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done");
- tsleep(xfer, PRIBIO, "usbsyn", 0);
+ /* hangs in ugen/apcupsd -wsr 2004/11/16 */
+ while (!xfer->done)
+ tsleep(xfer, PRIBIO, "usbsyn", 0);
}
splx(s);
return (xfer->status);
>Unformatted: