/* This file is part of TALER Copyright (C) 2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file taler-mdb-display.c * @brief turn on the display back light on or off * @author Boss Marco * @author Christian Grothoff */ #include "config.h" #include #include #include #include #include #include #include #include #include /* for adafruit pitft display */ #include /** * Handle for the Framebuffer device */ struct Display { /** * File descriptor for the screen */ int devicefd; /** * File descriptor to set backlight information */ int backlightfd; /** * The display memory to set the pixel information */ uint16_t *memory; /** * Original screen information */ struct fb_var_screeninfo orig_vinfo; /** * Variable screen information (color depth ...) */ struct fb_var_screeninfo var_info; /** * Fixed screen informtaion */ struct fb_fix_screeninfo fix_info; }; /** * Name of the framebuffer device (i.e. /dev/fb1). */ static char *framebuffer_device_filename; /** * Name of the backlight file of @e framebuffer_device_filename (i.e. /sys/class/backlight/soc:backlight/brightness). */ static char *framebuffer_backlight_filename; /** * Global option '-i' to invert backlight on/off values */ static int backlight_invert; /** * Standard backlight on value */ static char backlight_on = '1'; /** * Standard backlight off value */ static char backlight_off = '0'; /** * Handle for the framebuffer device */ static struct Display qrDisplay; static void shutdown_task (void *cls) { (void) cls; if (NULL != qrDisplay.memory) memset (qrDisplay.memory, 0xFF, qrDisplay.var_info.xres * qrDisplay.var_info.yres * sizeof (uint16_t)); if (NULL != qrDisplay.memory) { /* free the display data */ munmap (qrDisplay.memory, qrDisplay.fix_info.smem_len); qrDisplay.memory = NULL; /* close device */ GNUNET_break (0 == close (qrDisplay.devicefd)); qrDisplay.devicefd = -1; if (0 < qrDisplay.backlightfd) GNUNET_break (0 == close (qrDisplay.backlightfd)); qrDisplay.backlightfd = -1; } } /** * @brief Start the application * * @param cls closure * @param args arguments left * @param cfgfile config file name * @param cfg handle for the configuration file */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { (void) cls; (void) cfgfile; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "taler-mdb", "FRAMEBUFFER_DEVICE", &framebuffer_device_filename)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "taler-mdb", "FRAMEBUFFER_DEVICE"); framebuffer_device_filename = GNUNET_strdup ("/dev/fb1"); } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "taler-mdb", "FRAMEBUFFER_BACKLIGHT", &framebuffer_backlight_filename)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "taler-mdb", "FRAMEBUFFER_BACKLIGHT"); framebuffer_backlight_filename = GNUNET_strdup ( "/sys/class/backlight/soc:backlight/brightness"); } /* open the framebuffer device */ qrDisplay.devicefd = open (framebuffer_device_filename, O_RDWR); if (0 < qrDisplay.devicefd) { /* read information about the screen */ ioctl (qrDisplay.devicefd, FBIOGET_VSCREENINFO, &qrDisplay.var_info); /* store current screeninfo for reset */ qrDisplay.orig_vinfo = qrDisplay.var_info; if (16 != qrDisplay.var_info.bits_per_pixel) { /* Change variable info to 16 bit per pixel */ qrDisplay.var_info.bits_per_pixel = 16; if (0 > ioctl (qrDisplay.devicefd, FBIOPUT_VSCREENINFO, &qrDisplay.var_info)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl(FBIOPUT_VSCREENINFO)"); return; } } /* Get fixed screen information */ if (0 > ioctl (qrDisplay.devicefd, FBIOGET_FSCREENINFO, &qrDisplay.fix_info)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl(FBIOGET_FSCREENINFO)"); return; } /* get pointer onto frame buffer */ qrDisplay.memory = mmap (NULL, qrDisplay.fix_info.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, qrDisplay.devicefd, 0); /* open backlight file to turn display backlight on and off */ if (0 > qrDisplay.devicefd) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "mmap"); return; } memset (qrDisplay.memory, 0xFF, qrDisplay.var_info.xres * qrDisplay.var_info.yres * sizeof (uint16_t)); qrDisplay.backlightfd = open ( framebuffer_backlight_filename, O_WRONLY); if (0 > qrDisplay.backlightfd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", framebuffer_backlight_filename); } else { if (backlight_invert) { backlight_on = '0'; backlight_off = '1'; } (void) ! write (qrDisplay.backlightfd, &backlight_off, 1); } } else { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "open", framebuffer_device_filename); } GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); if (0 < qrDisplay.backlightfd) (void) ! write (qrDisplay.backlightfd, &backlight_on, 1); } int main (int argc, char*const*argv) { enum GNUNET_GenericReturnValue ret; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_option_flag ('i', "backlight-invert", "toggle on vs. off", &backlight_invert), GNUNET_GETOPT_OPTION_END }; ret = GNUNET_PROGRAM_run (argc, argv, "taler-mdb-display-on", "Turn frame buffer display on or off\n", options, &run, NULL); if (GNUNET_OK != ret) return 1; return 0; }