24 Commits

Author SHA1 Message Date
Egor Shestakov
0d5117d4e3 set proper version 2025-01-14 18:11:11 +07:00
Arnaud Ferraris
9f8ae70cba gitlab-ci: add static analysis check
Similar to the formatting check job, take advantage of the `clang-tidy`
configuration we just created to add a new job running this tool.

Running `clang-tidy` requires the following:
* build dependencies must be present on the system so it can resolve the
  includes
* the build folder must be configured as it relies on the
  `compile_commands.json` to get build flags (such as the include paths)

This could be run in the `build` job, but it would make it harder to
understand the actual underlying issue, so this is executed as a new,
separate job, re-using the artifacts from the `build` job.
2024-11-12 13:10:43 +01:00
Arnaud Ferraris
f978b775e0 src: fix issues reported by clang-tidy
Some of those are simply ignored as they're false positives.
2024-11-12 13:10:43 +01:00
Arnaud Ferraris
2c311b9022 add clang-tidy configuration
This will allow us to run a static analysis tool, catching the most
obvious issues (use-after-free, potential NULL dereference...) and
(hopefully) increasing this software's overall robustness.
2024-11-12 13:10:43 +01:00
Arnaud Ferraris
c785f7cb8d add gitlab CI pipeline
The current pipeline (from Mobian) just doesn't work, we should get to
a more efficient, simpler one.

With the `clang-format` config now in place, this pipeline has 2 jobs:
* ensure the code is properly formatted
* run a test build to make sure it won't break
2024-11-12 13:10:43 +01:00
Arnaud Ferraris
9f6178dafd src: format using clang-format 2024-10-30 12:01:46 +01:00
Arnaud Ferraris
57142c2c11 add clang-format configuration
This will ensure our coding style is more clearly defined and allow
contibutors to auto-format their code, bringing some more consistency.
2024-10-30 11:59:45 +01:00
Aren Moynihan
99aa7e2bf7 gpio: remove handling of W_DISABLE pin
The PinePhone has circuitry that makes this pin active-high, but the
PinePhone Pro doesn't appear to, which means we would need read active
high / active low from the config file. Since the modem works fine
without setting this pin, remove the logic to handle the W_DISBALE pin.
2024-10-28 16:08:37 -04:00
Aren Moynihan
ce0fc25892 at: don't clear the resetting state on sequence end
If the reset sequence fails, we don't want to transition to the powered
state, instead we should stay in the resetting state so we eventually
timeout and try a gpio reset. If the reset command succeeds the modem
will eventually send RDY and transition the state to STARTED.

Since this might take longer to change the modem state, add 15 seconds
(for a total of 45) to the at reset timeout just in case. It looks like
the modem typically takes about 20 between sending "AT+CFUN=1,1" and
receiving "RDY", so this should be plenty.
2024-10-28 12:48:08 -04:00
Aren Moynihan
ec96153b0f at: fix indentation
A few tabs slipped in here, convert them to spaces.
2024-10-28 12:47:24 -04:00
Arnaud Ferraris
b000a75238 meson.build: release version 0.5.1 2024-10-28 09:37:49 +01:00
Aren Moynihan
541aa00198 gpio: disable airplane mode when starting the modem
I'm not sure why this was being done when disabling the modem, move it
to the powerup sequence for more consistency.
2024-10-21 16:54:58 -04:00
Aren Moynihan
b53702ad0b manager: modem_reset: fix file descriptor leek
fd wasn't being closed if the write failed. Theoretically if a system
with an unstable modem ran for long enough, this could bring down
eg25-manager.
2024-10-21 16:54:58 -04:00
Aren Moynihan
1482899888 manager: reset using gpio pins if the mode is unresponsive
If the modem doesn't respond to the at reboot sequence, this will
attempt reboot the modem using both the power pin and then the reset pin
in case that doesn't work.
2024-10-21 16:54:58 -04:00
Aren Moynihan
c4b3b75047 manager: always set the reset line when exiting
This splits the logic from gpio_check_poweroff into two separate
functions, allowing the caller more control over when the reset line is
asserted to force the modem to turn off.

Previously if the modem didn't respond to the power key sequence in
quit_app, gpio_check_poweroff wouldn't set the reset pin, and
eg25-manager could leave the modem running after exiting.
2024-10-04 17:11:26 -04:00
Aren Moynihan
3c5d455f20 gpio: toggle the RESET_N pin before booting the modem to ensure it is actually off 2024-10-04 17:08:45 -04:00
Arnaud Ferraris
1acd15ca2f src: gnss: fix build on 32-bit architectures
It seems `off_t` is now 64-bits wide on 32-bit architectures, so using
`glong` causes a build failure in this case. Switch to using the correct
type from the `sendfile()` prototype to fix this.
2024-08-27 11:01:08 +02:00
Arnaud Ferraris
012c09e630 meson.build: release version 0.5.0 2024-08-27 09:45:45 +02:00
Arnaud Ferraris
40623d1572 src: gpio: small cleanups following the port to libgpiod 2.x 2024-08-27 09:44:52 +02:00
marcin
93bdfbdfa2 libgpiod 2.0: specify that we need at least libgpiod 2.0 2024-05-13 23:19:28 +02:00
marcin
bc5a25b17e gpio: libgpiod 2.0: port gpiod_line_{get,set}_value 2024-05-13 23:16:35 +02:00
marcin
b1bb871eb7 gpio: libgpiod 2.0: port gpiod_chip_num_lines 2024-05-13 23:16:35 +02:00
marcin
88e85ae7c2 gpio: libgpiod 2.0: port gpio_get_{input,output}_line 2024-05-13 23:16:27 +02:00
marcin
b8ff1ef3d4 gpio: libgpiod 2.0: port gpiod_chip_open_by_label 2024-05-13 23:02:58 +02:00
22 changed files with 2714 additions and 2273 deletions

48
.clang-format Normal file
View File

@@ -0,0 +1,48 @@
BasedOnStyle: LLVM
ColumnLimit: 100
IndentWidth: 4
IndentGotoLabels: false
AlignArrayOfStructures: Left
AlignConsecutiveAssignments: None
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveDeclarations:
Enabled: true
# Available only with clang-format 20+
# AlignFunctionDeclarations: true
AlignFunctionPointers: true
# Ensure we either have all args/params on a single line,
# or only one per line
BinPackArguments: false
BinPackParameters: false
# To be changed for clang-format 20+
# BinPackParameters: OnePerLine
# Avoid single-line enums/functions/ifs/loops/etc
AllowShortBlocksOnASingleLine: Never
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortCaseExpressionOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
BreakBeforeBinaryOperators: None
# Ensure function opening brackets are on their own line
BreakBeforeBraces: Linux
# Available only with clang-format 20+
# BreakBinaryOperations: OnePerLine
InsertNewlineAtEOF: true
# Don't be too strict on line lengths
PenaltyExcessCharacter: 10
# Prefer breaking arguments list over putting a function call
# on its own line after an assignment
PenaltyBreakAssignment: 200
PenaltyBreakBeforeFirstCallParameter: 200
# Ensure we never ever have the return type on a single line
PenaltyReturnTypeOnItsOwnLine: 1000

4
.clang-tidy Normal file
View File

@@ -0,0 +1,4 @@
# DeprecatedOrUnsafeBufferHandling requests that we use safe versions
# of mem{cpy,set} for example, but this would affect portability
Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling'
WarningsAsErrors: 'clang-diagnostic-*,clang-analyzer-*'

49
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,49 @@
stages:
- build
- check
variables:
CLANG_VERSION: 19
BUILD_DEPS_NO_MM: "build-essential libcurl4-openssl-dev libgpiod-dev libgudev-1.0-dev libusb-1.0-0-dev meson scdoc"
BUILD_DEPS: "${BUILD_DEPS_NO_MM} libmm-glib-dev"
image: debian:unstable-slim
build:
stage: build
script:
- apt-get update
- apt-get -y install ${BUILD_DEPS}
- meson build
- meson compile -C build
artifacts:
paths:
- build
# ModemManager is an optional dependency, let's ensure eg25-manager still builds fine without it
build-no-mm:
stage: build
script:
- apt-get update
- apt-get -y install ${BUILD_DEPS_NO_MM}
- meson build
- meson compile -C build
format:
stage: check
dependencies:
- build
script:
- apt-get update
- apt-get -y install ${BUILD_DEPS} clang-format-${CLANG_VERSION}
- ninja -C build clang-format-check
check:
stage: check
dependencies:
- build
script:
- apt-get update
# clang-tidy needs all dependencies to be installed so it can inspect their headers
- apt-get -y install ${BUILD_DEPS} clang-tidy-${CLANG_VERSION}
- ninja -C build clang-tidy

View File

@@ -15,7 +15,7 @@ It implements the following features:
`eg25-manager` requires the following development libraries:
- libglib2.0-dev
- libgpiod-dev
- libgpiod-dev (>= 2.0)
- libmm-glib-dev
## Building

View File

@@ -8,7 +8,7 @@
project (
'eg25-manager',
'c',
version : '0.4.6',
version : '0.5.2',
license : 'GPLv3+',
meson_version : '>= 0.58.0',
default_options :
@@ -59,7 +59,7 @@ mgr_deps = [
dependency('glib-2.0'),
dependency('gio-unix-2.0'),
dependency('gudev-1.0'),
dependency('libgpiod'),
dependency('libgpiod', version: '>= 2.0'),
dependency('libusb-1.0'),
dependency('libcurl'),
mmglib_dep,

View File

@@ -6,9 +6,9 @@
#include "at.h"
#include "config.h"
#include "suspend.h"
#include "gpio.h"
#include "gnss.h"
#include "gpio.h"
#include "suspend.h"
#include <errno.h>
#include <fcntl.h>
@@ -28,7 +28,7 @@ static GArray *reset_commands = NULL;
static int configure_serial(const char *tty)
{
struct termios ttycfg;
int fd;
int fd;
fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd > 0) {
@@ -50,52 +50,58 @@ static int configure_serial(const char *tty)
static void at_free_command(gpointer cmd, gpointer data)
{
struct AtCommand *at_cmd = cmd;
struct AtCommand *at_cmd = cmd;
struct EG25Manager *manager = data;
if (!at_cmd)
return;
if (manager && manager->at_cmds)
manager->at_cmds = g_list_remove(manager->at_cmds, at_cmd);
g_free(at_cmd->cmd);
g_free(at_cmd->subcmd);
g_free(at_cmd->value);
g_free(at_cmd->expected);
g_free(at_cmd);
if (manager && manager->at_cmds)
manager->at_cmds = g_list_remove(manager->at_cmds, at_cmd);
}
gboolean at_send_command(struct EG25Manager *manager)
{
char command[256];
char command[256];
struct AtCommand *at_cmd = manager->at_cmds ? g_list_nth_data(manager->at_cmds, 0) : NULL;
int ret, len = 0, pos = 0;
int ret, len = 0, pos = 0;
if (at_cmd) {
/* Wake up the modem from soft sleep before sending an AT command */
gpio_sequence_wake(manager);
/* Wake up the modem from soft sleep before sending an AT command */
gpio_sequence_wake(manager);
/* Send AT command */
/* Send AT command */
if (at_cmd->subcmd == NULL && at_cmd->value == NULL && at_cmd->expected == NULL)
len = snprintf(command, sizeof(command), "AT+%s\r\n", at_cmd->cmd);
else if (at_cmd->subcmd == NULL && at_cmd->value == NULL)
len = snprintf(command, sizeof(command), "AT+%s?\r\n", at_cmd->cmd);
else if (at_cmd->subcmd == NULL && at_cmd->value)
len = snprintf(command, sizeof(command),"AT+%s=%s\r\n", at_cmd->cmd, at_cmd->value);
len = snprintf(command, sizeof(command), "AT+%s=%s\r\n", at_cmd->cmd, at_cmd->value);
else if (at_cmd->subcmd && at_cmd->value == NULL)
len = snprintf(command, sizeof(command), "AT+%s=\"%s\"\r\n", at_cmd->cmd, at_cmd->subcmd);
else if (at_cmd->subcmd && at_cmd->value)
len = snprintf(command, sizeof(command), "AT+%s=\"%s\",%s\r\n", at_cmd->cmd, at_cmd->subcmd, at_cmd->value);
len = snprintf(command,
sizeof(command),
"AT+%s=\"%s\",%s\r\n",
at_cmd->cmd,
at_cmd->subcmd,
at_cmd->value);
if (len < 0) {
g_warning("snprintf(3) failed");
at_next_command(manager);
return FALSE;
}
else if (len >= sizeof(command)) {
} else if (len >= sizeof(command)) {
g_warning("AT command does not fit into buffer "
"(%d bytes required, %zu available)", len, sizeof(command));
"(%d bytes required, %zu available)",
len,
sizeof(command));
at_next_command(manager);
return FALSE;
}
@@ -117,8 +123,7 @@ gboolean at_send_command(struct EG25Manager *manager)
at_next_command(manager);
return FALSE;
}
}
else {
} else {
len -= ret;
pos += ret;
}
@@ -126,8 +131,8 @@ gboolean at_send_command(struct EG25Manager *manager)
g_message("Successfully sent command: %s", g_strstrip(command));
} else {
/* Allow the modem to enter soft sleep again when we sent the AT command*/
gpio_sequence_sleep(manager);
/* 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) {
@@ -146,8 +151,6 @@ gboolean at_send_command(struct EG25Manager *manager)
}
} 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;
}
}
@@ -178,8 +181,7 @@ static void retry_at_command(struct EG25Manager *manager)
}
}
void at_process_result(struct EG25Manager *manager,
const char *response)
void at_process_result(struct EG25Manager *manager, const char *response)
{
struct AtCommand *at_cmd = manager->at_cmds ? g_list_nth_data(manager->at_cmds, 0) : NULL;
@@ -203,9 +205,7 @@ int at_append_command(struct EG25Manager *manager,
const char *subcmd,
const char *value,
const char *expected,
void (*callback)
(struct EG25Manager *manager,
const char *response))
void (*callback)(struct EG25Manager *manager, const char *response))
{
struct AtCommand *at_cmd = calloc(1, sizeof(struct AtCommand));
@@ -229,14 +229,12 @@ int at_append_command(struct EG25Manager *manager,
#define READ_BUFFER_SIZE 256
static gboolean modem_response(gint fd,
GIOCondition event,
gpointer data)
static gboolean modem_response(gint fd, GIOCondition event, gpointer data)
{
struct EG25Manager *manager = data;
char response[READ_BUFFER_SIZE*4+1];
char tmp[READ_BUFFER_SIZE];
ssize_t ret, pos = 0;
char response[READ_BUFFER_SIZE * 4 + 1];
char tmp[READ_BUFFER_SIZE];
ssize_t ret, pos = 0;
/*
* Several reads can be necessary to get the full response, so we loop
@@ -321,8 +319,8 @@ static void parse_commands_list(toml_array_t *array, GArray **cmds)
g_array_set_size(*cmds, (guint)len);
for (int i = 0; i < len; i++) {
struct AtCommand *cmd = &g_array_index(*cmds, struct AtCommand, i);
toml_table_t *table = toml_table_at(array, i);
toml_datum_t value;
toml_table_t *table = toml_table_at(array, i);
toml_datum_t value;
if (!table)
continue;
@@ -348,7 +346,7 @@ static void parse_commands_list(toml_array_t *array, GArray **cmds)
int at_init(struct EG25Manager *manager, toml_table_t *config[])
{
toml_array_t *commands = NULL;
gchar *uart_port = NULL;
gchar *uart_port = NULL;
toml_table_t *at_config[EG25_CONFIG_COUNT];
for (int i = 0; i < EG25_CONFIG_COUNT; i++)

View File

@@ -13,25 +13,22 @@ typedef struct AtCommand {
char *subcmd;
char *value;
char *expected;
void (*callback)(struct EG25Manager *manager, const char *response);
int retries;
void (*callback)(struct EG25Manager *manager, const char *response);
int retries;
} AtCommand;
int at_init(struct EG25Manager *manager, toml_table_t *config[]);
int at_init(struct EG25Manager *manager, toml_table_t *config[]);
void at_destroy(struct EG25Manager *manager);
void at_process_result(struct EG25Manager *manager,
const char *response);
void at_next_command(struct EG25Manager *manager);
void at_process_result(struct EG25Manager *manager, const char *response);
void at_next_command(struct EG25Manager *manager);
gboolean at_send_command(struct EG25Manager *manager);
int at_append_command(struct EG25Manager *manager,
const char *cmd,
const char *subcmd,
const char *value,
const char *expected,
void (*callback)
(struct EG25Manager *manager,
const char *response));
int at_append_command(struct EG25Manager *manager,
const char *cmd,
const char *subcmd,
const char *value,
const char *expected,
void (*callback)(struct EG25Manager *manager, const char *response));
void at_sequence_configure(struct EG25Manager *manager);
void at_sequence_suspend(struct EG25Manager *manager);

View File

@@ -9,7 +9,7 @@
gboolean config_get_bool(toml_table_t **config, const gchar *key, gboolean *result)
{
toml_datum_t value = { .ok = 0 };
toml_datum_t value = {.ok = 0};
if (config[EG25_CONFIG_USER])
value = toml_bool_in(config[EG25_CONFIG_USER], key);
@@ -23,7 +23,7 @@ gboolean config_get_bool(toml_table_t **config, const gchar *key, gboolean *resu
gboolean config_get_int(toml_table_t **config, const gchar *key, gint *result)
{
toml_datum_t value = { .ok = 0 };
toml_datum_t value = {.ok = 0};
if (config[EG25_CONFIG_USER])
value = toml_int_in(config[EG25_CONFIG_USER], key);
@@ -37,7 +37,7 @@ gboolean config_get_int(toml_table_t **config, const gchar *key, gint *result)
gboolean config_get_uint(toml_table_t **config, const gchar *key, guint *result)
{
gint value;
gint value;
gboolean found;
found = config_get_int(config, key, &value);
@@ -49,14 +49,14 @@ gboolean config_get_uint(toml_table_t **config, const gchar *key, guint *result)
}
if (found && result)
*result = (guint) value;
*result = (guint)value;
return found;
}
gboolean config_get_string(toml_table_t **config, const gchar *key, gchar **result)
{
toml_datum_t value = { .ok = 0 };
toml_datum_t value = {.ok = 0};
if (config[EG25_CONFIG_USER])
value = toml_string_in(config[EG25_CONFIG_USER], key);

View File

@@ -4,18 +4,18 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "config.h"
#include "gnss.h"
#include "manager.h"
#include "at.h"
#include "config.h"
#include "manager.h"
#include <errno.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <errno.h>
#define BUFFER_SIZE 256
#define UPLOAD_DELAY_US 25000
#define UPLOAD_TIMEOUT_S 10
#define BUFFER_SIZE 256
#define UPLOAD_DELAY_US 25000
#define UPLOAD_TIMEOUT_S 10
#define RESCHEDULE_IN_SECS 30
static void gnss_step(struct EG25Manager *manager);
@@ -29,26 +29,25 @@ gboolean gnss_upload_assistance_data(struct EG25Manager *manager)
if (manager->gnss_assistance_step < EG25_GNSS_STEP_LAST) {
g_warning("GNSS assistance data upload already in process (%d/%d)",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
return FALSE;
}
/* data upload isn't necessary to bring the modem onine, so we should wait
* until we've finished the rest of our configuration */
if (!manager->modem_iface ||
manager->modem_state < EG25_STATE_CONFIGURED ||
manager->modem_state > EG25_STATE_CONNECTED) {
g_message ("Rescheduling upload since modem isn't online yet, in %ds",
RESCHEDULE_IN_SECS);
if (!manager->modem_iface || manager->modem_state < EG25_STATE_CONFIGURED ||
manager->modem_state > EG25_STATE_CONNECTED) {
g_message("Rescheduling upload since modem isn't online yet, in %ds", RESCHEDULE_IN_SECS);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
return TRUE;
}
#ifdef HAVE_MMGLIB
/* ModemManager's Location is only available after unlocking */
if(manager->modem_iface == MODEM_IFACE_MODEMMANAGER && !manager->mm_location) {
g_message ("Rescheduling upload since Location interface is not available, in %ds",
RESCHEDULE_IN_SECS);
if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER && !manager->mm_location) {
g_message("Rescheduling upload since Location interface is not available, in %ds",
RESCHEDULE_IN_SECS);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
return TRUE;
}
@@ -62,7 +61,7 @@ gboolean gnss_upload_assistance_data(struct EG25Manager *manager)
void gnss_init(struct EG25Manager *manager, toml_table_t *config[])
{
toml_table_t *gnss_config[EG25_CONFIG_COUNT];
g_autoptr (GError) error = NULL;
g_autoptr(GError) error = NULL;
for (int i = 0; i < EG25_CONFIG_COUNT; i++)
gnss_config[i] = config[i] ? toml_table_in(config[i], "gnss") : NULL;
@@ -92,12 +91,11 @@ void gnss_init(struct EG25Manager *manager, toml_table_t *config[])
/* Create temporary file to store assistance data */
manager->gnss_assistance_fd = g_file_open_tmp(NULL, NULL, &error);
if (error != NULL)
g_error ("Unable to create temporary file: %s", error->message);
g_error("Unable to create temporary file: %s", error->message);
/* Initialize state and schedule upload */
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
G_SOURCE_FUNC(gnss_upload_assistance_data), manager);
g_timeout_add_seconds(RESCHEDULE_IN_SECS, G_SOURCE_FUNC(gnss_upload_assistance_data), manager);
}
void gnss_destroy(struct EG25Manager *manager)
@@ -113,8 +111,8 @@ void gnss_destroy(struct EG25Manager *manager)
static void disable_mm_gnss(struct EG25Manager *manager)
{
MMModemLocationSource sources;
gboolean signals_location;
g_autoptr (GError) error = NULL;
gboolean signals_location;
g_autoptr(GError) error = NULL;
sources = mm_modem_location_get_enabled(manager->mm_location);
signals_location = mm_modem_location_signals_location(manager->mm_location);
@@ -140,17 +138,14 @@ static void disable_mm_gnss(struct EG25Manager *manager)
sources &= ~MM_MODEM_LOCATION_SOURCE_GPS_RAW;
sources &= ~MM_MODEM_LOCATION_SOURCE_GPS_NMEA;
sources &= ~MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED;
mm_modem_location_setup_sync(manager->mm_location, sources,
signals_location, NULL, &error);
mm_modem_location_setup_sync(manager->mm_location, sources, signals_location, NULL, &error);
if (error != NULL) {
g_warning("Unable to disable GNSS engine through ModemManager: %s",
error->message);
g_warning("Unable to disable GNSS engine through ModemManager: %s", error->message);
}
}
#endif
static void disable_at_gnss_cb(struct EG25Manager *manager,
const char *response)
static void disable_at_gnss_cb(struct EG25Manager *manager, const char *response)
{
/* Clear QGPSEND AT command and process next */
at_next_command(manager);
@@ -199,27 +194,25 @@ static void state_at_gnss(struct EG25Manager *manager)
static void fetch_assistance_data(struct EG25Manager *manager)
{
CURLcode response;
curl_off_t downloaded;
CURL *curl = NULL;
CURLcode response;
curl_off_t downloaded;
CURL *curl = NULL;
g_autofree gchar *url = NULL;
FILE *tmp_file = NULL;
gchar errbuf[CURL_ERROR_SIZE];
FILE *tmp_file = NULL;
gchar errbuf[CURL_ERROR_SIZE];
errbuf[0] = 0;
/* Fetch assistance data with curl */
tmp_file = fdopen(manager->gnss_assistance_fd, "wb+");
if (tmp_file == NULL) {
g_critical("Unable to open file to save assistance data: %s",
g_strerror(errno));
g_critical("Unable to open file to save assistance data: %s", g_strerror(errno));
goto bail;
}
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
if (ftruncate(manager->gnss_assistance_fd, 0) < 0)
g_warning("Unable to truncate file, assistance data might be invalid!");
url = g_strconcat(manager->gnss_assistance_url, "/",
manager->gnss_assistance_file, NULL);
url = g_strconcat(manager->gnss_assistance_url, "/", manager->gnss_assistance_file, NULL);
curl = curl_easy_init();
if (!curl) {
@@ -237,7 +230,8 @@ static void fetch_assistance_data(struct EG25Manager *manager)
response = curl_easy_perform(curl);
if (response != CURLE_OK) {
g_warning("Unable to fetch GNSS assistance data from %s: %s",
url, strlen(errbuf) ? errbuf : curl_easy_strerror(response));
url,
strlen(errbuf) ? errbuf : curl_easy_strerror(response));
goto bail;
}
@@ -252,24 +246,24 @@ static void fetch_assistance_data(struct EG25Manager *manager)
g_message("Fetching GNSS assistance data from %s was successful", url);
fflush(tmp_file);
curl_easy_cleanup(curl);
/* Go to the next step */
manager->gnss_assistance_step++;
gnss_step(manager);
return;
goto cleanup;
bail:
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
cleanup:
fflush(tmp_file);
fclose(tmp_file);
if (curl != NULL)
curl_easy_cleanup(curl);
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
}
/******************************************************************************/
static void init_assistance_data_upload_ready(struct EG25Manager *manager,
const char *response)
static void init_assistance_data_upload_ready(struct EG25Manager *manager, const char *response)
{
/* Search for 'CONNECT' in response to start upload */
if (strstr(response, "CONNECT")) {
@@ -285,8 +279,7 @@ static void init_assistance_data_upload_ready(struct EG25Manager *manager,
}
}
static void init_assistance_data_upload_start(struct EG25Manager *manager,
const char *response)
static void init_assistance_data_upload_start(struct EG25Manager *manager, const char *response)
{
gchar value[BUFFER_SIZE];
off_t size;
@@ -305,11 +298,14 @@ static void init_assistance_data_upload_start(struct EG25Manager *manager,
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
/* Start upload */
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\",%ld,%d",
manager->gnss_assistance_file, size, UPLOAD_TIMEOUT_S);
g_snprintf(value,
BUFFER_SIZE,
"\"RAM:%s\",%ld,%d",
manager->gnss_assistance_file,
size,
UPLOAD_TIMEOUT_S);
g_message("Initiate GNSS assistance data upload: %s", value);
at_append_command(manager, "QFUPL", NULL, value, NULL,
init_assistance_data_upload_ready);
at_append_command(manager, "QFUPL", NULL, value, NULL, init_assistance_data_upload_ready);
at_send_command(manager);
}
@@ -319,16 +315,15 @@ static void init_assistance_data_upload(struct EG25Manager *manager)
* Delete all previous GNSS assistance data files in RAM
* and start uploading the latest one to RAM.
*/
at_append_command(manager, "QFDEL", NULL, "\"RAM:*\"\r\n",
NULL, init_assistance_data_upload_start);
at_append_command(manager, "QFDEL", NULL, "\"RAM:*\"\r\n", NULL, init_assistance_data_upload_start);
at_send_command(manager);
}
static void upload_assistance_data(struct EG25Manager *manager)
{
gint error;
glong written_total = 0;
gint ret;
gint error;
off_t written_total = 0;
gint ret;
struct stat sb;
if (fstat(manager->gnss_assistance_fd, &sb) != 0) {
@@ -357,8 +352,7 @@ static void upload_assistance_data(struct EG25Manager *manager)
}
}
static void finish_assistance_data_upload_cb(struct EG25Manager *manager,
const char *response)
static void finish_assistance_data_upload_cb(struct EG25Manager *manager, const char *response)
{
/* Process response */
at_process_result(manager, response);
@@ -371,23 +365,20 @@ static void finish_assistance_data_upload_cb(struct EG25Manager *manager,
static void finish_assistance_data_upload(struct EG25Manager *manager)
{
gchar value[BUFFER_SIZE];
gchar value[BUFFER_SIZE];
GDateTime *datetime;
gchar *timestring;
gchar *timestring;
/* Configure GNSS assistance clock to current system time (UTC) */
datetime = g_date_time_new_now_utc();
timestring = g_date_time_format(datetime, "0,\"%Y/%m/%d,%H:%M:%S\"");
g_message("Setting GNSS assistance UTC clock to: %s", timestring);
at_append_command(manager, "QGPSXTRATIME", NULL, timestring, NULL,
at_process_result);
at_append_command(manager, "QGPSXTRATIME", NULL, timestring, NULL, at_process_result);
/* Configure GNSS engine to use uploaded GNSS assistance data */
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\"",
manager->gnss_assistance_file);
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\"", manager->gnss_assistance_file);
g_message("Setting GNSS assistance file to: %s", value);
at_append_command(manager, "QGPSXTRADATA", NULL, value, NULL,
finish_assistance_data_upload_cb);
at_append_command(manager, "QGPSXTRADATA", NULL, value, NULL, finish_assistance_data_upload_cb);
at_send_command(manager);
}
@@ -396,7 +387,7 @@ static void finish_assistance_data_upload(struct EG25Manager *manager)
#ifdef HAVE_MMGLIB
static void enable_mm_gnss(struct EG25Manager *manager)
{
g_autoptr (GError) error = NULL;
g_autoptr(GError) error = NULL;
MMModemLocationSource sources = mm_modem_location_get_enabled(manager->mm_location);
gboolean signal_location = mm_modem_location_signals_location(manager->mm_location);
@@ -407,11 +398,9 @@ static void enable_mm_gnss(struct EG25Manager *manager)
if (manager->gnss_sources & EG25_GNSS_SOURCE_RAW)
sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW;
mm_modem_location_setup_sync(manager->mm_location, sources,
signal_location, NULL, &error);
mm_modem_location_setup_sync(manager->mm_location, sources, signal_location, NULL, &error);
if (error != NULL)
g_warning("Unable to enable GNSS engine through ModemManager: %s",
error->message);
g_warning("Unable to enable GNSS engine through ModemManager: %s", error->message);
}
#endif
@@ -424,8 +413,7 @@ static void enable_at_gnss_cb(struct EG25Manager *manager, const char *response)
static void enable_at_gnss(struct EG25Manager *manager)
{
if (manager->gnss_sources & EG25_GNSS_SOURCE_QGPS) {
at_append_command(manager, "QGPS", NULL, "1", NULL,
enable_at_gnss_cb);
at_append_command(manager, "QGPS", NULL, "1", NULL, enable_at_gnss_cb);
at_send_command(manager);
return;
}
@@ -437,7 +425,7 @@ static void enable_at_gnss(struct EG25Manager *manager)
void gnss_step(struct EG25Manager *manager)
{
switch(manager->gnss_assistance_step) {
switch (manager->gnss_assistance_step) {
case EG25_GNSS_STEP_FIRST:
manager->gnss_assistance_step++;
g_message("GNSS assistance upload started...");
@@ -446,7 +434,8 @@ void gnss_step(struct EG25Manager *manager)
case EG25_GNSS_STEP_FETCH_ASSISTANCE_DATA:
g_message("GNSS assistance upload step (%d/%d): "
"fetching assistance data",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
fetch_assistance_data(manager);
break;
@@ -455,7 +444,8 @@ void gnss_step(struct EG25Manager *manager)
if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
g_message("GNSS assistance upload step (%d/%d): "
"disabling GNSS engine through ModemManager",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
disable_mm_gnss(manager);
}
manager->gnss_assistance_step++;
@@ -465,26 +455,30 @@ void gnss_step(struct EG25Manager *manager)
case EG25_GNSS_STEP_AT_GNSS_DISABLE:
g_message("GNSS assistance upload step (%d/%d): "
"disabling GNSS engine through AT+QGPS",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
state_at_gnss(manager);
break;
case EG25_GNSS_STEP_INIT_UPLOAD:
g_message("GNSS assistance upload step (%d/%d): initiating upload",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
init_assistance_data_upload(manager);
break;
case EG25_GNSS_STEP_UPLOAD:
g_message("GNSS assistance upload step (%d/%d): "
"uploading assistance data",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
upload_assistance_data(manager);
break;
case EG25_GNSS_STEP_FINISH_UPLOAD:
g_message("GNSS assistance upload step (%d/%d): finishing upload",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
finish_assistance_data_upload(manager);
break;
@@ -493,7 +487,8 @@ void gnss_step(struct EG25Manager *manager)
if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) {
g_message("GNSS assistance upload step (%d/%d): "
"re-enabling GNSS through ModemManager",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
enable_mm_gnss(manager);
}
manager->gnss_assistance_step++;
@@ -503,13 +498,15 @@ void gnss_step(struct EG25Manager *manager)
case EG25_GNSS_STEP_AT_QGPS_ENABLE:
g_message("GNSS assistance upload step (%d/%d): "
"re-enabling GNSS through AT+QGPS",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
enable_at_gnss(manager);
break;
case EG25_GNSS_STEP_LAST:
g_message("GNSS assistance upload step (%d/%d): finished",
manager->gnss_assistance_step, EG25_GNSS_STEP_LAST);
manager->gnss_assistance_step,
EG25_GNSS_STEP_LAST);
break;
}
}

View File

@@ -6,12 +6,12 @@
#pragma once
#include <curl/curl.h>
#include <time.h>
#include <unistd.h>
#include <curl/curl.h>
#include "manager.h"
void gnss_init(struct EG25Manager *manager, toml_table_t *config[]);
void gnss_destroy(struct EG25Manager *manager);
void gnss_init(struct EG25Manager *manager, toml_table_t *config[]);
void gnss_destroy(struct EG25Manager *manager);
gboolean gnss_upload_assistance_data(struct EG25Manager *manager);

View File

@@ -4,14 +4,16 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "config.h"
#include "gpio.h"
#include "config.h"
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
/* Those defines are used for legacy config files only */
#define GPIO_CHIP1_LABEL "1c20800.pinctrl"
#define GPIO_CHIP2_LABEL "1f02c00.pinctrl"
#define GPIO_CHIP1_LABEL "1c20800.pinctrl"
#define GPIO_CHIP2_LABEL "1f02c00.pinctrl"
#define MAX_GPIOCHIP_LINES 352
enum {
@@ -40,21 +42,78 @@ static char *gpio_in_names[] = {
"status",
};
enum gpiod_line_value gpio_line_get_value(struct EG25Manager *manager, int line)
{
enum gpiod_line_value value;
unsigned int offset;
gpiod_line_request_get_requested_offsets(manager->gpio_in[line], &offset, 1);
value = gpiod_line_request_get_value(manager->gpio_in[line], offset);
if (value == GPIOD_LINE_VALUE_ERROR) {
g_warning("gpio: couldn't get value on line %d", line);
}
return value;
}
int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_value value)
{
unsigned int offset;
int ret;
gpiod_line_request_get_requested_offsets(manager->gpio_out[line], &offset, 1);
ret = gpiod_line_request_set_value(manager->gpio_out[line], offset, value);
if (ret) {
g_warning("gpio: couldn't set value %d on line %d", value, line);
return -1;
} else {
manager->gpio_out_value[line] = value;
return 0;
}
}
int gpio_sequence_poweron(struct EG25Manager *manager)
{
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_PWRKEY], 1);
sleep(1);
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_PWRKEY], 0);
/*
* Force the modem to poweroff using the RESET_N pin before attempting to
* boot in case the it got into a bad state.
*
* If the modem was on, this will cause it to start booting, so press the
* power button while in reset to avoid a (probably only theoretical) race
* condition where it starts booting after reset, and then powers off from
* the power key.
*/
gpio_line_set_value(manager, GPIO_OUT_RESET, GPIOD_LINE_VALUE_ACTIVE);
gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_ACTIVE);
g_message("Executed power-on/off sequence");
/*
* The datasheet says to pull the pin low for between 150 and 460 ms. usleep
* should always sleep for at least the specified amount of time, so use
* 200ms because it's closer to the bottom of that range.
*/
usleep(200000);
gpio_line_set_value(manager, GPIO_OUT_RESET, GPIOD_LINE_VALUE_INACTIVE);
/*
* The modem has finished it's reset, now we wait to allow it a chance to
* react to the power key
*/
sleep(1);
gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_INACTIVE);
g_message("Executed power-on sequence");
return 0;
}
int gpio_sequence_shutdown(struct EG25Manager *manager)
{
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DISABLE], 1);
gpio_sequence_poweron(manager);
gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_ACTIVE);
sleep(1);
gpio_line_set_value(manager, GPIO_OUT_PWRKEY, GPIOD_LINE_VALUE_INACTIVE);
g_message("Executed power-off sequence");
@@ -63,7 +122,7 @@ 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);
gpio_line_set_value(manager, GPIO_OUT_APREADY, GPIOD_LINE_VALUE_ACTIVE);
g_message("Executed suspend sequence");
@@ -72,7 +131,7 @@ 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);
gpio_line_set_value(manager, GPIO_OUT_APREADY, GPIOD_LINE_VALUE_INACTIVE);
g_message("Executed resume sequence");
@@ -81,8 +140,8 @@ int gpio_sequence_resume(struct EG25Manager *manager)
int gpio_sequence_wake(struct EG25Manager *manager)
{
if (gpiod_line_get_value(manager->gpio_out[GPIO_OUT_DTR])) {
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 0);
if (manager->gpio_out_value[GPIO_OUT_DTR]) {
gpio_line_set_value(manager, GPIO_OUT_DTR, GPIOD_LINE_VALUE_INACTIVE);
/* Give the modem 200ms to wake from soft sleep */
usleep(200000);
@@ -95,47 +154,163 @@ int gpio_sequence_wake(struct EG25Manager *manager)
int gpio_sequence_sleep(struct EG25Manager *manager)
{
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_DTR], 1);
gpio_line_set_value(manager, GPIO_OUT_DTR, GPIOD_LINE_VALUE_ACTIVE);
g_message("Executed soft sleep sequence");
return 0;
}
struct gpiod_line *gpio_get_output_line(struct EG25Manager *manager, int chip, int line)
struct gpiod_line_request *gpio_request_line(struct EG25Manager *manager,
int chip,
unsigned int line,
enum gpiod_line_direction direction)
{
struct gpiod_line *gpio_line;
struct gpiod_line_request *request = NULL;
struct gpiod_line_settings *settings;
struct gpiod_line_config *line_cfg;
struct gpiod_request_config *req_cfg;
int ret;
gpio_line = gpiod_chip_get_line(manager->gpiochip[chip], line);
if (!gpio_line)
settings = gpiod_line_settings_new();
if (!settings)
return NULL;
if (gpiod_line_request_output(gpio_line, "eg25manager", 0) < 0) {
gpiod_line_release(gpio_line);
return NULL;
}
gpiod_line_settings_set_direction(settings, direction);
return gpio_line;
line_cfg = gpiod_line_config_new();
if (!line_cfg)
goto free_settings;
ret = gpiod_line_config_add_line_settings(line_cfg, &line, 1, settings);
if (ret)
goto free_line_config;
req_cfg = gpiod_request_config_new();
if (!req_cfg)
goto free_line_config;
gpiod_request_config_set_consumer(req_cfg, "eg25-manager");
request = gpiod_chip_request_lines(manager->gpiochip[chip], req_cfg, line_cfg);
gpiod_request_config_free(req_cfg);
free_line_config:
gpiod_line_config_free(line_cfg);
free_settings:
gpiod_line_settings_free(settings);
return request;
}
struct gpiod_line *gpio_get_input_line(struct EG25Manager *manager, int chip, int line)
static int gpio_chip_dir_filter(const struct dirent *entry)
{
struct gpiod_line *gpio_line;
struct stat sb;
int ret = 0;
char *path;
gpio_line = gpiod_chip_get_line(manager->gpiochip[chip], line);
if (!gpio_line)
return NULL;
if (asprintf(&path, "/dev/%s", entry->d_name) < 0)
return 0;
if (gpiod_line_request_input(gpio_line, "eg25manager") < 0) {
gpiod_line_release(gpio_line);
return NULL;
if ((lstat(path, &sb) == 0) && (!S_ISLNK(sb.st_mode)) && gpiod_is_gpiochip_device(path))
ret = 1;
free(path);
return ret;
}
int gpio_all_chip_paths(char ***paths_ptr)
{
int i, j, num_chips, ret = 0;
struct dirent **entries;
char **paths;
num_chips = scandir("/dev/", &entries, gpio_chip_dir_filter, alphasort);
if (num_chips < 0)
g_error("gpio: unable to scan /dev: %s", g_strerror(errno));
paths = calloc(num_chips, sizeof(*paths));
if (paths == NULL)
g_error("gpio: out of memory");
for (i = 0; i < num_chips; i++) {
if (asprintf(&paths[i], "/dev/%s", entries[i]->d_name) < 0) {
for (j = 0; j < i; j++)
free(paths[j]);
free(paths);
return 0;
}
}
return gpio_line;
*paths_ptr = paths;
ret = num_chips;
for (i = 0; i < num_chips; i++)
free(entries[i]);
free(entries);
return ret;
}
struct gpiod_chip *gpio_chip_open_by_label(const char *label)
{
int num_chips, i;
char **paths = NULL;
const char *clabel;
struct gpiod_chip *chip;
struct gpiod_chip_info *cinfo;
num_chips = gpio_all_chip_paths(&paths);
for (i = 0; i < num_chips; i++) {
chip = gpiod_chip_open(paths[i]);
if (!chip)
continue;
cinfo = gpiod_chip_get_info(chip);
if (!cinfo)
goto clean_chip_open;
clabel = gpiod_chip_info_get_label(cinfo);
if (strcmp(label, clabel) == 0) {
free(paths);
return chip;
}
clean_chip_open:
gpiod_chip_close(chip);
}
if (paths)
free(paths);
return NULL;
}
unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_num)
{
struct gpiod_chip *chip = manager->gpiochip[chip_num];
struct gpiod_chip_info *info;
unsigned int num_lines;
info = gpiod_chip_get_info(chip);
if (!info)
g_error("gpio: failed to read info: %s", strerror(errno));
num_lines = gpiod_chip_info_get_num_lines(info);
gpiod_chip_info_free(info);
return num_lines;
}
int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
{
int i;
int i;
toml_table_t *gpio_config[EG25_CONFIG_COUNT];
for (i = 0; i < EG25_CONFIG_COUNT; i++)
@@ -155,9 +330,8 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
* format, but error out if user config overrides gpios using the
* old format
*/
if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips"))
{
int numchips;
if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips")) {
int numchips;
toml_array_t *chipslist = NULL;
config_get_array(gpio_config, "chips", &chipslist);
@@ -169,14 +343,14 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
toml_datum_t data = toml_string_at(chipslist, i);
if (!data.ok)
continue;
manager->gpiochip[i] = gpiod_chip_open_by_label(data.u.s);
manager->gpiochip[i] = gpio_chip_open_by_label(data.u.s);
if (!manager->gpiochip[i])
g_error("Unable to find GPIO chip '%s'", data.u.s);
}
for (i = 0; i < GPIO_OUT_COUNT; i++) {
toml_table_t *table;
toml_datum_t chip, line;
toml_datum_t chip, line;
if (!config_get_table(gpio_config, gpio_out_names[i], &table))
g_error("Unable to get config for output GPIO '%s'", gpio_out_names[i]);
@@ -185,17 +359,20 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
g_error("Wrong chip ID for output GPIO '%s'", gpio_out_names[i]);
line = toml_int_in(table, "line");
if (!line.ok || line.u.i < 0 || line.u.i > gpiod_chip_num_lines(manager->gpiochip[chip.u.i]))
if (!line.ok || line.u.i < 0 || line.u.i > gpio_chip_num_lines(manager, chip.u.i))
g_error("Wrong line ID for output GPIO '%s'", gpio_out_names[i]);
manager->gpio_out[i] = gpio_get_output_line(manager, chip.u.i, line.u.i);
manager->gpio_out[i] = gpio_request_line(manager,
chip.u.i,
line.u.i,
GPIOD_LINE_DIRECTION_OUTPUT);
if (!manager->gpio_out[i])
g_error("Unable to get output GPIO %d", i);
}
for (i = 0; i < GPIO_IN_COUNT; i++) {
toml_table_t *table;
toml_datum_t chip, line;
toml_datum_t chip, line;
if (!config_get_table(gpio_config, gpio_in_names[i], &table)) {
// BH edition don't have the STATUS line connected, ignore it
@@ -209,10 +386,13 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
g_error("Wrong chip ID for input GPIO '%s'", gpio_in_names[i]);
line = toml_int_in(table, "line");
if (!line.ok || line.u.i < 0 || line.u.i > gpiod_chip_num_lines(manager->gpiochip[chip.u.i]))
if (!line.ok || line.u.i < 0 || line.u.i > gpio_chip_num_lines(manager, chip.u.i))
g_error("Wrong line ID for input GPIO '%s'", gpio_in_names[i]);
manager->gpio_in[i] = gpio_get_input_line(manager, chip.u.i, line.u.i);
manager->gpio_in[i] = gpio_request_line(manager,
chip.u.i,
line.u.i,
GPIOD_LINE_DIRECTION_INPUT);
if (!manager->gpio_in[i])
g_error("Unable to get input GPIO %d", i);
}
@@ -220,11 +400,11 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
guint offset, chipidx, gpio_idx;
/* Legacy config file, only used on the OG PinePhone */
manager->gpiochip[0] = gpiod_chip_open_by_label(GPIO_CHIP1_LABEL);
manager->gpiochip[0] = gpio_chip_open_by_label(GPIO_CHIP1_LABEL);
if (!manager->gpiochip[0])
g_error("Unable to open GPIO chip " GPIO_CHIP1_LABEL);
manager->gpiochip[1] = gpiod_chip_open_by_label(GPIO_CHIP2_LABEL);
manager->gpiochip[1] = gpio_chip_open_by_label(GPIO_CHIP2_LABEL);
if (!manager->gpiochip[1])
g_error("Unable to open GPIO chip " GPIO_CHIP2_LABEL);
@@ -240,7 +420,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
chipidx = 1;
}
manager->gpio_out[i] = gpio_get_input_line(manager, chipidx, offset);
manager->gpio_out[i] = gpio_request_line(manager,
chipidx,
offset,
GPIOD_LINE_DIRECTION_OUTPUT);
if (!manager->gpio_out[i])
g_error("Unable to get output GPIO %d", i);
}
@@ -257,7 +440,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
chipidx = 1;
}
manager->gpio_in[i] = gpio_get_input_line(manager, chipidx, offset);
manager->gpio_in[i] = gpio_request_line(manager,
chipidx,
offset,
GPIOD_LINE_DIRECTION_INPUT);
if (!manager->gpio_in[i])
g_error("Unable to get input GPIO %d", i);
}
@@ -266,16 +452,18 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
return 0;
}
gboolean gpio_check_poweroff(struct EG25Manager *manager, gboolean keep_down)
void gpio_force_off(struct EG25Manager *manager)
{
if (manager->gpio_out[GPIO_OUT_RESET]) {
g_message("Setting the reset pin to ensure the modem stays off");
gpio_line_set_value(manager, GPIO_OUT_RESET, GPIOD_LINE_VALUE_ACTIVE);
}
}
gboolean gpio_check_poweroff(struct EG25Manager *manager)
{
if (manager->gpio_in[GPIO_IN_STATUS] &&
gpiod_line_get_value(manager->gpio_in[GPIO_IN_STATUS]) == 1) {
if (keep_down && manager->gpio_out[GPIO_OUT_RESET]) {
// Asserting RESET line to prevent modem from rebooting
gpiod_line_set_value(manager->gpio_out[GPIO_OUT_RESET], 1);
}
gpio_line_get_value(manager, GPIO_IN_STATUS) == GPIOD_LINE_VALUE_ACTIVE) {
return TRUE;
}
@@ -288,12 +476,12 @@ void gpio_destroy(struct EG25Manager *manager)
for (i = 0; i < GPIO_OUT_COUNT; i++) {
if (manager->gpio_out[i])
gpiod_line_release(manager->gpio_out[i]);
gpiod_line_request_release(manager->gpio_out[i]);
}
for (i = 0; i < GPIO_IN_COUNT; i++) {
if (manager->gpio_in[i])
gpiod_line_release(manager->gpio_in[i]);
gpiod_line_request_release(manager->gpio_in[i]);
}
if (manager->gpiochip[0])

View File

@@ -8,7 +8,7 @@
#include "manager.h"
int gpio_init(struct EG25Manager *state, toml_table_t *config[]);
int gpio_init(struct EG25Manager *state, toml_table_t *config[]);
void gpio_destroy(struct EG25Manager *state);
int gpio_sequence_poweron(struct EG25Manager *state);
@@ -18,4 +18,5 @@ 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);
void gpio_force_off(struct EG25Manager *manager);
gboolean gpio_check_poweroff(struct EG25Manager *manager);

View File

@@ -4,19 +4,19 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "manager.h"
#include "at.h"
#include "config.h"
#include "gpio.h"
#include "manager.h"
#ifdef HAVE_MMGLIB
#include "mm-iface.h"
#endif
#include "gnss.h"
#include "ofono-iface.h"
#include "suspend.h"
#include "udev.h"
#include "gnss.h"
#include <fcntl.h>
#include <signal.h>
@@ -41,7 +41,7 @@
#define EG25_DEFAULT_VENDOR_ID 0x2c7c
#define EG25_DEFAULT_PRODUCT_ID 0x0125
#define POWERON_DELAY_US 100000UL
#define POWERON_DELAY_US 100000UL
static gboolean quit_app(struct EG25Manager *manager)
{
@@ -62,13 +62,17 @@ static gboolean quit_app(struct EG25Manager *manager)
gpio_sequence_shutdown(manager);
manager->modem_state = EG25_STATE_FINISHING;
for (i = 0; i < 30; i++) {
if (gpio_check_poweroff(manager, TRUE))
if (gpio_check_poweroff(manager)) {
g_message("Modem successfully powered down");
break;
}
sleep(1);
}
}
g_message("Modem down, quitting...");
gpio_force_off(manager);
g_message("Modem down, quitting...");
g_main_loop_quit(manager->loop);
return FALSE;
@@ -76,10 +80,10 @@ static gboolean quit_app(struct EG25Manager *manager)
static gboolean modem_start(struct EG25Manager *manager)
{
ssize_t i, count;
gboolean should_boot = TRUE;
libusb_context *ctx = NULL;
libusb_device **devices = NULL;
ssize_t i, count;
gboolean should_boot = TRUE;
libusb_context *ctx = NULL;
libusb_device **devices = NULL;
struct libusb_device_descriptor desc;
if (manager->use_libusb) {
@@ -98,7 +102,7 @@ static gboolean modem_start(struct EG25Manager *manager)
libusb_free_device_list(devices, 1);
libusb_exit(ctx);
} else if (!gpio_check_poweroff(manager, FALSE)) {
} else if (!gpio_check_poweroff(manager)) {
g_message("STATUS is low, modem already powered");
should_boot = FALSE;
}
@@ -141,7 +145,37 @@ void modem_configure(struct EG25Manager *manager)
at_sequence_configure(manager);
}
static gboolean modem_reset_done(struct EG25Manager* manager)
static gboolean modem_gpio_reset_done(struct EG25Manager *manager)
{
gpio_sequence_poweron(manager);
manager->modem_state = EG25_STATE_POWERED;
manager->complete_reset_timer = 0;
return G_SOURCE_REMOVE;
}
static gboolean modem_at_reset_done(struct EG25Manager *manager)
{
/*
* If the modem was successfully rebooted, then we should have received
* "RDY" by now which will transition the state to started.
*/
if (manager->modem_state != EG25_STATE_RESETTING) {
manager->complete_reset_timer = 0;
return G_SOURCE_REMOVE;
}
g_message("AT reset failed, falling back to GPIO reset");
gpio_sequence_shutdown(manager);
manager->complete_reset_timer = g_timeout_add_seconds(30,
G_SOURCE_FUNC(modem_gpio_reset_done),
manager);
return G_SOURCE_REMOVE;
}
static gboolean modem_rebind_done(struct EG25Manager *manager)
{
manager->modem_state = EG25_STATE_RESUMING;
manager->complete_reset_timer = 0;
@@ -194,24 +228,26 @@ gboolean modem_reset(struct EG25Manager *manager)
g_warning("Unable to open /sys/bus/usb/drivers/usb/unbind");
goto error;
}
ret = write(fd, manager->modem_usb_id, len);
close(fd);
if (ret < len) {
g_warning("Couldn't unbind modem: wrote %d/%d bytes", ret, len);
goto error;
}
close(fd);
fd = open("/sys/bus/usb/drivers/usb/bind", O_WRONLY);
if (fd < 0) {
g_warning("Unable to open /sys/bus/usb/drivers/usb/unbind");
g_warning("Unable to open /sys/bus/usb/drivers/usb/bind");
goto error;
}
ret = write(fd, manager->modem_usb_id, len);
close(fd);
if (ret < len) {
g_warning("Couldn't bind modem: wrote %d/%d bytes", ret, len);
goto error;
}
close(fd);
g_message("Successfully reset modem's USB connection");
@@ -219,7 +255,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->complete_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_rebind_done), manager);
return G_SOURCE_REMOVE;
@@ -237,7 +273,9 @@ error:
at_sequence_reset(manager);
// Setup timer for making sure we don't queue other reset commands
manager->complete_reset_timer = g_timeout_add_seconds(30, G_SOURCE_FUNC(modem_reset_done), manager);
manager->complete_reset_timer = g_timeout_add_seconds(45,
G_SOURCE_FUNC(modem_at_reset_done),
manager);
return G_SOURCE_REMOVE;
}
@@ -267,15 +305,15 @@ void modem_resume_post(struct EG25Manager *manager)
static toml_table_t *parse_config_file(char *config_file, gboolean force_default)
{
toml_table_t *toml_config;
gchar *compatible;
gchar error[256];
gsize len;
FILE *f = NULL;
gchar *compatible;
gchar error[256];
gsize len;
FILE *f = NULL;
if (config_file) {
f = fopen(config_file, "r");
} else if (g_file_get_contents("/proc/device-tree/compatible", &compatible, &len, NULL)) {
g_autoptr (GPtrArray) compat = g_ptr_array_new();
g_autoptr(GPtrArray) compat = g_ptr_array_new();
gsize pos = 0;
/*
@@ -290,9 +328,11 @@ static toml_table_t *parse_config_file(char *config_file, gboolean force_default
for (pos = 0; pos < compat->len; pos++) {
g_autofree gchar *filename = NULL;
if (force_default)
filename = g_strdup_printf(EG25_DATADIR "/%s.toml", (gchar *)g_ptr_array_index(compat, pos));
filename = g_strdup_printf(EG25_DATADIR "/%s.toml",
(gchar *)g_ptr_array_index(compat, pos));
else
filename = g_strdup_printf(EG25_CONFDIR "/%s.toml", (gchar *)g_ptr_array_index(compat, pos));
filename = g_strdup_printf(EG25_CONFDIR "/%s.toml",
(gchar *)g_ptr_array_index(compat, pos));
if (access(filename, F_OK) == 0) {
g_message("Opening config file: %s", filename);
@@ -321,15 +361,15 @@ int main(int argc, char *argv[])
g_autoptr(GOptionContext) opt_context = NULL;
g_autoptr(GError) err = NULL;
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];
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[] = {
{ "config", 'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file to use.", NULL },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Display version information and exit.", NULL },
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
{"config", 'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file to use.", NULL},
{"version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Display version information and exit.", NULL},
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
};
memset(&manager, 0, sizeof(manager));
@@ -338,10 +378,10 @@ int main(int argc, char *argv[])
manager.suspend_delay_fd = -1;
manager.suspend_block_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);
if (!g_option_context_parse (opt_context, &argc, &argv, &err)) {
g_warning ("%s", err->message);
opt_context = g_option_context_new("- Power management for the Quectel EG25 modem");
g_option_context_add_main_entries(opt_context, options, NULL);
if (!g_option_context_parse(opt_context, &argc, &argv, &err)) {
g_warning("%s", err->message);
return 1;
}

View File

@@ -41,19 +41,18 @@ typedef enum {
EG25_GNSS_SOURCE_QGPS = 1 << 3,
} EG25GNSSSource;
enum EG25State {
EG25_STATE_INIT = 0,
EG25_STATE_POWERED, // Power-on sequence has been executed, but the modem isn't on yet
EG25_STATE_STARTED, // Modem has been started and declared itdata ready
EG25_STATE_ACQUIRED, // Modem has been probed by ModemManager
EG25_STATE_POWERED, // Power-on sequence has been executed, but the modem isn't on yet
EG25_STATE_STARTED, // Modem has been started and declared itdata ready
EG25_STATE_ACQUIRED, // Modem has been probed by ModemManager
EG25_STATE_CONFIGURED, // Modem has been configured through AT commands
EG25_STATE_REGISTERED, // Modem is unlocked and registered to a network provider
EG25_STATE_CONNECTED, // Modem is connected (data connection active)
EG25_STATE_CONNECTED, // Modem is connected (data connection active)
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_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
};
@@ -71,42 +70,42 @@ enum EG25Config {
struct EG25Manager {
GMainLoop *loop;
guint complete_reset_timer;
guint schedule_reset_timer;
gboolean use_libusb;
guint usb_vid;
guint usb_pid;
guint poweron_delay;
guint complete_reset_timer;
guint schedule_reset_timer;
gboolean use_libusb;
guint usb_vid;
guint usb_pid;
guint poweron_delay;
int at_fd;
guint at_source;
int at_fd;
guint at_source;
GList *at_cmds;
void (*at_callback)(struct EG25Manager *manager, const char *response);
void (*at_callback)(struct EG25Manager *manager, const char *response);
enum EG25State modem_state;
gchar *modem_usb_id;
gchar *modem_usb_id;
gboolean gnss_assistance_enabled;
gboolean gnss_assistance_enabled;
EG25GNSSSource gnss_sources;
EG25GNSSStep gnss_assistance_step;
gint gnss_assistance_fd;
gchar *gnss_assistance_url;
gchar *gnss_assistance_file;
EG25GNSSStep gnss_assistance_step;
gint gnss_assistance_fd;
gchar *gnss_assistance_url;
gchar *gnss_assistance_file;
enum ModemIface modem_iface;
guint mm_watch;
guint mm_watch;
#ifdef HAVE_MMGLIB
MMManager *mm_manager;
MMModem *mm_modem;
MMManager *mm_manager;
MMModem *mm_modem;
MMModemLocation *mm_location;
#endif
guint ofono_watch;
GDBOManager *ofono_manager;
guint ofono_watch;
GDBOManager *ofono_manager;
GDBusConnection *ofono_connection;
GDBusProxy *suspend_proxy;
int suspend_delay_fd;
int suspend_block_fd;
int suspend_delay_fd;
int suspend_block_fd;
guint modem_recovery_timer;
guint modem_recovery_timeout;
@@ -115,17 +114,18 @@ struct EG25Manager {
GUdevClient *udev;
struct gpiod_chip *gpiochip[2];
struct gpiod_line *gpio_out[5];
struct gpiod_line *gpio_in[2];
struct gpiod_chip *gpiochip[2];
struct gpiod_line_request *gpio_out[5];
guint gpio_out_value[5];
struct gpiod_line_request *gpio_in[2];
};
void modem_configure(struct EG25Manager *data);
void modem_configure(struct EG25Manager *data);
gboolean modem_reset(struct EG25Manager *data);
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);
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

View File

@@ -12,11 +12,11 @@
#include <string.h>
static void state_changed_cb(MMModem *modem,
MMModemState old,
MMModemState new,
MMModemStateChangeReason reason,
struct EG25Manager *manager)
static void state_changed_cb(MMModem *modem,
MMModemState old,
MMModemState new,
MMModemStateChangeReason reason,
struct EG25Manager *manager)
{
if (manager->modem_state >= EG25_STATE_CONFIGURED)
modem_update_state(manager, new);
@@ -24,13 +24,13 @@ static void state_changed_cb(MMModem *modem,
static void add_modem(struct EG25Manager *manager, GDBusObject *object)
{
const gchar *path;
const gchar *path;
MmGdbusModem *gdbus_modem;
path = g_dbus_object_get_object_path(object);
g_message("Adding new modem `%s'", path);
g_assert(MM_IS_OBJECT (object));
g_assert(MM_IS_OBJECT(object));
manager->mm_modem = mm_object_get_modem(MM_OBJECT(object));
g_assert_nonnull(manager->mm_modem);
@@ -70,15 +70,16 @@ static void add_modem_location(struct EG25Manager *manager, GDBusObject *object)
g_assert_nonnull(manager->mm_location);
}
static void interface_added_cb (struct EG25Manager *manager,
GDBusObject *object,
GDBusInterface *interface)
static void interface_added_cb(struct EG25Manager *manager,
GDBusObject *object,
GDBusInterface *interface)
{
GDBusInterfaceInfo *info;
info = g_dbus_interface_get_info(interface);
g_message("ModemManager interface `%s' found on object `%s'",
info->name, g_dbus_object_get_object_path(object));
info->name,
g_dbus_object_get_object_path(object));
if (g_strcmp0(info->name, MM_DBUS_INTERFACE_MODEM) == 0)
add_modem(manager, object);
@@ -87,12 +88,11 @@ static void interface_added_cb (struct EG25Manager *manager,
add_modem_location(manager, object);
}
static void interface_removed_cb(struct EG25Manager *manager,
GDBusObject *object,
GDBusInterface *interface)
{
const gchar *path;
const gchar *path;
GDBusInterfaceInfo *info;
path = g_dbus_object_get_object_path(object);
@@ -104,7 +104,6 @@ static void interface_removed_cb(struct EG25Manager *manager,
manager->mm_modem = NULL;
}
static void add_mm_object(struct EG25Manager *manager, GDBusObject *object)
{
GList *ifaces, *node;
@@ -116,7 +115,6 @@ static void add_mm_object(struct EG25Manager *manager, GDBusObject *object)
g_list_free_full(ifaces, g_object_unref);
}
static void add_mm_objects(struct EG25Manager *manager)
{
GList *objects, *node;
@@ -128,14 +126,12 @@ static void add_mm_objects(struct EG25Manager *manager)
g_list_free_full(objects, g_object_unref);
}
static void object_added_cb(struct EG25Manager *manager, GDBusObject *object)
{
g_message("ModemManager object `%s' added", g_dbus_object_get_object_path(object));
add_mm_object(manager, object);
}
static void object_removed_cb(struct EG25Manager *manager, GDBusObject *object)
{
const gchar *path;
@@ -146,25 +142,32 @@ static void object_removed_cb(struct EG25Manager *manager, GDBusObject *object)
manager->mm_modem = NULL;
}
static void mm_manager_new_cb(GDBusConnection *connection,
GAsyncResult *res,
struct EG25Manager *manager)
{
g_autoptr (GError) error = NULL;
g_autoptr(GError) error = NULL;
manager->mm_manager = mm_manager_new_finish(res, &error);
if (!manager->mm_manager)
g_critical("Error creating ModemManager Manager: %s", error->message);
g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager),
"interface-added", G_CALLBACK(interface_added_cb), manager);
"interface-added",
G_CALLBACK(interface_added_cb),
manager);
g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager),
"interface-removed", G_CALLBACK(interface_removed_cb), manager);
"interface-removed",
G_CALLBACK(interface_removed_cb),
manager);
g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager),
"object-added", G_CALLBACK(object_added_cb), manager);
"object-added",
G_CALLBACK(object_added_cb),
manager);
g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager),
"object-removed", G_CALLBACK(object_removed_cb), manager);
"object-removed",
G_CALLBACK(object_removed_cb),
manager);
add_mm_objects(manager);
}
@@ -177,13 +180,18 @@ 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.");
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);
mm_manager_new(connection,
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
NULL,
(GAsyncReadyCallback)mm_manager_new_cb,
manager);
}
static void mm_iface_clean(struct EG25Manager *manager)
@@ -201,9 +209,7 @@ static void mm_iface_clean(struct EG25Manager *manager)
}
}
static void mm_vanished_cb(GDBusConnection *connection,
const gchar *name,
struct EG25Manager *manager)
static void mm_vanished_cb(GDBusConnection *connection, const gchar *name, struct EG25Manager *manager)
{
g_message("ModemManager vanished from D-Bus");
mm_iface_clean(manager);
@@ -211,11 +217,13 @@ static void mm_vanished_cb(GDBusConnection *connection,
void mm_iface_init(struct EG25Manager *manager, toml_table_t *config[])
{
manager->mm_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, MM_DBUS_SERVICE,
manager->mm_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
MM_DBUS_SERVICE,
G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
(GBusNameAppearedCallback)mm_appeared_cb,
(GBusNameVanishedCallback)mm_vanished_cb,
manager, NULL);
manager,
NULL);
}
void mm_iface_destroy(struct EG25Manager *manager)

View File

@@ -14,9 +14,9 @@
#define OFONO_SERVICE "org.ofono"
static void modem_added_cb(GDBOManager *manager_proxy,
const gchar *path,
GVariant *properties,
static void modem_added_cb(GDBOManager *manager_proxy,
const gchar *path,
GVariant *properties,
struct EG25Manager *manager)
{
GVariant *modem_path;
@@ -43,33 +43,28 @@ static void modem_added_cb(GDBOManager *manager_proxy,
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 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)
static void get_modems_cb(GDBOManager *manager_proxy, GAsyncResult *res, struct EG25Manager *manager)
{
gboolean ok;
GVariant *modems;
gboolean ok;
GVariant *modems;
GVariantIter *modems_iter = NULL;
g_autoptr(GError) error = NULL;
const gchar *path;
GVariant *properties;
GVariant *properties;
ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems,
res, &error);
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)) {
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);
}
@@ -87,7 +82,9 @@ static void ofono_appeared_cb(GDBusConnection *connection,
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.");
g_critical("Modem interface already found! Make sure to only run either of "
"ModemManager or "
"oFono.");
return;
}
/* now connect to oFono! */
@@ -105,14 +102,12 @@ static void ofono_appeared_cb(GDBusConnection *connection,
manager->modem_iface = MODEM_IFACE_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);
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,
(GAsyncReadyCallback)get_modems_cb,
manager);
}
@@ -130,11 +125,13 @@ static void ofono_vanished_cb(GDBusConnection *connection,
void ofono_iface_init(struct EG25Manager *manager, toml_table_t *config[])
{
manager->ofono_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, OFONO_SERVICE,
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);
manager,
NULL);
}
void ofono_iface_destroy(struct EG25Manager *manager)

View File

@@ -14,9 +14,9 @@
#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"
static void resume_ok(struct EG25Manager *manager)
{
@@ -50,8 +50,7 @@ static gboolean drop_inhibitor(struct EG25Manager *manager, gboolean block)
manager->suspend_block_fd = -1;
return TRUE;
}
}
else {
} else {
if (manager->suspend_delay_fd >= 0) {
g_message("dropping systemd sleep delay inhibitor");
close(manager->suspend_delay_fd);
@@ -62,18 +61,15 @@ static gboolean drop_inhibitor(struct EG25Manager *manager, gboolean block)
return FALSE;
}
static void inhibit_done_delay(GObject *source,
GAsyncResult *result,
gpointer user_data)
static void inhibit_done_delay(GObject *source, GAsyncResult *result, gpointer user_data)
{
GDBusProxy *suspend_proxy = G_DBUS_PROXY(source);
GDBusProxy *suspend_proxy = G_DBUS_PROXY(source);
struct EG25Manager *manager = user_data;
g_autoptr (GError) error = NULL;
GVariant *res;
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);
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 {
@@ -88,18 +84,15 @@ static void inhibit_done_delay(GObject *source,
}
}
static void inhibit_done_block(GObject *source,
GAsyncResult *result,
gpointer user_data)
static void inhibit_done_block(GObject *source, GAsyncResult *result, gpointer user_data)
{
GDBusProxy *suspend_proxy = G_DBUS_PROXY(source);
GDBusProxy *suspend_proxy = G_DBUS_PROXY(source);
struct EG25Manager *manager = user_data;
g_autoptr (GError) error = NULL;
GVariant *res;
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);
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 {
@@ -133,44 +126,59 @@ static void take_inhibitor(struct EG25Manager *manager, gboolean block)
GVariant *variant_arg;
if (block) {
if(manager->suspend_block_fd != -1)
if (manager->suspend_block_fd != -1)
drop_inhibitor(manager, TRUE);
variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager",
"eg25manager needs to wait for modem to be fully booted",
"block");
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 (blocking)");
g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit",
variant_arg, 0, G_MAXINT, NULL, NULL,
inhibit_done_block, manager);
g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy,
"Inhibit",
variant_arg,
0,
G_MAXINT,
NULL,
NULL,
inhibit_done_block,
manager);
manager->modem_boot_timer = g_timeout_add_seconds(manager->modem_boot_timeout,
G_SOURCE_FUNC(modem_fully_booted),
manager);
}
else {
if(manager->suspend_delay_fd != -1)
} else {
if (manager->suspend_delay_fd != -1)
drop_inhibitor(manager, FALSE);
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 prepare modem for sleep",
"delay");
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_delay, manager);
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,
static void signal_cb(GDBusProxy *proxy,
const gchar *sendername,
const gchar *signalname,
GVariant *args,
gpointer user_data)
GVariant *args,
gpointer user_data)
{
struct EG25Manager *manager = user_data;
gboolean is_about_to_suspend;
gboolean is_about_to_suspend;
if (strcmp(signalname, "PrepareForSleep") != 0)
return;
@@ -208,13 +216,11 @@ static void signal_cb(GDBusProxy *proxy,
}
}
static void name_owner_cb(GObject *object,
GParamSpec *pspec,
gpointer user_data)
static void name_owner_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
{
GDBusProxy *proxy = G_DBUS_PROXY(object);
GDBusProxy *proxy = G_DBUS_PROXY(object);
struct EG25Manager *manager = user_data;
char *owner;
char *owner;
g_assert(proxy == manager->suspend_proxy);
@@ -227,11 +233,9 @@ static void name_owner_cb(GObject *object,
}
}
static void on_proxy_acquired(GObject *object,
GAsyncResult *res,
struct EG25Manager *manager)
static void on_proxy_acquired(GObject *object, GAsyncResult *res, struct EG25Manager *manager)
{
g_autoptr (GError) error = NULL;
g_autoptr(GError) error = NULL;
char *owner;
manager->suspend_proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
@@ -240,10 +244,8 @@ static void on_proxy_acquired(GObject *object,
return;
}
g_signal_connect(manager->suspend_proxy, "notify::g-name-owner",
G_CALLBACK(name_owner_cb), manager);
g_signal_connect(manager->suspend_proxy, "g-signal",
G_CALLBACK(signal_cb), manager);
g_signal_connect(manager->suspend_proxy, "notify::g-name-owner", G_CALLBACK(name_owner_cb), manager);
g_signal_connect(manager->suspend_proxy, "g-signal", G_CALLBACK(signal_cb), manager);
owner = g_dbus_proxy_get_name_owner(manager->suspend_proxy);
if (owner) {
@@ -259,7 +261,7 @@ void suspend_init(struct EG25Manager *manager, toml_table_t *config[])
for (int i = 0; i < EG25_CONFIG_COUNT; i++)
suspend_config[i] = config[i] ? toml_table_in(config[i], "suspend") : NULL;
/*
/*
* The `suspend` section is optional in both the user and system config files,
* so let's make sure suspend_config[EG25_CONFIG_SYS] is valid if one of the
* files has it.
@@ -280,10 +282,16 @@ void suspend_init(struct EG25Manager *manager, toml_table_t *config[])
manager->modem_recovery_timeout = 9;
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM,
// NOLINTNEXTLINE Flags combination is valid even if not matching an enum entry
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL, SD_NAME, SD_PATH, SD_INTERFACE, NULL,
(GAsyncReadyCallback)on_proxy_acquired, manager);
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
SD_NAME,
SD_PATH,
SD_INTERFACE,
NULL,
(GAsyncReadyCallback)on_proxy_acquired,
manager);
}
void suspend_destroy(struct EG25Manager *manager)

View File

@@ -8,7 +8,7 @@
#include "manager.h"
void suspend_init (struct EG25Manager *data, toml_table_t *config[]);
void suspend_destroy (struct EG25Manager *data);
void suspend_init(struct EG25Manager *data, toml_table_t *config[]);
void suspend_destroy(struct EG25Manager *data);
void suspend_inhibit (struct EG25Manager *data, gboolean inhibit, gboolean block);
void suspend_inhibit(struct EG25Manager *data, gboolean inhibit, gboolean block);

3688
src/toml.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,19 @@
/*
MIT License
Copyright (c) 2017 - 2019 CK Tan
https://github.com/cktan/tomlc99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -25,10 +25,8 @@
#ifndef TOML_H
#define TOML_H
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
#define TOML_EXTERN extern "C"
@@ -37,139 +35,130 @@
#endif
typedef struct toml_timestamp_t toml_timestamp_t;
typedef struct toml_table_t toml_table_t;
typedef struct toml_array_t toml_array_t;
typedef struct toml_datum_t toml_datum_t;
typedef struct toml_table_t toml_table_t;
typedef struct toml_array_t toml_array_t;
typedef struct toml_datum_t toml_datum_t;
/* Parse a file. Return a table on success, or 0 otherwise.
/* Parse a file. Return a table on success, or 0 otherwise.
* Caller must toml_free(the-return-value) after use.
*/
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
char* errbuf,
int errbufsz);
TOML_EXTERN toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz);
/* Parse a string containing the full config.
/* Parse a string containing the full config.
* Return a table on success, or 0 otherwise.
* Caller must toml_free(the-return-value) after use.
*/
TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */
char* errbuf,
int errbufsz);
TOML_EXTERN toml_table_t *toml_parse(char *conf, /* NUL terminated, please. */
char *errbuf,
int errbufsz);
/* Free the table returned by toml_parse() or toml_parse_file(). Once
* this function is called, any handles accessed through this tab
/* Free the table returned by toml_parse() or toml_parse_file(). Once
* this function is called, any handles accessed through this tab
* directly or indirectly are no longer valid.
*/
TOML_EXTERN void toml_free(toml_table_t* tab);
TOML_EXTERN void toml_free(toml_table_t *tab);
/* Timestamp types. The year, month, day, hour, minute, second, z
/* Timestamp types. The year, month, day, hour, minute, second, z
* fields may be NULL if they are not relevant. e.g. In a DATE
* type, the hour, minute, second and z fields will be NULLs.
*/
struct toml_timestamp_t {
struct { /* internal. do not use. */
int year, month, day;
int hour, minute, second, millisec;
char z[10];
} __buffer;
int *year, *month, *day;
int *hour, *minute, *second, *millisec;
char* z;
struct { /* internal. do not use. */
int year, month, day;
int hour, minute, second, millisec;
char z[10];
} __buffer;
int *year, *month, *day;
int *hour, *minute, *second, *millisec;
char *z;
};
/*-----------------------------------------------------------------
* Enhanced access methods
* Enhanced access methods
*/
struct toml_datum_t {
int ok;
union {
toml_timestamp_t* ts; /* ts must be freed after use */
char* s; /* string value. s must be freed after use */
int b; /* bool value */
int64_t i; /* int value */
double d; /* double value */
} u;
int ok;
union {
toml_timestamp_t *ts; /* ts must be freed after use */
char *s; /* string value. s must be freed after use */
int b; /* bool value */
int64_t i; /* int value */
double d; /* double value */
} u;
};
/* on arrays: */
/* ... retrieve size of array. */
TOML_EXTERN int toml_array_nelem(const toml_array_t* arr);
TOML_EXTERN int toml_array_nelem(const toml_array_t *arr);
/* ... retrieve values using index. */
TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx);
/* ... retrieve array or table using index. */
TOML_EXTERN toml_array_t* toml_array_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_table_t* toml_table_at(const toml_array_t* arr, int idx);
TOML_EXTERN toml_array_t *toml_array_at(const toml_array_t *arr, int idx);
TOML_EXTERN toml_table_t *toml_table_at(const toml_array_t *arr, int idx);
/* on tables: */
/* ... retrieve the key in table at keyidx. Return 0 if out of range. */
TOML_EXTERN const char* toml_key_in(const toml_table_t* tab, int keyidx);
TOML_EXTERN const char *toml_key_in(const toml_table_t *tab, int keyidx);
/* ... retrieve values using key. */
TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t* arr, const char* key);
TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t* arr, const char* key);
TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t* arr, const char* key);
TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t* arr, const char* key);
TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t* arr, const char* key);
TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t *arr, const char *key);
TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key);
TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t *arr, const char *key);
TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t *arr, const char *key);
TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t *arr, const char *key);
/* .. retrieve array or table using key. */
TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab,
const char* key);
TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab,
const char* key);
TOML_EXTERN toml_array_t *toml_array_in(const toml_table_t *tab, const char *key);
TOML_EXTERN toml_table_t *toml_table_in(const toml_table_t *tab, const char *key);
/*-----------------------------------------------------------------
* lesser used
* lesser used
*/
/* Return the array kind: 't'able, 'a'rray, 'v'alue */
TOML_EXTERN char toml_array_kind(const toml_array_t* arr);
TOML_EXTERN char toml_array_kind(const toml_array_t *arr);
/* For array kind 'v'alue, return the type of values
/* For array kind 'v'alue, return the type of values
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp
0 if unknown
*/
TOML_EXTERN char toml_array_type(const toml_array_t* arr);
TOML_EXTERN char toml_array_type(const toml_array_t *arr);
/* Return the key of an array */
TOML_EXTERN const char* toml_array_key(const toml_array_t* arr);
TOML_EXTERN const char *toml_array_key(const toml_array_t *arr);
/* Return the number of key-values in a table */
TOML_EXTERN int toml_table_nkval(const toml_table_t* tab);
TOML_EXTERN int toml_table_nkval(const toml_table_t *tab);
/* Return the number of arrays in a table */
TOML_EXTERN int toml_table_narr(const toml_table_t* tab);
TOML_EXTERN int toml_table_narr(const toml_table_t *tab);
/* Return the number of sub-tables in a table */
TOML_EXTERN int toml_table_ntab(const toml_table_t* tab);
TOML_EXTERN int toml_table_ntab(const toml_table_t *tab);
/* Return the key of a table*/
TOML_EXTERN const char* toml_table_key(const toml_table_t* tab);
TOML_EXTERN const char *toml_table_key(const toml_table_t *tab);
/*--------------------------------------------------------------
* misc
* misc
*/
TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret);
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t),
void (*xxfree)(void*));
TOML_EXTERN int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret);
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
TOML_EXTERN void toml_set_memutil(void *(*xxmalloc)(size_t), void (*xxfree)(void *));
/*--------------------------------------------------------------
* deprecated
* deprecated
*/
/* A raw value, must be processed by toml_rto* before using. */
typedef const char* toml_raw_t;
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key);
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t* arr, int idx);
TOML_EXTERN int toml_rtos(toml_raw_t s, char** ret);
TOML_EXTERN int toml_rtob(toml_raw_t s, int* ret);
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t* ret);
TOML_EXTERN int toml_rtod(toml_raw_t s, double* ret);
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double* ret, char* buf, int buflen);
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t* ret);
typedef const char *toml_raw_t;
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key);
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t *arr, int idx);
TOML_EXTERN int toml_rtos(toml_raw_t s, char **ret);
TOML_EXTERN int toml_rtob(toml_raw_t s, int *ret);
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t *ret);
TOML_EXTERN int toml_rtod(toml_raw_t s, double *ret);
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double *ret, char *buf, int buflen);
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t *ret);
#endif /* TOML_H */

View File

@@ -11,14 +11,13 @@
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;
const gchar *prop;
long vid = 0, pid = 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) {
if (!manager->modem_usb_id || strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) {
return;
}
@@ -42,10 +41,8 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic
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 ||
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;
}
@@ -54,9 +51,9 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic
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[])
void udev_init(struct EG25Manager *manager, toml_table_t *config[])
{
const char * const subsystems[] = { "usb", NULL };
const char *const subsystems[] = {"usb", NULL};
manager->udev = g_udev_client_new(subsystems);
g_signal_connect(manager->udev, "uevent", G_CALLBACK(udev_event_cb), manager);
@@ -64,7 +61,7 @@ void udev_init (struct EG25Manager *manager, toml_table_t *config[])
return;
}
void udev_destroy (struct EG25Manager *manager)
void udev_destroy(struct EG25Manager *manager)
{
if (manager->udev) {
g_object_unref(manager->udev);

View File

@@ -8,5 +8,5 @@
#include "manager.h"
void udev_init (struct EG25Manager *data, toml_table_t *config[]);
void udev_destroy (struct EG25Manager *data);
void udev_init(struct EG25Manager *data, toml_table_t *config[]);
void udev_destroy(struct EG25Manager *data);