diff --git a/net-misc/modemmanager/Manifest b/net-misc/modemmanager/Manifest new file mode 100644 index 0000000..49e184e --- /dev/null +++ b/net-misc/modemmanager/Manifest @@ -0,0 +1 @@ +DIST ModemManager-1.16.2.tar.xz 2447936 BLAKE2B aafd2bde9fe72ec837a34987a698d82f4ba2aedf778c350263f8fe937ccd4b5b9b78fc66c58a39a8729c371788ab7b7782073726dc132b8f08bd2df0a9bc2da4 SHA512 c0b095972eba6e0f3a1ad22e425b412f17d8b60f0af4d423a92fdebcb6d2801f87e6af98758f8c2dc4db3586a3a15530a318805fda312443fa6abe2265ebd6b6 diff --git a/net-misc/modemmanager/files/0001-mm-broadband-modem-improve-voice-capabilities-detect.patch b/net-misc/modemmanager/files/0001-mm-broadband-modem-improve-voice-capabilities-detect.patch new file mode 100644 index 0000000..121c709 --- /dev/null +++ b/net-misc/modemmanager/files/0001-mm-broadband-modem-improve-voice-capabilities-detect.patch @@ -0,0 +1,25 @@ +From 2091ac5f75a6e025be896c21179b04bc53ce4bb0 Mon Sep 17 00:00:00 2001 +From: Arnaud Ferraris +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 + diff --git a/net-misc/modemmanager/files/0002-serial-parsers-do-not-fail-to-detect-a-valid-respons.patch b/net-misc/modemmanager/files/0002-serial-parsers-do-not-fail-to-detect-a-valid-respons.patch new file mode 100644 index 0000000..82c41f9 --- /dev/null +++ b/net-misc/modemmanager/files/0002-serial-parsers-do-not-fail-to-detect-a-valid-respons.patch @@ -0,0 +1,28 @@ +From 9a4e5a7c2da36288cd66c1500dcd0e1ba844c9cc Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +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 + diff --git a/net-misc/modemmanager/files/0003-context-add-test-no-suspend-resume-cli-parameter.patch b/net-misc/modemmanager/files/0003-context-add-test-no-suspend-resume-cli-parameter.patch new file mode 100644 index 0000000..59d79b2 --- /dev/null +++ b/net-misc/modemmanager/files/0003-context-add-test-no-suspend-resume-cli-parameter.patch @@ -0,0 +1,100 @@ +From f5ce1ae2282e6164efa6b1f9b973ff61e44a30ff Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +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 + diff --git a/net-misc/modemmanager/files/0004-broadband-modem-qmi_Enable_AT_URCs_and_QMI_indications.patch b/net-misc/modemmanager/files/0004-broadband-modem-qmi_Enable_AT_URCs_and_QMI_indications.patch new file mode 100644 index 0000000..9c67c3b --- /dev/null +++ b/net-misc/modemmanager/files/0004-broadband-modem-qmi_Enable_AT_URCs_and_QMI_indications.patch @@ -0,0 +1,167 @@ +From f83a4b5ed428dbe412b3c9cc779bd85fc8dbe583 Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +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 + diff --git a/net-misc/modemmanager/files/0004-mm-broadband-modem-qmi-Add-ID_MM_QMI_MESSAGING_AT_FA.patch b/net-misc/modemmanager/files/0004-mm-broadband-modem-qmi-Add-ID_MM_QMI_MESSAGING_AT_FA.patch new file mode 100644 index 0000000..94003da --- /dev/null +++ b/net-misc/modemmanager/files/0004-mm-broadband-modem-qmi-Add-ID_MM_QMI_MESSAGING_AT_FA.patch @@ -0,0 +1,109 @@ +From deccf35a68063ddae4a51a9ec99124fce998cf4b Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +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 diff --git a/net-misc/modemmanager/files/01-org.freedesktop.ModemManager1.rules b/net-misc/modemmanager/files/01-org.freedesktop.ModemManager1.rules new file mode 100644 index 0000000..7fca647 --- /dev/null +++ b/net-misc/modemmanager/files/01-org.freedesktop.ModemManager1.rules @@ -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"; + } +}); diff --git a/net-misc/modemmanager/files/modemmanager-pp.rules b/net-misc/modemmanager/files/modemmanager-pp.rules new file mode 100644 index 0000000..6b4a95f --- /dev/null +++ b/net-misc/modemmanager/files/modemmanager-pp.rules @@ -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"; + } +}); + diff --git a/net-misc/modemmanager/files/rpmsg-udev.rules b/net-misc/modemmanager/files/rpmsg-udev.rules new file mode 100644 index 0000000..e073ff0 --- /dev/null +++ b/net-misc/modemmanager/files/rpmsg-udev.rules @@ -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" diff --git a/net-misc/modemmanager/files/temp_eg25-manager_0001-suspend-add-boot-timer.patch b/net-misc/modemmanager/files/temp_eg25-manager_0001-suspend-add-boot-timer.patch new file mode 100644 index 0000000..f6b98a0 --- /dev/null +++ b/net-misc/modemmanager/files/temp_eg25-manager_0001-suspend-add-boot-timer.patch @@ -0,0 +1,264 @@ +From 6fad8948a7ba16c857b813ec532f32906055c695 Mon Sep 17 00:00:00 2001 +From: Dylan Van Assche +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 + + #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 + diff --git a/net-misc/modemmanager/files/temp_modemmanager_rpmsg.patch b/net-misc/modemmanager/files/temp_modemmanager_rpmsg.patch new file mode 100644 index 0000000..2a7d87c --- /dev/null +++ b/net-misc/modemmanager/files/temp_modemmanager_rpmsg.patch @@ -0,0 +1,434 @@ +From 482cfce46e1f8ec546499b782c2c2d96e6a9203e Mon Sep 17 00:00:00 2001 +From: Stephan Gerhold +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 + diff --git a/net-misc/modemmanager/modemmanager-1.16.2.ebuild b/net-misc/modemmanager/modemmanager-1.16.2.ebuild new file mode 100644 index 0000000..a3c3dce --- /dev/null +++ b/net-misc/modemmanager/modemmanager-1.16.2.ebuild @@ -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 +}