NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/60321: opening ulptN (ulpnN) for certain printers fails with EBUSY



>Number:         60321
>Category:       kern
>Synopsis:       opening ulptN (ulpnN) for certain printers fails with EBUSY
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jun 10 19:35:00 +0000 2026
>Originator:     Ivan Shmakov
>Release:        NetBSD 10.1
>Organization:
Dbus-free station.
>Environment:
Architecture: x86_64
Machine: amd64
>Description:

	Certain printers do not seem to be usable with ulpt(4) as of
	NetBSD 10.1.  In an irc://irc.libera.chat/%23netbsd discussion
	(2026-06-09 19:50 .. 21:27 UTC) it has been suggested that the
	problem has long been solved in other USB printer interface
	implementations, in particular OpenBSD ulpt.c (see below.)

	For an example, attaching HP LaserJet 1020 gives:

$ /sbin/dmesg | tail -n3 
[ 136251,756150] ulpt0 at uhub0 port 2 configuration 1 interface 0
[ 136251,756150] ulpt0: Hewlett-Packard (0x03f0) HP LaserJet 1020 (0x2b17),
 rev 2.00/1.00, addr 2, iclass 7/1
[ 136251,756150] ulpt0: using bi-directional mode
$ /sbin/drvctl -tl -- ehci0 
usb1
  uhub0
    ulpt0
$ 

	Actually attempting to interact with the device, however,
	inevitably fails after what appears to be a driver timeout of a few
	minutes.  Among the commands tried were (for ulpn0, ulpt0 both):

$ time -- cp -- sihp1020.image /dev/ulpn0 
cp: /dev/ulpn0: Device busy
real 340,87
user 0,01
sys 0,00
$ time -- dd if=sihp1020.image of=/dev/ulpn0 
dd: /dev/ulpn0: Device busy
real 681,66
user 0,00
sys 0,01
$ time -- sh -exuc ": > /dev/ulpn0 " 
sh: cannot create /dev/ulpn0: error 16
real 340,93
user 0,01
sys 0,00
$ 

	(The printer requires an executable image to be sent to it
	before it can actually be used; sihp1020.image is a copy of
	such an image produced with arm2hpdl(1) from foo2zjs.)

	The corresponding $ ps -o pid,stat,wchan,etime,args -x output
	(individual lines observed at different times - no two commands
	were running at the same time):

  499 D    usbxfer       4:36 cp -- sihp1020.image 
 5943 D    usbxfer       9:52 dd if=sihp1020.image of=/dev/ulpn0 
 4663 D    usbxfer       0:03 sh -exuc : > /dev/ulpn0 

	It was suggested that crash(8) is used to examine KVM state
	for one of the processes above, which confirmed that it is
	indeed at open(2) that the driver "hangs":

# crash 
crash> bt/t 0t5943 
trace: pid 5943 lid 5943 at 0xffff958075800a00
sleepq_block() at sleepq_block+0x13a
cv_wait() at cv_wait+0xb7
usbd_transfer() at usbd_transfer+0x2fa
usbd_do_request_len() at usbd_do_request_len+0xaa
usbd_do_request() at usbd_do_request+0x21
ulpt_status.isra.0() at ulpt_status.isra.0+0x33
ulptopen() at ulptopen+0xf5
cdev_open() at cdev_open+0x12b
spec_open() at spec_open+0x1e0
VOP_OPEN() at VOP_OPEN+0x3e
vn_open() at vn_open+0x2ec
do_open() at do_open+0xc3
do_sys_openat() at do_sys_openat+0x74
sys_open() at sys_open+0x24
syscall() at syscall+0x1fc
--- syscall (number 5) ---
syscall+0x1fc:
crash> 

	Following that, this OpenBSD Git commit was found:

commit a6eefab672c88d16a09bd086c54a1cd8998d802e
Author: deraadt <deraadt%openbsd.org@localhost>
Date:   Thu Oct 9 01:07:02 2008 +0000
    stop waiting for the printer to become ready, see PR 5427 for more
    information.  Also explains PR 4124 and 5318

[PR 5427] http://marc.info/?l=openbsd-bugs&m=117512145315766&w=2 [LJ 1022]
[PR 5318] http://marc.info/?l=openbsd-bugs&m=116503185421666&w=2 [FS-1030D]
[PR 4124] http://marc.info/?l=openbsd-bugs&m=110939774409572&w=2 [HL1440]

>How-To-Repeat:

	Attach an affected USB printer, such as HP LaserJet 1020,
	then try to open the corresponding ulptN or ulpnN device:
	the open(2) call will wait for a while in usbxfer, then fail
	with EBUSY.

>Fix:

	The patch suggested in OpenBSD [PR 5427] can be applied to
	NetBSD ulpt.c (as of 11 RC4) with little modification.
	I haven't tested it, though.

--- usr/src/sys/dev/usb/ulpt.c.~1~	2025-04-14 16:43:00 +0000
+++ usr/src/sys/dev/usb/ulpt.c	2026-06-10 18:58:22 +0000
@@ -436,7 +436,7 @@ ulptopen(dev_t dev, int flag, int mode,
 	u_char flags = ULPTFLAGS(dev);
 	struct ulpt_softc *sc;
 	usbd_status err;
-	int spin, error;
+	int error;
 
 	sc = device_lookup_private(&ulpt_cd, ULPTUNIT(dev));
 	if (sc == NULL)
@@ -455,24 +455,8 @@ ulptopen(dev_t dev, int flag, int mode,
 	error = 0;
 	sc->sc_refcnt++;
 
-	if ((flags & ULPT_NOPRIME) == 0)
+	if ((flags & ULPT_NOPRIME) == 0) {
 		ulpt_reset(sc);
-
-	for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) {
-		DPRINTFN(2, ("ulpt_open: waiting a while\n"));
-		if (spin >= TIMEOUT) {
-			error = EBUSY;
-			sc->sc_state = 0;
-			goto done;
-		}
-
-		/* wait 1/4 second, give up if we get a signal */
-		error = kpause("ulptop", true, STEP, NULL);
-		if (error != EWOULDBLOCK) {
-			sc->sc_state = 0;
-			goto done;
-		}
-
 		if (sc->sc_dying) {
 			error = ENXIO;
 			sc->sc_state = 0;




Home | Main Index | Thread Index | Old Index