^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * tmon.c Thermal Monitor (TMON) main function and entry point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Jacob Pan <jacob.jun.pan@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <getopt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <ncurses.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <syslog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "tmon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long ticktime = 1; /* seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned long no_control = 1; /* monitoring only or use cooling device for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * temperature control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) double time_elapsed = 0.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned long target_temp_user = 65; /* can be select by tui later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int dialogue_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int tmon_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static short daemon_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int logging; /* for recording thermal data to a file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int debug_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) FILE *tmon_log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*cooling device used for the PID controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) char ctrl_cdev[CDEV_NAME_SIZE] = "None";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int target_thermal_zone; /* user selected target zone instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void start_daemon_mode(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) pthread_t event_tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) pthread_mutex_t input_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) void usage(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) printf("Usage: tmon [OPTION...]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) printf(" -c, --control cooling device in control\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) printf(" -d, --daemon run as daemon, no TUI\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) printf(" -g, --debug debug message in syslog\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) printf(" -h, --help show this help message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) printf(" -l, --log log data to /var/tmp/tmon.log\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) printf(" -t, --time-interval sampling time interval, > 1 sec.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) printf(" -T, --target-temp initial target temperature\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) printf(" -v, --version show version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) printf(" -z, --zone target thermal zone id\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) void version(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) printf("TMON version %s\n", VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) exit(EXIT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void tmon_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) syslog(LOG_INFO, "TMON exit cleanup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (tmon_log)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) fclose(tmon_log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (event_tid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pthread_mutex_lock(&input_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) pthread_cancel(event_tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pthread_mutex_unlock(&input_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pthread_mutex_destroy(&input_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) closelog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* relax control knobs, undo throttling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) set_ctrl_state(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) keypad(stdscr, FALSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) echo();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) nocbreak();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) close_windows();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) endwin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) free_thermal_data();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void tmon_sig_handler(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) syslog(LOG_INFO, "TMON caught signal %d\n", sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) switch (sig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) case SIGTERM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) printf("sigterm, exit and clean up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) case SIGKILL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) printf("sigkill, exit and clean up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) case SIGINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) printf("ctrl-c, exit and clean up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) tmon_exit = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void start_syslog(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (debug_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) setlogmask(LOG_UPTO(LOG_DEBUG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) setlogmask(LOG_UPTO(LOG_ERR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) openlog("tmon.log", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) syslog(LOG_NOTICE, "TMON started by User %d", getuid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void prepare_logging(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct stat logstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!logging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* open local data log file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) tmon_log = fopen(TMON_LOG_FILE, "w+");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (!tmon_log) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) syslog(LOG_ERR, "failed to open log file %s\n", TMON_LOG_FILE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (lstat(TMON_LOG_FILE, &logstat) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) syslog(LOG_ERR, "Unable to stat log file %s\n", TMON_LOG_FILE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) fclose(tmon_log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) tmon_log = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* The log file must be a regular file owned by us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (S_ISLNK(logstat.st_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) syslog(LOG_ERR, "Log file is a symlink. Will not log\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fclose(tmon_log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) tmon_log = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (logstat.st_uid != getuid()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) syslog(LOG_ERR, "We don't own the log file. Not logging\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) fclose(tmon_log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) tmon_log = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) fprintf(tmon_log, "#----------- THERMAL SYSTEM CONFIG -------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) for (i = 0; i < ptdata.nr_tz_sensor; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) char binding_str[33]; /* size of long + 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) memset(binding_str, 0, sizeof(binding_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) for (j = 0; j < 32; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) binding_str[j] = (ptdata.tzi[i].cdev_binding & (1 << j)) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) '1' : '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) fprintf(tmon_log, "#thermal zone %s%02d cdevs binding: %32s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ptdata.tzi[i].type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ptdata.tzi[i].instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) binding_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) for (j = 0; j < ptdata.tzi[i].nr_trip_pts; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) fprintf(tmon_log, "#\tTP%02d type:%s, temp:%lu\n", j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) trip_type_name[ptdata.tzi[i].tp[j].type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ptdata.tzi[i].tp[j].temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) for (i = 0; i < ptdata.nr_cooling_dev; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) fprintf(tmon_log, "#cooling devices%02d: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) i, ptdata.cdi[i].type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) fprintf(tmon_log, "#---------- THERMAL DATA LOG STARTED -----------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) fprintf(tmon_log, "Samples TargetTemp ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) for (i = 0; i < ptdata.nr_tz_sensor; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fprintf(tmon_log, "%s%d ", ptdata.tzi[i].type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ptdata.tzi[i].instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = 0; i < ptdata.nr_cooling_dev; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) fprintf(tmon_log, "%s%d ", ptdata.cdi[i].type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ptdata.cdi[i].instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) fprintf(tmon_log, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static struct option opts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { "control", 1, NULL, 'c' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { "daemon", 0, NULL, 'd' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { "time-interval", 1, NULL, 't' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { "target-temp", 1, NULL, 'T' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) { "log", 0, NULL, 'l' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { "help", 0, NULL, 'h' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) { "version", 0, NULL, 'v' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { "debug", 0, NULL, 'g' },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) { 0, 0, NULL, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int id2 = 0, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) double yk = 0.0, temp; /* controller output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int target_tz_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (geteuid() != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) printf("TMON needs to be run as root\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) while ((c = getopt_long(argc, argv, "c:dlht:T:vgz:", opts, &id2)) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) no_control = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) strncpy(ctrl_cdev, optarg, CDEV_NAME_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) start_daemon_mode();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) printf("Run TMON in daemon mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ticktime = strtod(optarg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (ticktime < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ticktime = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case 'T':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) temp = strtod(optarg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (temp < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) fprintf(stderr, "error: temperature must be positive\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) target_temp_user = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) printf("Logging data to /var/tmp/tmon.log\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) logging = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case 'v':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) version();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) debug_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case 'z':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) target_thermal_zone = strtod(optarg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (pthread_mutex_init(&input_lock, NULL) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) fprintf(stderr, "\n mutex init failed, exit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) start_syslog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (signal(SIGINT, tmon_sig_handler) == SIG_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) syslog(LOG_DEBUG, "Cannot handle SIGINT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (signal(SIGTERM, tmon_sig_handler) == SIG_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) syslog(LOG_DEBUG, "Cannot handle SIGTERM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (probe_thermal_sysfs()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) pthread_mutex_destroy(&input_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) closelog();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) initialize_curses();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) setup_windows();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) signal(SIGWINCH, resize_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) show_title_bar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) show_sensors_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) show_cooling_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) update_thermal_data();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) show_data_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) prepare_logging();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) init_thermal_controller();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) nodelay(stdscr, TRUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) err = pthread_create(&event_tid, NULL, &handle_tui_events, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) printf("\ncan't create thread :[%s]", strerror(err));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) tmon_cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* validate range of user selected target zone, default to the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * instance if out of range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) target_tz_index = zone_instance_to_index(target_thermal_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (target_tz_index < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) target_thermal_zone = ptdata.tzi[0].instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) syslog(LOG_ERR, "target zone is not found, default to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) target_thermal_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) sleep(ticktime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) show_title_bar();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) show_sensors_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) update_thermal_data();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (!dialogue_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) show_data_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) show_cooling_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) time_elapsed += ticktime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) controller_handler(trec[0].temp[target_tz_index] / 1000, &yk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) trec[0].pid_out_pct = yk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!dialogue_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) show_control_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (tmon_exit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) tmon_cleanup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static void start_daemon_mode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) daemon_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* fork */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pid_t sid, pid = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (pid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) else if (pid > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* kill parent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) exit(EXIT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* disable TUI, it may not be necessary, but saves some resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) disable_tui();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* change the file mode mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) umask(S_IWGRP | S_IWOTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* new SID for the daemon process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) sid = setsid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (sid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* change working directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if ((chdir("/")) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) sleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) close(STDIN_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) close(STDOUT_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) close(STDERR_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }