/* * Copyright (C) 2020 Arnaud Ferraris * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "udev.h" #include 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; /* * 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 || manager->schedule_reset_timer != 0) { return; } g_message("Lost modem, resetting..."); manager->schedule_reset_timer = g_timeout_add_seconds(3, G_SOURCE_FUNC(modem_reset), manager); } void udev_init (struct EG25Manager *manager, toml_table_t *config[]) { const char * const subsystems[] = { "usb", NULL }; manager->udev = g_udev_client_new(subsystems); g_signal_connect(manager->udev, "uevent", G_CALLBACK(udev_event_cb), manager); return; } void udev_destroy (struct EG25Manager *manager) { if (manager->udev) { g_object_unref(manager->udev); manager->udev = NULL; } }