diff --git a/meson.build b/meson.build index 5fc84cf..6bea235 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ # project ( - 'eg25manager', + 'eg25-manager', 'c', version : '0.1.2', license : 'GPLv3+', @@ -41,6 +41,12 @@ else full_sysconfdir = join_paths(prefix, sysconfdir) endif +eg25_confdir = join_paths(full_sysconfdir, meson.project_name()) +eg25_datadir = join_paths(full_datadir, meson.project_name()) + +add_global_arguments('-D@0@="@1@"'.format('EG25_CONFDIR', eg25_confdir), language : 'c') +add_global_arguments('-D@0@="@1@"'.format('EG25_DATADIR', eg25_datadir), language : 'c') + mgr_deps = [ dependency('glib-2.0'), dependency('gio-unix-2.0'), diff --git a/src/at.c b/src/at.c index 661098a..8d32903 100644 --- a/src/at.c +++ b/src/at.c @@ -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) { diff --git a/src/at.h b/src/at.h index 958e26f..ba294a4 100644 --- a/src/at.h +++ b/src/at.h @@ -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); diff --git a/src/gpio.c b/src/gpio.c index e91bb5c..4117dea 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -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; diff --git a/src/gpio.h b/src/gpio.h index 1f1efa6..8d94013 100644 --- a/src/gpio.h +++ b/src/gpio.h @@ -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); diff --git a/src/manager.c b/src/manager.c index 964552e..f35b9cf 100644 --- a/src/manager.c +++ b/src/manager.c @@ -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); diff --git a/src/manager.h b/src/manager.h index 229f061..8c12ff5 100644 --- a/src/manager.h +++ b/src/manager.h @@ -11,6 +11,8 @@ #include #include +#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 diff --git a/src/mm-iface.c b/src/mm-iface.c index 8a273ea..8afe2ea 100644 --- a/src/mm-iface.c +++ b/src/mm-iface.c @@ -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, diff --git a/src/mm-iface.h b/src/mm-iface.h index 6cfe94e..1bc8164 100644 --- a/src/mm-iface.h +++ b/src/mm-iface.h @@ -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); diff --git a/src/suspend.c b/src/suspend.c index c584041..74c9c55 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -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 | diff --git a/src/suspend.h b/src/suspend.h index e82eeff..6b92015 100644 --- a/src/suspend.h +++ b/src/suspend.h @@ -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); diff --git a/src/udev.c b/src/udev.c index 5933290..10302cd 100644 --- a/src/udev.c +++ b/src/udev.c @@ -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 }; diff --git a/src/udev.h b/src/udev.h index bf166b1..6b17323 100644 --- a/src/udev.h +++ b/src/udev.h @@ -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);