^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) }