[-]
[+]
|
Changed |
_service:tar_git:eg25-manager.spec
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,7 +2,7 @@
<service name="tar_git">
<param name="url">https://github.com/sailfish-on-dontbeevil/eg25-manager</param>
<param name="branch">main</param>
- <param name="revision">0.4.2+git2</param>
+ <param name="revision">0.4.4+git1</param>
<param name="token"/>
<param name="debian">N</param>
<param name="dumb">N</param>
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/data/eg25-manager.service.in
^
|
@@ -4,7 +4,7 @@
[Service]
Type=simple
-ExecStart=@bindir@/eg25manager
+ExecStart=@bindir@/eg25-manager
Restart=on-failure
ProtectControlGroups=true
ProtectHome=true
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/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 @@
{ 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.
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/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 @@
{ 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.
|
[-]
[+]
|
Added |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/doc/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@/<compatible>.toml*: User-provided overrides (optional)
+ - *@eg25_datadir@/<compatible>.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)
|
[-]
[+]
|
Added |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/doc/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@/<compatible>.toml*: User-provided overrides (optional)
+ - *@eg25_datadir@/<compatible>.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)
|
[-]
[+]
|
Added |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/doc/meson.build
^
|
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2020 Arnaud Ferraris <arnaud.ferraris@gmail.com>
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+scdoc = dependency('scdoc', native: true, required: false)
+if scdoc.found()
+ scdoc_prog = find_program(scdoc.get_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.full_path())],
+ capture: true,
+ install: true,
+ install_dir: join_paths(get_option('mandir'), 'man@0@'.format(section)))
+ endforeach
+endif
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/meson.build
^
|
@@ -8,9 +8,9 @@
project (
'eg25-manager',
'c',
- version : '0.4.2',
+ version : '0.4.4',
license : 'GPLv3+',
- meson_version : '>= 0.50.0',
+ meson_version : '>= 0.58.0',
default_options :
[
'warning_level=1',
@@ -66,5 +66,6 @@
]
subdir('data')
+subdir('doc')
subdir('src')
subdir('udev')
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/src/gpio.c
^
|
@@ -144,7 +144,7 @@
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 @@
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)
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/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)
@@ -141,7 +144,7 @@
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 +152,18 @@
{
int fd, ret, len;
- if (manager->reset_timer) {
+ /* reset sequence started, cannot be canceled anymore */
+ 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...");
return G_SOURCE_REMOVE;
}
@@ -164,11 +178,6 @@
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;
@@ -210,7 +219,7 @@
* 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 +237,7 @@
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;
}
@@ -366,9 +375,11 @@
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);
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/src/manager.h
^
|
@@ -53,6 +53,7 @@
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
};
@@ -70,7 +71,8 @@
struct EG25Manager {
GMainLoop *loop;
- guint reset_timer;
+ guint complete_reset_timer;
+ guint schedule_reset_timer;
gboolean use_libusb;
guint usb_vid;
guint usb_pid;
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/src/meson.build
^
|
@@ -25,7 +25,7 @@
endif
executable (
- 'eg25manager',
+ 'eg25-manager',
src,
dependencies : mgr_deps,
link_with: gdbofono_lib,
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/src/udev.c
^
|
@@ -11,18 +11,47 @@
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 (strcmp(action, "unbind") != 0 ||
- manager->modem_state == EG25_STATE_RESETTING ||
- !manager->modem_usb_id) {
+ /*
+ * 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(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);
+ if (strcmp(action, "unbind") != 0 ||
+ manager->modem_state == EG25_STATE_UPDATING ||
+ manager->modem_state == EG25_STATE_RESETTING ||
+ manager->complete_reset_timer != 0 ||
+ manager->schedule_reset_timer != 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[])
|
[-]
[+]
|
Changed |
_service:tar_git:eg25-manager-0.4.4+git1.tar.bz2/eg25-manager/udev/80-modem-eg25.rules
^
|
@@ -1,4 +1,22 @@
-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{power/persist}="0"
+ACTION!="add", GOTO="eg25_end"
+SUBSYSTEM!="usb", GOTO="eg25_end"
+DRIVER!="usb", GOTO="eg25_end"
+ENV{DEVTYPE}!="usb_device", GOTO="eg25_end"
+
+# Default attributes values
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/control}="auto"
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/autosuspend_delay_ms}="3000"
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/wakeup}="enabled"
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/persist}="0"
+
+# If running the stock firmware, stop processing here
+ATTRS{serial}!="community_fw", GOTO="eg25_end"
+
+# power/control needs to be "on" for the community-maintained firmware
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", ATTR{power/control}="on"
+
+# Special trick for the PinePhone Pro: set power/persist to 1 *only* with the community FW
+# We can identify the PPP by looking for the string "pinephone-pro" in the device tree "compatible" property
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0125", PROGRAM=="/bin/grep pine64,pinephone-pro /proc/device-tree/compatible", ATTR{power/persist}="1"
+
+LABEL="eg25_end"
|