From 9e6bccdf37cf9815e66b0bca3a5673218b8d05fb Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 4 Jan 2022 15:26:43 +0100 Subject: [PATCH] udev: use USB vendor/product ID to determine behavior When going into firmware upgrade mode, the modem comes back with different IDs than in normal use. We should make sure we cancel the reset sequence when that happens, and not start a new one. --- src/manager.h | 1 + src/udev.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) 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; }