Timing issue between DeviceAdded and plugin_device_added() events

39 views
Skip to first unread message

Sanjay Sheth

unread,
Apr 27, 2025, 11:21:17 PMApr 27
to fwupd

logitech-rallysystem plugin support firmware upgrade of composite device. Device has multiple sub-devices:  Audio, TableHub etc. 


Device limitation:

Only Audio sub-device has topology information of all sub-devices, e.g. overall system version, version of each sub-devices etc. But only another sub-device (TableHub), can upgrade firmware for all sub-devices. 


Compute Host limitation:

Leveraging udev rules, it only communicates with one sub-device/pid to query overall system version and push new firmware, if needed. Since only TableHub sub-device can upgrade firmware, host leverages this sub-device/pid in udev rules file.


Current design:

Set version information of each sub-devices, as they are created (LOGITECH_RALLYSYSTEM_AUDIO_DEVICE/LOGITECH_RALLYSYSTEM_TABLEHUB_DEVICE), Leverage plugin_device_added() to overwrite version information of TableHub sub-device to system version. Since this is the sub-device that compute host leverage


Issue:

Leveraging udev rules, host queries version information of TableHub device when the device is plugged-in. Since udev rules (D-Bus signals) are triggered before plugin_device_added(), host assumes, version reported by TableHub sub-system, as overall system version. This impacts upgrade flow. If host waits, for few seconds after udev rules (D-Bus signal) are triggered, then it correctly gets system version, because by that time, plugin_device_added()  overwrites TableHub sub-system version with overall system version.


Is there any API we can leverage in plugin to defer/delay, until sub-device (TableHub) version is overwritten to system version?


Here are the verbose logs, all events happens virtually at same timestamp. In other words, it is a timing issue, when host query system version and trigger firmware upgrade:

19:56:33.695 FuPlugin             emit added from logitech_rallysystem: 34970f527332351a0bcf41f574486e570aa73309

19:56:33.695 FuDeviceList         ::added 34970f527332351a0bcf41f574486e570aa73309 [Logi Rally Table Hub]

19:56:33.695 FuMain               ADDED:

FuLogitechRallysystemTablehubDevice:

  DeviceId:             34970f527332351a0bcf41f574486e570aa73309

  Name:                 Logi Rally Table Hub

  Guid:                 afd482e8-642e-5592-aeda-d70e34fb5798 ← USB\VID_046D&PID_088F

  Plugin:               logitech_rallysystem

  Protocol:             com.logitech.vc.rallysystem

  Flags:                updatable|signed-payload|can-emulation-tag

  Vendor:               Logitech, Inc.

  VendorId:             USB:0x046D

  Version:              1.1.540

<...SNIP...>

19:56:33.695 FuPlugin             fu_plugin_device_added(logitech_rallysystem)

19:56:33.695 FuDevice             changing version for 34970f527332351a0bcf41f574486e570aa73309: 1.1.540->1.2.135

19:56:33.695 FuPluginLogitechRallysystem overwriting tablehub version to 1.2.135

Richard Hughes

unread,
Apr 28, 2025, 4:35:58 AMApr 28
to Sanjay Sheth, fwupd
On Monday, 28 April 2025 at 04:21, 'Sanjay Sheth' via fwupd <fw...@googlegroups.com> wrote:
> logitech-rallysystem plugin support firmware upgrade of composite device. Device has multiple sub-devices: Audio, TableHub etc.
> Leveraging udev rules, it only communicates with one sub-device/pid to query overall system version and push new firmware, if needed. Since only TableHub sub-device can upgrade firmware, host leverages this sub-device/pid in udev rules file.

These udev rules are not upstream and it's not something we can support -- for reasons you've shown here. When we have a dynamic device with child devices coming and going async from the main parent it's impossible to use udev rules to match against the *child* and then to use other children from the parent. It's one of the reasons fwupd is set up to be a daemon...

> If host waits, for few seconds after udev rules (D-Bus signal) are triggered, then it correctly gets system version, because by that time, plugin_device_added() overwrites TableHub sub-system version with overall system version.

Does it work correctly if using the daemon process and fwupdmgr?

Richard.

Sanjay Sheth

unread,
Apr 28, 2025, 5:29:36 AMApr 28
to fwupd
Yes, it works using daemon+fwupdmgr, but only if host waits few seconds before querying system version info and then trigger firmware upgrade, if needed. 

Richard Hughes

unread,
May 1, 2025, 12:49:29 PMMay 1
to Sanjay Sheth, fwupd
On Monday, 28 April 2025 at 10:29, 'Sanjay Sheth' via fwupd <fw...@googlegroups.com> wrote:
> Yes, it works using daemon+fwupdmgr, but only if host waits few seconds before querying system version info and then trigger firmware upgrade, if needed.

So that's certainly not ideal :)

The bit that's confusing me is that we seem to try really hard to set a version for the rallysystem device, and then just overwrite it with the audio device-derived version -- could we just use the rallysystem device version instead? Does the rallysystem device version get updated on firmware update? Certainly deleting fu_logitech_rallysystem_plugin_device_added would fix the events problem and also make it possible to record an emulation.

If that's not possible (and I'd hope it is, simpler code == better code) we could certainly split up fu_plugin_device_add() into something that adds the device to the plugin as a phase1 and then emits the "added" event as a phase2 but that will need some careful self tests as the plugin isn't expecting the same device to be added more than once.

It might be better to do two things:

* add a device inhibit in fu_logitech_rallysystem_tablehub_device_setup() so the device is not marked as updatable
* clear the device inhibit in fu_logitech_rallysystem_plugin_device_added when overwriting the version with the audio device version

That would mean the rallysystem device shows up with device-added (not updatable), then the audio device shows up with device-added, then the rallysystem device becomes updatable and we get device-changed as an event sent out. Depending on what UX you're wired up that might be good enough.

If you desperately have to trigger on device-added, then I'd do the inhibit thing AND also have a FU_DEVICE_PRIVATE_FLAG_INHIBIT_SIGNAL_ADDED defined in fu-device.h which just skips the "g_signal_emit(self, signals[SIGNAL_DEVICE_ADDED], 0, device);" in fu-plugin.c if the device is inhibited -- and then when the audio device sets the rallysystem device version in fu_logitech_rallysystem_plugin_device_added() we'd clear the inhibit. If FuPlugin connects to notify::flags then we could automatically emit SIGNAL_DEVICE_ADDED when FU_DEVICE_PRIVATE_FLAG_INHIBIT_SIGNAL_ADDED is set and the device is updatable.

Richard.

Sanjay Sheth

unread,
May 1, 2025, 1:08:52 PMMay 1
to fwupd
Thanks a lot Richard, will try those pointers. I understand the limitations of this composite device. 
FYI, In the worst case scenario, we have seen 3 second difference between DeviceAdded and plugin_device_added(). 
Reply all
Reply to author
Forward
0 new messages