blob: 257e5400a6404ff316ebb5cd43f1a701f1b13c23 [file] [log] [blame]
Amit Arora39f29542010-09-14 12:03:22 +05301/*******************************************************************************
Amit Kucheriac0e17fc2011-01-17 09:35:52 +02002 * Copyright (C) 2010, Linaro Limited.
Amit Arora39f29542010-09-14 12:03:22 +05303 *
4 * This file is part of PowerDebug.
5 *
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors:
12 * Amit Arora <amit.arora@linaro.org> (IBM Corporation)
13 * - initial API and implementation
14 *******************************************************************************/
15
Daniel Lezcano15627482011-06-15 15:45:12 +020016#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <ncurses.h>
Amit Arora47fd9182010-08-24 13:26:06 +053020#include "powerdebug.h"
Amit Arora17552782010-12-02 12:23:14 +053021#include "regulator.h"
Amit Aroraed3e5652010-10-27 12:02:53 +053022#include "display.h"
Amit Arora47fd9182010-08-24 13:26:06 +053023
24#define print(w, x, y, fmt, args...) do { mvwprintw(w, y, x, fmt, ##args); } while (0)
Amit Arora47fd9182010-08-24 13:26:06 +053025
Daniel Lezcanoeeb13762011-03-26 22:06:17 +010026enum { PT_COLOR_DEFAULT = 1,
27 PT_COLOR_HEADER_BAR,
28 PT_COLOR_ERROR,
29 PT_COLOR_RED,
30 PT_COLOR_YELLOW,
31 PT_COLOR_GREEN,
32 PT_COLOR_BRIGHT,
33 PT_COLOR_BLUE,
34};
35
Amit Arora47fd9182010-08-24 13:26:06 +053036static WINDOW *header_win;
Amit Arora47fd9182010-08-24 13:26:06 +053037static WINDOW *footer_win;
Daniel Lezcanod96731a2011-06-15 15:45:12 +020038static int current_win;
Amit Arora47fd9182010-08-24 13:26:06 +053039
40int maxx, maxy;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020041
42/* Number of lines in the virtual window */
43static const int maxrows = 1024;
44
Daniel Lezcano7b3da502011-06-15 15:45:12 +020045#define footer_label " Q (Quit) R (Refresh) Other Keys: 'Left', " \
46 "'Right' , 'Up', 'Down', 'enter', , 'Esc'"
Amit Arora47fd9182010-08-24 13:26:06 +053047
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020048struct rowdata {
49 int attr;
50 void *data;
51};
52
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020053struct windata {
Daniel Lezcanof6656822011-06-15 15:45:12 +020054 WINDOW *win;
55 WINDOW *pad;
Daniel Lezcanob301b082011-06-15 15:45:12 +020056 struct display_ops *ops;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020057 struct rowdata *rowdata;
58 char *name;
59 int nrdata;
60 int scrolling;
61 int cursor;
62};
63
Daniel Lezcano4120e262011-06-15 15:45:12 +020064/* Warning this is linked with the enum { CLOCK, REGULATOR, ... } */
Daniel Lezcano176e69d2011-06-15 15:45:12 +020065struct windata windata[] = {
Daniel Lezcano4120e262011-06-15 15:45:12 +020066 [CLOCK] = { .name = "Clocks" },
67 [REGULATOR] = { .name = "Regulators" },
68 [SENSOR] = { .name = "Sensors" },
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020069};
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020070
Daniel Lezcano3abd8b12011-03-26 22:06:15 +010071static void display_fini(void)
72{
73 endwin();
74}
75
Daniel Lezcano7b3da502011-06-15 15:45:12 +020076static int show_header_footer(int win)
77{
78 int i;
79 int curr_pointer = 0;
Daniel Lezcano4120e262011-06-15 15:45:12 +020080 size_t array_size = sizeof(windata) / sizeof(windata[0]);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020081
82 wattrset(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
83 wbkgd(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
84 werase(header_win);
85
86 print(header_win, curr_pointer, 0, "PowerDebug %s", VERSION);
87 curr_pointer += 20;
88
Daniel Lezcano4120e262011-06-15 15:45:12 +020089 for (i = 0; i < array_size; i++) {
Daniel Lezcano7b3da502011-06-15 15:45:12 +020090 if (win == i)
91 wattron(header_win, A_REVERSE);
92 else
93 wattroff(header_win, A_REVERSE);
94
95 print(header_win, curr_pointer, 0, " %s ", windata[i].name);
96 curr_pointer += strlen(windata[i].name) + 2;
97 }
98 wrefresh(header_win);
99 werase(footer_win);
100
101 wattron(footer_win, A_REVERSE);
102 print(footer_win, 0, 0, "%s", footer_label);
103 wattroff(footer_win, A_REVERSE);
104 wrefresh(footer_win);
105
106 return 0;
107}
108
109int display_init(int wdefault)
Amit Arora47fd9182010-08-24 13:26:06 +0530110{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200111 int i;
112 size_t array_size = sizeof(windata) / sizeof(windata[0]);
113
Daniel Lezcanod96731a2011-06-15 15:45:12 +0200114 current_win = wdefault;
115
Daniel Lezcanoca17a722011-03-26 22:06:16 +0100116 if (!initscr())
117 return -1;
118
Amit Arora6e774cd2010-10-28 11:31:24 +0530119 start_color();
Daniel Lezcanoca17a722011-03-26 22:06:16 +0100120 use_default_colors();
121
Amit Arora6e774cd2010-10-28 11:31:24 +0530122 keypad(stdscr, TRUE);
123 noecho();
124 cbreak();
125 curs_set(0);
126 nonl();
Amit Arora47fd9182010-08-24 13:26:06 +0530127
Daniel Lezcanoca17a722011-03-26 22:06:16 +0100128 if (init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK) ||
129 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED) ||
130 init_pair(PT_COLOR_HEADER_BAR, COLOR_WHITE, COLOR_BLACK) ||
131 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW) ||
132 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN) ||
133 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK) ||
134 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE) ||
135 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED))
136 return -1;
Amit Arora47fd9182010-08-24 13:26:06 +0530137
Daniel Lezcano1c25df92011-06-08 23:30:00 +0200138 if (atexit(display_fini))
139 return -1;
140
141 getmaxyx(stdscr, maxy, maxx);
142
Daniel Lezcanof6656822011-06-15 15:45:12 +0200143 for (i = 0; i < array_size; i++) {
Daniel Lezcano1c25df92011-06-08 23:30:00 +0200144
Daniel Lezcanof6656822011-06-15 15:45:12 +0200145 windata[i].win = subwin(stdscr, maxy - 2, maxx, 1, 0);
146 if (!windata[i].win)
147 return -1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200148
Daniel Lezcanof6656822011-06-15 15:45:12 +0200149 windata[i].pad = newpad(maxrows, maxx);
150 if (!windata[i].pad)
151 return -1;
Daniel Lezcano1c25df92011-06-08 23:30:00 +0200152
Daniel Lezcanof6656822011-06-15 15:45:12 +0200153 }
Daniel Lezcano1c25df92011-06-08 23:30:00 +0200154
155 header_win = subwin(stdscr, 1, maxx, 0, 0);
156 if (!header_win)
157 return -1;
158
159 footer_win = subwin(stdscr, 1, maxx, maxy-1, 0);
160 if (!footer_win)
161 return -1;
162
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200163 return show_header_footer(wdefault);
Amit Arora47fd9182010-08-24 13:26:06 +0530164}
165
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200166void print_regulator_header(void)
Amit Arora47fd9182010-08-24 13:26:06 +0530167{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200168 WINDOW *regulator_win = windata[REGULATOR].win;
169
Amit Arora47fd9182010-08-24 13:26:06 +0530170 werase(regulator_win);
171 wattron(regulator_win, A_BOLD);
Amit Arorac93e0712010-10-07 13:51:53 +0530172 print(regulator_win, 0, 0, "Name");
173 print(regulator_win, 12, 0, "Status");
174 print(regulator_win, 24, 0, "State");
175 print(regulator_win, 36, 0, "Type");
176 print(regulator_win, 48, 0, "Users");
177 print(regulator_win, 60, 0, "Microvolts");
178 print(regulator_win, 72, 0, "Min u-volts");
179 print(regulator_win, 84, 0, "Max u-volts");
Amit Arora47fd9182010-08-24 13:26:06 +0530180 wattroff(regulator_win, A_BOLD);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200181 wrefresh(regulator_win);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200182
183 show_header_footer(REGULATOR);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200184}
185
186void print_clock_header(void)
187{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200188 WINDOW *clock_win = windata[CLOCK].win;
189
190 werase(clock_win);
191 wattron(clock_win, A_BOLD);
192 print(clock_win, 0, 0, "Name");
193 print(clock_win, 56, 0, "Flags");
194 print(clock_win, 75, 0, "Rate");
195 print(clock_win, 88, 0, "Usecount");
196 print(clock_win, 98, 0, "Children");
197 wattroff(clock_win, A_BOLD);
198 wrefresh(clock_win);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200199
200 show_header_footer(CLOCK);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200201}
202
Amit Arora728e0c92010-09-14 12:06:09 +0530203void print_sensor_header(void)
204{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200205 WINDOW *sensor_win = windata[SENSOR].win;
206
Amit Arora6e774cd2010-10-28 11:31:24 +0530207 werase(sensor_win);
208 wattron(sensor_win, A_BOLD);
209 print(sensor_win, 0, 0, "Name");
Daniel Lezcano2e9df762011-06-15 15:45:12 +0200210 print(sensor_win, 36, 0, "Value");
Amit Arora6e774cd2010-10-28 11:31:24 +0530211 wattroff(sensor_win, A_BOLD);
Amit Arora728e0c92010-09-14 12:06:09 +0530212 wrefresh(sensor_win);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200213
214 show_header_footer(SENSOR);
Amit Arora728e0c92010-09-14 12:06:09 +0530215}
216
Daniel Lezcanob301b082011-06-15 15:45:12 +0200217int display_register(int win, struct display_ops *ops)
218{
Daniel Lezcano4120e262011-06-15 15:45:12 +0200219 size_t array_size = sizeof(windata) / sizeof(windata[0]);
220
221 if (win < 0 || win >= array_size)
Daniel Lezcanob301b082011-06-15 15:45:12 +0200222 return -1;
223
224 windata[win].ops = ops;
225
226 return 0;
227}
228
Daniel Lezcano971515a2011-06-15 15:45:12 +0200229int display_refresh(void)
230{
231 if (windata[current_win].ops && windata[current_win].ops->display)
232 return windata[current_win].ops->display();
233
234 return 0;
235}
236
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200237int display_refresh_pad(int win)
Amit Arora728e0c92010-09-14 12:06:09 +0530238{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200239 return prefresh(windata[win].pad, windata[win].scrolling,
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200240 0, 2, 0, maxy - 2, maxx);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200241}
Amit Aroraac4e8652010-11-09 11:16:53 +0530242
Daniel Lezcano28203df2011-06-15 15:45:12 +0200243static int display_show_unselection(int win, int line, bool bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200244{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200245 if (mvwchgat(windata[win].pad, line, 0, -1,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200246 bold ? WA_BOLD: WA_NORMAL, 0, NULL) < 0)
247 return -1;
248
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200249 return display_refresh_pad(win);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200250}
251
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200252void *display_get_row_data(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200253{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200254 return windata[win].rowdata[windata[win].cursor].data;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200255}
256
Daniel Lezcano28203df2011-06-15 15:45:12 +0200257static int display_select(void)
258{
259 if (windata[current_win].ops && windata[current_win].ops->select)
260 return windata[current_win].ops->select();
261
262 return 0;
263}
264
265static int display_next_panel(void)
266{
267 size_t array_size = sizeof(windata) / sizeof(windata[0]);
268
269 current_win++;
270 current_win %= array_size;
271
272 return current_win;
273}
274
275static int display_prev_panel(void)
276{
277 size_t array_size = sizeof(windata) / sizeof(windata[0]);
278
279 current_win--;
280 if (current_win < 0)
281 current_win = array_size - 1;
282
283 return current_win;
284}
285
286static int display_next_line(void)
287{
288 int cursor = windata[current_win].cursor;
289 int nrdata = windata[current_win].nrdata;
290 int scrolling = windata[current_win].scrolling;
291 struct rowdata *rowdata = windata[current_win].rowdata;
292
293 if (cursor >= nrdata)
294 return cursor;
295
296 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
297 if (cursor < nrdata - 1) {
298 if (cursor >= (maxy - 4 + scrolling))
299 scrolling++;
300 cursor++;
301 }
302
303 windata[current_win].scrolling = scrolling;
304 windata[current_win].cursor = cursor;
305
306 return cursor;
307}
308
309static int display_prev_line(void)
310{
311 int cursor = windata[current_win].cursor;
312 int nrdata = windata[current_win].nrdata;
313 int scrolling = windata[current_win].scrolling;
314 struct rowdata *rowdata = windata[current_win].rowdata;
315
316 if (cursor >= nrdata)
317 return cursor;
318
319 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
320 if (cursor > 0) {
321 if (cursor <= scrolling)
322 scrolling--;
323 cursor--;
324 }
325
326 windata[current_win].scrolling = scrolling;
327 windata[current_win].cursor = cursor;
328
329 return cursor;
330}
331
332static int display_set_row_data(int win, int line, void *data, int attr)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200333{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200334 struct rowdata *rowdata = windata[win].rowdata;
335
336 if (line >= windata[win].nrdata) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200337 rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1));
338 if (!rowdata)
339 return -1;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200340 windata[win].nrdata = line + 1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200341 }
342
343 rowdata[line].data = data;
344 rowdata[line].attr = attr;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200345 windata[win].rowdata = rowdata;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200346
347 return 0;
348}
349
Daniel Lezcanof6656822011-06-15 15:45:12 +0200350int display_reset_cursor(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200351{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200352 windata[win].nrdata = 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200353 werase(windata[win].pad);
354 return wmove(windata[win].pad, 0, 0);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200355}
356
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200357int display_print_line(int win, int line, char *str, int bold, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200358{
359 int attr = 0;
360
Amit Arora031263a2010-11-09 11:12:41 +0530361 if (bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200362 attr |= WA_BOLD;
363
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200364 if (line == windata[win].cursor)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200365 attr |= WA_STANDOUT;
366
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200367 if (display_set_row_data(win, line, data, attr))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200368 return -1;
369
370 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200371 wattron(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200372
Daniel Lezcanof6656822011-06-15 15:45:12 +0200373 wprintw(windata[win].pad, "%s\n", str);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200374
375 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200376 wattroff(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200377
378 return 0;
379}
380
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200381int display_keystroke(void *data)
382{
383 int *tick = data;
384 int keystroke = getch();
385
386 switch (keystroke) {
387
388 case KEY_RIGHT:
389 case '\t':
390 display_next_panel();
391 break;
392
393 case KEY_LEFT:
394 case KEY_BTAB:
395 display_prev_panel();
396 break;
397
398 case KEY_DOWN:
399 display_next_line();
400 break;
401
402 case KEY_UP:
403 display_prev_line();
404 break;
405
406 case '\r':
407 display_select();
408 break;
409
410 case EOF:
411 case 'q':
412 case 'Q':
413 return 1;
414
415 case 'r':
416 case 'R':
417 display_refresh();
418 *tick = 3;
419 break;
420 }
421
422 return 0;
423}