This commit is contained in:
Gerben Jan Dijkman 2021-07-01 11:02:55 +02:00
parent c45e6e27c8
commit 2f7df5e7c7
12 changed files with 3108 additions and 0 deletions

View File

@ -0,0 +1,44 @@
# Copyright 2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
inherit meson git-r3 systemd
DESCRIPTION="Daemon for managing the Quectel EG25 modem"
HOMEPAGE="https://gitlab.com/mobian1/devices/eg25-manager"
KEYWORDS="~arm64"
EGIT_REPO_URI="${HOMEPAGE}.git"
if [[ ${PV} != 9999 ]]; then
EGIT_COMMIT="73e16f76994b1d3c587796a35766cc668e30c0cd"
else
KEYWORDS=""
fi
LICENSE="GPL-3"
SLOT="0"
DEPEND="
dev-libs/libgpiod
virtual/libusb:1
net-misc/modemmanager
"
RDEPEND="${DEPEND}"
PATCHES=(
${FILESDIR}/18.patch
${FILESDIR}/15.patch
)
src_install() {
meson_src_install
systemd_dounit "${FILESDIR}"/eg25-manager.service
}
pkg_postinst() {
systemd_reenable --all eg25-manager
}

View File

@ -0,0 +1,297 @@
From b8d269cf2f5aed4ca0e0bcb9702b65897fda18bc 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 | 4 +-
src/manager.c | 5 +-
src/manager.h | 4 +-
src/suspend.c | 126 +++++++++++++++++++++++++++++++++++++++-----------
src/suspend.h | 2 +-
5 files changed, 108 insertions(+), 33 deletions(-)
diff --git a/src/at.c b/src/at.c
index 39a857a..661098a 100644
--- a/src/at.c
+++ b/src/at.c
@@ -202,8 +202,10 @@ static gboolean modem_response(gint fd,
g_message("Response: [%s]", response);
- if (strcmp(response, "RDY") == 0)
+ if (strcmp(response, "RDY") == 0) {
+ suspend_inhibit(manager, TRUE, TRUE);
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.c b/src/manager.c
index 6445e0f..912a095 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -178,7 +178,7 @@ void modem_suspend_post(struct EG25Manager *manager)
{
gpio_sequence_suspend(manager);
g_message("suspend sequence is over, drop inhibitor");
- suspend_inhibit(manager, FALSE);
+ suspend_inhibit(manager, FALSE, FALSE);
}
void modem_resume_pre(struct EG25Manager *manager)
@@ -205,7 +205,8 @@ int main(int argc, char *argv[])
memset(&manager, 0, sizeof(manager));
manager.at_fd = -1;
- manager.suspend_inhibit_fd = -1;
+ manager.delay_inhibit_fd = -1;
+ manager.block_inhibit_fd = -1;
opt_context = g_option_context_new ("- Power management for the Quectel EG25 modem");
g_option_context_add_main_entries (opt_context, options, NULL);
diff --git a/src/manager.h b/src/manager.h
index f6351be..21b3b67 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -43,8 +43,10 @@ struct EG25Manager {
MMModem *mm_modem;
GDBusProxy *suspend_proxy;
- int suspend_inhibit_fd;
+ int delay_inhibit_fd;
+ int block_inhibit_fd;
guint suspend_timer;
+ guint boot_timer;
GUdevClient *udev;
diff --git a/src/suspend.c b/src/suspend.c
index 4b1a026..622cf00 100644
--- a/src/suspend.c
+++ b/src/suspend.c
@@ -13,9 +13,10 @@
#include <gio/gunixfdlist.h>
-#define SD_NAME "org.freedesktop.login1"
-#define SD_PATH "/org/freedesktop/login1"
-#define SD_INTERFACE "org.freedesktop.login1.Manager"
+#define SD_NAME "org.freedesktop.login1"
+#define SD_PATH "/org/freedesktop/login1"
+#define SD_INTERFACE "org.freedesktop.login1.Manager"
+#define FULL_BOOT_DELAY 120
static gboolean check_modem_resume(struct EG25Manager *manager)
{
@@ -26,18 +27,28 @@ static gboolean check_modem_resume(struct EG25Manager *manager)
return FALSE;
}
-static gboolean drop_inhibitor(struct EG25Manager *manager)
+static gboolean drop_inhibitor(struct EG25Manager *manager, gboolean block)
{
- if (manager->suspend_inhibit_fd >= 0) {
- g_message("dropping systemd sleep inhibitor");
- close(manager->suspend_inhibit_fd);
- manager->suspend_inhibit_fd = -1;
- return TRUE;
+ if (block) {
+ if (manager->block_inhibit_fd >= 0) {
+ g_message("dropping systemd sleep block inhibitor");
+ close(manager->block_inhibit_fd);
+ manager->block_inhibit_fd = -1;
+ return TRUE;
+ }
+ }
+ else {
+ if (manager->delay_inhibit_fd >= 0) {
+ g_message("dropping systemd sleep delay inhibitor");
+ close(manager->delay_inhibit_fd);
+ manager->delay_inhibit_fd = -1;
+ return TRUE;
+ }
}
return FALSE;
}
-static void inhibit_done(GObject *source,
+static void inhibit_done_delay(GObject *source,
GAsyncResult *result,
gpointer user_data)
{
@@ -54,27 +65,81 @@ static void inhibit_done(GObject *source,
if (!fd_list || g_unix_fd_list_get_length(fd_list) != 1)
g_warning("didn't get a single fd back");
- manager->suspend_inhibit_fd = g_unix_fd_list_get(fd_list, 0, NULL);
+ manager->delay_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->delay_inhibit_fd);
g_object_unref(fd_list);
g_variant_unref(res);
}
}
-static void take_inhibitor(struct EG25Manager *manager)
+static void inhibit_done_block(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->block_inhibit_fd = g_unix_fd_list_get(fd_list, 0, NULL);
+
+ g_message("inhibitor block fd is %d", manager->block_inhibit_fd);
+ g_object_unref(fd_list);
+ g_variant_unref(res);
+ }
+}
+
+/*
+ * 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;
+ drop_inhibitor(manager, TRUE);
+
+ return FALSE;
+}
+
+static void take_inhibitor(struct EG25Manager *manager, gboolean block)
{
GVariant *variant_arg;
- if(manager->suspend_inhibit_fd != -1)
- drop_inhibitor(manager);
+ if (block) {
+ if(manager->block_inhibit_fd != -1)
+ drop_inhibitor(manager, TRUE);
- variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager",
- "eg25manager needs to prepare modem for sleep", "delay");
+ variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager",
+ "eg25manager needs to wait for modem to be fully booted", "block");
- g_message("taking systemd sleep inhibitor");
- g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", variant_arg,
- 0, G_MAXINT, NULL, NULL, inhibit_done, manager);
+ g_message("taking systemd sleep block inhibitor");
+ g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", variant_arg,
+ 0, G_MAXINT, NULL, NULL, inhibit_done_block, manager);
+ g_message("scheduling block inhibitor release");
+ manager->boot_timer = g_timeout_add_seconds(FULL_BOOT_DELAY, G_SOURCE_FUNC(modem_fully_booted), manager);
+ }
+ else {
+ if(manager->delay_inhibit_fd != -1)
+ drop_inhibitor(manager, FALSE);
+
+ variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager",
+ "eg25manager needs to prepare modem for sleep", "delay");
+
+ g_message("taking systemd sleep delay inhibitor");
+ g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", variant_arg,
+ 0, G_MAXINT, NULL, NULL, inhibit_done_delay, manager);
+ }
}
static void signal_cb(GDBusProxy *proxy,
@@ -97,7 +162,7 @@ static void signal_cb(GDBusProxy *proxy,
modem_suspend_pre(manager);
} else {
g_message("system is resuming");
- take_inhibitor(manager);
+ take_inhibitor(manager, FALSE);
modem_resume_pre(manager);
if (manager->mm_modem) {
/*
@@ -126,10 +191,10 @@ static void name_owner_cb(GObject *object,
owner = g_dbus_proxy_get_name_owner(proxy);
if (owner) {
- take_inhibitor(manager);
+ take_inhibitor(manager, FALSE);
g_free(owner);
} else {
- drop_inhibitor(manager);
+ drop_inhibitor(manager, FALSE);
}
}
@@ -151,7 +216,7 @@ static void on_proxy_acquired(GObject *object,
owner = g_dbus_proxy_get_name_owner(manager->suspend_proxy);
if (owner) {
- take_inhibitor(manager);
+ take_inhibitor(manager, FALSE);
g_free(owner);
}
}
@@ -167,21 +232,26 @@ void suspend_init(struct EG25Manager *manager)
void suspend_destroy(struct EG25Manager *manager)
{
- drop_inhibitor(manager);
+ drop_inhibitor(manager, FALSE);
+ drop_inhibitor(manager, TRUE);
if (manager->suspend_timer) {
g_source_remove(manager->suspend_timer);
manager->suspend_timer = 0;
}
+ 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;
}
}
-void suspend_inhibit(struct EG25Manager *manager, gboolean inhibit)
+void suspend_inhibit(struct EG25Manager *manager, gboolean inhibit, gboolean block)
{
if (inhibit)
- take_inhibitor(manager);
+ take_inhibitor(manager, block);
else
- drop_inhibitor(manager);
+ drop_inhibitor(manager, block);
}
diff --git a/src/suspend.h b/src/suspend.h
index 39832aa..e82eeff 100644
--- a/src/suspend.h
+++ b/src/suspend.h
@@ -11,4 +11,4 @@
void suspend_init (struct EG25Manager *data);
void suspend_destroy (struct EG25Manager *data);
-void suspend_inhibit (struct EG25Manager *data, gboolean inhibit);
+void suspend_inhibit (struct EG25Manager *data, gboolean inhibit, gboolean block);
--
GitLab

View File

@ -0,0 +1,57 @@
From 04eed2496d2a02bb23b4eae91be0264417fb28c6 Mon Sep 17 00:00:00 2001
From: Biktor <sleepyh@gmail.com>
Date: Wed, 24 Feb 2021 12:32:46 +0100
Subject: [PATCH] Set URC config to 'all' instead of 'usbat' dquote> When using
a custom kernel, if this setting is set to 'usbat' only, no RING urc is
reported on any interface. Changing QURCCFG to 'all' makes the modem report
RINGs on all supported interfaces, making receiving calls possible when using
a custom firmware
---
data/pine64,pinephone-1.0.toml | 2 +-
data/pine64,pinephone-1.1.toml | 2 +-
data/pine64,pinephone-1.2.toml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/data/pine64,pinephone-1.0.toml b/data/pine64,pinephone-1.0.toml
index c0e9192..7287298 100644
--- a/data/pine64,pinephone-1.0.toml
+++ b/data/pine64,pinephone-1.0.toml
@@ -39,7 +39,7 @@ configure = [
{ cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
{ cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
- { cmd = "QURCCFG", subcmd = "urcport", expect = "\"usbat\"" },
+ { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" }
diff --git a/data/pine64,pinephone-1.1.toml b/data/pine64,pinephone-1.1.toml
index c0e9192..7287298 100644
--- a/data/pine64,pinephone-1.1.toml
+++ b/data/pine64,pinephone-1.1.toml
@@ -39,7 +39,7 @@ configure = [
{ cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
{ cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
- { cmd = "QURCCFG", subcmd = "urcport", expect = "\"usbat\"" },
+ { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" }
diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml
index 566ac80..2effb30 100644
--- a/data/pine64,pinephone-1.2.toml
+++ b/data/pine64,pinephone-1.2.toml
@@ -32,7 +32,7 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "apready", expect = "1,0,500" },
- { cmd = "QURCCFG", subcmd = "urcport", expect = "\"usbat\"" },
+ { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" },
{ cmd = "QCFG", subcmd = "urc/cache", value = "0" }
--
GitLab

View File

@ -0,0 +1,49 @@
From d40bb283101fd9cf702e4944865aebef52c34185 Mon Sep 17 00:00:00 2001
From: Djhg2000 <github@djhg2000.net>
Date: Thu, 4 Mar 2021 20:08:12 +0100
Subject: [PATCH] Add a 60ms delay before PWRKEY sequence
This brings the power on sequence in line with the EG25-G Hardware Design
datasheet, which states we need to wait at least 30 ms after VBAT becomes stable
before pulling PWRKEY low (first action of the power on sequene).
After this change the sequence becomes as follows:
- Set RESET_N high
- Wait 60 ms (double 30 ms)
- Execute PWRKEY sequence
60 ms was choosen because we don't know when VBAT becomes stable, but it should
be much less than an additional 30 ms. Empirical evidence suggests PinePhone
units with a healthy battery do not see serious side effects from not doing
this, while the modem will fail to boot and/or throw random errors on boot with
a worn out battery.
---
src/manager.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/manager.c b/src/manager.c
index aaa3905..a992572 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -27,6 +27,9 @@
#define EG25_DATADIR "/usr/share/eg25-manager"
#endif
+// Delay between setting GPIO and PWRKEY sequence (60ms)
+#define MODEM_POWERON_DELAY 60000
+
static gboolean quit_app(struct EG25Manager *manager)
{
int i;
@@ -86,6 +89,8 @@ static gboolean modem_start(struct EG25Manager *manager)
if (should_boot) {
g_message("Starting modem...");
+ // Modem might crash on boot (especially with worn battery) if we don't delay here
+ usleep(MODEM_POWERON_DELAY);
gpio_sequence_poweron(manager);
manager->modem_state = EG25_STATE_POWERED;
} else {
--
GitLab

View File

@ -0,0 +1,65 @@
From 84a0ae603df95311a5d5cae9ca04b69fd6784827 Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bhush94@gmail.com>
Date: Fri, 26 Mar 2021 13:56:37 +0530
Subject: [PATCH] udev: use the udev rules directly to set attr
We don't need complicated script for this, we can just set required
attributes using udev rules.
---
udev/80-modem-eg25.rules | 6 +++++-
udev/eg25-configure-usb | 21 ---------------------
udev/meson.build | 1 -
3 files changed, 5 insertions(+), 23 deletions(-)
delete mode 100755 udev/eg25-configure-usb
diff --git a/udev/80-modem-eg25.rules b/udev/80-modem-eg25.rules
index 0ea9e6f..fc3b78f 100644
--- a/udev/80-modem-eg25.rules
+++ b/udev/80-modem-eg25.rules
@@ -1 +1,5 @@
-ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ENV{MINOR}=="0", RUN+="/usr/bin/eg25-configure-usb %p"
+ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/control}="auto"
+ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/autosuspend_delay_ms}="3000"
+ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/wakeup}="enabled"
+ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{avoid_reset_quirk}="1"
+ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/persist}="0"
diff --git a/udev/eg25-configure-usb b/udev/eg25-configure-usb
deleted file mode 100755
index 9972af7..0000000
--- a/udev/eg25-configure-usb
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-DEVPATH=/sys/$1
-USB_ID=
-
-[ -d ${DEVPATH} ] || exit 1
-
-while [ ! "${USB_ID}" ]; do
- if [ -f ${DEVPATH}/avoid_reset_quirk ]; then
- USB_ID=$(basename ${DEVPATH})
- break
- fi
- DEVPATH=$(dirname ${DEVPATH})
-done
-
-# Avoid USB resets
-echo "auto" > /sys/bus/usb/devices/${USB_ID}/power/control
-echo "3000" > /sys/bus/usb/devices/${USB_ID}/power/autosuspend_delay_ms
-echo "enabled" > /sys/bus/usb/devices/${USB_ID}/power/wakeup
-echo "1" > /sys/bus/usb/devices/${USB_ID}/avoid_reset_quirk
-echo "0" > /sys/bus/usb/devices/${USB_ID}/power/persist
diff --git a/udev/meson.build b/udev/meson.build
index fe558fc..1488660 100644
--- a/udev/meson.build
+++ b/udev/meson.build
@@ -4,5 +4,4 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
-install_data ('eg25-configure-usb', install_dir: bindir)
install_data ('80-modem-eg25.rules', install_dir: udevrulesdir)
--
GitLab

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
From 705950bb399781a291a3998014f916fc1effce16 Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bhush94@gmail.com>
Date: Thu, 15 Apr 2021 09:29:36 +0530
Subject: [PATCH] mm-iface: clean out modem_iface if mm disappears
otherwise we will be stuck in state where restarting of mm will not
reset the modem_iface and it will loop through hard resetting modem
---
src/mm-iface.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/mm-iface.c b/src/mm-iface.c
index d6a74f8..0409236 100644
--- a/src/mm-iface.c
+++ b/src/mm-iface.c
@@ -183,6 +183,9 @@ static void mm_iface_clean(struct EG25Manager *manager)
g_free(manager->modem_usb_id);
manager->modem_usb_id = NULL;
}
+ if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
+ manager->modem_iface = MODEM_IFACE_NONE;
+ }
}
static void mm_vanished_cb(GDBusConnection *connection,
--
GitLab

View File

@ -0,0 +1,101 @@
diff --git a/data/pine64,pinephone-1.0.toml b/data/pine64,pinephone-1.0.toml
index e127f1a..5269fc2 100644
--- a/data/pine64,pinephone-1.0.toml
+++ b/data/pine64,pinephone-1.0.toml
@@ -39,8 +39,8 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "urc/ri/ring", expect = "\"pulse\",2000,1000,5000,\"off\",1" },
- { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
- { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
+ { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000,1" },
+ { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1,1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QSCLK", value = "1" },
@@ -62,6 +62,15 @@ configure = [
{ cmd = "QGPSCFG", subcmd = "galileonmeatype", expect = "0" },
{ cmd = "QGPSCFG", subcmd = "beidounmeatype", expect = "0" },
{ cmd = "QGPSCFG", subcmd = "autogps", expect = "0" },
+# Reset modem-power configurations to what we expect
+ { cmd = "QCFG", subcmd = "urc/cache", expect = "0" },
+ { cmd = "QCFG", subcmd = "fast/poweroff", expect = "1" },
+ { cmd = "QCFG", subcmd = "apready", expect = "0,0,500" },
+ { cmd = "QCFG", subcmd = "sleepind/level", expect = "0" },
+ { cmd = "QCFG", subcmd = "wakeupin/level", expect = "0,0" },
+ { cmd = "QCFG", subcmd = "ApRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "ModemRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "urc/ri/pin", expect = "uart_ri" },
]
suspend = [
]
diff --git a/data/pine64,pinephone-1.1.toml b/data/pine64,pinephone-1.1.toml
index e127f1a..c2ee8bd 100644
--- a/data/pine64,pinephone-1.1.toml
+++ b/data/pine64,pinephone-1.1.toml
@@ -39,11 +39,20 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "urc/ri/ring", expect = "\"pulse\",2000,1000,5000,\"off\",1" },
- { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
- { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
+ { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000,1" },
+ { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1,1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QSCLK", value = "1" },
+# Reset modem-power configurations to what we expect
+ { cmd = "QCFG", subcmd = "urc/cache", expect = "0" },
+ { cmd = "QCFG", subcmd = "fast/poweroff", expect = "1" },
+ { cmd = "QCFG", subcmd = "apready", expect = "0,0,500" },
+ { cmd = "QCFG", subcmd = "sleepind/level", expect = "0" },
+ { cmd = "QCFG", subcmd = "wakeupin/level", expect = "0,0" },
+ { cmd = "QCFG", subcmd = "ApRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "ModemRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "urc/ri/pin", expect = "uart_ri" },
# GNSS configuration:
# * Enable A-GPS data upload support (XTRA)
# * Disable On-Demand-Positioning (ODP) mode
diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml
index e16f4f5..a45c7ec 100644
--- a/data/pine64,pinephone-1.2.toml
+++ b/data/pine64,pinephone-1.2.toml
@@ -36,8 +36,20 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "apready", expect = "1,0,500" },
+ { cmd = "QCFG", subcmd = "urc/ri/ring", expect = "\"pulse\",120,1000,5000,\"off\",1" },
+ { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",120,1" },
+ { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1,1" },
+ { cmd = "QCFG", subcmd = "urc/delay", expect = "0" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QSCLK", value = "1" },
+# Reset modem-power configurations to what we expect
+ { cmd = "QCFG", subcmd = "urc/cache", expect = "0" },
+ { cmd = "QCFG", subcmd = "fast/poweroff", expect = "1" },
+ { cmd = "QCFG", subcmd = "sleepind/level", expect = "0" },
+ { cmd = "QCFG", subcmd = "wakeupin/level", expect = "0,0" },
+ { cmd = "QCFG", subcmd = "ApRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "ModemRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "urc/ri/pin", expect = "uart_ri" },
# GNSS configuration:
# * Enable A-GPS data upload support (XTRA)
# * Disable On-Demand-Positioning (ODP) mode
diff --git a/src/at.c b/src/at.c
index f694507..7c5f092 100644
--- a/src/at.c
+++ b/src/at.c
@@ -222,7 +222,12 @@ static gboolean modem_response(gint fd,
else if (strstr(response, "QGPSURC: \"xtradataexpire\""))
gnss_upload_assistance_data(manager);
/* AT command failed, retry */
- else if (strstr(response, "ERROR"))
+ /*
+ * QCFG="fast/poweroff" configuration is only available in
+ * newer firmware versions
+ */
+ else if (strstr(response, "ERROR") && !strstr(response, "fast/poweroff"))
+
retry_at_command(manager);
/*
* Successfull AT responses contain 'OK', except for AT+QFUPL which also

View File

@ -0,0 +1,129 @@
From a046b539418958eeb2ee26ec5ef273835c98d0d2 Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Thu, 15 Apr 2021 20:11:03 +0200
Subject: [PATCH 1/2] config: synchronize with modem-power
We cannot assume default factory values if other drivers change them
---
data/pine64,pinephone-1.0.toml | 13 +++++++++++--
data/pine64,pinephone-1.1.toml | 13 +++++++++++--
data/pine64,pinephone-1.2.toml | 12 ++++++++++++
3 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/data/pine64,pinephone-1.0.toml b/data/pine64,pinephone-1.0.toml
index e1f5b24..6e21bda 100644
--- a/data/pine64,pinephone-1.0.toml
+++ b/data/pine64,pinephone-1.0.toml
@@ -39,12 +39,21 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "urc/ri/ring", expect = "\"pulse\",2000,1000,5000,\"off\",1" },
- { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
- { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
+ { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000,1" },
+ { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1,1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" },
+# Reset modem-power configurations to what we expect
+ { cmd = "QCFG", subcmd = "urc/cache", expect = "0" },
+ { cmd = "QCFG", subcmd = "fast/poweroff", expect = "1" },
+ { cmd = "QCFG", subcmd = "apready", expect = "0,0,500" },
+ { cmd = "QCFG", subcmd = "sleepind/level", expect = "0" },
+ { cmd = "QCFG", subcmd = "wakeupin/level", expect = "0,0" },
+ { cmd = "QCFG", subcmd = "ApRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "ModemRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "urc/ri/pin", expect = "uart_ri" },
]
suspend = [
{ cmd = "QGPSEND" },
diff --git a/data/pine64,pinephone-1.1.toml b/data/pine64,pinephone-1.1.toml
index e1f5b24..6e21bda 100644
--- a/data/pine64,pinephone-1.1.toml
+++ b/data/pine64,pinephone-1.1.toml
@@ -39,12 +39,21 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "urc/ri/ring", expect = "\"pulse\",2000,1000,5000,\"off\",1" },
- { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000" },
- { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1" },
+ { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",2000,1" },
+ { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1,1" },
{ cmd = "QCFG", subcmd = "urc/delay", expect = "1" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" },
+# Reset modem-power configurations to what we expect
+ { cmd = "QCFG", subcmd = "urc/cache", expect = "0" },
+ { cmd = "QCFG", subcmd = "fast/poweroff", expect = "1" },
+ { cmd = "QCFG", subcmd = "apready", expect = "0,0,500" },
+ { cmd = "QCFG", subcmd = "sleepind/level", expect = "0" },
+ { cmd = "QCFG", subcmd = "wakeupin/level", expect = "0,0" },
+ { cmd = "QCFG", subcmd = "ApRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "ModemRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "urc/ri/pin", expect = "uart_ri" },
]
suspend = [
{ cmd = "QGPSEND" },
diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml
index 4ca1274..598ebaf 100644
--- a/data/pine64,pinephone-1.2.toml
+++ b/data/pine64,pinephone-1.2.toml
@@ -36,9 +36,21 @@ configure = [
{ cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" },
{ cmd = "QCFG", subcmd = "ims", expect = "1" },
{ cmd = "QCFG", subcmd = "apready", expect = "1,0,500" },
+ { cmd = "QCFG", subcmd = "urc/ri/ring", expect = "\"pulse\",120,1000,5000,\"off\",1" },
+ { cmd = "QCFG", subcmd = "urc/ri/smsincoming", expect = "\"pulse\",120,1" },
+ { cmd = "QCFG", subcmd = "urc/ri/other", expect = "\"off\",1,1" },
+ { cmd = "QCFG", subcmd = "urc/delay", expect = "0" },
{ cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" },
{ cmd = "QGPS", value = "1" },
{ cmd = "QSCLK", value = "1" },
+# Reset modem-power configurations to what we expect
+ { cmd = "QCFG", subcmd = "urc/cache", expect = "0" },
+ { cmd = "QCFG", subcmd = "fast/poweroff", expect = "1" },
+ { cmd = "QCFG", subcmd = "sleepind/level", expect = "0" },
+ { cmd = "QCFG", subcmd = "wakeupin/level", expect = "0,0" },
+ { cmd = "QCFG", subcmd = "ApRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "ModemRstLevel", expect = "0" },
+ { cmd = "QCFG", subcmd = "urc/ri/pin", expect = "uart_ri" },
]
suspend = [
{ cmd = "QGPSEND" },
--
GitLab
From 0094dea49d8bc5a60c044da1e01417c29397c7b0 Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Sat, 17 Apr 2021 15:50:07 +0200
Subject: [PATCH 2/2] at: fast/poweroff is only available in newer firmware
versions
Do not retry the AT command of the fast/poweroff setting as it may not be supported by the firmware
---
src/at.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/at.c b/src/at.c
index a34025f..4469d26 100644
--- a/src/at.c
+++ b/src/at.c
@@ -215,7 +215,11 @@ static gboolean modem_response(gint fd,
suspend_inhibit(manager, TRUE, TRUE);
manager->modem_state = EG25_STATE_STARTED;
}
- else if (strstr(response, "ERROR"))
+ /*
+ * QCFG="fast/poweroff" configuration is only available in
+ * newer firmware versions
+ */
+ else if (strstr(response, "ERROR") && !strstr(response, "fast/poweroff"))
retry_at_command(manager);
else if (strstr(response, "OK"))
process_at_result(manager, response);
--
GitLab

View File

@ -0,0 +1,152 @@
From e690e2a17d9798ad22d961bd4ee2613593d68e44 Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Sun, 23 May 2021 20:00:42 +0200
Subject: [PATCH] at: wake only when sending AT commands
Allow the modem to enter soft sleep when
we don't talk to the modem using AT commands.
This was already the case in suspend, but
not during runtime. By only waking the modem
from soft sleep when we need to send
an AT command, we can save some power.
---
src/at.c | 36 +++++++++++++++++++++++-------------
src/gpio.c | 24 ++++++++++++++++++++++--
src/gpio.h | 2 ++
3 files changed, 47 insertions(+), 15 deletions(-)
diff --git a/src/at.c b/src/at.c
index a34025f..358d95a 100644
--- a/src/at.c
+++ b/src/at.c
@@ -6,6 +6,7 @@
#include "at.h"
#include "suspend.h"
+#include "gpio.h"
#include "gnss.h"
#include <fcntl.h>
@@ -52,6 +53,10 @@ gboolean at_send_command(struct EG25Mana
int ret, len = 0;
if (at_cmd) {
+ /* Wake up the modem from soft sleep before sending an AT command */
+ gpio_sequence_wake(manager);
+
+ /* Send AT command */
if (at_cmd->subcmd == NULL && at_cmd->value == NULL && at_cmd->expected == NULL)
len = sprintf(command, "AT+%s\r\n", at_cmd->cmd);
else if (at_cmd->subcmd == NULL && at_cmd->value == NULL)
@@ -69,23 +74,28 @@ gboolean at_send_command(struct EG25Mana
g_warning("Couldn't write full AT command: wrote %d/%d bytes", ret, len);
g_message("Sending command: %s", g_strstrip(command));
- } else if (manager->modem_state < EG25_STATE_CONFIGURED) {
- if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
+ } else {
+ /* Allow the modem to enter soft sleep again when we sent the AT command*/
+ gpio_sequence_sleep(manager);
+
+ if (manager->modem_state < EG25_STATE_CONFIGURED) {
+ if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
#ifdef HAVE_MMGLIB
- MMModemState modem_state = mm_modem_get_state(manager->mm_modem);
+ MMModemState modem_state = mm_modem_get_state(manager->mm_modem);
- if (manager->mm_modem && modem_state >= MM_MODEM_STATE_REGISTERED)
- modem_update_state(manager, modem_state);
- else
- manager->modem_state = EG25_STATE_CONFIGURED;
+ if (manager->mm_modem && modem_state >= MM_MODEM_STATE_REGISTERED)
+ modem_update_state(manager, modem_state);
+ else
+ manager->modem_state = EG25_STATE_CONFIGURED;
#endif
- } else {
- manager->modem_state = EG25_STATE_CONFIGURED;
+ } else {
+ manager->modem_state = EG25_STATE_CONFIGURED;
+ }
+ } else if (manager->modem_state == EG25_STATE_SUSPENDING) {
+ modem_suspend_post(manager);
+ } else if (manager->modem_state == EG25_STATE_RESETTING) {
+ manager->modem_state = EG25_STATE_POWERED;
}
- } else if (manager->modem_state == EG25_STATE_SUSPENDING) {
- modem_suspend_post(manager);
- } else if (manager->modem_state == EG25_STATE_RESETTING) {
- manager->modem_state = EG25_STATE_POWERED;
}
return FALSE;
diff --git a/src/gpio.c b/src/gpio.c
index a5d3bf0..617b69e 100644
--- a/src/gpio.c
+++ b/src/gpio.c
@@ -6,6 +6,8 @@
#include "gpio.h"
+#include <unistd.h>
+
#define GPIO_CHIP1_LABEL "1c20800.pinctrl"
#define GPIO_CHIP2_LABEL "1f02c00.pinctrl"
@@ -52,7 +54,6 @@ int gpio_sequence_shutdown(struct EG25Manager *manager)
int gpio_sequence_suspend(struct EG25Manager *manager)
{
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_APREADY], 1);
- gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 1);
g_message("Executed suspend sequence");
@@ -62,13 +63,32 @@ int gpio_sequence_suspend(struct EG25Manager *manager)
int gpio_sequence_resume(struct EG25Manager *manager)
{
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_APREADY], 0);
- gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 0);
g_message("Executed resume sequence");
return 0;
}
+int gpio_sequence_wake(struct EG25Manager *manager)
+{
+ gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 0);
+
+ /* Give the modem 5ms to wake from soft sleep */
+ usleep(5000);
+
+ g_message("Executed soft wake sequence");
+
+ return 0;
+}
+
+int gpio_sequence_sleep(struct EG25Manager *manager)
+{
+ gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 1);
+ g_message("Executed soft sleep sequence");
+
+ return 0;
+}
+
static guint get_config_gpio(toml_table_t *config, const char *id)
{
toml_datum_t value = toml_int_in(config, id);
diff --git a/src/gpio.h b/src/gpio.h
index 8d94013..a041bdc 100644
--- a/src/gpio.h
+++ b/src/gpio.h
@@ -15,5 +15,7 @@ int gpio_sequence_poweron(struct EG25Manager *state);
int gpio_sequence_shutdown(struct EG25Manager *state);
int gpio_sequence_suspend(struct EG25Manager *state);
int gpio_sequence_resume(struct EG25Manager *state);
+int gpio_sequence_wake(struct EG25Manager *state);
+int gpio_sequence_sleep(struct EG25Manager *state);
gboolean gpio_check_poweroff(struct EG25Manager *manager, gboolean keep_down);
--
GitLab

View File

@ -0,0 +1,895 @@
From 09c0ddfbb81f15bf732b9a5af15eee9eb1be848b Mon Sep 17 00:00:00 2001
From: Oliver Smith <ollieparanoid@postmarketos.org>
Date: Mon, 8 Feb 2021 10:29:56 +0530
Subject: [PATCH 1/5] src: add ofono-iface
Start work on new ofono interface. So far, this detects ofono on dbus
and complains if both mm and ofono are running.
---
src/manager.c | 10 ++++++++
src/manager.h | 8 ++++++
src/meson.build | 1 +
src/mm-iface.c | 7 ++++++
src/ofono-iface.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
src/ofono-iface.h | 12 +++++++++
6 files changed, 100 insertions(+)
create mode 100644 src/ofono-iface.c
create mode 100644 src/ofono-iface.h
diff --git a/src/manager.c b/src/manager.c
index aaa3905..7e43e62 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -8,6 +8,7 @@
#include "gpio.h"
#include "manager.h"
#include "mm-iface.h"
+#include "ofono-iface.h"
#include "suspend.h"
#include "udev.h"
@@ -35,6 +36,7 @@ static gboolean quit_app(struct EG25Manager *manager)
at_destroy(manager);
mm_iface_destroy(manager);
+ ofono_iface_destroy(manager);
suspend_destroy(manager);
udev_destroy(manager);
@@ -131,6 +133,13 @@ void modem_reset(struct EG25Manager *manager)
if (manager->reset_timer)
return;
+ /* If we are managing the modem through lets say ofono, we should not
+ * reset the modem based on the availability of USB ID
+ * TODO: Improve ofono plugin and add support for fetching USB ID
+ */
+ if (manager->modem_iface != MODEM_IFACE_MODEMMANAGER)
+ return;
+
if (manager->modem_recovery_timer) {
g_source_remove(manager->modem_recovery_timer);
manager->modem_recovery_timer = 0;
@@ -305,6 +314,7 @@ int main(int argc, char *argv[])
at_init(&manager, toml_table_in(toml_config, "at"));
gpio_init(&manager, toml_table_in(toml_config, "gpio"));
mm_iface_init(&manager, toml_table_in(toml_config, "mm-iface"));
+ ofono_iface_init(&manager);
suspend_init(&manager, toml_table_in(toml_config, "suspend"));
udev_init(&manager, toml_table_in(toml_config, "udev"));
diff --git a/src/manager.h b/src/manager.h
index 48ff237..5ed9e75 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -27,6 +27,12 @@ enum EG25State {
EG25_STATE_FINISHING
};
+enum ModemIface {
+ MODEM_IFACE_NONE = 0,
+ MODEM_IFACE_MODEMMANAGER,
+ MODEM_IFACE_OFONO
+};
+
struct EG25Manager {
GMainLoop *loop;
guint reset_timer;
@@ -41,9 +47,11 @@ struct EG25Manager {
enum EG25State modem_state;
gchar *modem_usb_id;
+ enum ModemIface modem_iface;
guint mm_watch;
MMManager *mm_manager;
MMModem *mm_modem;
+ guint ofono_watch;
GDBusProxy *suspend_proxy;
int suspend_delay_fd;
diff --git a/src/meson.build b/src/meson.build
index 0d10362..7429950 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -11,6 +11,7 @@ executable (
'gpio.c', 'gpio.h',
'manager.c', 'manager.h',
'mm-iface.c', 'mm-iface.h',
+ 'ofono-iface.c', 'ofono-iface.h',
'suspend.c', 'suspend.h',
'toml.c', 'toml.h',
'udev.c', 'udev.h',
diff --git a/src/mm-iface.c b/src/mm-iface.c
index 8afe2ea..e1e3726 100644
--- a/src/mm-iface.c
+++ b/src/mm-iface.c
@@ -163,6 +163,13 @@ static void mm_appeared_cb(GDBusConnection *connection,
{
g_message("ModemManager appeared on D-Bus");
+ if (manager->modem_iface != MODEM_IFACE_NONE) {
+ g_critical("Modem interface already found!");
+ g_critical("Make sure to only run either of ModemManager or oFono.");
+ return;
+ }
+ manager->modem_iface = MODEM_IFACE_MODEMMANAGER;
+
mm_manager_new(connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
NULL, (GAsyncReadyCallback)mm_manager_new_cb, manager);
}
diff --git a/src/ofono-iface.c b/src/ofono-iface.c
new file mode 100644
index 0000000..d9051a3
--- /dev/null
+++ b/src/ofono-iface.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 Oliver Smith <ollieparanoid@postmarketos.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "ofono-iface.h"
+
+#include <string.h>
+
+// #include <ofono/dbus.h>
+#define OFONO_SERVICE "org.ofono"
+
+static void ofono_appeared_cb(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ struct EG25Manager *manager)
+{
+ g_message("oFono appeared on D-Bus");
+
+ if (manager->modem_iface != MODEM_IFACE_NONE) {
+ g_critical("Modem interface already found!");
+ g_critical("Make sure to only run either of ModemManager or oFono.");
+ return;
+ }
+ manager->modem_iface = MODEM_IFACE_OFONO;
+
+ /* now connect to oFono! */
+}
+
+static void ofono_vanished_cb(GDBusConnection *connection,
+ const gchar *name,
+ struct EG25Manager *manager)
+{
+ g_message("oFono vanished from D-Bus");
+
+ if (manager->modem_iface == MODEM_IFACE_OFONO) {
+ manager->modem_iface = MODEM_IFACE_NONE;
+ ofono_iface_destroy(manager);
+ }
+}
+
+void ofono_iface_init(struct EG25Manager *manager)
+{
+ manager->ofono_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, OFONO_SERVICE,
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ (GBusNameAppearedCallback)ofono_appeared_cb,
+ (GBusNameVanishedCallback)ofono_vanished_cb,
+ manager, NULL);
+}
+
+void ofono_iface_destroy(struct EG25Manager *manager)
+{
+ if (manager->modem_usb_id) {
+ g_free(manager->modem_usb_id);
+ manager->modem_usb_id = NULL;
+ }
+ if (manager->ofono_watch != 0) {
+ g_bus_unwatch_name(manager->ofono_watch);
+ manager->ofono_watch = 0;
+ }
+}
diff --git a/src/ofono-iface.h b/src/ofono-iface.h
new file mode 100644
index 0000000..fd3766e
--- /dev/null
+++ b/src/ofono-iface.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2020 Oliver Smith <ollieparanoid@postmarketos.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "manager.h"
+
+void ofono_iface_init(struct EG25Manager *data);
+void ofono_iface_destroy(struct EG25Manager *data);
--
GitLab
From a3952107f5950535dd10d8c48ae807f3f4ec207e Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bhush94@gmail.com>
Date: Thu, 11 Mar 2021 11:58:46 +0530
Subject: [PATCH 2/5] src: watch ofono service for new modem
If system is using ofono, use ofono dbus service to figure out the
modem's USB id.
---
src/libgdbofono/dbus-introspect.sh | 11 ++
src/libgdbofono/manager.xml | 13 ++
src/libgdbofono/meson.build | 50 ++++++
src/libgdbofono/modem-full.xml | 249 +++++++++++++++++++++++++++++
src/libgdbofono/modem.xml | 37 +++++
src/manager.h | 4 +
src/meson.build | 4 +
src/ofono-iface.c | 100 +++++++++++-
8 files changed, 467 insertions(+), 1 deletion(-)
create mode 100755 src/libgdbofono/dbus-introspect.sh
create mode 100644 src/libgdbofono/manager.xml
create mode 100644 src/libgdbofono/meson.build
create mode 100644 src/libgdbofono/modem-full.xml
create mode 100644 src/libgdbofono/modem.xml
diff --git a/src/libgdbofono/dbus-introspect.sh b/src/libgdbofono/dbus-introspect.sh
new file mode 100755
index 0000000..5a851ad
--- /dev/null
+++ b/src/libgdbofono/dbus-introspect.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+DEST="$1"
+OBJ_PATH="$2"
+METHOD="$3"
+shift 3
+
+dbus-send "$@" --print-reply --dest="$DEST" "$OBJ_PATH" "$METHOD" | \
+ grep -v '^method return' | \
+ sed -e 's/^[[:space:]]\+string "</</' \
+ -e 's_</node>"_</node>_'
diff --git a/src/libgdbofono/manager.xml b/src/libgdbofono/manager.xml
new file mode 100644
index 0000000..13e9d56
--- /dev/null
+++ b/src/libgdbofono/manager.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+
+ <interface name="org.ofono.Manager"><method name="GetModems"><arg name="modems" type="a(oa{sv})" direction="out"/>
+</method><signal name="ModemAdded"><arg name="path" type="o"/>
+<arg name="properties" type="a{sv}"/>
+</signal>
+<signal name="ModemRemoved"><arg name="path" type="o"/>
+</signal>
+ </interface>
+
+</node>
diff --git a/src/libgdbofono/meson.build b/src/libgdbofono/meson.build
new file mode 100644
index 0000000..98eb9a3
--- /dev/null
+++ b/src/libgdbofono/meson.build
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2018 Purism SPC
+#
+# This file is part of Calls.
+#
+# Calls is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Calls is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Calls. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Bob Ham <bob.ham@puri.sm>
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+
+gnome = import('gnome')
+dbus_interfaces = ['manager', 'modem']
+
+gdbofono_src = []
+gdbofono_headers = []
+foreach iface: dbus_interfaces
+ src = gnome.gdbus_codegen(
+ 'gdbo-' + iface,
+ iface + '.xml',
+ interface_prefix: 'org.ofono.',
+ namespace: 'GDBO'
+ )
+ gdbofono_src += src
+ gdbofono_headers += src[1]
+endforeach
+
+gdbofono_deps = [
+ dependency('gio-2.0'),
+ dependency('gio-unix-2.0'),
+]
+
+gdbofono_lib = static_library(
+ 'gdbofono',
+ gdbofono_src,
+ dependencies: gdbofono_deps
+)
diff --git a/src/libgdbofono/modem-full.xml b/src/libgdbofono/modem-full.xml
new file mode 100644
index 0000000..5319672
--- /dev/null
+++ b/src/libgdbofono/modem-full.xml
@@ -0,0 +1,249 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+
+ <interface name="org.ofono.Modem"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.SimManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><method name="ChangePin"><arg name="type" type="s" direction="in"/>
+<arg name="oldpin" type="s" direction="in"/>
+<arg name="newpin" type="s" direction="in"/>
+</method><method name="EnterPin"><arg name="type" type="s" direction="in"/>
+<arg name="pin" type="s" direction="in"/>
+</method><method name="ResetPin"><arg name="type" type="s" direction="in"/>
+<arg name="puk" type="s" direction="in"/>
+<arg name="newpin" type="s" direction="in"/>
+</method><method name="LockPin"><arg name="type" type="s" direction="in"/>
+<arg name="pin" type="s" direction="in"/>
+</method><method name="UnlockPin"><arg name="type" type="s" direction="in"/>
+<arg name="pin" type="s" direction="in"/>
+</method><method name="GetIcon"><arg name="id" type="y" direction="in"/>
+<arg name="icon" type="ay" direction="out"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.VoiceCallManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="Dial"><arg name="number" type="s" direction="in"/>
+<arg name="hide_callerid" type="s" direction="in"/>
+<arg name="path" type="o" direction="out"/>
+</method><method name="DialLast"></method><method name="DialMemory"><arg name="memory_location" type="u" direction="in"/>
+</method><method name="Transfer"></method><method name="SwapCalls"></method><method name="ReleaseAndAnswer"></method><method name="ReleaseAndSwap"></method><method name="HoldAndAnswer"></method><method name="HangupAll"></method><method name="PrivateChat"><arg name="call" type="o" direction="in"/>
+<arg name="calls" type="ao" direction="out"/>
+</method><method name="CreateMultiparty"><arg name="calls" type="ao" direction="out"/>
+</method><method name="HangupMultiparty"></method><method name="SendTones"><arg name="SendTones" type="s" direction="in"/>
+</method><method name="GetCalls"><arg name="calls_with_properties" type="a(oa{sv})" direction="out"/>
+</method><signal name="Forwarded"><arg name="type" type="s"/>
+</signal>
+<signal name="BarringActive"><arg name="type" type="s"/>
+</signal>
+<signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+<signal name="CallAdded"><arg name="path" type="o"/>
+<arg name="properties" type="a{sv}"/>
+</signal>
+<signal name="CallRemoved"><arg name="path" type="o"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.AllowedAccessPoints"><method name="GetAllowedAccessPoints"><arg name="apnlist" type="as" direction="out"/>
+ </method></interface>
+
+ <interface name="org.ofono.SimAuthentication"><method name="GetApplications"><arg name="applications" type="a{oa{sv}}" direction="out"/>
+</method><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+ </method></interface>
+
+ <interface name="org.ofono.SimToolkit"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SelectItem"><arg name="item" type="y" direction="in"/>
+<arg name="agent" type="o" direction="in"/>
+</method><method name="RegisterAgent"><arg name="path" type="o" direction="in"/>
+</method><method name="UnregisterAgent"><arg name="path" type="o" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.CallForwarding"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><method name="DisableAll"><arg name="type" type="s" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.RadioSettings"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.TextTelephony"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.Phonebook"><method name="Import"><arg name="entries" type="s" direction="out"/>
+ </method></interface>
+
+ <interface name="org.ofono.MessageManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><method name="SendMessage"><arg name="to" type="s" direction="in"/>
+<arg name="text" type="s" direction="in"/>
+<arg name="path" type="o" direction="out"/>
+</method><method name="GetMessages"><arg name="messages" type="a(oa{sv})" direction="out"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+<signal name="IncomingMessage"><arg name="message" type="s"/>
+<arg name="info" type="a{sv}"/>
+</signal>
+<signal name="ImmediateMessage"><arg name="message" type="s"/>
+<arg name="info" type="a{sv}"/>
+</signal>
+<signal name="MessageAdded"><arg name="path" type="o"/>
+<arg name="properties" type="a{sv}"/>
+</signal>
+<signal name="MessageRemoved"><arg name="path" type="o"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.PushNotification"><method name="RegisterAgent"><arg name="path" type="o" direction="in"/>
+</method><method name="UnregisterAgent"><arg name="path" type="o" direction="in"/>
+ </method></interface>
+
+ <interface name="org.ofono.SmartMessaging"><method name="RegisterAgent"><arg name="path" type="o" direction="in"/>
+</method><method name="UnregisterAgent"><arg name="path" type="o" direction="in"/>
+</method><method name="SendBusinessCard"><arg name="to" type="s" direction="in"/>
+<arg name="card" type="ay" direction="in"/>
+<arg name="path" type="o" direction="out"/>
+</method><method name="SendAppointment"><arg name="to" type="s" direction="in"/>
+<arg name="appointment" type="ay" direction="in"/>
+<arg name="path" type="o" direction="out"/>
+ </method></interface>
+
+ <interface name="org.ofono.MessageWaiting"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.CallSettings"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="property" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.CallBarring"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+<arg name="pin2" type="s" direction="in"/>
+</method><method name="DisableAll"><arg name="password" type="s" direction="in"/>
+</method><method name="DisableAllIncoming"><arg name="password" type="s" direction="in"/>
+</method><method name="DisableAllOutgoing"><arg name="password" type="s" direction="in"/>
+</method><method name="ChangePassword"><arg name="old" type="s" direction="in"/>
+<arg name="new" type="s" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.SupplementaryServices"><method name="Initiate"><arg name="command" type="s" direction="in"/>
+<arg name="result_name" type="s" direction="out"/>
+<arg name="value" type="v" direction="out"/>
+</method><method name="Respond"><arg name="reply" type="s" direction="in"/>
+<arg name="result" type="s" direction="out"/>
+</method><method name="Cancel"></method><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><signal name="NotificationReceived"><arg name="message" type="s"/>
+</signal>
+<signal name="RequestReceived"><arg name="message" type="s"/>
+</signal>
+<signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.CallMeter"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+<arg name="password" type="s" direction="in"/>
+</method><method name="Reset"><arg name="passoword" type="s" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="property" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+<signal name="NearMaximumWarning"></signal>
+ </interface>
+
+ <interface name="org.ofono.CallVolume"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="property" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.NetworkRegistration"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="Register"></method><method name="GetOperators"><arg name="operators_with_properties" type="a(oa{sv})" direction="out"/>
+</method><method name="Scan"><arg name="operators_with_properties" type="a(oa{sv})" direction="out"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.CellBroadcast"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="property" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+<signal name="IncomingBroadcast"><arg name="message" type="s"/>
+<arg name="channel" type="q"/>
+</signal>
+<signal name="EmergencyBroadcast"><arg name="message" type="s"/>
+<arg name="dict" type="a{sv}"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.AssistedSatelliteNavigation"><method name="SendPositioningElement"><arg name="xml_elements" type="(null)" direction="in"/>
+</method><method name="RegisterPositioningRequestAgent"><arg name="agent" type="o" direction="in"/>
+</method><method name="UnregisterPositioningRequestAgent"><arg name="agent" type="o" direction="in"/>
+ </method></interface>
+
+ <interface name="org.ofono.ConnectionManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><method name="AddContext"><arg name="type" type="s" direction="in"/>
+<arg name="path" type="o" direction="out"/>
+</method><method name="RemoveContext"><arg name="path" type="o" direction="in"/>
+</method><method name="DeactivateAll"></method><method name="GetContexts"><arg name="contexts_with_properties" type="a(oa{sv})" direction="out"/>
+</method><method name="ResetContexts"></method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+<signal name="ContextAdded"><arg name="path" type="o"/>
+<arg name="properties" type="a{sv}"/>
+</signal>
+<signal name="ContextRemoved"><arg name="path" type="o"/>
+</signal>
+ </interface>
+
+</node>
diff --git a/src/libgdbofono/modem.xml b/src/libgdbofono/modem.xml
new file mode 100644
index 0000000..c02d250
--- /dev/null
+++ b/src/libgdbofono/modem.xml
@@ -0,0 +1,37 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+
+ <interface name="org.ofono.Modem"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="SetProperty"><arg name="property" type="s" direction="in"/>
+<arg name="value" type="v" direction="in"/>
+</method><signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+ </interface>
+
+ <interface name="org.ofono.VoiceCallManager"><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
+</method><method name="Dial"><arg name="number" type="s" direction="in"/>
+<arg name="hide_callerid" type="s" direction="in"/>
+<arg name="path" type="o" direction="out"/>
+</method><method name="DialLast"></method><method name="DialMemory"><arg name="memory_location" type="u" direction="in"/>
+</method><method name="Transfer"></method><method name="SwapCalls"></method><method name="ReleaseAndAnswer"></method><method name="ReleaseAndSwap"></method><method name="HoldAndAnswer"></method><method name="HangupAll"></method><method name="PrivateChat"><arg name="call" type="o" direction="in"/>
+<arg name="calls" type="ao" direction="out"/>
+</method><method name="CreateMultiparty"><arg name="calls" type="ao" direction="out"/>
+</method><method name="HangupMultiparty"></method><method name="SendTones"><arg name="SendTones" type="s" direction="in"/>
+</method><method name="GetCalls"><arg name="calls_with_properties" type="a(oa{sv})" direction="out"/>
+</method><signal name="Forwarded"><arg name="type" type="s"/>
+</signal>
+<signal name="BarringActive"><arg name="type" type="s"/>
+</signal>
+<signal name="PropertyChanged"><arg name="name" type="s"/>
+<arg name="value" type="v"/>
+</signal>
+<signal name="CallAdded"><arg name="path" type="o"/>
+<arg name="properties" type="a{sv}"/>
+</signal>
+<signal name="CallRemoved"><arg name="path" type="o"/>
+</signal>
+ </interface>
+
+</node>
diff --git a/src/manager.h b/src/manager.h
index 5ed9e75..ec5550b 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -10,6 +10,7 @@
#include <gpiod.h>
#include <gudev/gudev.h>
#include <libmm-glib.h>
+#include <libgdbofono/gdbo-manager.h>
#include "toml.h"
@@ -51,7 +52,10 @@ struct EG25Manager {
guint mm_watch;
MMManager *mm_manager;
MMModem *mm_modem;
+
guint ofono_watch;
+ GDBOManager *ofono_manager;
+ GDBusConnection *ofono_connection;
GDBusProxy *suspend_proxy;
int suspend_delay_fd;
diff --git a/src/meson.build b/src/meson.build
index 7429950..6a9f52d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -4,6 +4,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
+
+subdir('libgdbofono')
+
executable (
'eg25manager',
[
@@ -17,5 +20,6 @@ executable (
'udev.c', 'udev.h',
],
dependencies : mgr_deps,
+ link_with: gdbofono_lib,
install : true
)
diff --git a/src/ofono-iface.c b/src/ofono-iface.c
index d9051a3..00bf665 100644
--- a/src/ofono-iface.c
+++ b/src/ofono-iface.c
@@ -8,14 +8,91 @@
#include <string.h>
+#include <libgdbofono/gdbo-manager.h>
+#include <libgdbofono/gdbo-modem.h>
+
// #include <ofono/dbus.h>
#define OFONO_SERVICE "org.ofono"
+static void modem_added_cb(GDBOManager *manager_proxy,
+ const gchar *path,
+ GVariant *properties,
+ struct EG25Manager *manager)
+{
+ GVariant *modem_path;
+ /*
+ gdbo_modem_proxy_new(manager->ofono_connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ g_dbus_proxy_get_name(G_DBUS_PROXY(manager_proxy)),
+ path,
+ NULL,
+ (GAsyncReadyCallback) modem_proxy_new_cb,
+ manager);
+ */
+ g_debug("Adding ofono modem '%s'", path);
+
+ if (manager->modem_state == EG25_STATE_RESUMING) {
+ if (manager->modem_recovery_timer) {
+ g_source_remove(manager->modem_recovery_timer);
+ manager->modem_recovery_timer = 0;
+ }
+ modem_resume_post(manager);
+ manager->modem_state = EG25_STATE_CONFIGURED;
+ }
+
+ if (manager->modem_state < EG25_STATE_ACQUIRED)
+ manager->modem_state = EG25_STATE_ACQUIRED;
+
+ if (manager->modem_state < EG25_STATE_CONFIGURED)
+ modem_configure(manager);
+
+ modem_path = g_variant_lookup_value(properties, "SystemPath", G_VARIANT_TYPE_STRING);
+ if (manager->modem_usb_id)
+ g_free(manager->modem_usb_id);
+ manager->modem_usb_id = g_strdup(strrchr(g_variant_dup_string(modem_path, NULL), '/') + 1);
+}
+
+static void modem_removed_cb(GDBOManager *manager_proxy,
+ const gchar *path,
+ struct EG25Manager *manager)
+{
+}
+
+static void get_modems_cb(GDBOManager *manager_proxy,
+ GAsyncResult *res,
+ struct EG25Manager *manager)
+{
+ gboolean ok;
+ GVariant *modems;
+ GVariantIter *modems_iter = NULL;
+ g_autoptr(GError) error = NULL;
+
+ const gchar *path;
+ GVariant *properties;
+
+ ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems,
+ res, &error);
+ if (!ok) {
+ g_warning("Error getting modems from ofono manager: %s", error->message);
+ return;
+ }
+
+ g_variant_get(modems, "a(oa{sv})", &modems_iter);
+ while(g_variant_iter_loop(modems_iter, "(&o@a{sv})", &path, &properties)) {
+ g_debug("Got modem object path '%s'", path);
+ modem_added_cb(manager_proxy, path, properties, manager);
+ }
+ g_variant_iter_free(modems_iter);
+ g_variant_unref(modems);
+}
+
static void ofono_appeared_cb(GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
struct EG25Manager *manager)
{
+ GError *error = NULL;
+
g_message("oFono appeared on D-Bus");
if (manager->modem_iface != MODEM_IFACE_NONE) {
@@ -23,9 +100,30 @@ static void ofono_appeared_cb(GDBusConnection *connection,
g_critical("Make sure to only run either of ModemManager or oFono.");
return;
}
+ /* now connect to oFono! */
+ manager->ofono_connection = connection;
+ manager->ofono_manager = gdbo_manager_proxy_new_sync(connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ OFONO_SERVICE,
+ "/",
+ NULL,
+ &error);
+ if (!manager->ofono_manager) {
+ g_critical("Error creating ofono object manager proxy: %s", error->message);
+ return;
+ }
+
manager->modem_iface = MODEM_IFACE_OFONO;
- /* now connect to oFono! */
+ g_signal_connect(manager->ofono_manager, "modem-added",
+ G_CALLBACK(modem_added_cb), manager);
+ g_signal_connect(manager->ofono_manager, "modem-removed",
+ G_CALLBACK(modem_removed_cb), manager);
+
+ gdbo_manager_call_get_modems(manager->ofono_manager,
+ NULL,
+ (GAsyncReadyCallback) get_modems_cb,
+ manager);
}
static void ofono_vanished_cb(GDBusConnection *connection,
--
GitLab
From 9c4f5669fc6b76eac280f165aab972552f2df824 Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bhush94@gmail.com>
Date: Thu, 11 Mar 2021 12:13:04 +0530
Subject: [PATCH 3/5] at: if we are using ofono, don't query modem manager for
state
---
src/at.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/at.c b/src/at.c
index 4b5cd62..32138d0 100644
--- a/src/at.c
+++ b/src/at.c
@@ -76,12 +76,16 @@ static gboolean send_at_command(struct EG25Manager *manager)
g_message("Sending command: %s", g_strstrip(command));
} else if (manager->modem_state < EG25_STATE_CONFIGURED) {
- MMModemState modem_state = mm_modem_get_state(manager->mm_modem);
-
- if (manager->mm_modem && modem_state >= MM_MODEM_STATE_REGISTERED)
- modem_update_state(manager, modem_state);
- else
+ if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
+ MMModemState modem_state = mm_modem_get_state(manager->mm_modem);
+
+ if (manager->mm_modem && modem_state >= MM_MODEM_STATE_REGISTERED)
+ modem_update_state(manager, modem_state);
+ else
+ manager->modem_state = EG25_STATE_CONFIGURED;
+ } else {
manager->modem_state = EG25_STATE_CONFIGURED;
+ }
} else if (manager->modem_state == EG25_STATE_SUSPENDING) {
modem_suspend_post(manager);
} else if (manager->modem_state == EG25_STATE_RESETTING) {
--
GitLab
From 742172a9129a3c11c2825d323f8f98730f7533db Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bhush94@gmail.com>
Date: Thu, 11 Mar 2021 13:08:21 +0530
Subject: [PATCH 4/5] suspend: if we are using ofono, mark modem as resumed
immediately
---
src/suspend.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/suspend.c b/src/suspend.c
index 256636e..b82ca7e 100644
--- a/src/suspend.c
+++ b/src/suspend.c
@@ -170,11 +170,14 @@ static void signal_cb(GDBusProxy *proxy,
g_message("system is resuming");
take_inhibitor(manager, FALSE);
modem_resume_pre(manager);
- if (manager->mm_modem) {
+ if (manager->mm_modem || manager->modem_iface == MODEM_IFACE_OFONO) {
/*
* On some systems ModemManager doesn't handle suspend/resume, so
* we still have a valid/managed modem when resuming. In this case,
* do the whole resume sequence immediately.
+ *
+ * If modem is managed by ofono, we also do resume sequence immediately
+ * as ofono handles resuming from sleep itself.
*/
manager->modem_state = EG25_STATE_CONFIGURED;
modem_resume_post(manager);
--
GitLab
From 87ff1e0a5a6f379528e1e581372e9d60d35e044f Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bhush94@gmail.com>
Date: Thu, 11 Mar 2021 14:22:50 +0530
Subject: [PATCH 5/5] ofono-iface: add spdx copyright info
---
src/ofono-iface.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ofono-iface.c b/src/ofono-iface.c
index 00bf665..caf32dd 100644
--- a/src/ofono-iface.c
+++ b/src/ofono-iface.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2020 Oliver Smith <ollieparanoid@postmarketos.org>
+ * Copyright (C) 2021 Bhushan Shah <bshah@kde.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
--
GitLab

View File

@ -0,0 +1,29 @@
[Unit]
Description=Quectel EG25 modem
Before=ModemManager.service
[Service]
Type=simple
ExecStart=/usr/bin/eg25manager
Restart=on-failure
ProtectControlGroups=true
ProtectHome=true
ProtectKernelTunables=true
ProtectSystem=strict
RestrictSUIDSGID=true
PrivateTmp=true
ProtectedKernelModules=true
MemoryDenyWriteExecute=true
PrivateMounts=true
NoNewPrivileges=true
CapabilityBoundingSet=
ProtectProc=true
ProtectDevices=true
DeviceAllow=/dev/ttyS2
LockPersonality=true
PrivateNetwork=true
ProtectClock=true
ProtectKernelLog=true
[Install]
WantedBy=multi-user.target