blob: bd5971a503a9c972ba1fa6eeadbd886d3d43d1dc [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"
Daniel Lezcanodb145802011-06-21 00:57:08 +020021#include "mainloop.h"
Amit Arora17552782010-12-02 12:23:14 +053022#include "regulator.h"
Amit Aroraed3e5652010-10-27 12:02:53 +053023#include "display.h"
Amit Arora47fd9182010-08-24 13:26:06 +053024
Daniel Lezcanoeeb13762011-03-26 22:06:17 +010025enum { PT_COLOR_DEFAULT = 1,
26 PT_COLOR_HEADER_BAR,
27 PT_COLOR_ERROR,
28 PT_COLOR_RED,
29 PT_COLOR_YELLOW,
30 PT_COLOR_GREEN,
31 PT_COLOR_BRIGHT,
32 PT_COLOR_BLUE,
33};
34
Amit Arora47fd9182010-08-24 13:26:06 +053035static WINDOW *header_win;
Amit Arora47fd9182010-08-24 13:26:06 +053036static WINDOW *footer_win;
Daniel Lezcanoc196d432011-06-21 00:57:08 +020037static WINDOW *main_win;
Daniel Lezcanod96731a2011-06-15 15:45:12 +020038static int current_win;
Amit Arora47fd9182010-08-24 13:26:06 +053039
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020040/* Number of lines in the virtual window */
41static const int maxrows = 1024;
42
Daniel Lezcano7b3da502011-06-15 15:45:12 +020043#define footer_label " Q (Quit) R (Refresh) Other Keys: 'Left', " \
44 "'Right' , 'Up', 'Down', 'enter', , 'Esc'"
Amit Arora47fd9182010-08-24 13:26:06 +053045
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020046struct rowdata {
47 int attr;
48 void *data;
49};
50
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020051struct windata {
Daniel Lezcanof6656822011-06-15 15:45:12 +020052 WINDOW *pad;
Daniel Lezcanob301b082011-06-15 15:45:12 +020053 struct display_ops *ops;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020054 struct rowdata *rowdata;
55 char *name;
56 int nrdata;
57 int scrolling;
58 int cursor;
59};
60
Daniel Lezcano4120e262011-06-15 15:45:12 +020061/* Warning this is linked with the enum { CLOCK, REGULATOR, ... } */
Daniel Lezcano176e69d2011-06-15 15:45:12 +020062struct windata windata[] = {
Daniel Lezcano4120e262011-06-15 15:45:12 +020063 [CLOCK] = { .name = "Clocks" },
64 [REGULATOR] = { .name = "Regulators" },
65 [SENSOR] = { .name = "Sensors" },
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020066};
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020067
Daniel Lezcano3abd8b12011-03-26 22:06:15 +010068static void display_fini(void)
69{
70 endwin();
71}
72
Daniel Lezcano7b3da502011-06-15 15:45:12 +020073static int show_header_footer(int win)
74{
75 int i;
76 int curr_pointer = 0;
Daniel Lezcano4120e262011-06-15 15:45:12 +020077 size_t array_size = sizeof(windata) / sizeof(windata[0]);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020078
79 wattrset(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
80 wbkgd(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
81 werase(header_win);
82
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020083 mvwprintw(header_win, 0, curr_pointer, "PowerDebug %s", VERSION);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020084 curr_pointer += 20;
85
Daniel Lezcano4120e262011-06-15 15:45:12 +020086 for (i = 0; i < array_size; i++) {
Daniel Lezcano7b3da502011-06-15 15:45:12 +020087 if (win == i)
88 wattron(header_win, A_REVERSE);
89 else
90 wattroff(header_win, A_REVERSE);
91
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020092 mvwprintw(header_win, 0, curr_pointer, " %s ", windata[i].name);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020093 curr_pointer += strlen(windata[i].name) + 2;
94 }
95 wrefresh(header_win);
96 werase(footer_win);
97
98 wattron(footer_win, A_REVERSE);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020099 mvwprintw(footer_win, 0, 0, "%s", footer_label);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200100 wattroff(footer_win, A_REVERSE);
101 wrefresh(footer_win);
102
103 return 0;
104}
105
Daniel Lezcanodb145802011-06-21 00:57:08 +0200106int display_refresh(int win)
Amit Arora47fd9182010-08-24 13:26:06 +0530107{
Daniel Lezcanodb145802011-06-21 00:57:08 +0200108 /* we are trying to refresh a window which is not showed */
109 if (win != current_win)
110 return 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200111
Daniel Lezcanodb145802011-06-21 00:57:08 +0200112 if (windata[win].ops && windata[win].ops->display)
113 return windata[win].ops->display();
Daniel Lezcano971515a2011-06-15 15:45:12 +0200114
115 return 0;
116}
117
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200118int display_refresh_pad(int win)
Amit Arora728e0c92010-09-14 12:06:09 +0530119{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200120 int maxx, maxy;
121
122 getmaxyx(stdscr, maxy, maxx);
123
Daniel Lezcanof6656822011-06-15 15:45:12 +0200124 return prefresh(windata[win].pad, windata[win].scrolling,
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200125 0, 2, 0, maxy - 2, maxx);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200126}
Amit Aroraac4e8652010-11-09 11:16:53 +0530127
Daniel Lezcano28203df2011-06-15 15:45:12 +0200128static int display_show_unselection(int win, int line, bool bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200129{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200130 if (mvwchgat(windata[win].pad, line, 0, -1,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200131 bold ? WA_BOLD: WA_NORMAL, 0, NULL) < 0)
132 return -1;
133
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200134 return display_refresh_pad(win);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200135}
136
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200137void *display_get_row_data(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200138{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200139 return windata[win].rowdata[windata[win].cursor].data;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200140}
141
Daniel Lezcano28203df2011-06-15 15:45:12 +0200142static int display_select(void)
143{
144 if (windata[current_win].ops && windata[current_win].ops->select)
145 return windata[current_win].ops->select();
146
147 return 0;
148}
149
150static int display_next_panel(void)
151{
152 size_t array_size = sizeof(windata) / sizeof(windata[0]);
153
154 current_win++;
155 current_win %= array_size;
156
157 return current_win;
158}
159
160static int display_prev_panel(void)
161{
162 size_t array_size = sizeof(windata) / sizeof(windata[0]);
163
164 current_win--;
165 if (current_win < 0)
166 current_win = array_size - 1;
167
168 return current_win;
169}
170
171static int display_next_line(void)
172{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200173 int maxx, maxy;
Daniel Lezcano28203df2011-06-15 15:45:12 +0200174 int cursor = windata[current_win].cursor;
175 int nrdata = windata[current_win].nrdata;
176 int scrolling = windata[current_win].scrolling;
177 struct rowdata *rowdata = windata[current_win].rowdata;
178
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200179 getmaxyx(stdscr, maxy, maxx);
180
Daniel Lezcano28203df2011-06-15 15:45:12 +0200181 if (cursor >= nrdata)
182 return cursor;
183
184 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
185 if (cursor < nrdata - 1) {
186 if (cursor >= (maxy - 4 + scrolling))
187 scrolling++;
188 cursor++;
189 }
190
191 windata[current_win].scrolling = scrolling;
192 windata[current_win].cursor = cursor;
193
194 return cursor;
195}
196
197static int display_prev_line(void)
198{
199 int cursor = windata[current_win].cursor;
200 int nrdata = windata[current_win].nrdata;
201 int scrolling = windata[current_win].scrolling;
202 struct rowdata *rowdata = windata[current_win].rowdata;
203
204 if (cursor >= nrdata)
205 return cursor;
206
207 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
208 if (cursor > 0) {
209 if (cursor <= scrolling)
210 scrolling--;
211 cursor--;
212 }
213
214 windata[current_win].scrolling = scrolling;
215 windata[current_win].cursor = cursor;
216
217 return cursor;
218}
219
220static int display_set_row_data(int win, int line, void *data, int attr)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200221{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200222 struct rowdata *rowdata = windata[win].rowdata;
223
224 if (line >= windata[win].nrdata) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200225 rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1));
226 if (!rowdata)
227 return -1;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200228 windata[win].nrdata = line + 1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200229 }
230
231 rowdata[line].data = data;
232 rowdata[line].attr = attr;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200233 windata[win].rowdata = rowdata;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200234
235 return 0;
236}
237
Daniel Lezcanof6656822011-06-15 15:45:12 +0200238int display_reset_cursor(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200239{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200240 windata[win].nrdata = 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200241 werase(windata[win].pad);
242 return wmove(windata[win].pad, 0, 0);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200243}
244
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200245int display_print_line(int win, int line, char *str, int bold, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200246{
247 int attr = 0;
248
Amit Arora031263a2010-11-09 11:12:41 +0530249 if (bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200250 attr |= WA_BOLD;
251
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200252 if (line == windata[win].cursor)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200253 attr |= WA_STANDOUT;
254
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200255 if (display_set_row_data(win, line, data, attr))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200256 return -1;
257
258 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200259 wattron(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200260
Daniel Lezcanof6656822011-06-15 15:45:12 +0200261 wprintw(windata[win].pad, "%s\n", str);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200262
263 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200264 wattroff(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200265
266 return 0;
267}
268
Daniel Lezcanodb145802011-06-21 00:57:08 +0200269static int display_keystroke(int fd, void *data)
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200270{
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200271 int keystroke = getch();
272
273 switch (keystroke) {
274
275 case KEY_RIGHT:
276 case '\t':
277 display_next_panel();
278 break;
279
280 case KEY_LEFT:
281 case KEY_BTAB:
282 display_prev_panel();
283 break;
284
285 case KEY_DOWN:
286 display_next_line();
287 break;
288
289 case KEY_UP:
290 display_prev_line();
291 break;
292
293 case '\r':
294 display_select();
295 break;
296
297 case EOF:
298 case 'q':
299 case 'Q':
300 return 1;
301
302 case 'r':
303 case 'R':
Daniel Lezcanodb145802011-06-21 00:57:08 +0200304 /* refresh will be done after */
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200305 break;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200306 default:
307 return 0;
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200308 }
309
Daniel Lezcanodb145802011-06-21 00:57:08 +0200310 display_refresh(current_win);
311
312 return 0;
313}
314
315int display_init(int wdefault)
316{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200317 int i, maxx, maxy;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200318 size_t array_size = sizeof(windata) / sizeof(windata[0]);
319
320 current_win = wdefault;
321
322 if (mainloop_add(0, display_keystroke, NULL))
323 return -1;
324
325 if (!initscr())
326 return -1;
327
328 start_color();
329 use_default_colors();
330
331 keypad(stdscr, TRUE);
332 noecho();
333 cbreak();
334 curs_set(0);
335 nonl();
336
337 if (init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK) ||
338 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED) ||
339 init_pair(PT_COLOR_HEADER_BAR, COLOR_WHITE, COLOR_BLACK) ||
340 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW) ||
341 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN) ||
342 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK) ||
343 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE) ||
344 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED))
345 return -1;
346
347 if (atexit(display_fini))
348 return -1;
349
350 getmaxyx(stdscr, maxy, maxx);
351
352 for (i = 0; i < array_size; i++) {
353
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200354 main_win = subwin(stdscr, maxy - 2, maxx, 1, 0);
355 if (!main_win)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200356 return -1;
357
358 windata[i].pad = newpad(maxrows, maxx);
359 if (!windata[i].pad)
360 return -1;
361
362 }
363
364 header_win = subwin(stdscr, 1, maxx, 0, 0);
365 if (!header_win)
366 return -1;
367
368 footer_win = subwin(stdscr, 1, maxx, maxy-1, 0);
369 if (!footer_win)
370 return -1;
371
372 if (show_header_footer(wdefault))
373 return -1;
374
375 return display_refresh(wdefault);
376}
377
378void print_regulator_header(void)
379{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200380 werase(main_win);
381 wattron(main_win, A_BOLD);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200382 mvwprintw(main_win, 0, 0, "Name");
383 mvwprintw(main_win, 0, 12, "Status");
384 mvwprintw(main_win, 0, 24, "State");
385 mvwprintw(main_win, 0, 36, "Type");
386 mvwprintw(main_win, 0, 48, "Users");
387 mvwprintw(main_win, 0, 60, "Microvolts");
388 mvwprintw(main_win, 0, 72, "Min u-volts");
389 mvwprintw(main_win, 0, 84, "Max u-volts");
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200390 wattroff(main_win, A_BOLD);
391 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200392
393 show_header_footer(REGULATOR);
394}
395
396void print_clock_header(void)
397{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200398 werase(main_win);
399 wattron(main_win, A_BOLD);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200400 mvwprintw(main_win, 0, 0, "Name");
401 mvwprintw(main_win, 0, 56, "Flags");
402 mvwprintw(main_win, 0, 75, "Rate");
403 mvwprintw(main_win, 0, 88, "Usecount");
404 mvwprintw(main_win, 0, 98, "Children");
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200405 wattroff(main_win, A_BOLD);
406 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200407
408 show_header_footer(CLOCK);
409}
410
411void print_sensor_header(void)
412{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200413 werase(main_win);
414 wattron(main_win, A_BOLD);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200415 mvwprintw(main_win, 0, 0, "Name");
416 mvwprintw(main_win, 0, 36, "Value");
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200417 wattroff(main_win, A_BOLD);
418 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200419
420 show_header_footer(SENSOR);
421}
422
423int display_register(int win, struct display_ops *ops)
424{
425 size_t array_size = sizeof(windata) / sizeof(windata[0]);
426
427 if (win < 0 || win >= array_size)
428 return -1;
429
430 windata[win].ops = ops;
431
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200432 return 0;
433}