diff --git a/src/manager.h b/src/manager.h index bccf5dc..43d44bd 100644 --- a/src/manager.h +++ b/src/manager.h @@ -53,6 +53,7 @@ enum EG25State { EG25_STATE_SUSPENDING, // System is going into suspend EG25_STATE_RESUMING, // System is being resumed, waiting for modem to come back EG25_STATE_RESETTING, // Something went wrong, we're restarting the modem + EG25_STATE_UPDATING, // Modem is present but being updated EG25_STATE_FINISHING }; diff --git a/src/udev.c b/src/udev.c index a2e62a3..cc452b1 100644 --- a/src/udev.c +++ b/src/udev.c @@ -11,22 +11,42 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer data) { struct EG25Manager *manager = data; + const gchar *prop; + long vid = 0, pid = 0; - if (!manager->modem_usb_id) - return; - - if (strcmp(g_udev_device_get_name(device), manager->modem_usb_id) == 0 && - strcmp(action, "add") == 0 && manager->schedule_reset_timer != 0) { - g_message("Modem recovered before reset sequence was triggered, cancel reset."); - g_source_remove(manager->schedule_reset_timer); - manager->schedule_reset_timer = 0; + /* + * Act only if the device is the one identified as a modem by MM/ofono + */ + if (!manager->modem_usb_id || + strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { return; } + prop = g_udev_device_get_property(device, "ID_VENDOR_ID"); + if (prop) + vid = strtol(prop, NULL, 16); + + prop = g_udev_device_get_property(device, "ID_MODEL_ID"); + if (prop) + pid = strtol(prop, NULL, 16); + + if (strcmp(action, "bind") == 0 && vid != manager->usb_vid && pid != manager->usb_pid) { + /* + * Modem is probably executing a FW upgrade, make sure we don't interrupt it + */ + if (manager->schedule_reset_timer != 0) { + g_message("Modem re-appeared with different VID/PID, cancel reset."); + g_source_remove(manager->schedule_reset_timer); + manager->schedule_reset_timer = 0; + } + manager->modem_state = EG25_STATE_UPDATING; + } + if (strcmp(action, "unbind") != 0 || + manager->modem_state == EG25_STATE_UPDATING || manager->modem_state == EG25_STATE_RESETTING || manager->complete_reset_timer != 0 || - strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { + manager->schedule_reset_timer != 0) { return; }