From 88c68b9933f47f863e6685b2b6502d5d7ed1871c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20L=C3=BCke?= Date: Wed, 1 Dec 2021 21:59:46 +0100 Subject: [PATCH 01/16] suspend: actually check if the modem is found before resetting The timeout was meant to give more time to find the modem, yet the callback didn't actually check if it came back but blindly issued a reset. Add a check to the callback to see if the modem was found and only reset if not. Fixes https://gitlab.com/mobian1/devices/eg25-manager/-/issues/28 --- src/suspend.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/suspend.c b/src/suspend.c index 4bace47..190d48d 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -18,11 +18,22 @@ #define SD_PATH "/org/freedesktop/login1" #define SD_INTERFACE "org.freedesktop.login1.Manager" +static void resume_ok(struct EG25Manager *manager) +{ + manager->modem_state = EG25_STATE_CONFIGURED; + modem_resume_post(manager); +} + static gboolean check_modem_resume(struct EG25Manager *manager) { - g_message("Modem wasn't probed in time, restart it!"); manager->modem_recovery_timer = 0; - modem_reset(manager); + + if (manager->mm_modem) { + resume_ok(manager); + } else { + g_message("Modem wasn't probed in time, restart it!"); + modem_reset(manager); + } return FALSE; } @@ -184,8 +195,7 @@ static void signal_cb(GDBusProxy *proxy, * 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); + resume_ok(manager); } else { manager->modem_state = EG25_STATE_RESUMING; manager->modem_recovery_timer = g_timeout_add_seconds(manager->modem_recovery_timeout, From 8665f8a4a6a6742aed68e1ba50e23f625ba28d0b Mon Sep 17 00:00:00 2001 From: Rafael Diniz Date: Thu, 23 Dec 2021 21:12:24 +0300 Subject: [PATCH 02/16] Fix compile error when not using Modem Manager. --- src/suspend.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/suspend.c b/src/suspend.c index 190d48d..9485598 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -28,12 +28,15 @@ static gboolean check_modem_resume(struct EG25Manager *manager) { manager->modem_recovery_timer = 0; +#ifdef HAVE_MMGLIB if (manager->mm_modem) { resume_ok(manager); - } else { - g_message("Modem wasn't probed in time, restart it!"); - modem_reset(manager); + return FALSE; } +#endif + + g_message("Modem wasn't probed in time, restart it!"); + modem_reset(manager); return FALSE; } From fedce7298bd6441526e07aec021687b173142022 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Wed, 15 Dec 2021 15:27:47 +0100 Subject: [PATCH 03/16] manager: start udev monitoring module conditionally The problem addressed by monitoring the modem status through udev seems tied to the specific USB controller used by the A64. On RK3399 devices, this quirk is apparently unneeded, and actually harmful as it resets the modem USB connection while ModemManager is already configuring it. This commit adds an optional config parameter for disabling this module (enabled by default). --- src/manager.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/manager.c b/src/manager.c index cba4e72..4b0ef59 100644 --- a/src/manager.c +++ b/src/manager.c @@ -314,6 +314,7 @@ int main(int argc, char *argv[]) struct EG25Manager manager; gchar *config_file = NULL; gboolean show_version = FALSE; + gboolean monitor_udev = TRUE; toml_table_t *toml_config[EG25_CONFIG_COUNT]; toml_table_t *manager_config[EG25_CONFIG_COUNT]; const GOptionEntry options[] = { @@ -363,6 +364,7 @@ int main(int argc, char *argv[]) if (!manager_config[EG25_CONFIG_SYS]) g_error("Default config file lacks the 'manager' section!"); + config_get_bool(manager_config, "monitor_udev", &monitor_udev); config_get_bool(manager_config, "need_libusb", &manager.use_libusb); config_get_uint(manager_config, "usb_vid", &manager.usb_vid); config_get_uint(manager_config, "usb_pid", &manager.usb_pid); @@ -375,7 +377,8 @@ int main(int argc, char *argv[]) #endif ofono_iface_init(&manager, toml_config); suspend_init(&manager, toml_config); - udev_init(&manager, toml_config); + if (monitor_udev) + udev_init(&manager, toml_config); gnss_init(&manager, toml_config); for (int i = 0; i < EG25_CONFIG_COUNT; i++) { From 50b4c00c16250f76df69bed4bdc29d7cd200a44f Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Wed, 15 Dec 2021 15:29:29 +0100 Subject: [PATCH 04/16] data: add 'monitor_udev' parameter to existing configs We disable dev monitoring only for the PinePhone Pro, it remains enabled for all variants of the OG PinePhone. --- data/pine64,pinephone-1.0.toml | 1 + data/pine64,pinephone-1.1.toml | 1 + data/pine64,pinephone-1.2.toml | 1 + data/pine64,pinephone-pro.toml | 1 + 4 files changed, 4 insertions(+) diff --git a/data/pine64,pinephone-1.0.toml b/data/pine64,pinephone-1.0.toml index 10dbc1e..52df87d 100644 --- a/data/pine64,pinephone-1.0.toml +++ b/data/pine64,pinephone-1.0.toml @@ -1,4 +1,5 @@ [manager] +monitor_udev = true need_libusb = true usb_vid = 0x2c7c usb_pid = 0x0125 diff --git a/data/pine64,pinephone-1.1.toml b/data/pine64,pinephone-1.1.toml index 9242a91..acd8751 100644 --- a/data/pine64,pinephone-1.1.toml +++ b/data/pine64,pinephone-1.1.toml @@ -1,4 +1,5 @@ [manager] +monitor_udev = true need_libusb = true usb_vid = 0x2c7c usb_pid = 0x0125 diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml index 3754274..b3fd6f5 100644 --- a/data/pine64,pinephone-1.2.toml +++ b/data/pine64,pinephone-1.2.toml @@ -1,4 +1,5 @@ [manager] +monitor_udev = true # Delay between setting GPIO and PWRKEY sequence, set in microseconds poweron_delay = 100000 diff --git a/data/pine64,pinephone-pro.toml b/data/pine64,pinephone-pro.toml index 492de96..bdedad2 100644 --- a/data/pine64,pinephone-pro.toml +++ b/data/pine64,pinephone-pro.toml @@ -1,4 +1,5 @@ [manager] +monitor_udev = false # Delay between setting GPIO and PWRKEY sequence, set in microseconds poweron_delay = 100000 From 9cf51b9529f150e8f43582cbc44bc493b986f7e9 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Wed, 15 Dec 2021 15:32:18 +0100 Subject: [PATCH 05/16] pinephone-pro: switch to 16K audio As the modem is connected to a dedicated audio codec, we can select any sample rate. Let's go for 16K as it should improve call audio quality. Note: the bitclock's frequency is left untouched due to a bug in the EG25 kernel, so we can't take advantage of the recommended higher frequency. --- data/pine64,pinephone-pro.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/pine64,pinephone-pro.toml b/data/pine64,pinephone-pro.toml index bdedad2..f3f1733 100644 --- a/data/pine64,pinephone-pro.toml +++ b/data/pine64,pinephone-pro.toml @@ -36,7 +36,7 @@ configure = [ # Print software version { cmd = "QGMR" }, # Configure audio - { cmd = "QDAI", expect = "3,0,0,4,0,0,1,1" }, + { cmd = "QDAI", expect = "3,0,0,4,0,1,1,1" }, # RI signaling using physical RI pin { cmd = "QCFG", subcmd = "risignaltype", expect = "\"physical\"" }, # Enable VoLTE support From 61c89a003ae341334145b740ab5057c34a17aeb0 Mon Sep 17 00:00:00 2001 From: Dylan Van Assche Date: Mon, 20 Dec 2021 14:07:15 +0100 Subject: [PATCH 06/16] udev: cancel reset if modem is already back Cancel reset if modem is back before reset sequence is started. When upgrading the modem through fwupd, it will enter fastboot. Therefore, it disappears from the USB bus for a few ms. However, the eg25-manager considers this as an issue and resets the modem a bit later during the upgrade process. To avoid this, cancel the reset sequence if the modem is already back before the reset sequence is started. This will take less than 3 seconds. --- src/manager.c | 11 +++++++---- src/manager.h | 3 ++- src/udev.c | 23 ++++++++++++++++------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/manager.c b/src/manager.c index 4b0ef59..191dd53 100644 --- a/src/manager.c +++ b/src/manager.c @@ -141,7 +141,7 @@ void modem_configure(struct EG25Manager *manager) static gboolean modem_reset_done(struct EG25Manager* manager) { manager->modem_state = EG25_STATE_RESUMING; - manager->reset_timer = 0; + manager->complete_reset_timer = 0; return FALSE; } @@ -149,7 +149,10 @@ gboolean modem_reset(struct EG25Manager *manager) { int fd, ret, len; - if (manager->reset_timer) { + /* reset sequence started, cannot be canceled anymore */ + manager->schedule_reset_timer = 0; + + if (manager->complete_reset_timer) { g_message("modem_reset: timer already setup, skipping..."); return G_SOURCE_REMOVE; } @@ -210,7 +213,7 @@ gboolean modem_reset(struct EG25Manager *manager) * 3s is long enough to make sure the modem has been bound back and * short enough to ensure it hasn't been acquired by ModemManager */ - manager->reset_timer = g_timeout_add_seconds(3, G_SOURCE_FUNC(modem_reset_done), manager); + manager->complete_reset_timer = g_timeout_add_seconds(3, G_SOURCE_FUNC(modem_reset_done), manager); return G_SOURCE_REMOVE; @@ -228,7 +231,7 @@ error: at_sequence_reset(manager); // Setup timer for making sure we don't queue other reset commands - manager->reset_timer = g_timeout_add_seconds(30, G_SOURCE_FUNC(modem_reset_done), manager); + manager->complete_reset_timer = g_timeout_add_seconds(30, G_SOURCE_FUNC(modem_reset_done), manager); return G_SOURCE_REMOVE; } diff --git a/src/manager.h b/src/manager.h index 2c36348..bccf5dc 100644 --- a/src/manager.h +++ b/src/manager.h @@ -70,7 +70,8 @@ enum EG25Config { struct EG25Manager { GMainLoop *loop; - guint reset_timer; + guint complete_reset_timer; + guint schedule_reset_timer; gboolean use_libusb; guint usb_vid; guint usb_pid; diff --git a/src/udev.c b/src/udev.c index 9790c15..a2e62a3 100644 --- a/src/udev.c +++ b/src/udev.c @@ -12,17 +12,26 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic { struct EG25Manager *manager = data; - if (strcmp(action, "unbind") != 0 || - manager->modem_state == EG25_STATE_RESETTING || - !manager->modem_usb_id) { + if (!manager->modem_usb_id) return; - } if (strcmp(g_udev_device_get_name(device), manager->modem_usb_id) == 0 && - manager->reset_timer == 0) { - g_message("Lost modem, resetting..."); - g_timeout_add_seconds(2, G_SOURCE_FUNC(modem_reset), manager); + strcmp(action, "add") == 0 && manager->schedule_reset_timer != 0) { + g_message("Modem recovered before reset sequence was triggered, cancel reset."); + g_source_remove(manager->schedule_reset_timer); + manager->schedule_reset_timer = 0; + return; } + + if (strcmp(action, "unbind") != 0 || + manager->modem_state == EG25_STATE_RESETTING || + manager->complete_reset_timer != 0 || + strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { + return; + } + + g_message("Lost modem, resetting..."); + manager->schedule_reset_timer = g_timeout_add_seconds(3, G_SOURCE_FUNC(modem_reset), manager); } void udev_init (struct EG25Manager *manager, toml_table_t *config[]) From df7924782160aca6939c29b5b822d388c6a4eb6a Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 4 Jan 2022 15:24:01 +0100 Subject: [PATCH 07/16] manager: populate USB vendor/product ID's with default values We'll need those in the `udev` module, but never made it a mandatory config option. This commit makes sure those values are properly filled in. --- src/manager.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/manager.c b/src/manager.c index 191dd53..9c33e3f 100644 --- a/src/manager.c +++ b/src/manager.c @@ -38,6 +38,9 @@ #define EG25_VERSION "0.0.0" #endif +#define EG25_DEFAULT_VENDOR_ID 0x2c7c +#define EG25_DEFAULT_PRODUCT_ID 0x0125 + #define POWERON_DELAY_US 100000UL static gboolean quit_app(struct EG25Manager *manager) @@ -369,9 +372,11 @@ int main(int argc, char *argv[]) config_get_bool(manager_config, "monitor_udev", &monitor_udev); config_get_bool(manager_config, "need_libusb", &manager.use_libusb); - config_get_uint(manager_config, "usb_vid", &manager.usb_vid); - config_get_uint(manager_config, "usb_pid", &manager.usb_pid); config_get_uint(manager_config, "poweron_delay", &manager.poweron_delay); + if (!config_get_uint(manager_config, "usb_vid", &manager.usb_vid)) + manager.usb_vid = EG25_DEFAULT_VENDOR_ID; + if (!config_get_uint(manager_config, "usb_pid", &manager.usb_pid)) + manager.usb_pid = EG25_DEFAULT_PRODUCT_ID; at_init(&manager, toml_config); gpio_init(&manager, toml_config); From 9e6bccdf37cf9815e66b0bca3a5673218b8d05fb Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 4 Jan 2022 15:26:43 +0100 Subject: [PATCH 08/16] udev: use USB vendor/product ID to determine behavior When going into firmware upgrade mode, the modem comes back with different IDs than in normal use. We should make sure we cancel the reset sequence when that happens, and not start a new one. --- src/manager.h | 1 + src/udev.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/manager.h b/src/manager.h index bccf5dc..43d44bd 100644 --- a/src/manager.h +++ b/src/manager.h @@ -53,6 +53,7 @@ enum EG25State { EG25_STATE_SUSPENDING, // System is going into suspend EG25_STATE_RESUMING, // System is being resumed, waiting for modem to come back EG25_STATE_RESETTING, // Something went wrong, we're restarting the modem + EG25_STATE_UPDATING, // Modem is present but being updated EG25_STATE_FINISHING }; diff --git a/src/udev.c b/src/udev.c index a2e62a3..cc452b1 100644 --- a/src/udev.c +++ b/src/udev.c @@ -11,22 +11,42 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer data) { struct EG25Manager *manager = data; + const gchar *prop; + long vid = 0, pid = 0; - if (!manager->modem_usb_id) - return; - - if (strcmp(g_udev_device_get_name(device), manager->modem_usb_id) == 0 && - strcmp(action, "add") == 0 && manager->schedule_reset_timer != 0) { - g_message("Modem recovered before reset sequence was triggered, cancel reset."); - g_source_remove(manager->schedule_reset_timer); - manager->schedule_reset_timer = 0; + /* + * Act only if the device is the one identified as a modem by MM/ofono + */ + if (!manager->modem_usb_id || + strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { return; } + prop = g_udev_device_get_property(device, "ID_VENDOR_ID"); + if (prop) + vid = strtol(prop, NULL, 16); + + prop = g_udev_device_get_property(device, "ID_MODEL_ID"); + if (prop) + pid = strtol(prop, NULL, 16); + + if (strcmp(action, "bind") == 0 && vid != manager->usb_vid && pid != manager->usb_pid) { + /* + * Modem is probably executing a FW upgrade, make sure we don't interrupt it + */ + if (manager->schedule_reset_timer != 0) { + g_message("Modem re-appeared with different VID/PID, cancel reset."); + g_source_remove(manager->schedule_reset_timer); + manager->schedule_reset_timer = 0; + } + manager->modem_state = EG25_STATE_UPDATING; + } + if (strcmp(action, "unbind") != 0 || + manager->modem_state == EG25_STATE_UPDATING || manager->modem_state == EG25_STATE_RESETTING || manager->complete_reset_timer != 0 || - strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { + manager->schedule_reset_timer != 0) { return; } From 97b1878ebc78c4bac1c765847b37448426813a4a Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 4 Jan 2022 15:28:12 +0100 Subject: [PATCH 09/16] manager: disable reset timers once reset sequence starts `modem_reset()` can be called from multiple places, both tied to a specific timer. In order to prevent calling this function multiple times in a row, disable all related timers as soon as we enter this function. --- src/manager.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/manager.c b/src/manager.c index 9c33e3f..47cbc11 100644 --- a/src/manager.c +++ b/src/manager.c @@ -153,7 +153,15 @@ gboolean modem_reset(struct EG25Manager *manager) int fd, ret, len; /* reset sequence started, cannot be canceled anymore */ - manager->schedule_reset_timer = 0; + if (manager->schedule_reset_timer) { + g_source_remove(manager->schedule_reset_timer); + manager->schedule_reset_timer = 0; + } + + if (manager->modem_recovery_timer) { + g_source_remove(manager->modem_recovery_timer); + manager->modem_recovery_timer = 0; + } if (manager->complete_reset_timer) { g_message("modem_reset: timer already setup, skipping..."); @@ -170,11 +178,6 @@ gboolean modem_reset(struct EG25Manager *manager) return G_SOURCE_REMOVE; } - if (manager->modem_recovery_timer) { - g_source_remove(manager->modem_recovery_timer); - manager->modem_recovery_timer = 0; - } - if (!manager->modem_usb_id) { g_warning("Empty modem USB ID"); goto error; From 75400fb9c001311b8bb06b76dc025f31c8800acf Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 4 Jan 2022 15:29:56 +0100 Subject: [PATCH 10/16] data: add USB vendor/product IDs to all configs PP 1.2 and PPP configs were lacking this parameter. Although it's not a problem as `eg25-manager` will then use a default value, adding them won't harm and make them more consistent with other config files. --- data/pine64,pinephone-1.2.toml | 6 ++++-- data/pine64,pinephone-pro.toml | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/data/pine64,pinephone-1.2.toml b/data/pine64,pinephone-1.2.toml index b3fd6f5..6f06084 100644 --- a/data/pine64,pinephone-1.2.toml +++ b/data/pine64,pinephone-1.2.toml @@ -1,5 +1,7 @@ [manager] monitor_udev = true +usb_vid = 0x2c7c +usb_pid = 0x0125 # Delay between setting GPIO and PWRKEY sequence, set in microseconds poweron_delay = 100000 @@ -61,9 +63,9 @@ configure = [ { cmd = "QSCLK", value = "1" }, # GNSS configuration: # * Enable A-GPS data upload support (XTRA) -# * Disable On-Demand-Positioning (ODP) mode +# * Disable On-Demand-Positioning (ODP) mode # to avoid running the GNSS system in the background, even when not enabled. -# * Enable Dynamic Power Optimizations (DPO) mode to turn off GNSS RF radios +# * Enable Dynamic Power Optimizations (DPO) mode to turn off GNSS RF radios # when they are not in use. # * Only enable GPS and GLONASS, disable other GNSS systems. # A-GPS data upload doesn't work for Galileo anyway. diff --git a/data/pine64,pinephone-pro.toml b/data/pine64,pinephone-pro.toml index f3f1733..6b1348f 100644 --- a/data/pine64,pinephone-pro.toml +++ b/data/pine64,pinephone-pro.toml @@ -1,5 +1,7 @@ [manager] monitor_udev = false +usb_vid = 0x2c7c +usb_pid = 0x0125 # Delay between setting GPIO and PWRKEY sequence, set in microseconds poweron_delay = 100000 @@ -61,9 +63,9 @@ configure = [ { cmd = "QSCLK", value = "1" }, # GNSS configuration: # * Enable A-GPS data upload support (XTRA) -# * Disable On-Demand-Positioning (ODP) mode +# * Disable On-Demand-Positioning (ODP) mode # to avoid running the GNSS system in the background, even when not enabled. -# * Enable Dynamic Power Optimizations (DPO) mode to turn off GNSS RF radios +# * Enable Dynamic Power Optimizations (DPO) mode to turn off GNSS RF radios # when they are not in use. # * Only enable GPS and GLONASS, disable other GNSS systems. # A-GPS data upload doesn't work for Galileo anyway. From a3c51fc513ab8f0ac723875646480c4e0b470fea Mon Sep 17 00:00:00 2001 From: ArenM Date: Tue, 28 Dec 2021 22:32:53 -0500 Subject: [PATCH 11/16] Add manpages for eg25-manager and it's config file --- data/eg25-manager.5.scd | 106 ++++++++++++++++++++++++++++++++++++++++ data/eg25-manager.8.scd | 37 ++++++++++++++ data/meson.build | 28 +++++++++++ 3 files changed, 171 insertions(+) create mode 100644 data/eg25-manager.5.scd create mode 100644 data/eg25-manager.8.scd diff --git a/data/eg25-manager.5.scd b/data/eg25-manager.5.scd new file mode 100644 index 0000000..3d08fde --- /dev/null +++ b/data/eg25-manager.5.scd @@ -0,0 +1,106 @@ +eg25-manager(5) + +# NAME +eg25-manager configuration file format + +# SYNOPSIS +eg25-manager uses toml formatted files for configuration. + +Configurations are loaded from: + - *@eg25_confdir@/.toml*: User-provided overrides (optional) + - *@eg25_datadir@/.toml*: Default configuration (required) + +# SECTION: manager +General settings for eg25-manager. + +*poweron_delay* int (microseconds) + Delay between de-asserting RESET and starting the PWRKEY sequence. + +# SECTION: suspend +Settings for how to handle suspend on the system where eg25-manager is running. + +*boot_timeout* int (seconds) + Prevent the system from suspending for boot_timeout seconds to allow the + modem to fully boot. + + Default: 120 if unset or zero. + +*recovery_timeout* int (seconds) + Amount of time to wait for the modem to reappear after suspend. If the + timeout is reached the modem's USB connection will be reset. + + Default: 9 if unset or zero. + +# SECTION: at +AT commands to send when different events happen, and where to send them to. + +Each command has 4 possible elements: + - *cmd*: the AT command itself, which will be translated to "AT+`cmd`" + - *subcmd*: the subcommand in case a single AT command can be used to + change multiple parameters, such as QCFG + - *value*: the command's argument(s), usually used to set the value of a + specific parameter + - *expect*: the expected return value; the command is first executed + without any value in order to query the current state. This state is + then compared to the *expect* string; if they don't match, the command + is then executed with value *expect* in order to set the parameter to + the expected value +A command can have *expect* OR *value* configured, but it shouldn't have both + +*NOTE:* If a command sequence is configured in an override file, the default +commands won't be loaded from the system configuration. The default commands +should be copied into the override file when changing them. + +*uart* string + The serial port to use for sending AT commands to the modem. + +*configure* List of commands + AT commands to send to the modem when it is first started. + +*suspend* List of commands + AT commands to send to the modem before the system suspends. + +*resume* List of commands + AT commands to send to the modem after the system resumes from suspend. + +*reset* List of commands + AT commands to send to the modem if resetting the usb port fails. + +# SECTION: gnss +Settings for uploading AGPS assistance data to the modem. + +*enabled* boolean + Enable or disable uploading AGPS data to the modem + +*url* string + The directory on the server that contains the assistance files + + Example: https://xtrapath4.izatcloud.net + +*file* string + The name of the assistance file on the server. + + Example: xtra2.bin + +# SECTION: gpio +The *gpio* section defines the GPIO pins to use for different modem functions. +These settings should only be changed when porting eg25-manager to a new device; +for this reason they aren't documented here. + +# EXAMPLES +Print the firmware version every time the phone wakes from suspend: +``` +[at] +resume = [ + { cmd = "QGMR" }, +] +``` + +Disable uploading AGPS data to the modem: +``` +[gnss] +enabled = false +``` + +# SEE AlSO +*eg25-manager*(8) diff --git a/data/eg25-manager.8.scd b/data/eg25-manager.8.scd new file mode 100644 index 0000000..095c9e4 --- /dev/null +++ b/data/eg25-manager.8.scd @@ -0,0 +1,37 @@ +eg25-manager(8) + +# NAME +eg25-manager - a daemon for managing the Quectel EG25 modem found on the +Pine64 PinePhone. + +# SYNOPSIS +*eg25-manager* [-v] [-c config_file] + +# OPTIONS +*-v* + Show the version number and quit. +*-c* + User configuration file, defaults to the device configuration file in + /etc/eg25-manager. + +# FILES +Configurations are loaded from: + - *@eg25_confdir@/.toml*: User-provided overrides (optional) + - *@eg25_datadir@/.toml*: Default configuration (required) + +eg25-manager will search these folders for files named after the value of the +compatible device-tree property (with the .toml file extension) and use the +first matching file in each directory. If no matching default configuration is +found, eg25-manager will exit with an error message. + +Values from the user-provided overrides will take priority over values stored in +the default configuration. Only changed values must be stored as user overrides, +so eg25-manager can fall back to the default configuration as often as possible. + +The file names eg25-manager will check can be listed using: +``` +xargs -0 printf '%s.toml\\n' < /proc/device-tree/compatible +``` + +# SEE ALSO +*eg25-manager*(5) *ModemManager*(8) *ofono*(8) diff --git a/data/meson.build b/data/meson.build index f1fc8f0..4da2c6e 100644 --- a/data/meson.build +++ b/data/meson.build @@ -22,3 +22,31 @@ configure_file( configuration: serviceconf, install: true ) + +scdoc = dependency('scdoc', native: true, required: false) +if scdoc.found() + scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) + + foreach section: [5, 8] + name = 'eg25-manager' + out = '@0@.@1@'.format(name, section) + + preprocessed = configure_file( + input: '@0@.scd'.format(out), + output: '@BASENAME@.preprocessed', + configuration: { + 'eg25_confdir': eg25_confdir, + 'eg25_datadir': eg25_datadir, + } + ) + + custom_target( + out, + output: out, + input: preprocessed, + command: ['sh', '-c', '@0@ < @INPUT@'.format(scdoc_prog.path())], + capture: true, + install: true, + install_dir: join_paths(get_option('mandir'), 'man@0@'.format(section))) + endforeach +endif From 19eb488e290f1e76bfd7faa46e5222ab3d655bf8 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Wed, 16 Feb 2022 18:35:36 +0100 Subject: [PATCH 12/16] gpio: fix init for BH edition PinePhone BH PinePhone don't have the modem's `STATUS` pin connected to the SoC, and as such require using `libusb` for checking the modem power state. We didn't handle this case previously due to lack of on-device testing, causing BH phones to fail with newer versions. This patch ignores the `status` GPIO for devices relying on `libusb`, which are only pre-CE PinePhones. --- src/gpio.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gpio.c b/src/gpio.c index 49bee0d..ad74f34 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -144,7 +144,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) if (!gpio_config[EG25_CONFIG_SYS]) g_error("Default config file lacks the 'gpio' section!"); - /* + /* * The system config could have the `chips` key, but the user one * could still use the old format! In order to avoid problems, we * should use the new format only if: @@ -196,8 +196,13 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) for (i = 0; i < GPIO_IN_COUNT; i++) { toml_table_t *table; toml_datum_t chip, line; - if (!config_get_table(gpio_config, gpio_in_names[i], &table)) + + if (!config_get_table(gpio_config, gpio_in_names[i], &table)) { + // BH edition don't have the STATUS line connected, ignore it + if (manager->use_libusb && g_strcmp0(gpio_in_names[i], "status") == 0) + continue; g_error("Unable to get config for input GPIO '%s'", gpio_in_names[i]); + } chip = toml_int_in(table, "chip"); if (!chip.ok || chip.u.i < 0 || chip.u.i > 2) From be1ae18592efcb8d31704614ae820dd2eae03d49 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Sat, 19 Feb 2022 15:02:29 +0100 Subject: [PATCH 13/16] Move manpages to doc/ subfolder --- data/meson.build | 28 --------------------------- {data => doc}/eg25-manager.5.scd | 0 {data => doc}/eg25-manager.8.scd | 0 doc/meson.build | 33 ++++++++++++++++++++++++++++++++ meson.build | 1 + 5 files changed, 34 insertions(+), 28 deletions(-) rename {data => doc}/eg25-manager.5.scd (100%) rename {data => doc}/eg25-manager.8.scd (100%) create mode 100644 doc/meson.build diff --git a/data/meson.build b/data/meson.build index 4da2c6e..f1fc8f0 100644 --- a/data/meson.build +++ b/data/meson.build @@ -22,31 +22,3 @@ configure_file( configuration: serviceconf, install: true ) - -scdoc = dependency('scdoc', native: true, required: false) -if scdoc.found() - scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) - - foreach section: [5, 8] - name = 'eg25-manager' - out = '@0@.@1@'.format(name, section) - - preprocessed = configure_file( - input: '@0@.scd'.format(out), - output: '@BASENAME@.preprocessed', - configuration: { - 'eg25_confdir': eg25_confdir, - 'eg25_datadir': eg25_datadir, - } - ) - - custom_target( - out, - output: out, - input: preprocessed, - command: ['sh', '-c', '@0@ < @INPUT@'.format(scdoc_prog.path())], - capture: true, - install: true, - install_dir: join_paths(get_option('mandir'), 'man@0@'.format(section))) - endforeach -endif diff --git a/data/eg25-manager.5.scd b/doc/eg25-manager.5.scd similarity index 100% rename from data/eg25-manager.5.scd rename to doc/eg25-manager.5.scd diff --git a/data/eg25-manager.8.scd b/doc/eg25-manager.8.scd similarity index 100% rename from data/eg25-manager.8.scd rename to doc/eg25-manager.8.scd diff --git a/doc/meson.build b/doc/meson.build new file mode 100644 index 0000000..975d233 --- /dev/null +++ b/doc/meson.build @@ -0,0 +1,33 @@ +# +# Copyright (C) 2020 Arnaud Ferraris +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +scdoc = dependency('scdoc', native: true, required: false) +if scdoc.found() + scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) + + foreach section: [5, 8] + name = 'eg25-manager' + out = '@0@.@1@'.format(name, section) + + preprocessed = configure_file( + input: '@0@.scd'.format(out), + output: '@BASENAME@.preprocessed', + configuration: { + 'eg25_confdir': eg25_confdir, + 'eg25_datadir': eg25_datadir, + } + ) + + custom_target( + out, + output: out, + input: preprocessed, + command: ['sh', '-c', '@0@ < @INPUT@'.format(scdoc_prog.path())], + capture: true, + install: true, + install_dir: join_paths(get_option('mandir'), 'man@0@'.format(section))) + endforeach +endif diff --git a/meson.build b/meson.build index 535927a..d7eae66 100644 --- a/meson.build +++ b/meson.build @@ -66,5 +66,6 @@ mgr_deps = [ ] subdir('data') +subdir('doc') subdir('src') subdir('udev') From 5e4c797695d2989ef82e033bcc6ed26605d4a959 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Sat, 19 Feb 2022 15:05:31 +0100 Subject: [PATCH 14/16] meson: bump minimum version `doc/meson.build` used currently-deprecated functions. Replace those with the proper alternatives, which were introduced in a newer meson version than our requirement. As a consequence, bump minimal version. --- doc/meson.build | 4 ++-- meson.build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/meson.build b/doc/meson.build index 975d233..a86005a 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -6,7 +6,7 @@ scdoc = dependency('scdoc', native: true, required: false) if scdoc.found() - scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) + scdoc_prog = find_program(scdoc.get_variable('scdoc'), native: true) foreach section: [5, 8] name = 'eg25-manager' @@ -25,7 +25,7 @@ if scdoc.found() out, output: out, input: preprocessed, - command: ['sh', '-c', '@0@ < @INPUT@'.format(scdoc_prog.path())], + command: ['sh', '-c', '@0@ < @INPUT@'.format(scdoc_prog.full_path())], capture: true, install: true, install_dir: join_paths(get_option('mandir'), 'man@0@'.format(section))) diff --git a/meson.build b/meson.build index d7eae66..7ec7d24 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,7 @@ project ( 'c', version : '0.4.2', license : 'GPLv3+', - meson_version : '>= 0.50.0', + meson_version : '>= 0.58.0', default_options : [ 'warning_level=1', From 0e2311fb36b6c14348ab74c224786129cd5535c4 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Sat, 19 Feb 2022 15:06:36 +0100 Subject: [PATCH 15/16] Rename executable to `eg25-manager` This brings more consistency with how other components are named (repo, package, service file, manpages...). --- data/eg25-manager.service.in | 2 +- src/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/eg25-manager.service.in b/data/eg25-manager.service.in index fe050c1..7e1e6fc 100644 --- a/data/eg25-manager.service.in +++ b/data/eg25-manager.service.in @@ -4,7 +4,7 @@ Before=ModemManager.service [Service] Type=simple -ExecStart=@bindir@/eg25manager +ExecStart=@bindir@/eg25-manager Restart=on-failure ProtectControlGroups=true ProtectHome=true diff --git a/src/meson.build b/src/meson.build index cc13d2f..6f9e767 100644 --- a/src/meson.build +++ b/src/meson.build @@ -25,7 +25,7 @@ if mmglib_dep.found() endif executable ( - 'eg25manager', + 'eg25-manager', src, dependencies : mgr_deps, link_with: gdbofono_lib, From ee70cf7d2f3927a5f9feae9171805249abd6c32d Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Sat, 19 Feb 2022 15:06:53 +0100 Subject: [PATCH 16/16] meson.build: release version 0.4.3 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 7ec7d24..85d11ab 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,7 @@ project ( 'eg25-manager', 'c', - version : '0.4.2', + version : '0.4.3', license : 'GPLv3+', meson_version : '>= 0.58.0', default_options :