Linux USB
 help / color / mirror / Atom feed
* Missing uevents after successful USBDEVFS_RESET
@ 2026-09-15 21:48 Fabien Sanglard
  2026-09-16  2:37 ` Alan Stern
  0 siblings, 1 reply; 7+ messages in thread
From: Fabien Sanglard @ 2026-09-15 21:48 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh, stern

Hi,

I am investigating an issue where userspace processes using usbfs (such as
ADB) cannot reliably track device state across a USBDEVFS_RESET ioctl by
monitoring netlink uevents.

Repro steps: (Lenovo P620, kernel 7.1.6)
1. Plug an ADB device into your computer.
2. Open a console to monitor netlink events: udevadm monitor -p -u.
3. Send USBDEVFS_RESET a couple of times (i used adb_usbreset).
4. 50% of the time the event sequence is UNBIND/REMOVE/ADD/BIND. 50%
of the time, the event sequence is just UNBIND.

When USBDEVFS_RESET is issued via drivers/usb/core/devio.c, it calls
usb_reset_device() -> usb_reset_and_verify_device() in drivers/usb/core/hub.c.
Depending on the reset outcome, userspace sees inconsistent uevents:

Case 1: Full re-enumeration (descriptors changed or reset/verify failed)
The device is torn down and reprobed. Userspace receives:
  UNBIND -> REMOVE -> ADD -> BIND
Userspace processes monitoring uevents immediately detect that the device
is available again and re-open it.

Case 2: Reset succeeds without re-enumeration (descriptors unchanged)
The kernel unbinds usbfs/interface drivers before reset, generating a
KOBJ_UNBIND uevent. Because the usb_device structure is preserved and
usbfs does not re-probe, no subsequent KOBJ_BIND, KOBJ_ADD, or KOBJ_CHANGE
event is ever emitted.

As a result of Case 2, userspace receives an UNBIND ("disconnect") signal
and assumes the device went away, but never receives an event indicating
that the reset finished and the device is ready for reuse. This forces
daemons like adb to fall back to polling /dev/bus/usb instead of relying
on netlink/udev events.

Is the omission of a completion uevent after a successful reset without
re-enumeration intentional?

If not, would a patch emitting KOBJ_CHANGE (or re-binding/notifying userspace)
upon completion of usb_reset_device() be acceptable here?

Thanks,
Fab

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Missing uevents after successful USBDEVFS_RESET
  2026-09-15 21:48 Missing uevents after successful USBDEVFS_RESET Fabien Sanglard
@ 2026-09-16  2:37 ` Alan Stern
  2026-09-20  6:00   ` Fabien Sanglard
  0 siblings, 1 reply; 7+ messages in thread
From: Alan Stern @ 2026-09-16  2:37 UTC (permalink / raw)
  To: Fabien Sanglard; +Cc: linux-usb, gregkh

On Tue, Sep 15, 2026 at 02:48:08PM -0700, Fabien Sanglard wrote:
> Hi,
> 
> I am investigating an issue where userspace processes using usbfs (such as
> ADB) cannot reliably track device state across a USBDEVFS_RESET ioctl by
> monitoring netlink uevents.
> 
> Repro steps: (Lenovo P620, kernel 7.1.6)
> 1. Plug an ADB device into your computer.
> 2. Open a console to monitor netlink events: udevadm monitor -p -u.
> 3. Send USBDEVFS_RESET a couple of times (i used adb_usbreset).
> 4. 50% of the time the event sequence is UNBIND/REMOVE/ADD/BIND. 50%
> of the time, the event sequence is just UNBIND.
> 
> When USBDEVFS_RESET is issued via drivers/usb/core/devio.c, it calls
> usb_reset_device() -> usb_reset_and_verify_device() in drivers/usb/core/hub.c.
> Depending on the reset outcome, userspace sees inconsistent uevents:
> 
> Case 1: Full re-enumeration (descriptors changed or reset/verify failed)
> The device is torn down and reprobed. Userspace receives:
>   UNBIND -> REMOVE -> ADD -> BIND
> Userspace processes monitoring uevents immediately detect that the device
> is available again and re-open it.
> 
> Case 2: Reset succeeds without re-enumeration (descriptors unchanged)
> The kernel unbinds usbfs/interface drivers before reset, generating a
> KOBJ_UNBIND uevent. Because the usb_device structure is preserved and
> usbfs does not re-probe, no subsequent KOBJ_BIND, KOBJ_ADD, or KOBJ_CHANGE
> event is ever emitted.
> 
> As a result of Case 2, userspace receives an UNBIND ("disconnect") signal
> and assumes the device went away, but never receives an event indicating
> that the reset finished and the device is ready for reuse. This forces
> daemons like adb to fall back to polling /dev/bus/usb instead of relying
> on netlink/udev events.
> 
> Is the omission of a completion uevent after a successful reset without
> re-enumeration intentional?

It's more or less unintentional.

A normal driver would rebind automatically.  But usbfs isn't normal, in 
the sense that it won't bind to a device without a special user request 
(primarily the USBDEVFS_CLAIMINTERFACE ioctl but also some others).

> If not, would a patch emitting KOBJ_CHANGE (or re-binding/notifying userspace)
> upon completion of usb_reset_device() be acceptable here?

Yes.  But there are some things to bear in mind:

Adding pre_reset and post_reset handlers to the usbfs driver would 
prevent unbinding in case 2.  The problem is that there is no 
agreed-upon way to then let userspace clients know that the device has 
been reset, or to let them know beforehand that the device is going to 
be reset.  In other words, the two handlers wouldn't be able to do 
anything useful.

Emitting a KOBJ_CHANGE uevent instead would be more straightforward.  
But you would have to think carefully about the conditions under which 
it should be sent.

Alan Stern

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Missing uevents after successful USBDEVFS_RESET
  2026-09-16  2:37 ` Alan Stern
@ 2026-09-20  6:00   ` Fabien Sanglard
  2026-09-20 14:58     ` Alan Stern
  0 siblings, 1 reply; 7+ messages in thread
From: Fabien Sanglard @ 2026-09-20  6:00 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-usb, gregkh

Hi Alan,

> You would have to think carefully about the conditions under which
> it should be sent.

We only want to emit KOBJ_CHANGE on an interface when:
1. A driver was bound before reset and forcibly unbound.
2. The reset succeeded in-place.
3. No driver matched on re-probe, which happens for `usbfs`.

It looks like these three conditions are all met in `usb_rebind_intf()`.

I tested it with an Android device/ `adb_reset`/`udevadm monitor
--kernel --subsystem-match=usb`. When the in-place reset succeeds, I
now see `UNBIND` followed by `CHANGE`.

WDYT?

---
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7f33fe5ba03b..ec4762d260df 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1182,8 +1182,23 @@ static void usb_rebind_intf(struct usb_interface *intf)
  if (!intf->dev.power.is_prepared) {
  intf->needs_binding = 0;
  rc = device_attach(&intf->dev);
- if (rc < 0 && rc != -EPROBE_DEFER)
+ if (rc < 0 && rc != -EPROBE_DEFER) {
  dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+ } else if (rc == 0) {
+ /*
+ * Emit KOBJ_CHANGE to notify user space that the
+ * interface without driver is ready to be re-claimed.
+ * 1. A driver was bound and forcibly unbound (this
+ *    function usb_rebind_intf() is called in this
+ *    case only).
+ * 2. The reset succeeded in-place (this function is
+ *    called from
+ *    usb_unbind_and_rebind_marked_interfaces()).
+ * 3. No kernel driver matched on re-probe
+ *    (device_attach() returned 0).
+ */
+ kobject_uevent(&intf->dev.kobj, KOBJ_CHANGE);
+ }
  }
 }

On Tue, Sep 15, 2026 at 7:37 PM Alan Stern <stern@rowland.harvard.edu> wrote:
>
> On Tue, Sep 15, 2026 at 02:48:08PM -0700, Fabien Sanglard wrote:
> > Hi,
> >
> > I am investigating an issue where userspace processes using usbfs (such as
> > ADB) cannot reliably track device state across a USBDEVFS_RESET ioctl by
> > monitoring netlink uevents.
> >
> > Repro steps: (Lenovo P620, kernel 7.1.6)
> > 1. Plug an ADB device into your computer.
> > 2. Open a console to monitor netlink events: udevadm monitor -p -u.
> > 3. Send USBDEVFS_RESET a couple of times (i used adb_usbreset).
> > 4. 50% of the time the event sequence is UNBIND/REMOVE/ADD/BIND. 50%
> > of the time, the event sequence is just UNBIND.
> >
> > When USBDEVFS_RESET is issued via drivers/usb/core/devio.c, it calls
> > usb_reset_device() -> usb_reset_and_verify_device() in drivers/usb/core/hub.c.
> > Depending on the reset outcome, userspace sees inconsistent uevents:
> >
> > Case 1: Full re-enumeration (descriptors changed or reset/verify failed)
> > The device is torn down and reprobed. Userspace receives:
> >   UNBIND -> REMOVE -> ADD -> BIND
> > Userspace processes monitoring uevents immediately detect that the device
> > is available again and re-open it.
> >
> > Case 2: Reset succeeds without re-enumeration (descriptors unchanged)
> > The kernel unbinds usbfs/interface drivers before reset, generating a
> > KOBJ_UNBIND uevent. Because the usb_device structure is preserved and
> > usbfs does not re-probe, no subsequent KOBJ_BIND, KOBJ_ADD, or KOBJ_CHANGE
> > event is ever emitted.
> >
> > As a result of Case 2, userspace receives an UNBIND ("disconnect") signal
> > and assumes the device went away, but never receives an event indicating
> > that the reset finished and the device is ready for reuse. This forces
> > daemons like adb to fall back to polling /dev/bus/usb instead of relying
> > on netlink/udev events.
> >
> > Is the omission of a completion uevent after a successful reset without
> > re-enumeration intentional?
>
> It's more or less unintentional.
>
> A normal driver would rebind automatically.  But usbfs isn't normal, in
> the sense that it won't bind to a device without a special user request
> (primarily the USBDEVFS_CLAIMINTERFACE ioctl but also some others).
>
> > If not, would a patch emitting KOBJ_CHANGE (or re-binding/notifying userspace)
> > upon completion of usb_reset_device() be acceptable here?
>
> Yes.  But there are some things to bear in mind:
>
> Adding pre_reset and post_reset handlers to the usbfs driver would
> prevent unbinding in case 2.  The problem is that there is no
> agreed-upon way to then let userspace clients know that the device has
> been reset, or to let them know beforehand that the device is going to
> be reset.  In other words, the two handlers wouldn't be able to do
> anything useful.
>
> Emitting a KOBJ_CHANGE uevent instead would be more straightforward.
> But you would have to think carefully about the conditions under which
> it should be sent.
>
> Alan Stern

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: Missing uevents after successful USBDEVFS_RESET
  2026-09-20  6:00   ` Fabien Sanglard
@ 2026-09-20 14:58     ` Alan Stern
  2026-10-12 17:16       ` [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface Fabien Sanglard
  0 siblings, 1 reply; 7+ messages in thread
From: Alan Stern @ 2026-09-20 14:58 UTC (permalink / raw)
  To: Fabien Sanglard; +Cc: linux-usb, gregkh

On Sat, Sep 19, 2026 at 11:00:22PM -0700, Fabien Sanglard wrote:
> Hi Alan,
> 
> > You would have to think carefully about the conditions under which
> > it should be sent.
> 
> We only want to emit KOBJ_CHANGE on an interface when:
> 1. A driver was bound before reset and forcibly unbound.
> 2. The reset succeeded in-place.
> 3. No driver matched on re-probe, which happens for `usbfs`.
> 
> It looks like these three conditions are all met in `usb_rebind_intf()`.
> 
> I tested it with an Android device/ `adb_reset`/`udevadm monitor
> --kernel --subsystem-match=usb`. When the in-place reset succeeds, I
> now see `UNBIND` followed by `CHANGE`.

All right.

> WDYT?

The patch was corrupted by your email client.  Please fix this.

> ---
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index 7f33fe5ba03b..ec4762d260df 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -1182,8 +1182,23 @@ static void usb_rebind_intf(struct usb_interface *intf)
>   if (!intf->dev.power.is_prepared) {
>   intf->needs_binding = 0;
>   rc = device_attach(&intf->dev);
> - if (rc < 0 && rc != -EPROBE_DEFER)
> + if (rc < 0 && rc != -EPROBE_DEFER) {
>   dev_warn(&intf->dev, "rebind failed: %d\n", rc);
> + } else if (rc == 0) {
> + /*
> + * Emit KOBJ_CHANGE to notify user space that the
> + * interface without driver is ready to be re-claimed.
> + * 1. A driver was bound and forcibly unbound (this
> + *    function usb_rebind_intf() is called in this
> + *    case only).
> + * 2. The reset succeeded in-place (this function is
> + *    called from
> + *    usb_unbind_and_rebind_marked_interfaces()).
> + * 3. No kernel driver matched on re-probe
> + *    (device_attach() returned 0).
> + */

Much too verbose.  (Are people learning how to write patches by 
imitating what LLMs do?)  Something like that would be appropriate for 
the patch description, but not for a code comment.  It should be more 
like this:

	/*
	 * Emit KOBJ_CHANGED uevent to notify userspace that the
	 * interface could not be rebound.
	 */

> + kobject_uevent(&intf->dev.kobj, KOBJ_CHANGE);
> + }
>   }
>  }

Otherwise this seems okay.

Alan Stern

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface
  2026-09-20 14:58     ` Alan Stern
@ 2026-10-12 17:16       ` Fabien Sanglard
  2026-10-12 17:28         ` sashiko-bot
  2026-10-13  9:34         ` Oliver Neukum
  0 siblings, 2 replies; 7+ messages in thread
From: Fabien Sanglard @ 2026-10-12 17:16 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Alan Stern; +Cc: linux-usb, linux-kernel, Fabien Sanglard

When an interface driver is forcibly unbound before a device reset,
usb_rebind_intf() attempts to re-attach a driver once the reset
completes in-place. Normal kernel drivers rebind and emit UNBIND
followed by BIND. However, usbfs only binds on explicit userspace
requests (e.g., USBDEVFS_CLAIMINTERFACE), so device_attach() returns 0
and no uevent is emitted.

As a result, userspace clients like adb only see UNBIND and must poll
/dev/bus/usb to detect when the interface is ready again. Emit a
KOBJ_CHANGE uevent when device_attach() finds no matching driver so
userspace is notified that the interface can be reclaimed.

Link: https://lore.kernel.org/linux-usb/CAA92w6k-LA4tVXyX1mFNOR3e+_mC43F_BXqhXeWqQyFx2D4_Mg@mail.gmail.com/
Signed-off-by: Fabien Sanglard <sanglardf@google.com>
---
 drivers/usb/core/driver.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7f33fe5ba03b..25057423fda0 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1182,8 +1182,15 @@ static void usb_rebind_intf(struct usb_interface *intf)
 	if (!intf->dev.power.is_prepared) {
 		intf->needs_binding = 0;
 		rc = device_attach(&intf->dev);
-		if (rc < 0 && rc != -EPROBE_DEFER)
+		if (rc < 0 && rc != -EPROBE_DEFER) {
 			dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+		} else if (rc == 0) {
+			/*
+			 * Emit a KOBJ_CHANGE uevent to notify userspace
+			 * that the interface could not be rebound.
+			 */
+			kobject_uevent(&intf->dev.kobj, KOBJ_CHANGE);
+		}
 	}
 }
 
-- 
2.55.0.1082.g2b9226bbc0-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface
  2026-10-12 17:16       ` [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface Fabien Sanglard
@ 2026-10-12 17:28         ` sashiko-bot
  2026-10-13  9:34         ` Oliver Neukum
  1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-12 17:28 UTC (permalink / raw)
  To: Fabien Sanglard; +Cc: linux-usb

> When an interface driver is forcibly unbound before a device reset,
> usb_rebind_intf() attempts to re-attach a driver once the reset
> completes in-place. Normal kernel drivers rebind and emit UNBIND
> followed by BIND. However, usbfs only binds on explicit userspace
> requests (e.g., USBDEVFS_CLAIMINTERFACE), so device_attach() returns 0
> and no uevent is emitted.
> 
> As a result, userspace clients like adb only see UNBIND and must poll
> /dev/bus/usb to detect when the interface is ready again. Emit a
> KOBJ_CHANGE uevent when device_attach() finds no matching driver so
> userspace is notified that the interface can be reclaimed.
> 
> Link: https://lore.kernel.org/linux-usb/CAA92w6k-LA4tVXyX1mFNOR3e+_mC43F_BXqhXeWqQyFx2D4_Mg@mail.gmail.com/
> Signed-off-by: Fabien Sanglard <sanglardf@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261012171609.88273-1-sanglardf@google.com?part=1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface
  2026-10-12 17:16       ` [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface Fabien Sanglard
  2026-10-12 17:28         ` sashiko-bot
@ 2026-10-13  9:34         ` Oliver Neukum
  1 sibling, 0 replies; 7+ messages in thread
From: Oliver Neukum @ 2026-10-13  9:34 UTC (permalink / raw)
  To: Fabien Sanglard, Greg Kroah-Hartman, Alan Stern; +Cc: linux-usb, linux-kernel

On 12.10.26 19:16, Fabien Sanglard wrote:

> As a result, userspace clients like adb only see UNBIND and must poll
> /dev/bus/usb to detect when the interface is ready again. Emit a
> KOBJ_CHANGE uevent when device_attach() finds no matching driver so
> userspace is notified that the interface can be reclaimed.

Hi,

why do you want to limit this to that specific case?
Why not not always tell user space tat a device has
been reset?

	Regards
		Oliver


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-13  9:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-15 21:48 Missing uevents after successful USBDEVFS_RESET Fabien Sanglard
2026-09-16  2:37 ` Alan Stern
2026-09-20  6:00   ` Fabien Sanglard
2026-09-20 14:58     ` Alan Stern
2026-10-12 17:16       ` [PATCH] usb: core: Emit KOBJ_CHANGE on unbound interface Fabien Sanglard
2026-10-12 17:28         ` sashiko-bot
2026-10-13  9:34         ` Oliver Neukum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox