From 04eed2496d2a02bb23b4eae91be0264417fb28c6 Mon Sep 17 00:00:00 2001 From: Biktor Date: Wed, 24 Feb 2021 12:32:46 +0100 Subject: [PATCH 01/13] 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" } From dcb1a9a050a936ebfd748b20a1ad9d4ee1cb84c0 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Mon, 8 Feb 2021 10:29:56 +0530 Subject: [PATCH 02/13] 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 | 11 +++++++++ src/manager.h | 8 +++++++ src/meson.build | 1 + src/mm-iface.c | 6 +++++ src/ofono-iface.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ src/ofono-iface.h | 12 ++++++++++ 6 files changed, 98 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..7c55cd9 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,14 @@ 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 +315,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..d6a74f8 100644 --- a/src/mm-iface.c +++ b/src/mm-iface.c @@ -163,6 +163,12 @@ 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! 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..58c8b5a --- /dev/null +++ b/src/ofono-iface.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2020 Oliver Smith + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "ofono-iface.h" + +#include + +#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! 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 + * + * 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); From 060dc9ae324944bb76adc3b017c1b2b50a454615 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Mon, 15 Mar 2021 12:29:47 +0530 Subject: [PATCH 03/13] 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 | 91 ++++++++++- 8 files changed, 458 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 ""__' 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 @@ + + + + + + + + + + + + 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 . +# +# Author: Bob Ham +# +# 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 #include #include +#include #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 58c8b5a..bbf8dbc 100644 --- a/src/ofono-iface.c +++ b/src/ofono-iface.c @@ -8,22 +8,111 @@ #include +#include +#include + #define OFONO_SERVICE "org.ofono" +static void modem_added_cb(GDBOManager *manager_proxy, + const gchar *path, + GVariant *properties, + struct EG25Manager *manager) +{ + GVariant *modem_path; + 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) { g_critical("Modem interface already found! 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, From 032bd4651cb9dc06630ece548d9bbf22143533df Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Thu, 11 Mar 2021 12:13:04 +0530 Subject: [PATCH 04/13] at: if we are using ofono, don't query modem manager for state --- src/at.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 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->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 + 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) { From 52488d2e2abe1ea826409c90e9955b2d5f90c6d0 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Thu, 11 Mar 2021 13:08:21 +0530 Subject: [PATCH 05/13] 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); From 2e7a5a696b63d0c9a290a4d7c2d871f860ae52b5 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Thu, 11 Mar 2021 14:22:50 +0530 Subject: [PATCH 06/13] 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 bbf8dbc..bc37f38 100644 --- a/src/ofono-iface.c +++ b/src/ofono-iface.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2020 Oliver Smith + * Copyright (C) 2021 Bhushan Shah * * SPDX-License-Identifier: GPL-3.0-or-later */ From 528fe7e07c1e9cc98b1243daa3913e89ec0fec90 Mon Sep 17 00:00:00 2001 From: Djhg2000 Date: Thu, 4 Mar 2021 20:08:12 +0100 Subject: [PATCH 07/13] Add a 100ms 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. --- data/pine64,pinephone-1.0.toml | 3 +++ data/pine64,pinephone-1.1.toml | 3 +++ data/pine64,pinephone-1.2.toml | 4 ++++ src/manager.c | 14 ++++++++++++++ src/manager.h | 1 + 5 files changed, 25 insertions(+) diff --git a/data/pine64,pinephone-1.0.toml b/data/pine64,pinephone-1.0.toml index c0e9192..f5d2451 100644 --- a/data/pine64,pinephone-1.0.toml +++ b/data/pine64,pinephone-1.0.toml @@ -3,6 +3,9 @@ need_libusb = true usb_vid = 0x2c7c usb_pid = 0x0125 +# Delay between setting GPIO and PWRKEY sequence, set in microseconds +poweron_delay = 100000 + # Uncomment the following if you need to change the modem detection timeout on # resume and/or the time during which suspend is blocked after modem boot #[suspend] diff --git a/data/pine64,pinephone-1.1.toml b/data/pine64,pinephone-1.1.toml index c0e9192..f5d2451 100644 --- a/data/pine64,pinephone-1.1.toml +++ b/data/pine64,pinephone-1.1.toml @@ -3,6 +3,9 @@ need_libusb = true usb_vid = 0x2c7c usb_pid = 0x0125 +# Delay between setting GPIO and PWRKEY sequence, set in microseconds +poweron_delay = 100000 + # Uncomment the following if you need to change the modem detection timeout on # resume and/or the time during which suspend is blocked after modem boot #[suspend] diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml index 566ac80..f35c84e 100644 --- a/data/pine64,pinephone-1.2.toml +++ b/data/pine64,pinephone-1.2.toml @@ -1,3 +1,7 @@ +[manager] +# Delay between setting GPIO and PWRKEY sequence, set in microseconds +poweron_delay = 100000 + # Uncomment the following if you need to change the modem detection timeout on # resume and/or the time during which suspend is blocked after modem boot #[suspend] diff --git a/src/manager.c b/src/manager.c index aaa3905..75a88f2 100644 --- a/src/manager.c +++ b/src/manager.c @@ -86,6 +86,9 @@ 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 + if (manager->poweron_delay > 0) + g_usleep(manager->poweron_delay); gpio_sequence_poweron(manager); manager->modem_state = EG25_STATE_POWERED; } else { @@ -300,6 +303,17 @@ int main(int argc, char *argv[]) toml_value = toml_int_in(toml_manager, "usb_pid"); if (toml_value.ok) manager.usb_pid = toml_value.u.i; + + toml_value = toml_int_in(toml_manager, "poweron_delay"); + if (toml_value.ok) { + if (toml_value.u.i >= 0 && toml_value.u.i <= G_MAXULONG) { + // Safe to cast into gulong + manager.poweron_delay = (gulong) toml_value.u.i; + } else { + // Changed from initialized default value but not in range + g_message("Configured poweron_delay out of range, using default"); + } + } } at_init(&manager, toml_table_in(toml_config, "at")); diff --git a/src/manager.h b/src/manager.h index 48ff237..041928a 100644 --- a/src/manager.h +++ b/src/manager.h @@ -33,6 +33,7 @@ struct EG25Manager { gboolean use_libusb; guint usb_vid; guint usb_pid; + gulong poweron_delay; int at_fd; guint at_source; From 84a0ae603df95311a5d5cae9ca04b69fd6784827 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Fri, 26 Mar 2021 13:56:37 +0530 Subject: [PATCH 08/13] 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) From 40136c2a520d3be681aac4201a0e8ef324616140 Mon Sep 17 00:00:00 2001 From: Adam Pigg Date: Wed, 31 Mar 2021 20:13:27 +0100 Subject: [PATCH 09/13] Allow to build without mmglib --- meson.build | 6 +++++- src/at.c | 2 ++ src/manager.c | 10 ++++++++++ src/manager.h | 7 ++++++- src/meson.build | 15 ++++++++++----- src/suspend.c | 6 +++++- 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index fffeada..4c7a523 100644 --- a/meson.build +++ b/meson.build @@ -53,9 +53,13 @@ mgr_deps = [ dependency('gudev-1.0'), dependency('libgpiod'), dependency('libusb-1.0'), - dependency('mm-glib'), ] +mmglib_dep = dependency('mm-glib', required : false) +if mmglib_dep.found() + add_global_arguments('-DHAVE_MMGLIB=1', language : 'c') +endif + subdir('data') subdir('src') subdir('udev') diff --git a/src/at.c b/src/at.c index 32138d0..a34025f 100644 --- a/src/at.c +++ b/src/at.c @@ -77,12 +77,14 @@ static gboolean send_at_command(struct EG25Manager *manager) g_message("Sending command: %s", g_strstrip(command)); } else 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); 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; } diff --git a/src/manager.c b/src/manager.c index dd857b6..c0b8a43 100644 --- a/src/manager.c +++ b/src/manager.c @@ -7,7 +7,11 @@ #include "at.h" #include "gpio.h" #include "manager.h" + +#ifdef HAVE_MMGLIB #include "mm-iface.h" +#endif + #include "ofono-iface.h" #include "suspend.h" #include "udev.h" @@ -35,7 +39,9 @@ static gboolean quit_app(struct EG25Manager *manager) g_message("Request to quit..."); at_destroy(manager); +#ifdef HAVE_MMGLIB mm_iface_destroy(manager); +#endif ofono_iface_destroy(manager); suspend_destroy(manager); udev_destroy(manager); @@ -100,6 +106,7 @@ static gboolean modem_start(struct EG25Manager *manager) return FALSE; } +#ifdef HAVE_MMGLIB void modem_update_state(struct EG25Manager *manager, MMModemState state) { switch (state) { @@ -116,6 +123,7 @@ void modem_update_state(struct EG25Manager *manager, MMModemState state) break; } } +#endif void modem_configure(struct EG25Manager *manager) { @@ -328,7 +336,9 @@ int main(int argc, char *argv[]) at_init(&manager, toml_table_in(toml_config, "at")); gpio_init(&manager, toml_table_in(toml_config, "gpio")); +#ifdef HAVE_MMGLIB mm_iface_init(&manager, toml_table_in(toml_config, "mm-iface")); +#endif 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 d326dc1..30028e6 100644 --- a/src/manager.h +++ b/src/manager.h @@ -9,7 +9,9 @@ #include #include #include +#ifdef HAVE_MMGLIB #include +#endif #include #include "toml.h" @@ -51,9 +53,10 @@ struct EG25Manager { enum ModemIface modem_iface; guint mm_watch; +#ifdef HAVE_MMGLIB MMManager *mm_manager; MMModem *mm_modem; - +#endif guint ofono_watch; GDBOManager *ofono_manager; GDBusConnection *ofono_connection; @@ -80,4 +83,6 @@ void modem_suspend_pre(struct EG25Manager *data); void modem_suspend_post(struct EG25Manager *data); void modem_resume_pre(struct EG25Manager *data); void modem_resume_post(struct EG25Manager *data); +#ifdef HAVE_MMGLIB void modem_update_state(struct EG25Manager *data, MMModemState state); +#endif diff --git a/src/meson.build b/src/meson.build index 6a9f52d..f9eb27f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,18 +7,23 @@ subdir('libgdbofono') -executable ( - 'eg25manager', - [ +src = [ 'at.c', 'at.h', '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', - ], +] + +if mmglib_dep.found() + src += ['mm-iface.c', 'mm-iface.h'] +endif + +executable ( + 'eg25manager', + src, dependencies : mgr_deps, link_with: gdbofono_lib, install : true diff --git a/src/suspend.c b/src/suspend.c index b82ca7e..f9bedf9 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -170,7 +170,11 @@ static void signal_cb(GDBusProxy *proxy, g_message("system is resuming"); take_inhibitor(manager, FALSE); modem_resume_pre(manager); - if (manager->mm_modem || manager->modem_iface == MODEM_IFACE_OFONO) { + if ( +#ifdef HAVE_MMGLIB + manager->mm_modem || +#endif + 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, From dfeab4c79b7a6dddd34eae5e6705d1ccda1348f1 Mon Sep 17 00:00:00 2001 From: Adam Pigg Date: Fri, 9 Apr 2021 08:31:27 +0100 Subject: [PATCH 10/13] Re-order mmglib checking as per suggestion --- meson.build | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/meson.build b/meson.build index 4c7a523..de72a90 100644 --- a/meson.build +++ b/meson.build @@ -47,19 +47,20 @@ eg25_datadir = join_paths(full_datadir, meson.project_name()) add_global_arguments('-D@0@="@1@"'.format('EG25_CONFDIR', eg25_confdir), language : 'c') add_global_arguments('-D@0@="@1@"'.format('EG25_DATADIR', eg25_datadir), language : 'c') +mmglib_dep = dependency('mm-glib', required : false) +if mmglib_dep.found() + add_global_arguments('-DHAVE_MMGLIB=1', language : 'c') +endif + mgr_deps = [ dependency('glib-2.0'), dependency('gio-unix-2.0'), dependency('gudev-1.0'), dependency('libgpiod'), dependency('libusb-1.0'), + mmglib_dep, ] -mmglib_dep = dependency('mm-glib', required : false) -if mmglib_dep.found() - add_global_arguments('-DHAVE_MMGLIB=1', language : 'c') -endif - subdir('data') subdir('src') subdir('udev') From d665ea9639e13de2cd68d93934b75a84ed88bf04 Mon Sep 17 00:00:00 2001 From: Dylan Van Assche Date: Fri, 9 Apr 2021 10:28:39 +0200 Subject: [PATCH 11/13] config: drop URC cache In some internal discussions between me, the ModemManager maintainer and a Quectel engineer, the URC cache we use is unnecessary. I did some testing and removed the URC cache from the configs and it works reliable without affecting the functionality. --- data/pine64,pinephone-1.0.toml | 3 --- data/pine64,pinephone-1.1.toml | 3 --- data/pine64,pinephone-1.2.toml | 3 --- 3 files changed, 9 deletions(-) diff --git a/data/pine64,pinephone-1.0.toml b/data/pine64,pinephone-1.0.toml index cf709f6..e1f5b24 100644 --- a/data/pine64,pinephone-1.0.toml +++ b/data/pine64,pinephone-1.0.toml @@ -45,14 +45,11 @@ configure = [ { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" }, { cmd = "QGPS", value = "1" }, { cmd = "QSCLK", value = "1" }, - { cmd = "QCFG", subcmd = "urc/cache", value = "0" } ] suspend = [ { cmd = "QGPSEND" }, - { cmd = "QCFG", subcmd = "urc/cache", value = "1" } ] resume = [ - { cmd = "QCFG", subcmd = "urc/cache", value = "0" }, { cmd = "QGPS", value = "1" } ] reset = [ { cmd = "CFUN", value = "1,1" } ] diff --git a/data/pine64,pinephone-1.1.toml b/data/pine64,pinephone-1.1.toml index cf709f6..e1f5b24 100644 --- a/data/pine64,pinephone-1.1.toml +++ b/data/pine64,pinephone-1.1.toml @@ -45,14 +45,11 @@ configure = [ { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" }, { cmd = "QGPS", value = "1" }, { cmd = "QSCLK", value = "1" }, - { cmd = "QCFG", subcmd = "urc/cache", value = "0" } ] suspend = [ { cmd = "QGPSEND" }, - { cmd = "QCFG", subcmd = "urc/cache", value = "1" } ] resume = [ - { cmd = "QCFG", subcmd = "urc/cache", value = "0" }, { cmd = "QGPS", value = "1" } ] reset = [ { cmd = "CFUN", value = "1,1" } ] diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml index b22b30f..4ca1274 100644 --- a/data/pine64,pinephone-1.2.toml +++ b/data/pine64,pinephone-1.2.toml @@ -39,14 +39,11 @@ configure = [ { cmd = "QURCCFG", subcmd = "urcport", expect = "\"all\"" }, { cmd = "QGPS", value = "1" }, { cmd = "QSCLK", value = "1" }, - { cmd = "QCFG", subcmd = "urc/cache", value = "0" } ] suspend = [ { cmd = "QGPSEND" }, - { cmd = "QCFG", subcmd = "urc/cache", value = "1" } ] resume = [ - { cmd = "QCFG", subcmd = "urc/cache", value = "0" }, { cmd = "QGPS", value = "1" } ] reset = [ { cmd = "CFUN", value = "1,1" } ] From 0d46f42d78549427d648ba7dc85ba038c3c73f61 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Fri, 9 Apr 2021 14:39:53 +0530 Subject: [PATCH 12/13] udev: match only USB device and not USB interfaces Interfaces can not have a power control, only usb devices. --- udev/80-modem-eg25.rules | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/udev/80-modem-eg25.rules b/udev/80-modem-eg25.rules index fc3b78f..5fb6970 100644 --- a/udev/80-modem-eg25.rules +++ b/udev/80-modem-eg25.rules @@ -1,5 +1,5 @@ -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" +ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/control}="auto" +ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/autosuspend_delay_ms}="3000" +ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/wakeup}="enabled" +ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{avoid_reset_quirk}="1" +ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/persist}="0" From 73e16f76994b1d3c587796a35766cc668e30c0cd Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Fri, 9 Apr 2021 11:29:26 +0200 Subject: [PATCH 13/13] meson.build: release version 0.3.0 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index de72a90..d57d2cb 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,7 @@ project ( 'eg25-manager', 'c', - version : '0.2.0', + version : '0.3.0', license : 'GPLv3+', meson_version : '>= 0.50.0', default_options :