10 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
21 changed files with 2484 additions and 2251 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

@@ -8,7 +8,7 @@
project ( project (
'eg25-manager', 'eg25-manager',
'c', 'c',
version : '0.5.1', version : '0.5.2',
license : 'GPLv3+', license : 'GPLv3+',
meson_version : '>= 0.58.0', meson_version : '>= 0.58.0',
default_options : default_options :

View File

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

View File

@@ -13,25 +13,22 @@ typedef struct AtCommand {
char *subcmd; char *subcmd;
char *value; char *value;
char *expected; char *expected;
void (*callback)(struct EG25Manager *manager, const char *response); void (*callback)(struct EG25Manager *manager, const char *response);
int retries; int retries;
} AtCommand; } 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_destroy(struct EG25Manager *manager);
void at_process_result(struct EG25Manager *manager, void at_process_result(struct EG25Manager *manager, const char *response);
const char *response); void at_next_command(struct EG25Manager *manager);
void at_next_command(struct EG25Manager *manager);
gboolean at_send_command(struct EG25Manager *manager); gboolean at_send_command(struct EG25Manager *manager);
int at_append_command(struct EG25Manager *manager, int at_append_command(struct EG25Manager *manager,
const char *cmd, const char *cmd,
const char *subcmd, const char *subcmd,
const char *value, const char *value,
const char *expected, const char *expected,
void (*callback) void (*callback)(struct EG25Manager *manager, const char *response));
(struct EG25Manager *manager,
const char *response));
void at_sequence_configure(struct EG25Manager *manager); void at_sequence_configure(struct EG25Manager *manager);
void at_sequence_suspend(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) 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]) if (config[EG25_CONFIG_USER])
value = toml_bool_in(config[EG25_CONFIG_USER], key); 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) 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]) if (config[EG25_CONFIG_USER])
value = toml_int_in(config[EG25_CONFIG_USER], key); 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) gboolean config_get_uint(toml_table_t **config, const gchar *key, guint *result)
{ {
gint value; gint value;
gboolean found; gboolean found;
found = config_get_int(config, key, &value); 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) if (found && result)
*result = (guint) value; *result = (guint)value;
return found; return found;
} }
gboolean config_get_string(toml_table_t **config, const gchar *key, gchar **result) 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]) if (config[EG25_CONFIG_USER])
value = toml_string_in(config[EG25_CONFIG_USER], key); value = toml_string_in(config[EG25_CONFIG_USER], key);

View File

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

View File

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

View File

@@ -4,16 +4,16 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include "config.h"
#include "gpio.h" #include "gpio.h"
#include "config.h"
#include <unistd.h>
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
/* Those defines are used for legacy config files only */ /* Those defines are used for legacy config files only */
#define GPIO_CHIP1_LABEL "1c20800.pinctrl" #define GPIO_CHIP1_LABEL "1c20800.pinctrl"
#define GPIO_CHIP2_LABEL "1f02c00.pinctrl" #define GPIO_CHIP2_LABEL "1f02c00.pinctrl"
#define MAX_GPIOCHIP_LINES 352 #define MAX_GPIOCHIP_LINES 352
enum { enum {
@@ -42,31 +42,32 @@ static char *gpio_in_names[] = {
"status", "status",
}; };
enum gpiod_line_value gpio_line_get_value(struct EG25Manager *manager, int line) { enum gpiod_line_value gpio_line_get_value(struct EG25Manager *manager, int line)
{
enum gpiod_line_value value; enum gpiod_line_value value;
unsigned int offset; unsigned int offset;
gpiod_line_request_get_requested_offsets(manager->gpio_in[line], &offset, 1); gpiod_line_request_get_requested_offsets(manager->gpio_in[line], &offset, 1);
value = gpiod_line_request_get_value(manager->gpio_in[line], offset); value = gpiod_line_request_get_value(manager->gpio_in[line], offset);
if (value == GPIOD_LINE_VALUE_ERROR) { if (value == GPIOD_LINE_VALUE_ERROR) {
g_warning("gpio: couldn't get value on line %d", line); g_warning("gpio: couldn't get value on line %d", line);
} }
return value; return value;
} }
int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_value value) { int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_value value)
{
unsigned int offset; unsigned int offset;
int ret; int ret;
gpiod_line_request_get_requested_offsets(manager->gpio_out[line], &offset, 1); gpiod_line_request_get_requested_offsets(manager->gpio_out[line], &offset, 1);
ret = gpiod_line_request_set_value(manager->gpio_out[line], offset, value); ret = gpiod_line_request_set_value(manager->gpio_out[line], offset, value);
if (ret) { if (ret) {
g_warning("gpio: couldn't set value %d on line %d", value, line); g_warning("gpio: couldn't set value %d on line %d", value, line);
return -1; return -1;
} } else {
else {
manager->gpio_out_value[line] = value; manager->gpio_out_value[line] = value;
return 0; return 0;
} }
@@ -74,10 +75,6 @@ int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_v
int gpio_sequence_poweron(struct EG25Manager *manager) int gpio_sequence_poweron(struct EG25Manager *manager)
{ {
/* Disable airplane mode in case it was enabled by other software. The
* W_DISABLE pin is active-low, so we set it to high here. */
gpio_line_set_value(manager, GPIO_OUT_DISABLE, GPIOD_LINE_VALUE_ACTIVE);
/* /*
* Force the modem to poweroff using the RESET_N pin before attempting to * Force the modem to poweroff using the RESET_N pin before attempting to
* boot in case the it got into a bad state. * boot in case the it got into a bad state.
@@ -163,12 +160,16 @@ int gpio_sequence_sleep(struct EG25Manager *manager)
return 0; return 0;
} }
struct gpiod_line_request *gpio_request_line(struct EG25Manager *manager, int chip, unsigned int line, enum gpiod_line_direction direction) { struct gpiod_line_request *gpio_request_line(struct EG25Manager *manager,
struct gpiod_line_request *request = NULL; int chip,
struct gpiod_line_settings *settings; unsigned int line,
struct gpiod_line_config *line_cfg; enum gpiod_line_direction direction)
{
struct gpiod_line_request *request = NULL;
struct gpiod_line_settings *settings;
struct gpiod_line_config *line_cfg;
struct gpiod_request_config *req_cfg; struct gpiod_request_config *req_cfg;
int ret; int ret;
settings = gpiod_line_settings_new(); settings = gpiod_line_settings_new();
if (!settings) if (!settings)
@@ -206,14 +207,13 @@ free_settings:
static int gpio_chip_dir_filter(const struct dirent *entry) static int gpio_chip_dir_filter(const struct dirent *entry)
{ {
struct stat sb; struct stat sb;
int ret = 0; int ret = 0;
char *path; char *path;
if (asprintf(&path, "/dev/%s", entry->d_name) < 0) if (asprintf(&path, "/dev/%s", entry->d_name) < 0)
return 0; return 0;
if ((lstat(path, &sb) == 0) && (!S_ISLNK(sb.st_mode)) && if ((lstat(path, &sb) == 0) && (!S_ISLNK(sb.st_mode)) && gpiod_is_gpiochip_device(path))
gpiod_is_gpiochip_device(path))
ret = 1; ret = 1;
free(path); free(path);
@@ -223,9 +223,9 @@ static int gpio_chip_dir_filter(const struct dirent *entry)
int gpio_all_chip_paths(char ***paths_ptr) int gpio_all_chip_paths(char ***paths_ptr)
{ {
int i, j, num_chips, ret = 0; int i, j, num_chips, ret = 0;
struct dirent **entries; struct dirent **entries;
char **paths; char **paths;
num_chips = scandir("/dev/", &entries, gpio_chip_dir_filter, alphasort); num_chips = scandir("/dev/", &entries, gpio_chip_dir_filter, alphasort);
if (num_chips < 0) if (num_chips < 0)
@@ -257,10 +257,10 @@ int gpio_all_chip_paths(char ***paths_ptr)
struct gpiod_chip *gpio_chip_open_by_label(const char *label) struct gpiod_chip *gpio_chip_open_by_label(const char *label)
{ {
int num_chips, i; int num_chips, i;
char **paths; char **paths = NULL;
const char *clabel; const char *clabel;
struct gpiod_chip *chip; struct gpiod_chip *chip;
struct gpiod_chip_info *cinfo; struct gpiod_chip_info *cinfo;
num_chips = gpio_all_chip_paths(&paths); num_chips = gpio_all_chip_paths(&paths);
@@ -277,6 +277,7 @@ struct gpiod_chip *gpio_chip_open_by_label(const char *label)
clabel = gpiod_chip_info_get_label(cinfo); clabel = gpiod_chip_info_get_label(cinfo);
if (strcmp(label, clabel) == 0) { if (strcmp(label, clabel) == 0) {
free(paths);
return chip; return chip;
} }
@@ -284,13 +285,17 @@ clean_chip_open:
gpiod_chip_close(chip); gpiod_chip_close(chip);
} }
if (paths)
free(paths);
return NULL; return NULL;
} }
unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_num) { unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_num)
struct gpiod_chip *chip = manager->gpiochip[chip_num]; {
struct gpiod_chip *chip = manager->gpiochip[chip_num];
struct gpiod_chip_info *info; struct gpiod_chip_info *info;
unsigned int num_lines; unsigned int num_lines;
info = gpiod_chip_get_info(chip); info = gpiod_chip_get_info(chip);
if (!info) if (!info)
@@ -305,7 +310,7 @@ unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_
int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
{ {
int i; int i;
toml_table_t *gpio_config[EG25_CONFIG_COUNT]; toml_table_t *gpio_config[EG25_CONFIG_COUNT];
for (i = 0; i < EG25_CONFIG_COUNT; i++) for (i = 0; i < EG25_CONFIG_COUNT; i++)
@@ -325,9 +330,8 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
* format, but error out if user config overrides gpios using the * format, but error out if user config overrides gpios using the
* old format * old format
*/ */
if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips")) if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips")) {
{ int numchips;
int numchips;
toml_array_t *chipslist = NULL; toml_array_t *chipslist = NULL;
config_get_array(gpio_config, "chips", &chipslist); config_get_array(gpio_config, "chips", &chipslist);
@@ -346,7 +350,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
for (i = 0; i < GPIO_OUT_COUNT; i++) { for (i = 0; i < GPIO_OUT_COUNT; i++) {
toml_table_t *table; 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)) 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]); g_error("Unable to get config for output GPIO '%s'", gpio_out_names[i]);
@@ -358,14 +362,17 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
if (!line.ok || line.u.i < 0 || line.u.i > gpio_chip_num_lines(manager, 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]); g_error("Wrong line ID for output GPIO '%s'", gpio_out_names[i]);
manager->gpio_out[i] = gpio_request_line(manager, chip.u.i, line.u.i, GPIOD_LINE_DIRECTION_OUTPUT); manager->gpio_out[i] = gpio_request_line(manager,
chip.u.i,
line.u.i,
GPIOD_LINE_DIRECTION_OUTPUT);
if (!manager->gpio_out[i]) if (!manager->gpio_out[i])
g_error("Unable to get output GPIO %d", i); g_error("Unable to get output GPIO %d", i);
} }
for (i = 0; i < GPIO_IN_COUNT; i++) { for (i = 0; i < GPIO_IN_COUNT; i++) {
toml_table_t *table; 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)) { if (!config_get_table(gpio_config, gpio_in_names[i], &table)) {
// BH edition don't have the STATUS line connected, ignore it // BH edition don't have the STATUS line connected, ignore it
@@ -382,7 +389,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
if (!line.ok || line.u.i < 0 || line.u.i > gpio_chip_num_lines(manager, 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]); g_error("Wrong line ID for input GPIO '%s'", gpio_in_names[i]);
manager->gpio_in[i] = gpio_request_line(manager, chip.u.i, line.u.i, GPIOD_LINE_DIRECTION_INPUT); manager->gpio_in[i] = gpio_request_line(manager,
chip.u.i,
line.u.i,
GPIOD_LINE_DIRECTION_INPUT);
if (!manager->gpio_in[i]) if (!manager->gpio_in[i])
g_error("Unable to get input GPIO %d", i); g_error("Unable to get input GPIO %d", i);
} }
@@ -410,7 +420,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
chipidx = 1; chipidx = 1;
} }
manager->gpio_out[i] = gpio_request_line(manager, chipidx, offset, GPIOD_LINE_DIRECTION_OUTPUT); manager->gpio_out[i] = gpio_request_line(manager,
chipidx,
offset,
GPIOD_LINE_DIRECTION_OUTPUT);
if (!manager->gpio_out[i]) if (!manager->gpio_out[i])
g_error("Unable to get output GPIO %d", i); g_error("Unable to get output GPIO %d", i);
} }
@@ -427,7 +440,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[])
chipidx = 1; chipidx = 1;
} }
manager->gpio_in[i] = gpio_request_line(manager, chipidx, offset, GPIOD_LINE_DIRECTION_INPUT); manager->gpio_in[i] = gpio_request_line(manager,
chipidx,
offset,
GPIOD_LINE_DIRECTION_INPUT);
if (!manager->gpio_in[i]) if (!manager->gpio_in[i])
g_error("Unable to get input GPIO %d", i); g_error("Unable to get input GPIO %d", i);
} }

View File

@@ -8,7 +8,7 @@
#include "manager.h" #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); void gpio_destroy(struct EG25Manager *state);
int gpio_sequence_poweron(struct EG25Manager *state); int gpio_sequence_poweron(struct EG25Manager *state);
@@ -18,5 +18,5 @@ int gpio_sequence_resume(struct EG25Manager *state);
int gpio_sequence_wake(struct EG25Manager *state); int gpio_sequence_wake(struct EG25Manager *state);
int gpio_sequence_sleep(struct EG25Manager *state); int gpio_sequence_sleep(struct EG25Manager *state);
void gpio_force_off(struct EG25Manager *manager); void gpio_force_off(struct EG25Manager *manager);
gboolean gpio_check_poweroff(struct EG25Manager *manager); gboolean gpio_check_poweroff(struct EG25Manager *manager);

View File

@@ -4,19 +4,19 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include "manager.h"
#include "at.h" #include "at.h"
#include "config.h" #include "config.h"
#include "gpio.h" #include "gpio.h"
#include "manager.h"
#ifdef HAVE_MMGLIB #ifdef HAVE_MMGLIB
#include "mm-iface.h" #include "mm-iface.h"
#endif #endif
#include "gnss.h"
#include "ofono-iface.h" #include "ofono-iface.h"
#include "suspend.h" #include "suspend.h"
#include "udev.h" #include "udev.h"
#include "gnss.h"
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
@@ -41,7 +41,7 @@
#define EG25_DEFAULT_VENDOR_ID 0x2c7c #define EG25_DEFAULT_VENDOR_ID 0x2c7c
#define EG25_DEFAULT_PRODUCT_ID 0x0125 #define EG25_DEFAULT_PRODUCT_ID 0x0125
#define POWERON_DELAY_US 100000UL #define POWERON_DELAY_US 100000UL
static gboolean quit_app(struct EG25Manager *manager) static gboolean quit_app(struct EG25Manager *manager)
{ {
@@ -80,10 +80,10 @@ static gboolean quit_app(struct EG25Manager *manager)
static gboolean modem_start(struct EG25Manager *manager) static gboolean modem_start(struct EG25Manager *manager)
{ {
ssize_t i, count; ssize_t i, count;
gboolean should_boot = TRUE; gboolean should_boot = TRUE;
libusb_context *ctx = NULL; libusb_context *ctx = NULL;
libusb_device **devices = NULL; libusb_device **devices = NULL;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
if (manager->use_libusb) { if (manager->use_libusb) {
@@ -154,7 +154,7 @@ static gboolean modem_gpio_reset_done(struct EG25Manager *manager)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static gboolean modem_at_reset_done(struct EG25Manager* manager) static gboolean modem_at_reset_done(struct EG25Manager *manager)
{ {
/* /*
* If the modem was successfully rebooted, then we should have received * If the modem was successfully rebooted, then we should have received
@@ -168,12 +168,14 @@ static gboolean modem_at_reset_done(struct EG25Manager* manager)
g_message("AT reset failed, falling back to GPIO reset"); g_message("AT reset failed, falling back to GPIO reset");
gpio_sequence_shutdown(manager); gpio_sequence_shutdown(manager);
manager->complete_reset_timer = g_timeout_add_seconds(30, G_SOURCE_FUNC(modem_gpio_reset_done), manager); manager->complete_reset_timer = g_timeout_add_seconds(30,
G_SOURCE_FUNC(modem_gpio_reset_done),
manager);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static gboolean modem_rebind_done(struct EG25Manager* manager) static gboolean modem_rebind_done(struct EG25Manager *manager)
{ {
manager->modem_state = EG25_STATE_RESUMING; manager->modem_state = EG25_STATE_RESUMING;
manager->complete_reset_timer = 0; manager->complete_reset_timer = 0;
@@ -271,7 +273,9 @@ error:
at_sequence_reset(manager); at_sequence_reset(manager);
// Setup timer for making sure we don't queue other reset commands // 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_at_reset_done), manager); manager->complete_reset_timer = g_timeout_add_seconds(45,
G_SOURCE_FUNC(modem_at_reset_done),
manager);
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
@@ -301,15 +305,15 @@ void modem_resume_post(struct EG25Manager *manager)
static toml_table_t *parse_config_file(char *config_file, gboolean force_default) static toml_table_t *parse_config_file(char *config_file, gboolean force_default)
{ {
toml_table_t *toml_config; toml_table_t *toml_config;
gchar *compatible; gchar *compatible;
gchar error[256]; gchar error[256];
gsize len; gsize len;
FILE *f = NULL; FILE *f = NULL;
if (config_file) { if (config_file) {
f = fopen(config_file, "r"); f = fopen(config_file, "r");
} else if (g_file_get_contents("/proc/device-tree/compatible", &compatible, &len, NULL)) { } 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; gsize pos = 0;
/* /*
@@ -324,9 +328,11 @@ static toml_table_t *parse_config_file(char *config_file, gboolean force_default
for (pos = 0; pos < compat->len; pos++) { for (pos = 0; pos < compat->len; pos++) {
g_autofree gchar *filename = NULL; g_autofree gchar *filename = NULL;
if (force_default) 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 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) { if (access(filename, F_OK) == 0) {
g_message("Opening config file: %s", filename); g_message("Opening config file: %s", filename);
@@ -355,15 +361,15 @@ int main(int argc, char *argv[])
g_autoptr(GOptionContext) opt_context = NULL; g_autoptr(GOptionContext) opt_context = NULL;
g_autoptr(GError) err = NULL; g_autoptr(GError) err = NULL;
struct EG25Manager manager; struct EG25Manager manager;
gchar *config_file = NULL; gchar *config_file = NULL;
gboolean show_version = FALSE; gboolean show_version = FALSE;
gboolean monitor_udev = TRUE; gboolean monitor_udev = TRUE;
toml_table_t *toml_config[EG25_CONFIG_COUNT]; toml_table_t *toml_config[EG25_CONFIG_COUNT];
toml_table_t *manager_config[EG25_CONFIG_COUNT]; toml_table_t *manager_config[EG25_CONFIG_COUNT];
const GOptionEntry options[] = { const GOptionEntry options[] = {
{ "config", 'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file to use.", 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 }, {"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 } {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
memset(&manager, 0, sizeof(manager)); memset(&manager, 0, sizeof(manager));
@@ -372,10 +378,10 @@ int main(int argc, char *argv[])
manager.suspend_delay_fd = -1; manager.suspend_delay_fd = -1;
manager.suspend_block_fd = -1; manager.suspend_block_fd = -1;
opt_context = g_option_context_new ("- Power management for the Quectel EG25 modem"); opt_context = g_option_context_new("- Power management for the Quectel EG25 modem");
g_option_context_add_main_entries (opt_context, options, NULL); g_option_context_add_main_entries(opt_context, options, NULL);
if (!g_option_context_parse (opt_context, &argc, &argv, &err)) { if (!g_option_context_parse(opt_context, &argc, &argv, &err)) {
g_warning ("%s", err->message); g_warning("%s", err->message);
return 1; return 1;
} }

View File

@@ -41,19 +41,18 @@ typedef enum {
EG25_GNSS_SOURCE_QGPS = 1 << 3, EG25_GNSS_SOURCE_QGPS = 1 << 3,
} EG25GNSSSource; } EG25GNSSSource;
enum EG25State { enum EG25State {
EG25_STATE_INIT = 0, EG25_STATE_INIT = 0,
EG25_STATE_POWERED, // Power-on sequence has been executed, but the modem isn't on yet 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_STARTED, // Modem has been started and declared itdata ready
EG25_STATE_ACQUIRED, // Modem has been probed by ModemManager EG25_STATE_ACQUIRED, // Modem has been probed by ModemManager
EG25_STATE_CONFIGURED, // Modem has been configured through AT commands EG25_STATE_CONFIGURED, // Modem has been configured through AT commands
EG25_STATE_REGISTERED, // Modem is unlocked and registered to a network provider 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_SUSPENDING, // System is going into suspend
EG25_STATE_RESUMING, // System is being resumed, waiting for modem to come back 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_RESETTING, // Something went wrong, we're restarting the modem
EG25_STATE_UPDATING, // Modem is present but being updated EG25_STATE_UPDATING, // Modem is present but being updated
EG25_STATE_FINISHING EG25_STATE_FINISHING
}; };
@@ -71,42 +70,42 @@ enum EG25Config {
struct EG25Manager { struct EG25Manager {
GMainLoop *loop; GMainLoop *loop;
guint complete_reset_timer; guint complete_reset_timer;
guint schedule_reset_timer; guint schedule_reset_timer;
gboolean use_libusb; gboolean use_libusb;
guint usb_vid; guint usb_vid;
guint usb_pid; guint usb_pid;
guint poweron_delay; guint poweron_delay;
int at_fd; int at_fd;
guint at_source; guint at_source;
GList *at_cmds; 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; enum EG25State modem_state;
gchar *modem_usb_id; gchar *modem_usb_id;
gboolean gnss_assistance_enabled; gboolean gnss_assistance_enabled;
EG25GNSSSource gnss_sources; EG25GNSSSource gnss_sources;
EG25GNSSStep gnss_assistance_step; EG25GNSSStep gnss_assistance_step;
gint gnss_assistance_fd; gint gnss_assistance_fd;
gchar *gnss_assistance_url; gchar *gnss_assistance_url;
gchar *gnss_assistance_file; gchar *gnss_assistance_file;
enum ModemIface modem_iface; enum ModemIface modem_iface;
guint mm_watch; guint mm_watch;
#ifdef HAVE_MMGLIB #ifdef HAVE_MMGLIB
MMManager *mm_manager; MMManager *mm_manager;
MMModem *mm_modem; MMModem *mm_modem;
MMModemLocation *mm_location; MMModemLocation *mm_location;
#endif #endif
guint ofono_watch; guint ofono_watch;
GDBOManager *ofono_manager; GDBOManager *ofono_manager;
GDBusConnection *ofono_connection; GDBusConnection *ofono_connection;
GDBusProxy *suspend_proxy; GDBusProxy *suspend_proxy;
int suspend_delay_fd; int suspend_delay_fd;
int suspend_block_fd; int suspend_block_fd;
guint modem_recovery_timer; guint modem_recovery_timer;
guint modem_recovery_timeout; guint modem_recovery_timeout;
@@ -115,18 +114,18 @@ struct EG25Manager {
GUdevClient *udev; GUdevClient *udev;
struct gpiod_chip *gpiochip[2]; struct gpiod_chip *gpiochip[2];
struct gpiod_line_request *gpio_out[5]; struct gpiod_line_request *gpio_out[5];
guint gpio_out_value[5]; guint gpio_out_value[5];
struct gpiod_line_request *gpio_in[2]; 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); gboolean modem_reset(struct EG25Manager *data);
void modem_suspend_pre(struct EG25Manager *data); void modem_suspend_pre(struct EG25Manager *data);
void modem_suspend_post(struct EG25Manager *data); void modem_suspend_post(struct EG25Manager *data);
void modem_resume_pre(struct EG25Manager *data); void modem_resume_pre(struct EG25Manager *data);
void modem_resume_post(struct EG25Manager *data); void modem_resume_post(struct EG25Manager *data);
#ifdef HAVE_MMGLIB #ifdef HAVE_MMGLIB
void modem_update_state(struct EG25Manager *data, MMModemState state); void modem_update_state(struct EG25Manager *data, MMModemState state);
#endif #endif

View File

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

View File

@@ -14,9 +14,9 @@
#define OFONO_SERVICE "org.ofono" #define OFONO_SERVICE "org.ofono"
static void modem_added_cb(GDBOManager *manager_proxy, static void modem_added_cb(GDBOManager *manager_proxy,
const gchar *path, const gchar *path,
GVariant *properties, GVariant *properties,
struct EG25Manager *manager) struct EG25Manager *manager)
{ {
GVariant *modem_path; 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); manager->modem_usb_id = g_strdup(strrchr(g_variant_dup_string(modem_path, NULL), '/') + 1);
} }
static void modem_removed_cb(GDBOManager *manager_proxy, static void modem_removed_cb(GDBOManager *manager_proxy, const gchar *path, struct EG25Manager *manager)
const gchar *path,
struct EG25Manager *manager)
{ {
} }
static void get_modems_cb(GDBOManager *manager_proxy, static void get_modems_cb(GDBOManager *manager_proxy, GAsyncResult *res, struct EG25Manager *manager)
GAsyncResult *res,
struct EG25Manager *manager)
{ {
gboolean ok; gboolean ok;
GVariant *modems; GVariant *modems;
GVariantIter *modems_iter = NULL; GVariantIter *modems_iter = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
const gchar *path; const gchar *path;
GVariant *properties; GVariant *properties;
ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems, ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems, res, &error);
res, &error);
if (!ok) { if (!ok) {
g_warning("Error getting modems from ofono manager: %s", error->message); g_warning("Error getting modems from ofono manager: %s", error->message);
return; return;
} }
g_variant_get(modems, "a(oa{sv})", &modems_iter); 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); g_debug("Got modem object path '%s'", path);
modem_added_cb(manager_proxy, path, properties, manager); 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"); g_message("oFono appeared on D-Bus");
if (manager->modem_iface != MODEM_IFACE_NONE) { 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; return;
} }
/* now connect to oFono! */ /* now connect to oFono! */
@@ -105,14 +102,12 @@ static void ofono_appeared_cb(GDBusConnection *connection,
manager->modem_iface = MODEM_IFACE_OFONO; manager->modem_iface = MODEM_IFACE_OFONO;
g_signal_connect(manager->ofono_manager, "modem-added", g_signal_connect(manager->ofono_manager, "modem-added", G_CALLBACK(modem_added_cb), manager);
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-removed",
G_CALLBACK(modem_removed_cb), manager);
gdbo_manager_call_get_modems(manager->ofono_manager, gdbo_manager_call_get_modems(manager->ofono_manager,
NULL, NULL,
(GAsyncReadyCallback) get_modems_cb, (GAsyncReadyCallback)get_modems_cb,
manager); manager);
} }
@@ -130,11 +125,13 @@ static void ofono_vanished_cb(GDBusConnection *connection,
void ofono_iface_init(struct EG25Manager *manager, toml_table_t *config[]) 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, G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
(GBusNameAppearedCallback)ofono_appeared_cb, (GBusNameAppearedCallback)ofono_appeared_cb,
(GBusNameVanishedCallback)ofono_vanished_cb, (GBusNameVanishedCallback)ofono_vanished_cb,
manager, NULL); manager,
NULL);
} }
void ofono_iface_destroy(struct EG25Manager *manager) void ofono_iface_destroy(struct EG25Manager *manager)

View File

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

View File

@@ -8,7 +8,7 @@
#include "manager.h" #include "manager.h"
void suspend_init (struct EG25Manager *data, toml_table_t *config[]); void suspend_init(struct EG25Manager *data, toml_table_t *config[]);
void suspend_destroy (struct EG25Manager *data); 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 MIT License
Copyright (c) 2017 - 2019 CK Tan Copyright (c) 2017 - 2019 CK Tan
https://github.com/cktan/tomlc99 https://github.com/cktan/tomlc99
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -25,10 +25,8 @@
#ifndef TOML_H #ifndef TOML_H
#define TOML_H #define TOML_H
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus #ifdef __cplusplus
#define TOML_EXTERN extern "C" #define TOML_EXTERN extern "C"
@@ -37,139 +35,130 @@
#endif #endif
typedef struct toml_timestamp_t toml_timestamp_t; typedef struct toml_timestamp_t toml_timestamp_t;
typedef struct toml_table_t toml_table_t; typedef struct toml_table_t toml_table_t;
typedef struct toml_array_t toml_array_t; typedef struct toml_array_t toml_array_t;
typedef struct toml_datum_t toml_datum_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. * Caller must toml_free(the-return-value) after use.
*/ */
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp, TOML_EXTERN toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz);
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. * Return a table on success, or 0 otherwise.
* Caller must toml_free(the-return-value) after use. * Caller must toml_free(the-return-value) after use.
*/ */
TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */ TOML_EXTERN toml_table_t *toml_parse(char *conf, /* NUL terminated, please. */
char* errbuf, char *errbuf,
int errbufsz); int errbufsz);
/* Free the table returned by toml_parse() or toml_parse_file(). Once /* Free the table returned by toml_parse() or toml_parse_file(). Once
* this function is called, any handles accessed through this tab * this function is called, any handles accessed through this tab
* directly or indirectly are no longer valid. * 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 * 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. * type, the hour, minute, second and z fields will be NULLs.
*/ */
struct toml_timestamp_t { struct toml_timestamp_t {
struct { /* internal. do not use. */ struct { /* internal. do not use. */
int year, month, day; int year, month, day;
int hour, minute, second, millisec; int hour, minute, second, millisec;
char z[10]; char z[10];
} __buffer; } __buffer;
int *year, *month, *day; int *year, *month, *day;
int *hour, *minute, *second, *millisec; int *hour, *minute, *second, *millisec;
char* z; char *z;
}; };
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
* Enhanced access methods * Enhanced access methods
*/ */
struct toml_datum_t { struct toml_datum_t {
int ok; int ok;
union { union {
toml_timestamp_t* ts; /* ts must be freed after use */ toml_timestamp_t *ts; /* ts must be freed after use */
char* s; /* string value. s must be freed after use */ char *s; /* string value. s must be freed after use */
int b; /* bool value */ int b; /* bool value */
int64_t i; /* int value */ int64_t i; /* int value */
double d; /* double value */ double d; /* double value */
} u; } u;
}; };
/* on arrays: */ /* on arrays: */
/* ... retrieve size of array. */ /* ... 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. */ /* ... 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_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_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_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_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_timestamp_at(const toml_array_t *arr, int idx);
/* ... retrieve array or table using index. */ /* ... retrieve array or table using index. */
TOML_EXTERN toml_array_t* toml_array_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); TOML_EXTERN toml_table_t *toml_table_at(const toml_array_t *arr, int idx);
/* on tables: */ /* on tables: */
/* ... retrieve the key in table at keyidx. Return 0 if out of range. */ /* ... 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. */ /* ... 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_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_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_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_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_timestamp_in(const toml_table_t *arr, const char *key);
/* .. retrieve array or table using key. */ /* .. retrieve array or table using key. */
TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab, TOML_EXTERN toml_array_t *toml_array_in(const toml_table_t *tab, const char *key);
const char* key); TOML_EXTERN toml_table_t *toml_table_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 */ /* 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 i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp
0 if unknown 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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*/ /* 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_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 int toml_ucs_to_utf8(int64_t code, char buf[6]);
TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t), TOML_EXTERN void toml_set_memutil(void *(*xxmalloc)(size_t), void (*xxfree)(void *));
void (*xxfree)(void*));
/*-------------------------------------------------------------- /*--------------------------------------------------------------
* deprecated * deprecated
*/ */
/* A raw value, must be processed by toml_rto* before using. */ /* A raw value, must be processed by toml_rto* before using. */
typedef const char* toml_raw_t; 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_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 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_rtos(toml_raw_t s, char **ret);
TOML_EXTERN int toml_rtob(toml_raw_t s, int* 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_rtoi(toml_raw_t s, int64_t *ret);
TOML_EXTERN int toml_rtod(toml_raw_t s, double* 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_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); TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t *ret);
#endif /* TOML_H */ #endif /* TOML_H */

View File

@@ -11,14 +11,13 @@
static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer data) static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer data)
{ {
struct EG25Manager *manager = data; struct EG25Manager *manager = data;
const gchar *prop; const gchar *prop;
long vid = 0, pid = 0; long vid = 0, pid = 0;
/* /*
* Act only if the device is the one identified as a modem by MM/ofono * Act only if the device is the one identified as a modem by MM/ofono
*/ */
if (!manager->modem_usb_id || if (!manager->modem_usb_id || strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) {
strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) {
return; return;
} }
@@ -42,10 +41,8 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic
manager->modem_state = EG25_STATE_UPDATING; manager->modem_state = EG25_STATE_UPDATING;
} }
if (strcmp(action, "unbind") != 0 || if (strcmp(action, "unbind") != 0 || manager->modem_state == EG25_STATE_UPDATING ||
manager->modem_state == EG25_STATE_UPDATING || manager->modem_state == EG25_STATE_RESETTING || manager->complete_reset_timer != 0 ||
manager->modem_state == EG25_STATE_RESETTING ||
manager->complete_reset_timer != 0 ||
manager->schedule_reset_timer != 0) { manager->schedule_reset_timer != 0) {
return; 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); 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); manager->udev = g_udev_client_new(subsystems);
g_signal_connect(manager->udev, "uevent", G_CALLBACK(udev_event_cb), manager); 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; return;
} }
void udev_destroy (struct EG25Manager *manager) void udev_destroy(struct EG25Manager *manager)
{ {
if (manager->udev) { if (manager->udev) {
g_object_unref(manager->udev); g_object_unref(manager->udev);

View File

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