src: implement config file lookup and initial parsing

This commit prepares the use of device-specific configuration files. 
These files should be named after the device-tree `compatible` string 
with the `toml` extension.

`eg25-manager` will search for config files in 
`<prefix>/etc/eg25-manager` first (or `/etc/eg25-manager` if prefix is 
`/usr`), then in `<prefix>/share/eg25-manager`.
This commit is contained in:
Arnaud Ferraris
2021-02-20 15:26:06 +01:00
parent c92746e875
commit d9256251fd
13 changed files with 90 additions and 27 deletions

View File

@@ -218,7 +218,7 @@ static gboolean modem_response(gint fd,
return TRUE;
}
int at_init(struct EG25Manager *manager)
int at_init(struct EG25Manager *manager, toml_table_t *config)
{
manager->at_fd = configure_serial(MODEM_UART);
if (manager->at_fd < 0) {

View File

@@ -8,7 +8,7 @@
#include "manager.h"
int at_init(struct EG25Manager *data);
int at_init(struct EG25Manager *data, toml_table_t *config);
void at_destroy(struct EG25Manager *data);
void at_sequence_configure(struct EG25Manager *data);

View File

@@ -92,7 +92,7 @@ int gpio_sequence_resume(struct EG25Manager *manager)
return 0;
}
int gpio_init(struct EG25Manager *manager)
int gpio_init(struct EG25Manager *manager, toml_table_t *config)
{
int i, ret;
unsigned *gpio_in_idx;

View File

@@ -8,7 +8,7 @@
#include "manager.h"
int gpio_init(struct EG25Manager *state);
int gpio_init(struct EG25Manager *state, toml_table_t *config);
void gpio_destroy(struct EG25Manager *state);
int gpio_sequence_poweron(struct EG25Manager *state);

View File

@@ -21,6 +21,13 @@
#define EG25_USB_VID 0x2c7c
#define EG25_USB_PID 0x0125
#ifndef EG25_CONFDIR
#define EG25_CONFDIR "/etc/eg25-manager"
#endif
#ifndef EG25_DATADIR
#define EG25_DATADIR "/usr/share/eg25-manager"
#endif
static gboolean quit_app(struct EG25Manager *manager)
{
@@ -198,15 +205,71 @@ void modem_resume_post(struct EG25Manager *manager)
at_sequence_resume(manager);
}
static toml_table_t *parse_config_file(char *config_file)
{
toml_table_t *toml_config;
gchar *compatible;
gchar error[256];
gsize len;
FILE *f = NULL;
if (config_file) {
f = fopen(config_file, "r");
} else if (g_file_get_contents("/proc/device-tree/compatible", &compatible, &len, NULL)) {
g_autoptr (GPtrArray) compat = g_ptr_array_new();
gsize pos = 0;
/*
* `compatible` file is a list of NULL-terminated strings, convert it
* to an array
*/
do {
g_ptr_array_add(compat, &compatible[pos]);
pos += strlen(&compatible[pos]) + 1;
} while (pos < len);
for (pos = 0; pos < compat->len; pos++) {
g_autofree gchar *filename = g_strdup_printf(EG25_CONFDIR "/%s.toml", (gchar *)g_ptr_array_index(compat, pos));
if (access(filename, F_OK) == 0) {
g_message("Opening config file: %s", filename);
f = fopen(filename, "r");
break;
}
}
if (!f) {
for (pos = 0; pos < compat->len; pos++) {
g_autofree gchar *filename = g_strdup_printf(EG25_DATADIR "/%s.toml", (gchar *)g_ptr_array_index(compat, pos));
if (access(filename, F_OK) == 0) {
g_message("Opening config file: %s", filename);
f = fopen(filename, "r");
break;
}
}
}
}
if (!f)
g_error("unable to find a suitable config file!");
toml_config = toml_parse_file(f, error, sizeof(error));
if (!toml_config)
g_error("unable to parse config file: %s", error);
return toml_config;
}
int main(int argc, char *argv[])
{
g_autoptr(GOptionContext) opt_context = NULL;
g_autoptr(GError) err = NULL;
struct EG25Manager manager;
char compatible[32];
int fd, ret;
gchar *config_file = NULL;
toml_table_t *toml_config;
toml_datum_t toml_value;
const GOptionEntry options[] = {
{ "gnss", 'g', 0, G_OPTION_ARG_NONE, &manager.manage_gnss, "Manage the GNSS feature.", NULL },
{ "config", 'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file to use.", NULL },
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
};
@@ -224,21 +287,13 @@ int main(int argc, char *argv[])
manager.loop = g_main_loop_new(NULL, FALSE);
fd = open("/proc/device-tree/compatible", O_RDONLY);
if (fd < 0) {
g_critical("Unable to read 'compatible' string from device tree");
return 1;
}
ret = read(fd, compatible, sizeof(compatible));
if (ret > 0 && !strstr(compatible, "pine64,pinephone-1.2"))
manager.braveheart = TRUE;
close(fd);
toml_config = parse_config_file(config_file);
at_init(&manager);
gpio_init(&manager);
mm_iface_init(&manager);
suspend_init(&manager);
udev_init(&manager);
at_init(&manager, toml_table_in(toml_config, "at"));
gpio_init(&manager, toml_table_in(toml_config, "gpio"));
mm_iface_init(&manager, toml_table_in(toml_config, "mm-iface"));
suspend_init(&manager, toml_table_in(toml_config, "suspend"));
udev_init(&manager, toml_table_in(toml_config, "udev"));
g_idle_add(G_SOURCE_FUNC(modem_start), &manager);

View File

@@ -11,6 +11,8 @@
#include <gudev/gudev.h>
#include <libmm-glib.h>
#include "toml.h"
enum EG25State {
EG25_STATE_INIT = 0,
EG25_STATE_POWERED, // Power-on sequence has been executed, but the modem isn't on yet

View File

@@ -187,7 +187,7 @@ static void mm_vanished_cb(GDBusConnection *connection,
mm_iface_clean(manager);
}
void mm_iface_init(struct EG25Manager *manager)
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,
G_BUS_NAME_WATCHER_FLAGS_AUTO_START,

View File

@@ -8,5 +8,5 @@
#include "manager.h"
void mm_iface_init(struct EG25Manager *data);
void mm_iface_init(struct EG25Manager *data, toml_table_t *config);
void mm_iface_destroy(struct EG25Manager *data);

View File

@@ -232,7 +232,7 @@ static void on_proxy_acquired(GObject *object,
}
}
void suspend_init(struct EG25Manager *manager)
void suspend_init(struct EG25Manager *manager, toml_table_t *config)
{
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |

View File

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

View File

@@ -25,7 +25,7 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic
}
}
void udev_init (struct EG25Manager *manager)
void udev_init (struct EG25Manager *manager, toml_table_t *config)
{
const char * const subsystems[] = { "usb", NULL };

View File

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