Added ModemManager

This commit is contained in:
Gerben Jan Dijkman 2021-03-24 22:57:24 +01:00
parent 41221b558e
commit 0974983d2c
12 changed files with 1289 additions and 0 deletions

View File

@ -0,0 +1 @@
DIST ModemManager-1.16.2.tar.xz 2447936 BLAKE2B aafd2bde9fe72ec837a34987a698d82f4ba2aedf778c350263f8fe937ccd4b5b9b78fc66c58a39a8729c371788ab7b7782073726dc132b8f08bd2df0a9bc2da4 SHA512 c0b095972eba6e0f3a1ad22e425b412f17d8b60f0af4d423a92fdebcb6d2801f87e6af98758f8c2dc4db3586a3a15530a318805fda312443fa6abe2265ebd6b6

View File

@ -0,0 +1,25 @@
From 2091ac5f75a6e025be896c21179b04bc53ce4bb0 Mon Sep 17 00:00:00 2001
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
Date: Sat, 23 May 2020 17:14:36 +0200
Subject: [PATCH] mm-broadband-modem: improve voice capabilities detection
---
src/mm-broadband-modem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index fdbd13b0..6dadb90e 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -7400,7 +7400,7 @@ modem_voice_check_support (MMIfaceModemVoice *self,
/* Check ATH support */
mm_base_modem_at_command (MM_BASE_MODEM (self),
- "H",
+ "I",
3,
FALSE,
(GAsyncReadyCallback)ath_format_check_ready,
--
2.26.2

View File

@ -0,0 +1,28 @@
From 9a4e5a7c2da36288cd66c1500dcd0e1ba844c9cc Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Wed, 25 Nov 2020 19:58:25 +0100
Subject: [PATCH] serial-parsers: do not fail to detect a valid response with a
call or text incoming
Upstreaming at
https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/406
---
src/mm-serial-parsers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c
index b511302e..248cc685 100644
--- a/src/mm-serial-parsers.c
+++ b/src/mm-serial-parsers.c
@@ -108,7 +108,7 @@ mm_serial_parser_v1_new (void)
parser = g_slice_new (MMSerialParserV1);
- parser->regex_ok = g_regex_new ("\\r\\nOK(\\r\\n)+$", flags, 0, NULL);
+ parser->regex_ok = g_regex_new ("\\r\\nOK(\\r\\n)+", flags, 0, NULL);
parser->regex_connect = g_regex_new ("\\r\\nCONNECT.*\\r\\n", flags, 0, NULL);
parser->regex_sms = g_regex_new ("\\r\\n>\\s*$", flags, 0, NULL);
parser->regex_cme_error = g_regex_new ("\\r\\n\\+CME ERROR:\\s*(\\d+)\\r\\n$", flags, 0, NULL);
--
2.25.1

View File

@ -0,0 +1,100 @@
From f5ce1ae2282e6164efa6b1f9b973ff61e44a30ff Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Sun, 31 Jan 2021 15:38:31 +0100
Subject: [PATCH 1/2] context: add test-no-suspend-resume cli parameter
Disables suspend/resume support at runtime.
This is useful for modems which are never turned off
or suspended when the host suspends.
---
src/main.c | 10 +++++++---
src/mm-context.c | 18 ++++++++++++++++++
src/mm-context.h | 9 ++++++---
3 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/src/main.c b/src/main.c
index 9963c7cc..928078a3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -195,9 +195,13 @@ main (int argc, char *argv[])
{
MMSleepMonitor *sleep_monitor;
- sleep_monitor = mm_sleep_monitor_get ();
- g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_SLEEPING, G_CALLBACK (sleeping_cb), NULL);
- g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_RESUMING, G_CALLBACK (resuming_cb), NULL);
+ if (mm_context_get_test_no_suspend_resume())
+ mm_dbg ("Suspend/resume support disabled at runtime");
+ else {
+ sleep_monitor = mm_sleep_monitor_get ();
+ g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_SLEEPING, G_CALLBACK (sleeping_cb), NULL);
+ g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_RESUMING, G_CALLBACK (resuming_cb), NULL);
+ }
}
#endif
diff --git a/src/mm-context.c b/src/mm-context.c
index 8f20d2e8..6d25c1bd 100644
--- a/src/mm-context.c
+++ b/src/mm-context.c
@@ -222,6 +222,9 @@ mm_context_get_log_relative_timestamps (void)
static gboolean test_session;
static gboolean test_enable;
static gchar *test_plugin_dir;
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+static gboolean test_no_suspend_resume;
+#endif
static const GOptionEntry test_entries[] = {
{
@@ -239,6 +242,13 @@ static const GOptionEntry test_entries[] = {
"Path to look for plugins",
"[PATH]"
},
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+ {
+ "test-no-suspend-resume", 0, 0, G_OPTION_ARG_NONE, &test_no_suspend_resume,
+ "Disable suspend/resume support at runtime even if available",
+ NULL
+ },
+#endif
{ NULL }
};
@@ -274,6 +284,14 @@ mm_context_get_test_plugin_dir (void)
return test_plugin_dir ? test_plugin_dir : PLUGINDIR;
}
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+gboolean
+mm_context_get_test_no_suspend_resume (void)
+{
+ return test_no_suspend_resume;
+}
+#endif
+
/*****************************************************************************/
static void
diff --git a/src/mm-context.h b/src/mm-context.h
index ff5f1343..5a9be51f 100644
--- a/src/mm-context.h
+++ b/src/mm-context.h
@@ -43,8 +43,11 @@ gboolean mm_context_get_log_timestamps (void);
gboolean mm_context_get_log_relative_timestamps (void);
/* Testing support */
-gboolean mm_context_get_test_session (void);
-gboolean mm_context_get_test_enable (void);
-const gchar *mm_context_get_test_plugin_dir (void);
+gboolean mm_context_get_test_session (void);
+gboolean mm_context_get_test_enable (void);
+const gchar *mm_context_get_test_plugin_dir (void);
+#if defined WITH_SYSTEMD_SUSPEND_RESUME
+gboolean mm_context_get_test_no_suspend_resume (void);
+#endif
#endif /* MM_CONTEXT_H */
--
2.30.0

View File

@ -0,0 +1,167 @@
From f83a4b5ed428dbe412b3c9cc779bd85fc8dbe583 Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Sat, 30 Jan 2021 21:57:50 +0100
Subject: [PATCH] broadband-modem-qmi: Enable AT URCs and QMI indications
Enable both AT URCs and QMI indications for messaging events.
This allows to receive text messages during suspend
on the PinePhone with a Quectel EG25 modem.
---
src/mm-broadband-modem-qmi.c | 109 +++++++++++++++++++++++++----------
1 file changed, 80 insertions(+), 29 deletions(-)
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index d161d96ec..bac5cf1b2 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -6115,13 +6115,6 @@ messaging_cleanup_unsolicited_events_finish (MMIfaceModemMessaging *_self,
GAsyncResult *res,
GError **error)
{
- MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
-
- /* Handle fallback */
- if (self->priv->messaging_fallback_at) {
- return iface_modem_messaging_parent->cleanup_unsolicited_events_finish (_self, res, error);
- }
-
return g_task_propagate_boolean (G_TASK (res), error);
}
@@ -6130,14 +6123,39 @@ messaging_setup_unsolicited_events_finish (MMIfaceModemMessaging *_self,
GAsyncResult *res,
GError **error)
{
- MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
- /* Handle fallback */
- if (self->priv->messaging_fallback_at) {
- return iface_modem_messaging_parent->setup_unsolicited_events_finish (_self, res, error);
- }
+static void
+common_cleanup_unsolicited_events_finish (MMIfaceModemMessaging *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
- return g_task_propagate_boolean (G_TASK (res), error);
+ messaging_cleanup_unsolicited_events_finish (self, res, &error);
+ if (error)
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_object_unref (task);
+}
+
+static void
+common_setup_unsolicited_events_finish (MMIfaceModemMessaging *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ messaging_setup_unsolicited_events_finish (self, res, &error);
+ if (error)
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_object_unref (task);
}
static void
@@ -6185,6 +6203,26 @@ common_setup_cleanup_messaging_unsolicited_events (MMBroadbandModemQmi *self,
g_object_unref (task);
}
+static void
+parent_messaging_cleanup_unsolicited_events_ready (MMIfaceModemMessaging *_self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!iface_modem_messaging_parent->cleanup_unsolicited_events_finish (_self, res, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ /* Disable QMI indications */
+ common_setup_cleanup_messaging_unsolicited_events (MM_BROADBAND_MODEM_QMI (_self),
+ FALSE,
+ (GAsyncReadyCallback)common_cleanup_unsolicited_events_finish,
+ task);
+}
+
static void
messaging_cleanup_unsolicited_events (MMIfaceModemMessaging *_self,
GAsyncReadyCallback callback,
@@ -6192,15 +6230,32 @@ messaging_cleanup_unsolicited_events (MMIfaceModemMessaging *_self,
{
MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
- /* Handle fallback */
- if (self->priv->messaging_fallback_at) {
- return iface_modem_messaging_parent->cleanup_unsolicited_events (_self, callback, user_data);
+ /* Disable AT URCs parent and chain QMI indications disabling */
+ iface_modem_messaging_parent->cleanup_unsolicited_events (
+ _self,
+ (GAsyncReadyCallback)parent_messaging_cleanup_unsolicited_events_ready,
+ g_task_new (self, NULL, callback, user_data));
+}
+
+static void
+parent_messaging_setup_unsolicited_events_ready (MMIfaceModemMessaging *_self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!iface_modem_messaging_parent->setup_unsolicited_events_finish (_self, res, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
}
- common_setup_cleanup_messaging_unsolicited_events (MM_BROADBAND_MODEM_QMI (self),
- FALSE,
- callback,
- user_data);
+ /* Enable QMI indications */
+ common_setup_cleanup_messaging_unsolicited_events (MM_BROADBAND_MODEM_QMI (_self),
+ TRUE,
+ (GAsyncReadyCallback)common_setup_unsolicited_events_finish,
+ task);
+
}
static void
@@ -6210,15 +6265,11 @@ messaging_setup_unsolicited_events (MMIfaceModemMessaging *_self,
{
MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
- /* Handle fallback */
- if (self->priv->messaging_fallback_at) {
- return iface_modem_messaging_parent->setup_unsolicited_events (_self, callback, user_data);
- }
-
- common_setup_cleanup_messaging_unsolicited_events (MM_BROADBAND_MODEM_QMI (self),
- TRUE,
- callback,
- user_data);
+ /* Enable AT URCs parent and chain QMI indication enabling */
+ iface_modem_messaging_parent->setup_unsolicited_events (
+ _self,
+ (GAsyncReadyCallback)parent_messaging_setup_unsolicited_events_ready,
+ g_task_new (self, NULL, callback, user_data));
}
/*****************************************************************************/
--
GitLab

View File

@ -0,0 +1,109 @@
From deccf35a68063ddae4a51a9ec99124fce998cf4b Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Sat, 30 Jan 2021 21:57:50 +0100
Subject: [PATCH] mm-broadband-modem-qmi: Add
ID_MM_QMI_MESSAGING_AT_FALLBACK_ENABLE
Allows to force a fallback to AT URCs for detecting
messaging events instead of QMI indications.
This allows to receive text messages during suspend
on the PinePhone with a Quectel EG25 modem.
---
.../quectel/77-mm-quectel-port-types.rules | 2 ++
src/mm-broadband-modem-qmi.c | 34 +++++++++++++++++--
src/mm-broadband-modem-qmi.h | 1 +
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/plugins/quectel/77-mm-quectel-port-types.rules b/plugins/quectel/77-mm-quectel-port-types.rules
index 54778d24..fab1f6fa 100644
--- a/plugins/quectel/77-mm-quectel-port-types.rules
+++ b/plugins/quectel/77-mm-quectel-port-types.rules
@@ -48,10 +48,12 @@ ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0296", ENV{.MM_USBIFNUM}=="02", ENV{
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0296", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
# Quectel EC25/EG25
+# Always fallback to AT URCs for messaging notifications
# ttyUSB0 (if #0): QCDM/DIAG port
# ttyUSB1 (if #1): GPS data port
# ttyUSB2 (if #2): AT primary port
# ttyUSB3 (if #3): AT secondary port
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{ID_MM_QMI_MESSAGING_AT_FALLBACK_ENABLE}="1"
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_TYPE_QCDM}="1"
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_GPS}="1"
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index ae27b333..4735e616 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -173,6 +173,30 @@ shared_qmi_peek_client (MMSharedQmi *self,
return client;
}
+/*****************************************************************************/
+
+MMPortQmi *
+mm_broadband_modem_qmi_peek_port_qmi (MMBroadbandModemQmi *self)
+{
+ MMPortQmi *primary_qmi_port = NULL;
+ GList *qmi_ports;
+
+ g_assert (MM_IS_BROADBAND_MODEM_QMI (self));
+
+ qmi_ports = mm_base_modem_find_ports (MM_BASE_MODEM (self),
+ MM_PORT_SUBSYS_UNKNOWN,
+ MM_PORT_TYPE_QMI,
+ NULL);
+
+ /* First QMI port in the list is the primary one always */
+ if (qmi_ports)
+ primary_qmi_port = MM_PORT_QMI (qmi_ports->data);
+
+ g_list_free_full (qmi_ports, g_object_unref);
+
+ return primary_qmi_port;
+}
+
/*****************************************************************************/
/* Create Bearer (Modem interface) */
@@ -6186,9 +6210,12 @@ messaging_cleanup_unsolicited_events (MMIfaceModemMessaging *_self,
gpointer user_data)
{
MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ MMPort *port = MM_PORT (mm_broadband_modem_qmi_peek_port_qmi (self));
/* Handle fallback */
- if (self->priv->messaging_fallback_at) {
+ if (self->priv->messaging_fallback_at ||
+ mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port),
+ "ID_MM_QMI_MESSAGING_AT_FALLBACK_ENABLE")) {
return iface_modem_messaging_parent->cleanup_unsolicited_events (_self, callback, user_data);
}
@@ -6204,9 +6231,12 @@ messaging_setup_unsolicited_events (MMIfaceModemMessaging *_self,
gpointer user_data)
{
MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ MMPort *port = MM_PORT (mm_broadband_modem_qmi_peek_port_qmi (self));
/* Handle fallback */
- if (self->priv->messaging_fallback_at) {
+ if (self->priv->messaging_fallback_at ||
+ mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port),
+ "ID_MM_QMI_MESSAGING_AT_FALLBACK_ENABLE")) {
return iface_modem_messaging_parent->setup_unsolicited_events (_self, callback, user_data);
}
diff --git a/src/mm-broadband-modem-qmi.h b/src/mm-broadband-modem-qmi.h
index 23825068..c9b50f15 100644
--- a/src/mm-broadband-modem-qmi.h
+++ b/src/mm-broadband-modem-qmi.h
@@ -46,5 +46,6 @@ MMBroadbandModemQmi *mm_broadband_modem_qmi_new (const gchar *device,
const gchar *plugin,
guint16 vendor_id,
guint16 product_id);
+MMPortQmi *mm_broadband_modem_qmi_peek_port_qmi (MMBroadbandModemQmi *self);
#endif /* MM_BROADBAND_MODEM_QMI_H */
--
2.30.0

View File

@ -0,0 +1,7 @@
// Let users in plugdev group modify ModemManager
polkit.addRule(function(action, subject) {
if (/^org\.freedesktop\.ModemManager1\.(Device\.Control|Contacts|Messaging|Location)$/.test(action.id) &&
subject.isInGroup("plugdev") && subject.active) {
return "yes";
}
});

View File

@ -0,0 +1,11 @@
// Let users in plugdev group modify ModemManager
polkit.addRule(function(action, subject) {
if ((action.id == "org.freedesktop.ModemManager1.Device.Control" ||
action.id == "org.freedesktop.ModemManager1.Contacts" ||
action.id == "org.freedesktop.ModemManager1.Messaging" ||
action.id == "org.freedesktop.ModemManager1.Location") &&
subject.isInGroup("plugdev") && subject.active) {
return "yes";
}
});

View File

@ -0,0 +1,3 @@
SYMLINK=="modem", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PORT_TYPE_QCDM}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
SYMLINK=="modem-at", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
ENV{INTERFACE}=="rmnet0", SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"

View File

@ -0,0 +1,264 @@
From 6fad8948a7ba16c857b813ec532f32906055c695 Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Sat, 6 Feb 2021 07:52:32 +0100
Subject: [PATCH] suspend: add boot timer
The EG25 modem needs at least 2 minutes after indicating 'RDY'
to be fully operational. If the modem is suspended before that,
calls or texts may not be seen by the userspace.
This mostly occurs when a full reboot or poweroff/poweron
sequence of the phone is performed.
---
src/at.c | 19 ++++++++++-
src/manager.h | 2 ++
src/suspend.c | 95 +++++++++++++++++++++++++++++++++++++++++++--------
src/suspend.h | 1 +
4 files changed, 101 insertions(+), 16 deletions(-)
diff --git a/src/at.c b/src/at.c
index 39a857a..c8fa6f5 100644
--- a/src/at.c
+++ b/src/at.c
@@ -17,6 +17,7 @@
#include <glib-unix.h>
#define MODEM_UART "/dev/ttyS2"
+#define FULL_BOOT_DELAY 120
struct AtCommand {
char *cmd;
@@ -26,6 +27,20 @@ struct AtCommand {
int retries;
};
+/*
+ * After the EG25 modem sends 'RDY', it takes up to 2 minutes before all
+ * capabilities are operational. If the modem is suspended before that,
+ * calls and texts may be not recognized properly.
+ */
+static gboolean modem_fully_booted(struct EG25Manager *manager)
+{
+ g_message("Modem is up for %d seconds and fully ready", FULL_BOOT_DELAY);
+ manager->boot_timer = 0;
+ boot_inhibit(manager, FALSE);
+
+ return FALSE;
+}
+
static int configure_serial(const char *tty)
{
struct termios ttycfg;
@@ -202,8 +217,10 @@ static gboolean modem_response(gint fd,
g_message("Response: [%s]", response);
- if (strcmp(response, "RDY") == 0)
+ if (strcmp(response, "RDY") == 0) {
+ manager->boot_timer = g_timeout_add_seconds(FULL_BOOT_DELAY, G_SOURCE_FUNC(modem_fully_booted), manager);
manager->modem_state = EG25_STATE_STARTED;
+ }
else if (strstr(response, "ERROR"))
retry_at_command(manager);
else if (strstr(response, "OK"))
diff --git a/src/manager.h b/src/manager.h
index f6351be..d00754d 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -44,7 +44,9 @@ struct EG25Manager {
GDBusProxy *suspend_proxy;
int suspend_inhibit_fd;
+ int boot_inhibit_fd;
guint suspend_timer;
+ guint boot_timer;
GUdevClient *udev;
diff --git a/src/suspend.c b/src/suspend.c
index 4b1a026..93e0c84 100644
--- a/src/suspend.c
+++ b/src/suspend.c
@@ -26,10 +26,10 @@ static gboolean check_modem_resume(struct EG25Manager *manager)
return FALSE;
}
-static gboolean drop_inhibitor(struct EG25Manager *manager)
+static gboolean drop_inhibitor_suspend(struct EG25Manager *manager)
{
if (manager->suspend_inhibit_fd >= 0) {
- g_message("dropping systemd sleep inhibitor");
+ g_message("dropping systemd sleep suspend inhibitor");
close(manager->suspend_inhibit_fd);
manager->suspend_inhibit_fd = -1;
return TRUE;
@@ -37,7 +37,18 @@ static gboolean drop_inhibitor(struct EG25Manager *manager)
return FALSE;
}
-static void inhibit_done(GObject *source,
+static gboolean drop_inhibitor_boot(struct EG25Manager *manager)
+{
+ if (manager->boot_inhibit_fd >= 0) {
+ g_message("dropping systemd sleep boot inhibitor");
+ close(manager->boot_inhibit_fd);
+ manager->boot_inhibit_fd = -1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void inhibit_done_suspend(GObject *source,
GAsyncResult *result,
gpointer user_data)
{
@@ -56,25 +67,65 @@ static void inhibit_done(GObject *source,
manager->suspend_inhibit_fd = g_unix_fd_list_get(fd_list, 0, NULL);
- g_message("inhibitor fd is %d", manager->suspend_inhibit_fd);
+ g_message("inhibitor sleep fd is %d", manager->suspend_inhibit_fd);
g_object_unref(fd_list);
g_variant_unref(res);
}
}
-static void take_inhibitor(struct EG25Manager *manager)
+static void inhibit_done_boot(GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GDBusProxy *suspend_proxy = G_DBUS_PROXY(source);
+ struct EG25Manager *manager = user_data;
+ g_autoptr (GError) error = NULL;
+ GVariant *res;
+ GUnixFDList *fd_list;
+
+ res = g_dbus_proxy_call_with_unix_fd_list_finish(suspend_proxy, &fd_list, result, &error);
+ if (!res) {
+ g_warning("inhibit failed: %s", error->message);
+ } else {
+ if (!fd_list || g_unix_fd_list_get_length(fd_list) != 1)
+ g_warning("didn't get a single fd back");
+
+ manager->boot_inhibit_fd = g_unix_fd_list_get(fd_list, 0, NULL);
+
+ g_message("inhibitor boot fd is %d", manager->boot_inhibit_fd);
+ g_object_unref(fd_list);
+ g_variant_unref(res);
+ }
+}
+
+static void take_inhibitor_suspend(struct EG25Manager *manager)
{
GVariant *variant_arg;
if(manager->suspend_inhibit_fd != -1)
- drop_inhibitor(manager);
+ drop_inhibitor_suspend(manager);
variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager",
"eg25manager needs to prepare modem for sleep", "delay");
- g_message("taking systemd sleep inhibitor");
+ g_message("taking systemd sleep suspend inhibitor");
g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", variant_arg,
- 0, G_MAXINT, NULL, NULL, inhibit_done, manager);
+ 0, G_MAXINT, NULL, NULL, inhibit_done_suspend, manager);
+}
+
+static void take_inhibitor_boot(struct EG25Manager *manager)
+{
+ GVariant *variant_arg;
+
+ if(manager->boot_inhibit_fd != -1)
+ drop_inhibitor_boot(manager);
+
+ variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager",
+ "eg25manager needs to wait for modem to be fully booted", "block");
+
+ g_message("taking systemd sleep boot inhibitor");
+ g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", variant_arg,
+ 0, G_MAXINT, NULL, NULL, inhibit_done_boot, manager);
}
static void signal_cb(GDBusProxy *proxy,
@@ -97,7 +148,7 @@ static void signal_cb(GDBusProxy *proxy,
modem_suspend_pre(manager);
} else {
g_message("system is resuming");
- take_inhibitor(manager);
+ take_inhibitor_suspend(manager);
modem_resume_pre(manager);
if (manager->mm_modem) {
/*
@@ -126,10 +177,10 @@ static void name_owner_cb(GObject *object,
owner = g_dbus_proxy_get_name_owner(proxy);
if (owner) {
- take_inhibitor(manager);
+ take_inhibitor_suspend(manager);
g_free(owner);
} else {
- drop_inhibitor(manager);
+ drop_inhibitor_suspend(manager);
}
}
@@ -151,7 +202,8 @@ static void on_proxy_acquired(GObject *object,
owner = g_dbus_proxy_get_name_owner(manager->suspend_proxy);
if (owner) {
- take_inhibitor(manager);
+ take_inhibitor_suspend(manager);
+ take_inhibitor_boot(manager);
g_free(owner);
}
}
@@ -167,11 +219,16 @@ void suspend_init(struct EG25Manager *manager)
void suspend_destroy(struct EG25Manager *manager)
{
- drop_inhibitor(manager);
+ drop_inhibitor_suspend(manager);
if (manager->suspend_timer) {
g_source_remove(manager->suspend_timer);
manager->suspend_timer = 0;
}
+ drop_inhibitor_boot(manager);
+ if (manager->boot_timer) {
+ g_source_remove(manager->boot_timer);
+ manager->boot_timer = 0;
+ }
if (manager->suspend_proxy) {
g_object_unref(manager->suspend_proxy);
manager->suspend_proxy = NULL;
@@ -181,7 +238,15 @@ void suspend_destroy(struct EG25Manager *manager)
void suspend_inhibit(struct EG25Manager *manager, gboolean inhibit)
{
if (inhibit)
- take_inhibitor(manager);
+ take_inhibitor_suspend(manager);
+ else
+ drop_inhibitor_suspend(manager);
+}
+
+void boot_inhibit(struct EG25Manager *manager, gboolean inhibit)
+{
+ if (inhibit)
+ take_inhibitor_boot(manager);
else
- drop_inhibitor(manager);
+ drop_inhibitor_boot(manager);
}
diff --git a/src/suspend.h b/src/suspend.h
index 39832aa..38e591c 100644
--- a/src/suspend.h
+++ b/src/suspend.h
@@ -12,3 +12,4 @@ void suspend_init (struct EG25Manager *data);
void suspend_destroy (struct EG25Manager *data);
void suspend_inhibit (struct EG25Manager *data, gboolean inhibit);
+void boot_inhibit (struct EG25Manager *data, gboolean inhibit);
--
2.30.1

View File

@ -0,0 +1,434 @@
From 482cfce46e1f8ec546499b782c2c2d96e6a9203e Mon Sep 17 00:00:00 2001
From: Stephan Gerhold <stephan@gerhold.net>
Date: Sat, 21 Dec 2019 18:30:13 +0100
Subject: [PATCH] core: Add support for Qualcomm MSM/QMI modems via rpmsg
Most older Qualcomm SoCs (e.g. MSM8916, MSM8974, ...) communicate with
the integrated modem via shared memory (SMD channels). This is similar
to QRTR on newer SoCs, but without the "network" layer. In fact, the older
SoCs also have QRTR, but the modem QMI services are not exposed there.
The mainline Linux kernel exposes SMD channels via the "remote processor
messaging bus" (rpmsg). Through special IOCTL calls it is possible to
create a char device for a rpmsg/SMD channel. We can then use these to
send QMI/AT messages to the modem, much like the ordinary serial char
devices when using a Qualcomm modem through USB.
The QMI/AT messages needed to use the modem seem to be pretty much
the same as when using QMI via USB. We have tested on a few smartphones
with MSM8916 which are running a (close-to) mainline kernel, e.g.:
- BQ Aquaris X5
- Motorola Moto G4 Play
- Samsung Galaxy A3/A5 (2015)
- Wileyfox Swift
- Xiaomi Redmi 2
Most of the modem functionality seems to be working fine, without any
changes to the QMI/AT messages that are sent to the modem:
- Voice calls
- SMS
- Mobile Internet
- GPS (modem sends NMEA messages, so far we were unable to get a fix
for some reason...)
However, note that the implementation of voice call audio and network
interface is very different from the USB modems. It is completely
independent of the rpmsg channels that are used to control the modem.
I have written special drivers for:
- Voice call audio (q6voice) [1]
- Network interface (BAM DMUX) [2]
(Note: Newer SoCs use IPA (IP Accelerator) instead of BAM DMUX...)
I have plans to upstream these, but there is still some more work
needed (mostly fine tuning for some edge cases). This is independent of the
changes in ModemManager, because the additional drivers are only necessary
if you want to have audio/Internet actually working.
This commit adds support for probing rpmsg ports within ModemManager.
I think most of the changes are quite straightforward, but there are
some FIXME comments scattered over the code where I was not sure about
the best way to implement it. Those still need to be discussed :)
Note: This commit does not add the udev rules necessary to use rpmsg
modems with ModemManager. The reason for that is that you typically need
additional system services/tools and udev rules anyway for the modem to work.
Currently I'm using:
SYMLINK=="modem", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PORT_TYPE_QCDM}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
SYMLINK=="modem-at", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
ENV{INTERFACE}=="rmnet0", SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
The purpose of `ENV{ID_MM_PHYSDEV_UID}` is to link the network interface
to the modem in ModemManager, since it isn't related to the rpmsg ports
in any way. Of course this is rather naive because there could be also
other network interfaces called `rmnet0`...
Also, the udev rules assume that we already have set up the rpmsg
char devices at /dev/modem (SMD channel `DATA5_CNTL`) and /dev/modem-at
(SMD channel `DATA4`). Those can be set up using rpmsgexport [3].
In postmarketOS [4], this is handled using additional udev rules, see [5].
[1]: https://github.com/msm8916-mainline/linux/commits/q6voice
[2]: https://github.com/msm8916-mainline/linux/commits/bam-dmux
[3]: https://github.com/andersson/rpmsgexport
[4]: https://postmarketos.org
[5]: https://gitlab.com/postmarketOS/pmaports/-/blob/master/modem/msm-modem/udev-rpmsg.rules
---
plugins/generic/mm-plugin-generic.c | 2 +-
src/mm-base-manager.c | 12 +++++--
src/mm-base-modem.c | 55 ++++++++++++++++++++++++-----
src/mm-broadband-modem-qmi.c | 12 ++++++-
src/mm-plugin.c | 19 ++++++++++
src/mm-port-probe.c | 24 ++++++++++---
src/mm-port-qmi.c | 7 ++--
src/mm-port-qmi.h | 2 +-
src/mm-port-serial-at.c | 3 +-
src/mm-port.h | 3 +-
10 files changed, 118 insertions(+), 21 deletions(-)
diff --git a/plugins/generic/mm-plugin-generic.c b/plugins/generic/mm-plugin-generic.c
index c2e3a07e..db4e3462 100644
--- a/plugins/generic/mm-plugin-generic.c
+++ b/plugins/generic/mm-plugin-generic.c
@@ -91,7 +91,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
- static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
+ static const gchar *subsystems[] = { "tty", "net", "usb", "rpmsg", NULL };
return MM_PLUGIN (
g_object_new (MM_TYPE_PLUGIN_GENERIC,
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index 653adb5c..da2a3294 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -467,7 +467,8 @@ handle_uevent (GUdevClient *client,
/* A bit paranoid */
subsys = g_udev_device_get_subsystem (device);
g_return_if_fail (subsys != NULL);
- g_return_if_fail (g_str_equal (subsys, "tty") || g_str_equal (subsys, "net") || g_str_has_prefix (subsys, "usb"));
+ g_return_if_fail (g_str_equal (subsys, "tty") || g_str_equal (subsys, "net") ||
+ g_str_has_prefix (subsys, "usb") || g_str_equal (subsys, "rpmsg"));
kernel_device = mm_kernel_device_udev_new (device);
@@ -561,6 +562,13 @@ process_scan (MMBaseManager *self,
g_object_unref (G_OBJECT (iter->data));
}
g_list_free (devices);
+
+ devices = g_udev_client_query_by_subsystem (self->priv->udev, "rpmsg");
+ for (iter = devices; iter; iter = g_list_next (iter)) {
+ start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan);
+ g_object_unref (G_OBJECT (iter->data));
+ }
+ g_list_free (devices);
}
#endif
@@ -1448,7 +1456,7 @@ mm_base_manager_init (MMBaseManager *self)
#if defined WITH_UDEV
{
- const gchar *subsys[5] = { "tty", "net", "usb", "usbmisc", NULL };
+ const gchar *subsys[] = { "tty", "net", "usb", "usbmisc", "rpmsg", NULL };
/* Setup UDev client */
self->priv->udev = g_udev_client_new (subsys);
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index 0805cedb..e4aef11a 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -175,6 +175,7 @@ mm_base_modem_grab_port (MMBaseModem *self,
if (!g_str_equal (subsys, "net") &&
!g_str_equal (subsys, "tty") &&
!(g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm")) &&
+ !g_str_equal (subsys, "rpmsg") &&
!g_str_equal (subsys, "virtual")) {
g_set_error (error,
MM_CORE_ERROR,
@@ -297,7 +298,7 @@ mm_base_modem_grab_port (MMBaseModem *self,
g_str_has_prefix (name, "cdc-wdm")) {
#if defined WITH_QMI
if (ptype == MM_PORT_TYPE_QMI)
- port = MM_PORT (mm_port_qmi_new (name));
+ port = MM_PORT (mm_port_qmi_new (name, MM_PORT_SUBSYS_USB));
#endif
#if defined WITH_MBIM
if (!port && ptype == MM_PORT_TYPE_MBIM)
@@ -340,6 +341,36 @@ mm_base_modem_grab_port (MMBaseModem *self,
/* Store flags already */
mm_port_serial_at_set_flags (MM_PORT_SERIAL_AT (port), at_pflags);
}
+ /* rpmsg ports... */
+ else if (g_str_equal (subsys, "rpmsg")) {
+#if defined WITH_QMI
+ if (ptype == MM_PORT_TYPE_QMI)
+ port = MM_PORT (mm_port_qmi_new (name, MM_PORT_SUBSYS_RPMSG));
+#endif
+ /* Non-serial AT port */
+ if (!port && ptype == MM_PORT_TYPE_AT) {
+ port = MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_RPMSG));
+
+ /* Set common response parser */
+ mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (port),
+ mm_serial_parser_v1_parse,
+ mm_serial_parser_v1_new (),
+ mm_serial_parser_v1_destroy);
+ /* Store flags already */
+ mm_port_serial_at_set_flags (MM_PORT_SERIAL_AT (port), at_pflags);
+ }
+
+ if (!port) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot add port '%s/%s', unsupported",
+ subsys,
+ name);
+ g_free (key);
+ return FALSE;
+ }
+ }
else
/* We already filter out before all non-tty, non-net, non-cdc-wdm ports */
g_assert_not_reached ();
@@ -711,7 +742,17 @@ mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self,
{
GList *cdc_wdm_qmi_ports, *l;
const gchar *net_port_parent_path;
- MMPortQmi *found = NULL;
+ MMPortQmi *found = NULL, *primary;
+
+ /* FIXME: For RPMSG modems the network interface is not related to the
+ * QMI device, they are managed through completely different subsystems.
+ * For now there should be just one QMI and one net port so we can just
+ * return the primary QMI port.
+ */
+ primary = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self));
+ if (primary && mm_port_get_subsys (MM_PORT (primary)) == MM_PORT_SUBSYS_RPMSG)
+ /* Assume there is just one QMI port */
+ return primary;
g_warn_if_fail (mm_port_get_subsys (data) == MM_PORT_SUBSYS_NET);
net_port_parent_path = mm_kernel_device_get_interface_sysfs_path (mm_port_peek_kernel_device (data));
@@ -1239,13 +1280,11 @@ mm_base_modem_organize_ports (MMBaseModem *self,
secondary = backup_primary ? backup_primary : backup_secondary;
#if defined WITH_QMI
- /* On QMI-based modems, we need to have at least a net port */
+ /* On QMI-based modems, a net port is required for broadband.
+ * However, all other functionality works without so just warn about this.
+ */
if (qmi_primary && !data_primary) {
- g_set_error_literal (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Failed to find a net port in the QMI modem");
- return FALSE;
+ mm_obj_warn (self, "Failed to find a net port in the QMI modem");
}
#endif
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 83e808c2..e641c401 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -9457,7 +9457,17 @@ initialization_started (MMBroadbandModem *self,
/* Now open our QMI port */
mm_port_qmi_open (ctx->qmi,
- TRUE,
+ /* FIXME: Parts of the "data format" functionality on libqmi
+ * assume that we are talking to qmi_wwan, which exposes the
+ * kernel data format through sysfs.
+ *
+ * For RPMSG modems the driver that manages the net port
+ * is a different one, and setting the kernel data format
+ * therefore eventually works differently there.
+ * For now skip setting the data format entirely for RPMSG
+ * to avoid a Segmentation Fault.
+ */
+ mm_port_get_subsys (MM_PORT (ctx->qmi)) != MM_PORT_SUBSYS_RPMSG,
NULL,
(GAsyncReadyCallback)qmi_port_open_ready,
task);
diff --git a/src/mm-plugin.c b/src/mm-plugin.c
index 77bd6528..f6bee411 100644
--- a/src/mm-plugin.c
+++ b/src/mm-plugin.c
@@ -773,6 +773,12 @@ mm_plugin_supports_port (MMPlugin *self,
/* Build flags depending on what probing needed */
probe_run_flags = MM_PORT_PROBE_NONE;
+ if (g_str_equal (mm_kernel_device_get_subsystem (port), "rpmsg")) {
+ if (self->priv->at)
+ probe_run_flags |= MM_PORT_PROBE_AT;
+ if (self->priv->qmi)
+ probe_run_flags |= MM_PORT_PROBE_QMI;
+ } else
if (!g_str_has_prefix (mm_kernel_device_get_name (port), "cdc-wdm")) {
/* Serial ports... */
if (self->priv->at)
@@ -958,6 +964,18 @@ mm_plugin_create_modem (MMPlugin *self,
}
#if defined WITH_QMI
+/* FIXME: For RPMSG modems the network interface usually won't be managed
+ * by the USB qmi_wwan driver so the check below prevents them from getting
+ * registered in ModemManager.
+ *
+ * I guess it should be just skipped in the RPMSG case. However, to detect that
+ * it seems like we would need to iterate another time over "port_probes"
+ * to see if the QMI port is provided by the RPMSG subsystem.
+ *
+ * I'm not sure if there is a simple way to detect this situation only based
+ * on the network device itself (which has nothing to do with RPMSG).
+ */
+#if 0
if (MM_IS_BROADBAND_MODEM_QMI (modem) &&
port_type == MM_PORT_TYPE_NET &&
g_strcmp0 (driver, "qmi_wwan") != 0) {
@@ -966,6 +984,7 @@ mm_plugin_create_modem (MMPlugin *self,
force_ignored = TRUE;
goto grab_port;
}
+#endif
if (!MM_IS_BROADBAND_MODEM_QMI (modem) &&
port_type == MM_PORT_TYPE_NET &&
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index 0c1edef1..b062f236 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -484,6 +484,9 @@ static void
wdm_probe_qmi (MMPortProbe *self)
{
PortProbeRunContext *ctx;
+#if defined WITH_QMI
+ MMPortSubsys subsys = MM_PORT_SUBSYS_USB;
+#endif
g_assert (self->priv->task);
ctx = g_task_get_task_data (self->priv->task);
@@ -491,8 +494,11 @@ wdm_probe_qmi (MMPortProbe *self)
#if defined WITH_QMI
mm_obj_dbg (self, "probing QMI...");
+ if (g_str_equal (mm_kernel_device_get_subsystem (self->priv->port), "rpmsg"))
+ subsys = MM_PORT_SUBSYS_RPMSG;
+
/* Create a port and try to open it */
- ctx->port_qmi = mm_port_qmi_new (mm_kernel_device_get_name (self->priv->port));
+ ctx->port_qmi = mm_port_qmi_new (mm_kernel_device_get_name (self->priv->port), subsys);
mm_port_qmi_open (ctx->port_qmi,
FALSE,
NULL,
@@ -1269,6 +1275,8 @@ serial_open_at (MMPortProbe *self)
if (g_str_has_prefix (mm_kernel_device_get_subsystem (self->priv->port), "usb"))
subsys = MM_PORT_SUBSYS_USB;
+ if (g_str_equal (mm_kernel_device_get_subsystem (self->priv->port), "rpmsg"))
+ subsys = MM_PORT_SUBSYS_RPMSG;
ctx->serial = MM_PORT_SERIAL (mm_port_serial_at_new (mm_kernel_device_get_name (self->priv->port), subsys));
if (!ctx->serial) {
@@ -1570,9 +1578,10 @@ mm_port_probe_is_qmi (MMPortProbe *self)
subsys = mm_kernel_device_get_subsystem (self->priv->port);
name = mm_kernel_device_get_name (self->priv->port);
- if (!g_str_has_prefix (subsys, "usb") ||
- !name ||
- !g_str_has_prefix (name, "cdc-wdm"))
+ if ((!g_str_has_prefix (subsys, "usb") ||
+ !name ||
+ !g_str_has_prefix (name, "cdc-wdm")) &&
+ !g_str_equal (subsys, "rpmsg"))
return FALSE;
return self->priv->is_qmi;
@@ -1656,6 +1665,13 @@ mm_port_probe_get_port_type (MMPortProbe *self)
}
}
+ if (g_str_equal (subsys, "rpmsg")) {
+#if defined WITH_QMI
+ if (self->priv->is_qmi)
+ return MM_PORT_TYPE_QMI;
+#endif
+ }
+
if (self->priv->flags & MM_PORT_PROBE_QCDM &&
self->priv->is_qcdm)
return MM_PORT_TYPE_QCDM;
diff --git a/src/mm-port-qmi.c b/src/mm-port-qmi.c
index 83d92b9d..0c4a4a98 100644
--- a/src/mm-port-qmi.c
+++ b/src/mm-port-qmi.c
@@ -788,11 +788,14 @@ mm_port_qmi_close (MMPortQmi *self,
/*****************************************************************************/
MMPortQmi *
-mm_port_qmi_new (const gchar *name)
+mm_port_qmi_new (const gchar *name, MMPortSubsys subsys)
{
+ g_return_val_if_fail (subsys == MM_PORT_SUBSYS_USB ||
+ subsys == MM_PORT_SUBSYS_RPMSG, NULL);
+
return MM_PORT_QMI (g_object_new (MM_TYPE_PORT_QMI,
MM_PORT_DEVICE, name,
- MM_PORT_SUBSYS, MM_PORT_SUBSYS_USB,
+ MM_PORT_SUBSYS, subsys,
MM_PORT_TYPE, MM_PORT_TYPE_QMI,
NULL));
}
diff --git a/src/mm-port-qmi.h b/src/mm-port-qmi.h
index b4e8460c..6a5c298a 100644
--- a/src/mm-port-qmi.h
+++ b/src/mm-port-qmi.h
@@ -46,7 +46,7 @@ struct _MMPortQmiClass {
GType mm_port_qmi_get_type (void);
-MMPortQmi *mm_port_qmi_new (const gchar *name);
+MMPortQmi *mm_port_qmi_new (const gchar *name, MMPortSubsys subsys);
void mm_port_qmi_open (MMPortQmi *self,
gboolean set_data_format,
diff --git a/src/mm-port-serial-at.c b/src/mm-port-serial-at.c
index c8e4782f..11a086ed 100644
--- a/src/mm-port-serial-at.c
+++ b/src/mm-port-serial-at.c
@@ -532,7 +532,8 @@ mm_port_serial_at_new (const char *name,
{
g_return_val_if_fail (subsys == MM_PORT_SUBSYS_TTY ||
subsys == MM_PORT_SUBSYS_USB ||
- subsys == MM_PORT_SUBSYS_UNIX, NULL);
+ subsys == MM_PORT_SUBSYS_UNIX ||
+ subsys == MM_PORT_SUBSYS_RPMSG, NULL);
return MM_PORT_SERIAL_AT (g_object_new (MM_TYPE_PORT_SERIAL_AT,
MM_PORT_DEVICE, name,
diff --git a/src/mm-port.h b/src/mm-port.h
index 33b07d97..861a086b 100644
--- a/src/mm-port.h
+++ b/src/mm-port.h
@@ -28,8 +28,9 @@ typedef enum { /*< underscore_name=mm_port_subsys >*/
MM_PORT_SUBSYS_NET,
MM_PORT_SUBSYS_USB,
MM_PORT_SUBSYS_UNIX,
+ MM_PORT_SUBSYS_RPMSG,
- MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_UNIX /*< skip >*/
+ MM_PORT_SUBSYS_LAST = MM_PORT_SUBSYS_RPMSG /*< skip >*/
} MMPortSubsys;
typedef enum { /*< underscore_name=mm_port_type >*/
--
2.28.0

View File

@ -0,0 +1,140 @@
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
VALA_USE_DEPEND="vapigen"
inherit gnome2 readme.gentoo-r1 systemd toolchain-funcs udev vala
DESCRIPTION="Modem and mobile broadband management libraries"
HOMEPAGE="https://www.freedesktop.org/wiki/Software/ModemManager/"
SRC_URI="https://www.freedesktop.org/software/ModemManager/ModemManager-${PV}.tar.xz"
LICENSE="GPL-2+"
SLOT="0/1" # subslot = dbus interface version, i.e. N in org.freedesktop.ModemManager${N}
KEYWORDS="~arm64"
IUSE="elogind +introspection mbim policykit +qmi systemd +udev vala"
REQUIRED_USE="
?? ( elogind systemd )
vala? ( introspection )
"
DEPEND="
>=dev-libs/glib-2.48.0:2
udev? ( >=dev-libs/libgudev-230:= )
introspection? ( >=dev-libs/gobject-introspection-0.9.6:= )
mbim? ( >=net-libs/libmbim-1.24.0 )
policykit? ( >=sys-auth/polkit-0.106[introspection] )
qmi? ( >=net-libs/libqmi-1.26.0:= )
elogind? ( sys-auth/elogind )
systemd? ( >=sys-apps/systemd-209 )
"
RDEPEND="${DEPEND}
policykit? ( acct-group/plugdev )
"
BDEPEND="
dev-util/gdbus-codegen
dev-util/glib-utils
>=dev-util/gtk-doc-am-1
>=sys-devel/gettext-0.19.8
virtual/pkgconfig
vala? ( $(vala_depend) )
"
PATCHES="
${FILESDIR}/0001-mm-broadband-modem-improve-voice-capabilities-detect.patch
${FILESDIR}/0002-serial-parsers-do-not-fail-to-detect-a-valid-respons.patch
${FILESDIR}/0003-context-add-test-no-suspend-resume-cli-parameter.patch
${FILESDIR}/0004-broadband-modem-qmi_Enable_AT_URCs_and_QMI_indications.patch
${FILESDIR}/temp_modemmanager_rpmsg.patch
"
S="${WORKDIR}/ModemManager-${PV}"
src_prepare() {
DOC_CONTENTS="
If your USB modem shows up only as a storage device when you plug it in,
then you should install sys-apps/usb_modeswitch, which will automatically
switch it over to USB modem mode whenever you plug it in.\n"
if use policykit; then
DOC_CONTENTS+="\nTo control your modem without needing to enter the root password,
add your user account to the 'plugdev' group."
fi
use vala && vala_src_prepare
gnome2_src_prepare
}
src_configure() {
local myconf=(
--disable-Werror
--disable-static
--with-dist-version=${PVR}
--with-udev-base-dir="$(get_udevdir)"
$(use_with udev)
$(use_enable introspection)
$(use_with mbim)
$(use_with policykit polkit)
$(use_with systemd systemd-suspend-resume)
$(use_with systemd systemd-journal)
$(use_with qmi)
$(use_enable vala)
)
if use elogind; then
local pkgconfig="$(tc-getPKG_CONFIG)"
myconf+=(
--with-systemd-suspend-resume
LIBSYSTEMD_LOGIN_CFLAGS="$(${pkgconfig} --cflags "libelogind")"
LIBSYSTEMD_LOGIN_LIBS="$(${pkgconfig} --libs "libelogind")"
)
fi
gnome2_src_configure "${myconf[@]}"
}
src_install() {
gnome2_src_install
# Allow users in plugdev group full control over their modem
if use policykit; then
insinto /usr/share/polkit-1/rules.d/
doins "${FILESDIR}"/01-org.freedesktop.ModemManager1.rules
insinto /usr/lib/udev/rules.d/
newins "${FILESDIR}"/rpmsg-udev.rules 80-modemmanager-mjr.rules
fi
# Disable suspend/resume hooks for the EG25-G modem in the PinePhone
sed -i -e 's|bin/ModemManager|bin/ModemManager --test-no-suspend-resume|g' \ "${D}/lib/systemd/system/ModemManager.service"
readme.gentoo_create_doc
}
pkg_postinst() {
gnome2_pkg_postinst
# The polkit rules file moved to /usr/share
old_rules="${EROOT}/etc/polkit-1/rules.d/01-org.freedesktop.ModemManager.rules"
if [[ -f "${old_rules}" ]]; then
case "$(md5sum ${old_rules})" in
c5ff02532cb1da2c7545c3069e5d0992* | 5c50f0dc603c0a56e2851a5ce9389335* )
# Automatically delete the old rules.d file if the user did not change it
elog
elog "Removing old ${old_rules} ..."
rm -f "${old_rules}" || eerror "Failed, please remove ${old_rules} manually"
;;
* )
elog "The ${old_rules}"
elog "file moved to /usr/share/polkit-1/rules.d/ in >=modemmanager-0.5.2.0-r2"
elog "If you edited ${old_rules}"
elog "without changing its behavior, you may want to remove it."
;;
esac
fi
if ! use udev; then
ewarn "You have built ModemManager without udev support. You may have to teach it"
ewarn "about your modem port manually."
fi
systemd_reenable ModemManager.service
readme.gentoo_print_elog
}