udev: handle removal of parent usb devices
fix device removal event handling to remove modems if the associated parent usb device is removed
This commit is contained in:

committed by
Alexander Sack

parent
d317254a3b
commit
53af144f49
@@ -261,6 +261,24 @@ impl_manager_enumerate_devices (MMManager *manager,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MMModem *
|
||||
find_modem_for_device (MMManager *manager, const char *device)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->modems);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
MMModem *modem = MM_MODEM (value);
|
||||
|
||||
if (!strcmp (device, mm_modem_get_device (modem)))
|
||||
return modem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static MMModem *
|
||||
find_modem_for_port (MMManager *manager, const char *subsys, const char *name)
|
||||
{
|
||||
@@ -533,11 +551,33 @@ device_removed (MMManager *manager, GUdevDevice *device)
|
||||
|
||||
subsys = g_udev_device_get_subsystem (device);
|
||||
name = g_udev_device_get_name (device);
|
||||
|
||||
if (strcmp (subsys, "usb") != 0) {
|
||||
/* find_modem_for_port handles tty and net removal */
|
||||
modem = find_modem_for_port (manager, subsys, name);
|
||||
if (modem) {
|
||||
mm_modem_release_port (modem, subsys, name);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* This case is designed to handle the case where, at least with kernel 2.6.31, unplugging
|
||||
* an in-use ttyACMx device results in udev generating remove events for the usb, but the
|
||||
* ttyACMx device (subsystem tty) is not removed, since it was in-use. So if we have not
|
||||
* found a modem for the port (above), we're going to look here to see if we have a modem
|
||||
* associated with the newly removed device. If so, we'll remove the modem, since the
|
||||
* device has been removed. That way, if the device is reinserted later, we'll go through
|
||||
* the process of exporting it.
|
||||
*/
|
||||
const char *sysfs_path = g_udev_device_get_sysfs_path (device);
|
||||
|
||||
// g_debug ("Looking for a modem for removed device %s", sysfs_path);
|
||||
modem = find_modem_for_device (manager, sysfs_path);
|
||||
if (modem) {
|
||||
g_debug ("Removing modem claimed by removed device %s", sysfs_path);
|
||||
remove_modem (manager, modem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe a plugin is checking whether or not the port is supported */
|
||||
key = get_key (subsys, name);
|
||||
@@ -567,9 +607,12 @@ handle_uevent (GUdevClient *client,
|
||||
subsys = g_udev_device_get_subsystem (device);
|
||||
g_return_if_fail (subsys != NULL);
|
||||
|
||||
g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net"));
|
||||
g_return_if_fail (!strcmp (subsys, "tty") || !strcmp (subsys, "net") || !strcmp (subsys, "usb"));
|
||||
|
||||
if (!strcmp (action, "add"))
|
||||
/* We only care about tty/net devices when adding modem ports,
|
||||
* but for remove, also handle usb parent device remove events
|
||||
*/
|
||||
if (!strcmp (action, "add") && strcmp (subsys, "usb") !=0 )
|
||||
device_added (self, device);
|
||||
else if (!strcmp (action, "remove"))
|
||||
device_removed (self, device);
|
||||
@@ -599,7 +642,7 @@ static void
|
||||
mm_manager_init (MMManager *manager)
|
||||
{
|
||||
MMManagerPrivate *priv = MM_MANAGER_GET_PRIVATE (manager);
|
||||
const char *subsys[3] = { "tty", "net", NULL };
|
||||
const char *subsys[4] = { "tty", "net", "usb", NULL };
|
||||
|
||||
priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
load_plugins (manager);
|
||||
|
Reference in New Issue
Block a user