From af976f7e524746b1b55645967e11ab8250f593a8 Mon Sep 17 00:00:00 2001 From: Zhenhua Zhang Date: Tue, 11 May 2010 09:04:28 +0800 Subject: Fix Use hashtable to record udev path Sometimes, Udev device 'remove' event could not report correct parent node of current udev_device. Current code replies on the devpath attached on the parent node to find modem and then remove it. This fix is to change the way to store the devpath info into a hashtable. So that we search hashtable to get devpath and remove the modem. --- plugins/udev.c | 58 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'plugins') diff --git a/plugins/udev.c b/plugins/udev.c index 4aaeeb97..3a6ea285 100644 --- a/plugins/udev.c +++ b/plugins/udev.c @@ -36,6 +36,7 @@ #include static GSList *modem_list = NULL; +static GHashTable *devpath_list = NULL; static struct ofono_modem *find_modem(const char *devpath) { @@ -259,7 +260,7 @@ static void add_modem(struct udev_device *udev_device) { struct ofono_modem *modem; struct udev_device *parent; - const char *devpath, *driver; + const char *devpath, *curpath, *driver; parent = udev_device_get_parent(udev_device); if (parent == NULL) @@ -295,6 +296,12 @@ static void add_modem(struct udev_device *udev_device) modem_list = g_slist_prepend(modem_list, modem); } + curpath = udev_device_get_devpath(udev_device); + if (curpath == NULL) + return; + + g_hash_table_insert(devpath_list, g_strdup(curpath), g_strdup(devpath)); + if (g_strcmp0(driver, "mbm") == 0) add_mbm(modem, udev_device); else if (g_strcmp0(driver, "hso") == 0) @@ -307,30 +314,25 @@ static void add_modem(struct udev_device *udev_device) add_novatel(modem, udev_device); } +static gboolean devpath_remove(gpointer key, gpointer value, gpointer user_data) +{ + const char *path = value; + const char *devpath = user_data; + + return g_str_equal(path, devpath); +} + static void remove_modem(struct udev_device *udev_device) { struct ofono_modem *modem; - struct udev_device *parent; - const char *devpath, *driver = NULL; + const char *curpath = udev_device_get_devpath(udev_device); + char *devpath, *remove; - parent = udev_device_get_parent(udev_device); - if (parent == NULL) + if (curpath == NULL) return; - driver = get_driver(parent); - if (driver == NULL) { - parent = udev_device_get_parent(parent); - driver = get_driver(parent); - if (driver == NULL) { - parent = udev_device_get_parent(parent); - driver = get_driver(parent); - if (driver == NULL) - return; - } - } - - devpath = udev_device_get_devpath(parent); - if (devpath == NULL) + devpath = g_hash_table_lookup(devpath_list, curpath); + if (!devpath) return; modem = find_modem(devpath); @@ -340,6 +342,12 @@ static void remove_modem(struct udev_device *udev_device) modem_list = g_slist_remove(modem_list, modem); ofono_modem_remove(modem); + + remove = g_strdup(devpath); + + g_hash_table_foreach_remove(devpath_list, devpath_remove, remove); + + g_free(remove); } static void enumerate_devices(struct udev *context) @@ -444,15 +452,24 @@ static void udev_start(void) static int udev_init(void) { + devpath_list = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + if (!devpath_list) { + ofono_error("Failed to create udev path list"); + return -ENOMEM; + } + udev_ctx = udev_new(); if (udev_ctx == NULL) { ofono_error("Failed to create udev context"); + g_hash_table_destroy(devpath_list); return -EIO; } udev_mon = udev_monitor_new_from_netlink(udev_ctx, "udev"); if (udev_mon == NULL) { ofono_error("Failed to create udev monitor"); + g_hash_table_destroy(devpath_list); udev_unref(udev_ctx); udev_ctx = NULL; return -EIO; @@ -484,6 +501,9 @@ static void udev_exit(void) g_slist_free(modem_list); modem_list = NULL; + g_hash_table_destroy(devpath_list); + devpath_list = NULL; + if (udev_ctx == NULL) return; -- cgit v1.2.3