diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 691f630..99caad5 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -11,7 +11,7 @@ bin_PROGRAMS = x52d # Service daemon that manages the X52 device x52d_SOURCES = \ x52d_main.c x52d_config_parser.c x52d_config.c \ - x52d_device.c + x52d_device.c x52d_clock.c x52d_CFLAGS = \ -I $(top_srcdir) \ @@ -33,6 +33,7 @@ x52d_LDADD = \ @LTLIBINTL@ EXTRA_DIST = \ + x52d_clock.h \ x52d_config.def \ x52d_config.h \ x52d_const.h \ diff --git a/daemon/x52d_clock.c b/daemon/x52d_clock.c new file mode 100644 index 0000000..c67807e --- /dev/null +++ b/daemon/x52d_clock.c @@ -0,0 +1,168 @@ +/* + * Saitek X52 Pro MFD & LED driver - Clock manager + * + * Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#include "pinelog.h" +#include "x52d_config.h" +#include "x52d_clock.h" +#include "x52d_const.h" +#include "x52d_device.h" + +static bool clock_enabled = false; +static int clock_primary_is_local = false; + +void x52d_cfg_set_Clock_Enabled(bool enabled) +{ + PINELOG_DEBUG(_("Setting clock enable to %s"), + enabled ? "on" : "off"); + clock_enabled = enabled; +} + +void x52d_cfg_set_Clock_PrimaryIsLocal(bool param) +{ + PINELOG_DEBUG(_("Setting primary clock timezone to %s"), + param ? "local" : "UTC"); + clock_primary_is_local = !!param; +} + +static int get_tz_offset(const char *tz) +{ + char *orig_tz = NULL; + char *orig_tz_copy = NULL; + time_t t; + struct tm *timeval; + char *new_tz = NULL; + size_t new_tz_len; + int offset = 0; + + new_tz_len = strlen(tz) + 2; + new_tz = malloc(new_tz_len); + if (new_tz == NULL) { + PINELOG_WARN(_("Unable to allocate memory for timezone. Falling back to UTC")); + goto cleanup; + } + snprintf(new_tz, new_tz_len, ":%s", tz); + + orig_tz = getenv("TZ"); + if (orig_tz != NULL) { + /* TZ was set in the environment */ + orig_tz_copy = strdup(orig_tz); + if (orig_tz_copy == NULL) { + PINELOG_WARN(_("Unable to backup timezone environment. Falling back to UTC")); + goto cleanup; + } + } + + setenv("TZ", new_tz, true); + t = time(NULL); + timeval = localtime(&t); + if (timeval != NULL) { + #if HAVE_STRUCT_TM_TM_GMTOFF + /* If valid, then timeval.tm_gmtoff contains the offset in seconds east + * of GMT. Divide by 60 to get the offset in minutes east of GMT. + */ + offset = (int)(timeval->tm_gmtoff / 60); + #else + /* The compiler does not provide tm_gmtoff. Fallback to using the + * timezone variable, which is in seconds west of GMT. Divide by -60 to + * get the offset in minutes east of GMT. + * + * ============ + * XXX NOTE XXX + * ============ + * timezone is always the default (non-summer) timezone offset from GMT. + * Therefore, this may not be accurate during the summer time months + * for the region in question. + */ + offset = (int)(timezone / -60); + #endif + } + +cleanup: + if (orig_tz == NULL) { + unsetenv("TZ"); + } else { + setenv("TZ", orig_tz_copy, true); + free(orig_tz_copy); + } + + if (new_tz != NULL) { + free(new_tz); + } + + tzset(); + PINELOG_DEBUG("Offset for timezone '%s' is %d", tz, offset); + return offset; +} + +void x52d_cfg_set_Clock_Secondary(char* param) +{ + PINELOG_TRACE("Setting secondary clock timezone to %s", param); + x52d_dev_set_clock_timezone(LIBX52_CLOCK_2, get_tz_offset(param)); +} + +void x52d_cfg_set_Clock_Tertiary(char* param) +{ + PINELOG_TRACE("Setting tertiary clock timezone to %s", param); + x52d_dev_set_clock_timezone(LIBX52_CLOCK_3, get_tz_offset(param)); +} + +static pthread_t clock_thr; + +static void * x52_clock_thr(void *param) +{ + int rc; + + PINELOG_TRACE("Starting X52 clock thread"); + for (;;) { + time_t cur_time; + + sleep(1); + if (!clock_enabled) { + /* Clock thread is disabled, check again next time */ + continue; + } + + if (time(&cur_time) < 0) { + PINELOG_WARN(_("Error %d retrieving current time: %s"), + errno, strerror(errno)); + continue; + } + rc = x52d_dev_set_clock(cur_time, clock_primary_is_local); + if (rc == LIBX52_SUCCESS) { + // Device manager will update the clock, this is only for debugging + PINELOG_TRACE("Setting X52 clock to %ld", cur_time); + } + } + + return NULL; +} + +void x52d_clock_init(void) +{ + int rc; + + PINELOG_TRACE("Initializing clock manager"); + rc = pthread_create(&clock_thr, NULL, x52_clock_thr, NULL); + if (rc != 0) { + PINELOG_FATAL(_("Error %d initializing clock thread: %s"), + rc, strerror(rc)); + } +} + +void x52d_clock_exit(void) +{ + PINELOG_TRACE("Shutting down clock thread"); + pthread_cancel(clock_thr); +} diff --git a/daemon/x52d_clock.h b/daemon/x52d_clock.h new file mode 100644 index 0000000..3bfd631 --- /dev/null +++ b/daemon/x52d_clock.h @@ -0,0 +1,15 @@ +/* + * Saitek X52 Pro MFD & LED driver - Clock manager + * + * Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 + */ + +#ifndef X52D_CLOCK_H +#define X52D_CLOCK_H + +void x52d_clock_init(void); +void x52d_clock_exit(void); + +#endif // !defined X52D_CLOCK_H diff --git a/daemon/x52d_config.c b/daemon/x52d_config.c index 06bfc4c..72c4758 100644 --- a/daemon/x52d_config.c +++ b/daemon/x52d_config.c @@ -43,10 +43,6 @@ void x52d_config_load(const char *cfg_file) /* Callback stubs * TODO: Remove the ones below when their implementation is complete */ -void x52d_cfg_set_Clock_Enabled(bool param) { (void)param; } -void x52d_cfg_set_Clock_PrimaryIsLocal(bool param) { (void)param; } -void x52d_cfg_set_Clock_Secondary(char* param) { (void)param; } -void x52d_cfg_set_Clock_Tertiary(char* param) { (void)param; } void x52d_cfg_set_LED_Fire(libx52_led_state param) { (void)param; } void x52d_cfg_set_LED_Throttle(libx52_led_state param) { (void)param; } void x52d_cfg_set_LED_A(libx52_led_state param) { (void)param; } diff --git a/daemon/x52d_main.c b/daemon/x52d_main.c index 5faa24f..d2192a3 100644 --- a/daemon/x52d_main.c +++ b/daemon/x52d_main.c @@ -12,6 +12,7 @@ #include #include +#include "x52d_clock.h" #include "x52d_const.h" #include "x52d_config.h" #include "x52d_device.h" @@ -134,6 +135,7 @@ int main(int argc, char **argv) // Start device threads x52d_dev_init(); + x52d_clock_init(); // Apply configuration x52d_config_apply(); diff --git a/po/POTFILES.in b/po/POTFILES.in index 5819676..20b29c4 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -12,6 +12,7 @@ utils/test/x52_test_led.c utils/test/x52_test_mfd.c daemon/x52d_main.c +daemon/x52d_clock.c daemon/x52d_config.c daemon/x52d_config_parser.c daemon/x52d_device.c diff --git a/po/x52pro-linux.pot b/po/x52pro-linux.pot index 749d20e..2956086 100644 --- a/po/x52pro-linux.pot +++ b/po/x52pro-linux.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: x52pro-linux 0.2.1\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/x52pro-linux/issues\n" -"POT-Creation-Date: 2021-07-16 00:26-0700\n" +"POT-Creation-Date: 2021-07-23 09:47-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -370,21 +370,49 @@ msgstr "" msgid "OK" msgstr "" -#: daemon/x52d_main.c:33 +#: daemon/x52d_main.c:35 #, c-format msgid "Error %d setting log file: %s\n" msgstr "" -#: daemon/x52d_main.c:44 +#: daemon/x52d_main.c:46 #, c-format msgid "Usage: %s [-f] [-v] [-q] [-l log-file] [-o override] [-c config-file]\n" msgstr "" -#: daemon/x52d_main.c:105 +#: daemon/x52d_main.c:107 #, c-format msgid "Unable to parse configuration override '%s'\n" msgstr "" +#: daemon/x52d_clock.c:27 +#, c-format +msgid "Setting clock enable to %s" +msgstr "" + +#: daemon/x52d_clock.c:34 +#, c-format +msgid "Setting primary clock timezone to %s" +msgstr "" + +#: daemon/x52d_clock.c:52 +msgid "Unable to allocate memory for timezone. Falling back to UTC" +msgstr "" + +#: daemon/x52d_clock.c:62 +msgid "Unable to backup timezone environment. Falling back to UTC" +msgstr "" + +#: daemon/x52d_clock.c:132 +#, c-format +msgid "Error %d retrieving current time: %s" +msgstr "" + +#: daemon/x52d_clock.c:153 +#, c-format +msgid "Error %d initializing clock thread: %s" +msgstr "" + #: daemon/x52d_config.c:26 #, c-format msgid "Error %d setting configuration defaults: %s" @@ -428,22 +456,22 @@ msgstr "" msgid "Error processing override '%s.%s=%s'" msgstr "" -#: daemon/x52d_device.c:45 +#: daemon/x52d_device.c:49 #, c-format msgid "Error %d connecting to device: %s" msgstr "" -#: daemon/x52d_device.c:63 +#: daemon/x52d_device.c:102 #, c-format msgid "Failure %d initializing libx52: %s" msgstr "" -#: daemon/x52d_device.c:83 +#: daemon/x52d_device.c:136 #, c-format msgid "Error %d when updating X52 parameter: %s" msgstr "" -#: daemon/x52d_device.c:145 +#: daemon/x52d_device.c:205 #, c-format msgid "Error %d when updating X52 device: %s" msgstr "" diff --git a/po/xx_PL.po b/po/xx_PL.po index ee01b03..041f05c 100644 --- a/po/xx_PL.po +++ b/po/xx_PL.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: x52pro-linux 0.2.1\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/x52pro-linux/issues\n" -"POT-Creation-Date: 2021-07-16 00:26-0700\n" -"PO-Revision-Date: 2021-07-15 15:09-0700\n" +"POT-Creation-Date: 2021-07-23 09:47-0700\n" +"PO-Revision-Date: 2021-07-23 09:51-0700\n" "Last-Translator: Nirenjan Krishnan \n" "Language-Team: Dummy Language for testing i18n\n" "Language: xx_PL\n" @@ -413,23 +413,54 @@ msgstr "Estingtay aracterchay 0x%02x..." msgid "OK" msgstr "OKay" -#: daemon/x52d_main.c:33 +#: daemon/x52d_main.c:35 #, c-format msgid "Error %d setting log file: %s\n" msgstr "Erroray %d ettingsay oglay ilefay: %s\n" -#: daemon/x52d_main.c:44 +#: daemon/x52d_main.c:46 #, c-format msgid "Usage: %s [-f] [-v] [-q] [-l log-file] [-o override] [-c config-file]\n" msgstr "" "Usageay: %s [-f] [-v] [-q] [-l oglay-ilefay] [-o overrideay] [-c onfigcay-" "ilefay]\n" -#: daemon/x52d_main.c:105 +#: daemon/x52d_main.c:107 #, c-format msgid "Unable to parse configuration override '%s'\n" msgstr "Unableay otay arsepay onfigurationcay overrideay '%s'\n" +#: daemon/x52d_clock.c:27 +#, c-format +msgid "Setting clock enable to %s" +msgstr "Ettingsay ockclay enableay otay %s" + +#: daemon/x52d_clock.c:34 +#, c-format +msgid "Setting primary clock timezone to %s" +msgstr "Ettingsay imarypray ockclay imezonetay otay %s" + +#: daemon/x52d_clock.c:52 +msgid "Unable to allocate memory for timezone. Falling back to UTC" +msgstr "" +"Unableay otay allocateay emorymay orfay imezonetay. Allingfay ackbay otay " +"UTCay" + +#: daemon/x52d_clock.c:62 +msgid "Unable to backup timezone environment. Falling back to UTC" +msgstr "" +"Unableay otay ackupbay imezonetay environmentay. Allingfay ackbay otay UTCay" + +#: daemon/x52d_clock.c:132 +#, c-format +msgid "Error %d retrieving current time: %s" +msgstr "Erroray %d etrievingray urrentcay imetay: %s" + +#: daemon/x52d_clock.c:153 +#, c-format +msgid "Error %d initializing clock thread: %s" +msgstr "Erroray %d initializingay ockclay eadthray: %s" + #: daemon/x52d_config.c:26 #, c-format msgid "Error %d setting configuration defaults: %s" @@ -473,22 +504,22 @@ msgstr "Onay aluevay oundfay inay overrideay ingstray '%s'" msgid "Error processing override '%s.%s=%s'" msgstr "Erroray ocessingpray overriday '%s.%s=%s'" -#: daemon/x52d_device.c:45 +#: daemon/x52d_device.c:49 #, c-format msgid "Error %d connecting to device: %s" msgstr "Erroray %d onnectingcay otay eviceday: %s" -#: daemon/x52d_device.c:63 +#: daemon/x52d_device.c:102 #, c-format msgid "Failure %d initializing libx52: %s" msgstr "Ailurefay %d initializeay libx52: %s" -#: daemon/x52d_device.c:83 +#: daemon/x52d_device.c:136 #, c-format msgid "Error %d when updating X52 parameter: %s" msgstr "Erroray %d enwhay updatingay X52 arameterpay: %s" -#: daemon/x52d_device.c:145 +#: daemon/x52d_device.c:205 #, c-format msgid "Error %d when updating X52 device: %s" msgstr "Erroray %d enwhay updatingay X52 eviceday: %s"