diff --git a/meson.build b/meson.build index ba38ca3..70c6338 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,7 @@ endif mgr_deps = [ dependency('glib-2.0'), dependency('gio-unix-2.0'), + dependency('gudev-1.0'), dependency('libgpiod'), dependency('libusb-1.0'), dependency('mm-glib'), diff --git a/src/manager.c b/src/manager.c index be72c57..a7dc2ff 100644 --- a/src/manager.c +++ b/src/manager.c @@ -9,6 +9,7 @@ #include "manager.h" #include "mm-iface.h" #include "suspend.h" +#include "udev.h" #include #include @@ -30,6 +31,7 @@ static gboolean quit_app(struct EG25Manager *manager) at_destroy(manager); mm_iface_destroy(manager); suspend_destroy(manager); + udev_destroy(manager); if (manager->modem_state >= EG25_STATE_STARTED) { g_message("Powering down the modem..."); @@ -202,6 +204,7 @@ int main(int argc, char *argv[]) gpio_init(&manager); mm_iface_init(&manager); suspend_init(&manager); + udev_init(&manager); g_idle_add(G_SOURCE_FUNC(modem_start), &manager); diff --git a/src/manager.h b/src/manager.h index 8c12741..feaca9b 100644 --- a/src/manager.h +++ b/src/manager.h @@ -8,6 +8,7 @@ #include #include +#include #include enum EG25State { @@ -44,6 +45,7 @@ struct EG25Manager { int suspend_inhibit_fd; guint suspend_source; + GUdevClient *udev; struct gpiod_chip *gpiochip[2]; struct gpiod_line *gpio_out[5]; diff --git a/src/meson.build b/src/meson.build index eb4b690..012773c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -12,6 +12,7 @@ executable ( 'manager.c', 'manager.h', 'mm-iface.c', 'mm-iface.h', 'suspend.c', 'suspend.h', + 'udev.c', 'udev.h', ], dependencies : mgr_deps, install : true diff --git a/src/suspend.c b/src/suspend.c index 4aa5de6..92260a9 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -158,6 +158,10 @@ void suspend_init(struct EG25Manager *manager) void suspend_destroy(struct EG25Manager *manager) { drop_inhibitor(manager); + if (manager->suspend_source) { + g_source_remove(manager->suspend_source); + manager->suspend_source = 0; + } if (manager->suspend_proxy) { g_object_unref(manager->suspend_proxy); manager->suspend_proxy = NULL; diff --git a/src/udev.c b/src/udev.c new file mode 100644 index 0000000..acf10f8 --- /dev/null +++ b/src/udev.c @@ -0,0 +1,41 @@ +/* + * 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; + + if (strcmp(action, "unbind") != 0 || manager->modem_state == EG25_STATE_RESETTING) + return; + + if (strncmp(g_udev_device_get_name(device), manager->modem_usb_id, strlen(manager->modem_usb_id)) == 0 && + manager->reset_timer == 0) { + g_message("Lost modem, resetting..."); + modem_reset(manager); + } +} + +void udev_init (struct EG25Manager *manager) +{ + 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; + } +} diff --git a/src/udev.h b/src/udev.h new file mode 100644 index 0000000..bf166b1 --- /dev/null +++ b/src/udev.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2020 Arnaud Ferraris + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include "manager.h" + +void udev_init (struct EG25Manager *data); +void udev_destroy (struct EG25Manager *data);