taler-mdb-display.c (7788B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 FITNESS FOR 12 A PARTICULAR PURPOSE. See the GNU General Public License for more 13 details. 14 15 You should have received a copy of the GNU General Public License 16 along with 17 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file taler-mdb-display.c 21 * @brief turn on the display back light on or off 22 * @author Boss Marco 23 * @author Christian Grothoff 24 */ 25 #include "config.h" 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <errno.h> 31 #include <gnunet/gnunet_util_lib.h> 32 #include <sys/mman.h> 33 #include <sys/ioctl.h> 34 #include <fcntl.h> 35 /* for adafruit pitft display */ 36 #include <linux/fb.h> 37 #include "taler_mdb_util.h" 38 39 /** 40 * Handle for the Framebuffer device 41 */ 42 struct Display 43 { 44 /** 45 * File descriptor for the screen 46 */ 47 int devicefd; 48 49 /** 50 * File descriptor to set backlight information 51 */ 52 int backlightfd; 53 54 /** 55 * The display memory to set the pixel information 56 */ 57 uint16_t *memory; 58 59 /** 60 * Original screen information 61 */ 62 struct fb_var_screeninfo orig_vinfo; 63 64 /** 65 * Variable screen information (color depth ...) 66 */ 67 struct fb_var_screeninfo var_info; 68 69 /** 70 * Fixed screen informtaion 71 */ 72 struct fb_fix_screeninfo fix_info; 73 }; 74 75 76 /** 77 * Name of the framebuffer device (i.e. /dev/fb1). 78 */ 79 static char *framebuffer_device_filename; 80 81 /** 82 * Name of the backlight file of @e framebuffer_device_filename (i.e. /sys/class/backlight/soc:backlight/brightness). 83 */ 84 static char *framebuffer_backlight_filename; 85 86 /** 87 * Global option '-i' to invert backlight on/off values 88 */ 89 static int backlight_invert; 90 91 /** 92 * Standard backlight on value 93 */ 94 static char backlight_on = '1'; 95 96 /** 97 * Standard backlight off value 98 */ 99 static char backlight_off = '0'; 100 101 /** 102 * Handle for the framebuffer device 103 */ 104 static struct Display qrDisplay; 105 106 107 static void 108 shutdown_task (void *cls) 109 { 110 (void) cls; 111 if (NULL != qrDisplay.memory) 112 memset (qrDisplay.memory, 113 0xFF, 114 qrDisplay.var_info.xres * qrDisplay.var_info.yres 115 * sizeof (uint16_t)); 116 if (NULL != qrDisplay.memory) 117 { 118 /* free the display data */ 119 munmap (qrDisplay.memory, 120 qrDisplay.fix_info.smem_len); 121 qrDisplay.memory = NULL; 122 /* close device */ 123 GNUNET_break (0 == close (qrDisplay.devicefd)); 124 qrDisplay.devicefd = -1; 125 if (0 < qrDisplay.backlightfd) 126 GNUNET_break (0 == close (qrDisplay.backlightfd)); 127 qrDisplay.backlightfd = -1; 128 } 129 } 130 131 132 /** 133 * @brief Start the application 134 * 135 * @param cls closure 136 * @param args arguments left 137 * @param cfgfile config file name 138 * @param cfg handle for the configuration file 139 */ 140 static void 141 run (void *cls, 142 char *const *args, 143 const char *cfgfile, 144 const struct GNUNET_CONFIGURATION_Handle *cfg) 145 { 146 (void) cls; 147 (void) cfgfile; 148 149 if (GNUNET_OK != 150 GNUNET_CONFIGURATION_get_value_filename (cfg, 151 "taler-mdb", 152 "FRAMEBUFFER_DEVICE", 153 &framebuffer_device_filename)) 154 { 155 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 156 "taler-mdb", 157 "FRAMEBUFFER_DEVICE"); 158 framebuffer_device_filename = GNUNET_strdup ("/dev/fb1"); 159 } 160 if (GNUNET_OK != 161 GNUNET_CONFIGURATION_get_value_filename (cfg, 162 "taler-mdb", 163 "FRAMEBUFFER_BACKLIGHT", 164 &framebuffer_backlight_filename)) 165 { 166 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 167 "taler-mdb", 168 "FRAMEBUFFER_BACKLIGHT"); 169 framebuffer_backlight_filename = GNUNET_strdup ( 170 "/sys/class/backlight/soc:backlight/brightness"); 171 } 172 /* open the framebuffer device */ 173 qrDisplay.devicefd = open (framebuffer_device_filename, 174 O_RDWR); 175 if (0 < qrDisplay.devicefd) 176 { 177 /* read information about the screen */ 178 ioctl (qrDisplay.devicefd, 179 FBIOGET_VSCREENINFO, 180 &qrDisplay.var_info); 181 182 /* store current screeninfo for reset */ 183 qrDisplay.orig_vinfo = qrDisplay.var_info; 184 185 if (16 != qrDisplay.var_info.bits_per_pixel) 186 { 187 /* Change variable info to 16 bit per pixel */ 188 qrDisplay.var_info.bits_per_pixel = 16; 189 if (0 > ioctl (qrDisplay.devicefd, 190 FBIOPUT_VSCREENINFO, 191 &qrDisplay.var_info)) 192 { 193 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 194 "ioctl(FBIOPUT_VSCREENINFO)"); 195 return; 196 } 197 } 198 199 /* Get fixed screen information */ 200 if (0 > ioctl (qrDisplay.devicefd, 201 FBIOGET_FSCREENINFO, 202 &qrDisplay.fix_info)) 203 { 204 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 205 "ioctl(FBIOGET_FSCREENINFO)"); 206 return; 207 } 208 209 /* get pointer onto frame buffer */ 210 qrDisplay.memory = mmap (NULL, 211 qrDisplay.fix_info.smem_len, 212 PROT_READ | PROT_WRITE, MAP_SHARED, 213 qrDisplay.devicefd, 214 0); 215 216 /* open backlight file to turn display backlight on and off */ 217 if (0 > qrDisplay.devicefd) 218 { 219 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, 220 "mmap"); 221 return; 222 } 223 224 memset (qrDisplay.memory, 225 0xFF, 226 qrDisplay.var_info.xres * qrDisplay.var_info.yres 227 * sizeof (uint16_t)); 228 229 qrDisplay.backlightfd = open ( 230 framebuffer_backlight_filename, O_WRONLY); 231 if (0 > qrDisplay.backlightfd) 232 { 233 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 234 "open", 235 framebuffer_backlight_filename); 236 } 237 else 238 { 239 if (backlight_invert) 240 { 241 backlight_on = '0'; 242 backlight_off = '1'; 243 } 244 (void) ! write (qrDisplay.backlightfd, 245 &backlight_off, 246 1); 247 } 248 } 249 else 250 { 251 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 252 "open", 253 framebuffer_device_filename); 254 } 255 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 256 NULL); 257 258 if (0 < qrDisplay.backlightfd) 259 (void) ! write (qrDisplay.backlightfd, 260 &backlight_on, 261 1); 262 } 263 264 265 int 266 main (int argc, 267 char*const*argv) 268 { 269 enum GNUNET_GenericReturnValue ret; 270 struct GNUNET_GETOPT_CommandLineOption options[] = { 271 GNUNET_GETOPT_option_flag ('i', 272 "backlight-invert", 273 "toggle on vs. off", 274 &backlight_invert), 275 GNUNET_GETOPT_OPTION_END 276 }; 277 278 ret = GNUNET_PROGRAM_run (TALER_MDB_project_data (), 279 argc, 280 argv, 281 "taler-mdb-display", 282 "Turn frame buffer display on or off\n", 283 options, 284 &run, 285 NULL); 286 if (GNUNET_OK != ret) 287 return 1; 288 return 0; 289 }