/*
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;
}