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)  * tui.c ncurses text user interface for TMON program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2013 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 <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <stdint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <ncurses.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <syslog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <panel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "tmon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define min(x, y) ({				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	typeof(x) _min1 = (x);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	typeof(y) _min2 = (y);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	(void) (&_min1 == &_min2);		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	_min1 < _min2 ? _min1 : _min2; })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define max(x, y) ({				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	typeof(x) _max1 = (x);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	typeof(y) _max2 = (y);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	(void) (&_max1 == &_max2);		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	_max1 > _max2 ? _max1 : _max2; })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static PANEL *data_panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static PANEL *dialogue_panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static PANEL *top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static WINDOW *title_bar_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static WINDOW *tz_sensor_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) static WINDOW *cooling_device_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static WINDOW *control_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static WINDOW *status_bar_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static WINDOW *thermal_data_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static WINDOW *dialogue_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) char status_bar_slots[10][40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) static void draw_hbar(WINDOW *win, int y, int start, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		unsigned long pattern, bool end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static int maxx, maxy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) static int maxwidth = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define TITLE_BAR_HIGHT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define SENSOR_WIN_HIGHT 4 /* one row for tz name, one for trip points */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) /* daemon mode flag (set by startup parameter -d) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static int  tui_disabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static void close_panel(PANEL *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		del_panel(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static void close_window(WINDOW *win)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (win) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		delwin(win);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		win = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) void close_windows(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (tui_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	/* must delete panels before their attached windows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (dialogue_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		close_panel(dialogue_panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	if (cooling_device_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		close_panel(data_panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	close_window(title_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	close_window(tz_sensor_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	close_window(status_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	close_window(cooling_device_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	close_window(control_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	close_window(thermal_data_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	close_window(dialogue_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^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) void write_status_bar(int x, char *line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	mvwprintw(status_bar_window, 0, x, "%s", line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	wrefresh(status_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* wrap at 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define DIAG_DEV_ROWS  5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * list cooling devices + "set temp" entry; wraps after 5 rows, if they fit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int diag_dev_rows(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	int entries = ptdata.nr_cooling_dev + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	int rows = max(DIAG_DEV_ROWS, (entries + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	return min(rows, entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) void setup_windows(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	int y_begin = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	if (tui_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	getmaxyx(stdscr, maxy, maxx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	resizeterm(maxy, maxx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	title_bar_window = subwin(stdscr, TITLE_BAR_HIGHT, maxx, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	y_begin += TITLE_BAR_HIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	tz_sensor_window = subwin(stdscr, SENSOR_WIN_HIGHT, maxx, y_begin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	y_begin += SENSOR_WIN_HIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	cooling_device_window = subwin(stdscr, ptdata.nr_cooling_dev + 3, maxx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 				y_begin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	y_begin += ptdata.nr_cooling_dev + 3; /* 2 lines for border */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	/* two lines to show borders, one line per tz show trip point position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	 * and value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	 * dialogue window is a pop-up, when needed it lays on top of cdev win
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	dialogue_window = subwin(stdscr, diag_dev_rows() + 5, maxx-50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 				DIAG_Y, DIAG_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	thermal_data_window = subwin(stdscr, ptdata.nr_tz_sensor *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 				NR_LINES_TZDATA + 3, maxx, y_begin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	y_begin += ptdata.nr_tz_sensor * NR_LINES_TZDATA + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	control_window = subwin(stdscr, 4, maxx, y_begin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	scrollok(cooling_device_window, TRUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	maxwidth = maxx - 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	strcpy(status_bar_slots[0], " Ctrl-c - Quit ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	strcpy(status_bar_slots[1], " TAB - Tuning ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	wmove(status_bar_window, 1, 30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	/* prepare panels for dialogue, if panel already created then we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	 * be doing resizing, so just replace windows with new ones, old ones
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	 * should have been deleted by close_window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	data_panel = new_panel(cooling_device_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (!data_panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		syslog(LOG_DEBUG, "No data panel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		if (dialogue_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			dialogue_panel = new_panel(dialogue_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			if (!dialogue_panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				syslog(LOG_DEBUG, "No dialogue panel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				/* Set up the user pointer to the next panel*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				set_panel_userptr(data_panel, dialogue_panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 				set_panel_userptr(dialogue_panel, data_panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				top = data_panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			syslog(LOG_INFO, "no dialogue win, term too small\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	doupdate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	werase(stdscr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) void resize_handler(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	/* start over when term gets resized, but first we clean up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	close_windows();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	endwin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	clear();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	getmaxyx(stdscr, maxy, maxx);  /* get the new screen size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	setup_windows();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	/* rate limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	sleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	syslog(LOG_DEBUG, "SIG %d, term resized to %d x %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		sig, maxy, maxx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	signal(SIGWINCH, resize_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) const char cdev_title[] = " COOLING DEVICES ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) void show_cooling_device(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	int i, j, x, y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	if (tui_disabled || !cooling_device_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	werase(cooling_device_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	wattron(cooling_device_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	mvwprintw(cooling_device_window,  1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		"ID  Cooling Dev   Cur    Max   Thermal Zone Binding");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	wattroff(cooling_device_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	for (j = 0; j <	ptdata.nr_cooling_dev; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		/* draw cooling device list on the left in the order of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		 * cooling device instances. skip unused idr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		mvwprintw(cooling_device_window, j + 2, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			"%02d %12.12s%6d %6d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			ptdata.cdi[j].instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			ptdata.cdi[j].type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 			ptdata.cdi[j].cur_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			ptdata.cdi[j].max_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	/* show cdev binding, y is the global cooling device instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	for (i = 0; i < ptdata.nr_tz_sensor; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		int tz_inst = ptdata.tzi[i].instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		for (j = 0; j < ptdata.nr_cooling_dev; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			int cdev_inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			y = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			x = tz_inst * TZONE_RECORD_SIZE + TZ_LEFT_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			draw_hbar(cooling_device_window, y+2, x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 				TZONE_RECORD_SIZE-1, ACS_VLINE, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			/* draw a column of spaces to separate thermal zones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			mvwprintw(cooling_device_window, y+2, x-1, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			if (ptdata.tzi[i].cdev_binding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 				cdev_inst = ptdata.cdi[j].instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 				unsigned long trip_binding =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 					ptdata.tzi[i].trip_binding[cdev_inst];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 				int k = 0; /* per zone trip point id that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 					    * binded to this cdev, one to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 					    * many possible based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 					    * binding bitmask.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 					    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 				syslog(LOG_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 					"bind tz%d cdev%d tp%lx %d cdev%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 					i, j, trip_binding, y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 					ptdata.tzi[i].cdev_binding);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 				/* draw each trip binding for the cdev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 				while (trip_binding >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 					k++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 					if (!(trip_binding & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 						continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 					/* draw '*' to show binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 					mvwprintw(cooling_device_window,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 						y + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 						x + ptdata.tzi[i].nr_trip_pts -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 						k - 1, "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	/* draw border after data so that border will not be messed up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	 * even there is not enough space for all the data to be shown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	wborder(cooling_device_window, 0, 0, 0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	wattron(cooling_device_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	mvwprintw(cooling_device_window, 0, maxx/2 - sizeof(cdev_title),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		cdev_title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	wattroff(cooling_device_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	wrefresh(cooling_device_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) const char DIAG_TITLE[] = "[ TUNABLES ]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) void show_dialogue(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	int j, x = 0, y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	int rows, cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	WINDOW *w = dialogue_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (tui_disabled || !w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	getmaxyx(w, rows, cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	/* Silence compiler 'unused' warnings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	(void)cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	werase(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	box(w, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	mvwprintw(w, 0, maxx/4, DIAG_TITLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	/* list all the available tunables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	for (j = 0; j <= ptdata.nr_cooling_dev; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		y = j % diag_dev_rows();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		if (y == 0 && j != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			x += 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		if (j == ptdata.nr_cooling_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			/* save last choice for target temp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			mvwprintw(w, y+1, x+1, "%C-%.12s", 'A'+j, "Set Temp");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			mvwprintw(w, y+1, x+1, "%C-%.10s-%2d", 'A'+j,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 				ptdata.cdi[j].type, ptdata.cdi[j].instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	wattron(w, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	mvwprintw(w, diag_dev_rows()+1, 1, "Enter Choice [A-Z]?");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	wattroff(w, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	/* print legend at the bottom line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	mvwprintw(w, rows - 2, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		"Legend: A=Active, P=Passive, C=Critical");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	wrefresh(dialogue_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) void write_dialogue_win(char *buf, int y, int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	WINDOW *w = dialogue_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	mvwprintw(w, y, x, "%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) const char control_title[] = " CONTROLS ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) void show_control_w(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	unsigned long state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	get_ctrl_state(&state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (tui_disabled || !control_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	werase(control_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	mvwprintw(control_window, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		"PID gain: kp=%2.2f ki=%2.2f kd=%2.2f Output %2.2f",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		p_param.kp, p_param.ki, p_param.kd, p_param.y_k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	mvwprintw(control_window, 2, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		"Target Temp: %2.1fC, Zone: %d, Control Device: %.12s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		p_param.t_target, target_thermal_zone, ctrl_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	/* draw border last such that everything is within boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	wborder(control_window, 0, 0, 0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	wattron(control_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	mvwprintw(control_window, 0, maxx/2 - sizeof(control_title),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		control_title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	wattroff(control_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	wrefresh(control_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) void initialize_curses(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	if (tui_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	initscr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	start_color();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	keypad(stdscr, TRUE);	/* enable keyboard mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	nonl();			/* tell curses not to do NL->CR/NL on output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	cbreak();		/* take input chars one at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	noecho();		/* dont echo input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	curs_set(0);		/* turn off cursor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	use_default_colors();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	init_pair(PT_COLOR_HEADER_BAR, COLOR_BLACK, COLOR_WHITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) void show_title_bar(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	int x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (tui_disabled || !title_bar_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	wattrset(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	wbkgd(title_bar_window, COLOR_PAIR(PT_COLOR_HEADER_BAR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	werase(title_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	mvwprintw(title_bar_window, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		"     TMON v%s", VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	wrefresh(title_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	werase(status_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	for (i = 0; i < 10; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		if (strlen(status_bar_slots[i]) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		wattron(status_bar_window, A_REVERSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		mvwprintw(status_bar_window, 0, x, "%s", status_bar_slots[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		wattroff(status_bar_window, A_REVERSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		x += strlen(status_bar_slots[i]) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	wrefresh(status_bar_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static void handle_input_val(int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	char buf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	char path[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	WINDOW *w = dialogue_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	echo();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	keypad(w, TRUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	wgetnstr(w, buf, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	val = atoi(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (ch == ptdata.nr_cooling_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		snprintf(buf, 31, "Invalid Temp %d! %d-%d", val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			MIN_CTRL_TEMP, MAX_CTRL_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		if (val < MIN_CTRL_TEMP || val > MAX_CTRL_TEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			write_status_bar(40, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 			p_param.t_target = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 			snprintf(buf, 31, "Set New Target Temp %d", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 			write_status_bar(40, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		snprintf(path, 256, "%s/%s%d", THERMAL_SYSFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			CDEV, ptdata.cdi[ch].instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		sysfs_set_ulong(path, "cur_state", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	noecho();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	dialogue_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	show_data_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	show_control_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	top = (PANEL *)panel_userptr(top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	top_panel(top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void handle_input_choice(int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	char buf[48];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	int base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	int cdev_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	if ((ch >= 'A' && ch <= 'A' + ptdata.nr_cooling_dev) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		(ch >= 'a' && ch <= 'a' + ptdata.nr_cooling_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		base = (ch < 'a') ? 'A' : 'a';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		cdev_id = ch - base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		if (ptdata.nr_cooling_dev == cdev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			snprintf(buf, sizeof(buf), "New Target Temp:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			snprintf(buf, sizeof(buf), "New Value for %.10s-%2d: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 				ptdata.cdi[cdev_id].type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 				ptdata.cdi[cdev_id].instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		write_dialogue_win(buf, diag_dev_rows() + 2, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		handle_input_val(cdev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		snprintf(buf, sizeof(buf), "Invalid selection %d", ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		write_dialogue_win(buf, 8, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) void *handle_tui_events(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	int ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	keypad(cooling_device_window, TRUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	while ((ch = wgetch(cooling_device_window)) != EOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		if (tmon_exit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		/* when term size is too small, no dialogue panels are set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		 * we need to filter out such cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		if (!data_panel || !dialogue_panel ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 			!cooling_device_window ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			!dialogue_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		pthread_mutex_lock(&input_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		if (dialogue_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 			handle_input_choice(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 			/* top panel filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 			if (ch == 'q' || ch == 'Q')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 				ch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		switch (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		case KEY_LEFT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 			box(cooling_device_window, 10, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		case 9: /* TAB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 			top = (PANEL *)panel_userptr(top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 			top_panel(top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 			if (top == dialogue_panel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 				dialogue_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 				show_dialogue();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 				dialogue_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 				/* force refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 				show_data_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 				show_control_w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		case 'q':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		case 'Q':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 			tmon_exit = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		update_panels();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		doupdate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		pthread_mutex_unlock(&input_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	if (arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		*(int *)arg = 0; /* make gcc happy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* draw a horizontal bar in given pattern */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static void draw_hbar(WINDOW *win, int y, int start, int len, unsigned long ptn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		bool end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	mvwaddch(win, y, start, ptn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	whline(win, ptn, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	if (end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		mvwaddch(win, y, MAX_DISP_TEMP+TDATA_LEFT, ']');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static char trip_type_to_char(int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	case THERMAL_TRIP_CRITICAL: return 'C';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	case THERMAL_TRIP_HOT: return 'H';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	case THERMAL_TRIP_PASSIVE: return 'P';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	case THERMAL_TRIP_ACTIVE: return 'A';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		return '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* fill a string with trip point type and value in one line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)  * e.g.      P(56)    C(106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)  * maintain the distance one degree per char
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static void draw_tp_line(int tz, int y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	for (j = 0; j < ptdata.tzi[tz].nr_trip_pts; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		x = ptdata.tzi[tz].tp[j].temp / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		mvwprintw(thermal_data_window, y + 0, x + TDATA_LEFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			"%c%d", trip_type_to_char(ptdata.tzi[tz].tp[j].type),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		syslog(LOG_INFO, "%s:tz %d tp %d temp = %lu\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 			tz, j, ptdata.tzi[tz].tp[j].temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) const char data_win_title[] = " THERMAL DATA ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) void show_data_w(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	if (tui_disabled || !thermal_data_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	werase(thermal_data_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	wattron(thermal_data_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	mvwprintw(thermal_data_window, 0, maxx/2 - sizeof(data_win_title),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		data_win_title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	wattroff(thermal_data_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	/* draw a line as ruler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	for (i = 10; i < MAX_DISP_TEMP; i += 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		mvwprintw(thermal_data_window, 1, i+TDATA_LEFT, "%2d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	for (i = 0; i < ptdata.nr_tz_sensor; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		int temp = trec[cur_thermal_record].temp[i] / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		int y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		y = i * NR_LINES_TZDATA + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		/* y at tz temp data line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		mvwprintw(thermal_data_window, y, 1, "%6.6s%2d:[%3d][",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 			ptdata.tzi[i].type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			ptdata.tzi[i].instance, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		draw_hbar(thermal_data_window, y, TDATA_LEFT, temp, ACS_RARROW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 			true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		draw_tp_line(i, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	wborder(thermal_data_window, 0, 0, 0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	wrefresh(thermal_data_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) const char tz_title[] = "THERMAL ZONES(SENSORS)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) void show_sensors_w(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	char buffer[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	if (tui_disabled || !tz_sensor_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	werase(tz_sensor_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	memset(buffer, 0, sizeof(buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	wattron(tz_sensor_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	mvwprintw(tz_sensor_window, 1, 1, "Thermal Zones:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	wattroff(tz_sensor_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	mvwprintw(tz_sensor_window, 1, TZ_LEFT_ALIGN, "%s", buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	/* fill trip points for each tzone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	wattron(tz_sensor_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	mvwprintw(tz_sensor_window, 2, 1, "Trip Points:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	wattroff(tz_sensor_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	/* draw trip point from low to high for each tz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	for (i = 0; i < ptdata.nr_tz_sensor; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		int inst = ptdata.tzi[i].instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		mvwprintw(tz_sensor_window, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			TZ_LEFT_ALIGN+TZONE_RECORD_SIZE * inst, "%.9s%02d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 			ptdata.tzi[i].type, ptdata.tzi[i].instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		for (j = ptdata.tzi[i].nr_trip_pts - 1; j >= 0; j--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 			/* loop through all trip points */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 			char type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 			int tp_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 			/* reverse the order here since trips are sorted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 			 * in ascending order in terms of temperature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 			tp_pos = ptdata.tzi[i].nr_trip_pts - j - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 			type = trip_type_to_char(ptdata.tzi[i].tp[j].type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 			mvwaddch(tz_sensor_window, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 				inst * TZONE_RECORD_SIZE + TZ_LEFT_ALIGN +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 				tp_pos,	type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 			syslog(LOG_DEBUG, "draw tz %d tp %d ch:%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 				inst, j, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	wborder(tz_sensor_window, 0, 0, 0, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	wattron(tz_sensor_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	mvwprintw(tz_sensor_window, 0, maxx/2 - sizeof(tz_title), tz_title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	wattroff(tz_sensor_window, A_BOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	wrefresh(tz_sensor_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) void disable_tui(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	tui_disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }