Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }