summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorZhenhua Zhang <zhenhua.zhang@intel.com>2010-05-11 09:04:28 +0800
committerDenis Kenzior <denkenz@gmail.com>2010-05-11 09:18:55 -0500
commitaf976f7e524746b1b55645967e11ab8250f593a8 (patch)
tree62405de182cba35f6e98e0ac2bae474bfe107b18 /plugins
parentdea4c88906bdbc1fb488cc3239ba08342209e006 (diff)
downloadofono-af976f7e524746b1b55645967e11ab8250f593a8.tar.bz2
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.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/udev.c58
1 files changed, 39 insertions, 19 deletions
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 <ofono/log.h>
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;