[PATCH] Fix dock station status detection
Holger Macht
hmacht at suse.de
Thu Mar 13 13:19:41 PDT 2008
On Do 13. Mär - 19:38:42, Holger Macht wrote:
> On Do 13. Mär - 19:25:14, Danny Kukawka wrote:
> > On Donnerstag, 13. März 2008, Holger Macht wrote:
> > > When the user triggers an undock operation, the kernel assumes that the
> > > undock cannot fail (which is pretty true) and sends out the 'UNDOCK' udev
> > > event before actually doing it. So when HAL comes down to
> > > platform_refresh() and reads the 'docked' sysfs file, it still contains
> > > 'docked' (at odd times, it's a race).
> >
> > Sound to me like a kernel bug. Should the kernel get fixed to send the UNDOCK
> > first if the sysfs attribute is changed?
>
> Same considerations over here ;-) but...
>
> AFAIK, it can't, because for sending the udev event, the device structure
> has to be still present.
>
> The more clean solution would be to catch the UNDOCK_EVENT and to wait in
> a loop for the undock to fail or succeed (according to the flags). The
> only thing the dock driver signals is "now I'm starting the undock
> operation", which is correct. Userspace can check if it succeeded or not.
>
> But I think the overhead would be too high in comparison to what it
> gains.
Well, cleanest way is to add a g_timeout_add in case the undock is still
in progress. I used a interval of 300 milliseconds. This was enough for
the callback to be called only once, even under heavy load on my X60. And
note: This timeout is only installed when you're actually doing a undock
operation, not on every platform_refresh. Please change if you prefer to
use g_timout_add_seconds().
Regards,
Holger
---
diff --git a/hald/linux/device.c b/hald/linux/device.c
index c41edf3..c648c04 100644
--- a/hald/linux/device.c
+++ b/hald/linux/device.c
@@ -75,6 +75,7 @@ gboolean _have_sysfs_sleep_button = FALSE;
gboolean _have_sysfs_power_supply = FALSE;
#define POWER_SUPPLY_BATTERY_POLL_INTERVAL 30 /* in seconds */
+#define DOCK_STATION_UNDOCK_POLL_INTERVAL 300 /* in milliseconds */
/* we must use this kernel-compatible implementation */
#define BITS_PER_LONG (sizeof(long) * 8)
@@ -2016,10 +2017,30 @@ platform_compute_udi (HalDevice *d)
}
static gboolean
+platform_refresh_undock (gpointer data)
+{
+ HalDevice *d = (HalDevice *) data;
+ gint flags, docked;
+ const gchar *sysfs_path;
+
+ sysfs_path = hal_device_property_get_string(d, "linux.sysfs_path");
+ hal_util_get_int_from_file (sysfs_path, "flags", &flags, 0);
+
+ /* check for != 0, maybe the user did an immediate dock */
+ if (flags != 0)
+ return TRUE;
+
+ hal_util_get_int_from_file (sysfs_path, "docked", &docked, 0);
+ hal_device_property_set_bool (d, "info.docked", docked);
+
+ return FALSE;
+}
+
+static gboolean
platform_refresh (HalDevice *d)
{
const gchar *id, *sysfs_path;
- int docked;
+ gint docked, flags;
id = hal_device_property_get_string (d, "platform.id");
if (strncmp (id, "dock", 4) != 0)
@@ -2027,8 +2048,18 @@ platform_refresh (HalDevice *d)
sysfs_path = hal_device_property_get_string(d, "linux.sysfs_path");
hal_util_get_int_from_file (sysfs_path, "docked", &docked, 0);
- hal_device_property_set_bool (d, "info.docked", docked);
+ if (docked == 1) {
+ /* undock still in progress? */
+ hal_util_get_int_from_file (sysfs_path, "flags", &flags, 0);
+ if (flags == 2) {
+ g_timeout_add (DOCK_STATION_UNDOCK_POLL_INTERVAL,
+ platform_refresh_undock, d);
+ return TRUE;
+ }
+ }
+
+ hal_device_property_set_bool (d, "info.docked", docked);
return TRUE;
}
More information about the hal
mailing list