blob: 1af12a3e6b708756d677b8205c56d598ae52d0bf [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
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 *pad;
Daniel Lezcanob301b082011-06-15 15:45:12 +020055 struct display_ops *ops;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020056 struct rowdata *rowdata;
57 char *name;
58 int nrdata;
59 int scrolling;
60 int cursor;
61};
62
Daniel Lezcano4120e262011-06-15 15:45:12 +020063/* Warning this is linked with the enum { CLOCK, REGULATOR, ... } */
Daniel Lezcano176e69d2011-06-15 15:45:12 +020064struct windata windata[] = {
Daniel Lezcano4120e262011-06-15 15:45:12 +020065 [CLOCK] = { .name = "Clocks" },
66 [REGULATOR] = { .name = "Regulators" },
67 [SENSOR] = { .name = "Sensors" },
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020068};
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020069
Daniel Lezcano3abd8b12011-03-26 22:06:15 +010070static void display_fini(void)
71{
72 endwin();
73}
74
Daniel Lezcano7b3da502011-06-15 15:45:12 +020075static int show_header_footer(int win)
76{
77 int i;
78 int curr_pointer = 0;
Daniel Lezcano4120e262011-06-15 15:45:12 +020079 size_t array_size = sizeof(windata) / sizeof(windata[0]);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020080
81 wattrset(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
82 wbkgd(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
83 werase(header_win);
84
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020085 mvwprintw(header_win, 0, curr_pointer, "PowerDebug %s", VERSION);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020086 curr_pointer += 20;
87
Daniel Lezcano4120e262011-06-15 15:45:12 +020088 for (i = 0; i < array_size; i++) {
Daniel Lezcano7b3da502011-06-15 15:45:12 +020089 if (win == i)
90 wattron(header_win, A_REVERSE);
91 else
92 wattroff(header_win, A_REVERSE);
93
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020094 mvwprintw(header_win, 0, curr_pointer, " %s ", windata[i].name);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020095 curr_pointer += strlen(windata[i].name) + 2;
96 }
97 wrefresh(header_win);
98 werase(footer_win);
99
100 wattron(footer_win, A_REVERSE);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200101 mvwprintw(footer_win, 0, 0, "%s", footer_label);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200102 wattroff(footer_win, A_REVERSE);
103 wrefresh(footer_win);
104
105 return 0;
106}
107
Daniel Lezcanodb145802011-06-21 00:57:08 +0200108int display_refresh(int win)
Amit Arora47fd9182010-08-24 13:26:06 +0530109{
Daniel Lezcanodb145802011-06-21 00:57:08 +0200110 /* we are trying to refresh a window which is not showed */
111 if (win != current_win)
112 return 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200113
Daniel Lezcanodb145802011-06-21 00:57:08 +0200114 if (windata[win].ops && windata[win].ops->display)
115 return windata[win].ops->display();
Daniel Lezcano971515a2011-06-15 15:45:12 +0200116
117 return 0;
118}
119
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200120int display_refresh_pad(int win)
Amit Arora728e0c92010-09-14 12:06:09 +0530121{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200122 return prefresh(windata[win].pad, windata[win].scrolling,
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200123 0, 2, 0, maxy - 2, maxx);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200124}
Amit Aroraac4e8652010-11-09 11:16:53 +0530125
Daniel Lezcano28203df2011-06-15 15:45:12 +0200126static int display_show_unselection(int win, int line, bool bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200127{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200128 if (mvwchgat(windata[win].pad, line, 0, -1,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200129 bold ? WA_BOLD: WA_NORMAL, 0, NULL) < 0)
130 return -1;
131
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200132 return display_refresh_pad(win);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200133}
134
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200135void *display_get_row_data(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200136{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200137 return windata[win].rowdata[windata[win].cursor].data;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200138}
139
Daniel Lezcano28203df2011-06-15 15:45:12 +0200140static int display_select(void)
141{
142 if (windata[current_win].ops && windata[current_win].ops->select)
143 return windata[current_win].ops->select();
144
145 return 0;
146}
147
148static int display_next_panel(void)
149{
150 size_t array_size = sizeof(windata) / sizeof(windata[0]);
151
152 current_win++;
153 current_win %= array_size;
154
155 return current_win;
156}
157
158static int display_prev_panel(void)
159{
160 size_t array_size = sizeof(windata) / sizeof(windata[0]);
161
162 current_win--;
163 if (current_win < 0)
164 current_win = array_size - 1;
165
166 return current_win;
167}
168
169static int display_next_line(void)
170{
171 int cursor = windata[current_win].cursor;
172 int nrdata = windata[current_win].nrdata;
173 int scrolling = windata[current_win].scrolling;
174 struct rowdata *rowdata = windata[current_win].rowdata;
175
176 if (cursor >= nrdata)
177 return cursor;
178
179 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
180 if (cursor < nrdata - 1) {
181 if (cursor >= (maxy - 4 + scrolling))
182 scrolling++;
183 cursor++;
184 }
185
186 windata[current_win].scrolling = scrolling;
187 windata[current_win].cursor = cursor;
188
189 return cursor;
190}
191
192static int display_prev_line(void)
193{
194 int cursor = windata[current_win].cursor;
195 int nrdata = windata[current_win].nrdata;
196 int scrolling = windata[current_win].scrolling;
197 struct rowdata *rowdata = windata[current_win].rowdata;
198
199 if (cursor >= nrdata)
200 return cursor;
201
202 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
203 if (cursor > 0) {
204 if (cursor <= scrolling)
205 scrolling--;
206 cursor--;
207 }
208
209 windata[current_win].scrolling = scrolling;
210 windata[current_win].cursor = cursor;
211
212 return cursor;
213}
214
215static int display_set_row_data(int win, int line, void *data, int attr)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200216{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200217 struct rowdata *rowdata = windata[win].rowdata;
218
219 if (line >= windata[win].nrdata) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200220 rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1));
221 if (!rowdata)
222 return -1;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200223 windata[win].nrdata = line + 1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200224 }
225
226 rowdata[line].data = data;
227 rowdata[line].attr = attr;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200228 windata[win].rowdata = rowdata;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200229
230 return 0;
231}
232
Daniel Lezcanof6656822011-06-15 15:45:12 +0200233int display_reset_cursor(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200234{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200235 windata[win].nrdata = 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200236 werase(windata[win].pad);
237 return wmove(windata[win].pad, 0, 0);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200238}
239
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200240int display_print_line(int win, int line, char *str, int bold, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200241{
242 int attr = 0;
243
Amit Arora031263a2010-11-09 11:12:41 +0530244 if (bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200245 attr |= WA_BOLD;
246
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200247 if (line == windata[win].cursor)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200248 attr |= WA_STANDOUT;
249
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200250 if (display_set_row_data(win, line, data, attr))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200251 return -1;
252
253 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200254 wattron(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200255
Daniel Lezcanof6656822011-06-15 15:45:12 +0200256 wprintw(windata[win].pad, "%s\n", str);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200257
258 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200259 wattroff(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200260
261 return 0;
262}
263
Daniel Lezcanodb145802011-06-21 00:57:08 +0200264static int display_keystroke(int fd, void *data)
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200265{
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200266 int keystroke = getch();
267
268 switch (keystroke) {
269
270 case KEY_RIGHT:
271 case '\t':
272 display_next_panel();
273 break;
274
275 case KEY_LEFT:
276 case KEY_BTAB:
277 display_prev_panel();
278 break;
279
280 case KEY_DOWN:
281 display_next_line();
282 break;
283
284 case KEY_UP:
285 display_prev_line();
286 break;
287
288 case '\r':
289 display_select();
290 break;
291
292 case EOF:
293 case 'q':
294 case 'Q':
295 return 1;
296
297 case 'r':
298 case 'R':
Daniel Lezcanodb145802011-06-21 00:57:08 +0200299 /* refresh will be done after */
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200300 break;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200301 default:
302 return 0;
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200303 }
304
Daniel Lezcanodb145802011-06-21 00:57:08 +0200305 display_refresh(current_win);
306
307 return 0;
308}
309
310int display_init(int wdefault)
311{
312 int i;
313 size_t array_size = sizeof(windata) / sizeof(windata[0]);
314
315 current_win = wdefault;
316
317 if (mainloop_add(0, display_keystroke, NULL))
318 return -1;
319
320 if (!initscr())
321 return -1;
322
323 start_color();
324 use_default_colors();
325
326 keypad(stdscr, TRUE);
327 noecho();
328 cbreak();
329 curs_set(0);
330 nonl();
331
332 if (init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK) ||
333 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED) ||
334 init_pair(PT_COLOR_HEADER_BAR, COLOR_WHITE, COLOR_BLACK) ||
335 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW) ||
336 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN) ||
337 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK) ||
338 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE) ||
339 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED))
340 return -1;
341
342 if (atexit(display_fini))
343 return -1;
344
345 getmaxyx(stdscr, maxy, maxx);
346
347 for (i = 0; i < array_size; i++) {
348
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200349 main_win = subwin(stdscr, maxy - 2, maxx, 1, 0);
350 if (!main_win)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200351 return -1;
352
353 windata[i].pad = newpad(maxrows, maxx);
354 if (!windata[i].pad)
355 return -1;
356
357 }
358
359 header_win = subwin(stdscr, 1, maxx, 0, 0);
360 if (!header_win)
361 return -1;
362
363 footer_win = subwin(stdscr, 1, maxx, maxy-1, 0);
364 if (!footer_win)
365 return -1;
366
367 if (show_header_footer(wdefault))
368 return -1;
369
370 return display_refresh(wdefault);
371}
372
373void print_regulator_header(void)
374{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200375 werase(main_win);
376 wattron(main_win, A_BOLD);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200377 mvwprintw(main_win, 0, 0, "Name");
378 mvwprintw(main_win, 0, 12, "Status");
379 mvwprintw(main_win, 0, 24, "State");
380 mvwprintw(main_win, 0, 36, "Type");
381 mvwprintw(main_win, 0, 48, "Users");
382 mvwprintw(main_win, 0, 60, "Microvolts");
383 mvwprintw(main_win, 0, 72, "Min u-volts");
384 mvwprintw(main_win, 0, 84, "Max u-volts");
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200385 wattroff(main_win, A_BOLD);
386 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200387
388 show_header_footer(REGULATOR);
389}
390
391void print_clock_header(void)
392{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200393 werase(main_win);
394 wattron(main_win, A_BOLD);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200395 mvwprintw(main_win, 0, 0, "Name");
396 mvwprintw(main_win, 0, 56, "Flags");
397 mvwprintw(main_win, 0, 75, "Rate");
398 mvwprintw(main_win, 0, 88, "Usecount");
399 mvwprintw(main_win, 0, 98, "Children");
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200400 wattroff(main_win, A_BOLD);
401 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200402
403 show_header_footer(CLOCK);
404}
405
406void print_sensor_header(void)
407{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200408 werase(main_win);
409 wattron(main_win, A_BOLD);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200410 mvwprintw(main_win, 0, 0, "Name");
411 mvwprintw(main_win, 0, 36, "Value");
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200412 wattroff(main_win, A_BOLD);
413 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200414
415 show_header_footer(SENSOR);
416}
417
418int display_register(int win, struct display_ops *ops)
419{
420 size_t array_size = sizeof(windata) / sizeof(windata[0]);
421
422 if (win < 0 || win >= array_size)
423 return -1;
424
425 windata[win].ops = ops;
426
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200427 return 0;
428}