OpenCPN Partial API docs
linux_usb_watch.cpp
1 /***************************************************************************
2  * Copyright (C) 2024 Alec Leamas *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 2 of the License, or *
7  * (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License *
15  * along with this program; if not, write to the *
16  * Free Software Foundation, Inc., *
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18  **************************************************************************/
19 
26 #include "model/linux_usb_watch.h"
27 
28 // Definitions for "New device" and "device gone" events. Could be any device,
29 // but in real life this is only USB.
30 static const char* const kDevSender = "org.freedesktop.systemd1";
31 static const char* const kDevInterface = "org.freedesktop.systemd1.Manager";
32 static const char* const kDevAddMember = "UnitNew";
33 static const char* const kDevRemoveMember = "UnitRemoved";
34 
35 // Definitions for suspend/resume event
36 // Link:
37 // https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html#Signals
38 static const char* const kResSender = "org.freedesktop.login1";
39 static const char* const kResInterface = "org.freedesktop.login1.Manager";
40 static const char* const kResMember = "PrepareForSleep";
41 
42 static void dev_signal_cb(GDBusConnection* connection, const gchar* sender,
43  const gchar* object_path, const gchar* interface,
44  const gchar* signal, GVariant* parameters,
45  gpointer user_data) {
46  auto watch_daemon = static_cast<LinuxUsbWatchDaemon*>(user_data);
47  watch_daemon->m_sys_events.evt_dev_change.Notify();
48 }
49 
50 static void prepare_for_sleep_cb(GDBusConnection* connection,
51  const gchar* sender, const gchar* object_path,
52  const gchar* interface, const gchar* signal,
53  GVariant* parameters, gpointer user_data) {
54  gboolean suspending;
55  g_variant_get(parameters, "(b)", &suspending);
56  auto watch_daemon = static_cast<LinuxUsbWatchDaemon*>(user_data);
57  if (!suspending) watch_daemon->m_sys_events.evt_resume.Notify();
58 
59  // printf("Resume callback, arg: %s", suspending ? "true" : "false");
60 }
61 
62 LinuxUsbWatchDaemon::~LinuxUsbWatchDaemon() { Stop(); }
63 
64 void LinuxUsbWatchDaemon::DoStart() {
65  g_main_context_push_thread_default(m_worker_context);
66  g_main_loop_run(m_main_loop);
67  g_main_context_pop_thread_default(m_worker_context);
68 }
69 
70 void LinuxUsbWatchDaemon::Start() {
71  int filter_id_dev;
72  int filter_id_res;
73  GError* err = 0;
74 
75  if (m_thread.joinable()) return; // already running
76  m_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, 0, &err);
77  g_dbus_connection_signal_subscribe(
78  m_conn, kDevSender, kDevInterface, kDevAddMember, 0, 0,
79  G_DBUS_SIGNAL_FLAGS_NONE, dev_signal_cb, this, 0);
80  g_dbus_connection_signal_subscribe(
81  m_conn, kDevSender, kDevInterface, kDevRemoveMember, 0, 0,
82  G_DBUS_SIGNAL_FLAGS_NONE, dev_signal_cb, this, 0);
83  g_dbus_connection_signal_subscribe(
84  m_conn, kResSender, kResInterface, kResMember, 0, 0,
85  G_DBUS_SIGNAL_FLAGS_NONE, prepare_for_sleep_cb, this, 0);
86  m_worker_context = g_main_context_new();
87  m_main_loop = g_main_loop_new(m_worker_context, false);
88  m_thread = std::thread([&]{ DoStart(); });
89 }
90 
91 void LinuxUsbWatchDaemon::Stop() {
92  if (!m_thread.joinable()) return; // Already stopped
93  g_main_loop_unref(m_main_loop);
94  g_main_loop_quit(m_main_loop);
95  m_thread.join();
96 }
const void Notify()
Notify all listeners, no data supplied.
Listen to DBus system bus signals reflecting for example suspend/resume, new USB devicesbeing plugged...
EventVar evt_resume
Notified when resuming from hibernate.
Definition: sys_events.h:38
EventVar evt_dev_change
Notified when a new or removed device is detected, usually an USB hotplug event:
Definition: sys_events.h:44
Linux specific hardware events DBus interface.