blob: 43f379782e204c2e6d1daeecd097a91e8bc9d157 [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>
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +020020#include <form.h>
Amit Arora47fd9182010-08-24 13:26:06 +053021#include "powerdebug.h"
Daniel Lezcanodb145802011-06-21 00:57:08 +020022#include "mainloop.h"
Amit Arora17552782010-12-02 12:23:14 +053023#include "regulator.h"
Amit Aroraed3e5652010-10-27 12:02:53 +053024#include "display.h"
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 Lezcanoc196d432011-06-21 00:57:08 +020038static WINDOW *main_win;
Daniel Lezcanod96731a2011-06-15 15:45:12 +020039static int current_win;
Amit Arora47fd9182010-08-24 13:26:06 +053040
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020041/* Number of lines in the virtual window */
42static const int maxrows = 1024;
43
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020044struct rowdata {
45 int attr;
46 void *data;
47};
48
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020049struct windata {
Daniel Lezcanof6656822011-06-15 15:45:12 +020050 WINDOW *pad;
Daniel Lezcanob301b082011-06-15 15:45:12 +020051 struct display_ops *ops;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020052 struct rowdata *rowdata;
53 char *name;
54 int nrdata;
55 int scrolling;
56 int cursor;
57};
58
Daniel Lezcano4120e262011-06-15 15:45:12 +020059/* Warning this is linked with the enum { CLOCK, REGULATOR, ... } */
Daniel Lezcano176e69d2011-06-15 15:45:12 +020060struct windata windata[] = {
Daniel Lezcano4120e262011-06-15 15:45:12 +020061 [CLOCK] = { .name = "Clocks" },
62 [REGULATOR] = { .name = "Regulators" },
63 [SENSOR] = { .name = "Sensors" },
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020064};
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020065
Daniel Lezcano3abd8b12011-03-26 22:06:15 +010066static void display_fini(void)
67{
68 endwin();
69}
70
Daniel Lezcano653cb4a2011-06-21 00:57:08 +020071static int display_show_header(int win)
Daniel Lezcano7b3da502011-06-15 15:45:12 +020072{
73 int i;
74 int curr_pointer = 0;
Daniel Lezcano4120e262011-06-15 15:45:12 +020075 size_t array_size = sizeof(windata) / sizeof(windata[0]);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020076
77 wattrset(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
78 wbkgd(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
79 werase(header_win);
80
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020081 mvwprintw(header_win, 0, curr_pointer, "PowerDebug %s", VERSION);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020082 curr_pointer += 20;
83
Daniel Lezcano4120e262011-06-15 15:45:12 +020084 for (i = 0; i < array_size; i++) {
Daniel Lezcano7b3da502011-06-15 15:45:12 +020085 if (win == i)
86 wattron(header_win, A_REVERSE);
87 else
88 wattroff(header_win, A_REVERSE);
89
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020090 mvwprintw(header_win, 0, curr_pointer, " %s ", windata[i].name);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020091 curr_pointer += strlen(windata[i].name) + 2;
92 }
93 wrefresh(header_win);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020094
Daniel Lezcano653cb4a2011-06-21 00:57:08 +020095 return 0;
96}
97
98#define footer_label " Q (Quit) R (Refresh) Other Keys: 'Left', " \
99 "'Right' , 'Up', 'Down', 'enter', , 'Esc'"
100
101static int display_show_footer(int win)
102{
103 werase(footer_win);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200104 wattron(footer_win, A_REVERSE);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200105 mvwprintw(footer_win, 0, 0, "%s", footer_label);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200106 wattroff(footer_win, A_REVERSE);
107 wrefresh(footer_win);
108
109 return 0;
110}
111
Daniel Lezcanodb145802011-06-21 00:57:08 +0200112int display_refresh(int win)
Amit Arora47fd9182010-08-24 13:26:06 +0530113{
Daniel Lezcanodb145802011-06-21 00:57:08 +0200114 /* we are trying to refresh a window which is not showed */
115 if (win != current_win)
116 return 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200117
Daniel Lezcanodb145802011-06-21 00:57:08 +0200118 if (windata[win].ops && windata[win].ops->display)
119 return windata[win].ops->display();
Daniel Lezcano971515a2011-06-15 15:45:12 +0200120
121 return 0;
122}
123
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200124int display_refresh_pad(int win)
Amit Arora728e0c92010-09-14 12:06:09 +0530125{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200126 int maxx, maxy;
127
128 getmaxyx(stdscr, maxy, maxx);
129
Daniel Lezcanof6656822011-06-15 15:45:12 +0200130 return prefresh(windata[win].pad, windata[win].scrolling,
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200131 0, 2, 0, maxy - 2, maxx);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200132}
Amit Aroraac4e8652010-11-09 11:16:53 +0530133
Daniel Lezcano28203df2011-06-15 15:45:12 +0200134static int display_show_unselection(int win, int line, bool bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200135{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200136 if (mvwchgat(windata[win].pad, line, 0, -1,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200137 bold ? WA_BOLD: WA_NORMAL, 0, NULL) < 0)
138 return -1;
139
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200140 return display_refresh_pad(win);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200141}
142
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200143void *display_get_row_data(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200144{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200145 return windata[win].rowdata[windata[win].cursor].data;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200146}
147
Daniel Lezcano28203df2011-06-15 15:45:12 +0200148static int display_select(void)
149{
150 if (windata[current_win].ops && windata[current_win].ops->select)
151 return windata[current_win].ops->select();
152
153 return 0;
154}
155
156static int display_next_panel(void)
157{
158 size_t array_size = sizeof(windata) / sizeof(windata[0]);
159
160 current_win++;
161 current_win %= array_size;
162
163 return current_win;
164}
165
166static int display_prev_panel(void)
167{
168 size_t array_size = sizeof(windata) / sizeof(windata[0]);
169
170 current_win--;
171 if (current_win < 0)
172 current_win = array_size - 1;
173
174 return current_win;
175}
176
177static int display_next_line(void)
178{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200179 int maxx, maxy;
Daniel Lezcano28203df2011-06-15 15:45:12 +0200180 int cursor = windata[current_win].cursor;
181 int nrdata = windata[current_win].nrdata;
182 int scrolling = windata[current_win].scrolling;
183 struct rowdata *rowdata = windata[current_win].rowdata;
184
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200185 getmaxyx(stdscr, maxy, maxx);
186
Daniel Lezcano28203df2011-06-15 15:45:12 +0200187 if (cursor >= nrdata)
188 return cursor;
189
190 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
191 if (cursor < nrdata - 1) {
192 if (cursor >= (maxy - 4 + scrolling))
193 scrolling++;
194 cursor++;
195 }
196
197 windata[current_win].scrolling = scrolling;
198 windata[current_win].cursor = cursor;
199
200 return cursor;
201}
202
203static int display_prev_line(void)
204{
205 int cursor = windata[current_win].cursor;
206 int nrdata = windata[current_win].nrdata;
207 int scrolling = windata[current_win].scrolling;
208 struct rowdata *rowdata = windata[current_win].rowdata;
209
210 if (cursor >= nrdata)
211 return cursor;
212
213 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
214 if (cursor > 0) {
215 if (cursor <= scrolling)
216 scrolling--;
217 cursor--;
218 }
219
220 windata[current_win].scrolling = scrolling;
221 windata[current_win].cursor = cursor;
222
223 return cursor;
224}
225
226static int display_set_row_data(int win, int line, void *data, int attr)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200227{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200228 struct rowdata *rowdata = windata[win].rowdata;
229
230 if (line >= windata[win].nrdata) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200231 rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1));
232 if (!rowdata)
233 return -1;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200234 windata[win].nrdata = line + 1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200235 }
236
237 rowdata[line].data = data;
238 rowdata[line].attr = attr;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200239 windata[win].rowdata = rowdata;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200240
241 return 0;
242}
243
Daniel Lezcanof6656822011-06-15 15:45:12 +0200244int display_reset_cursor(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200245{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200246 windata[win].nrdata = 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200247 werase(windata[win].pad);
248 return wmove(windata[win].pad, 0, 0);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200249}
250
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200251int display_print_line(int win, int line, char *str, int bold, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200252{
253 int attr = 0;
254
Amit Arora031263a2010-11-09 11:12:41 +0530255 if (bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200256 attr |= WA_BOLD;
257
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200258 if (line == windata[win].cursor)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200259 attr |= WA_STANDOUT;
260
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200261 if (display_set_row_data(win, line, data, attr))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200262 return -1;
263
264 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200265 wattron(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200266
Daniel Lezcanof6656822011-06-15 15:45:12 +0200267 wprintw(windata[win].pad, "%s\n", str);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200268
269 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200270 wattroff(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200271
272 return 0;
273}
274
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +0200275static int display_find_keystroke(int fd, void *data);
276
277static int display_switch_to_find(int fd)
278{
279 if (mainloop_del(fd))
280 return -1;
281
282 if (mainloop_add(fd, display_find_keystroke, NULL))
283 return -1;
284
285 return 0;
286}
287
Daniel Lezcanodb145802011-06-21 00:57:08 +0200288static int display_keystroke(int fd, void *data)
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200289{
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200290 int keystroke = getch();
291
292 switch (keystroke) {
293
294 case KEY_RIGHT:
295 case '\t':
296 display_next_panel();
297 break;
298
299 case KEY_LEFT:
300 case KEY_BTAB:
301 display_prev_panel();
302 break;
303
304 case KEY_DOWN:
305 display_next_line();
306 break;
307
308 case KEY_UP:
309 display_prev_line();
310 break;
311
312 case '\r':
313 display_select();
314 break;
315
316 case EOF:
317 case 'q':
318 case 'Q':
319 return 1;
320
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +0200321 case '/':
322 return display_switch_to_find(fd);
323
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200324 case 'r':
325 case 'R':
Daniel Lezcanodb145802011-06-21 00:57:08 +0200326 /* refresh will be done after */
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200327 break;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200328 default:
329 return 0;
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200330 }
331
Daniel Lezcanodb145802011-06-21 00:57:08 +0200332 display_refresh(current_win);
333
334 return 0;
335}
336
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +0200337static int display_switch_to_main(int fd)
338{
339 if (mainloop_del(fd))
340 return -1;
341
342 if (mainloop_add(fd, display_keystroke, NULL))
343 return -1;
344
345 display_refresh(current_win);
346
347 return 0;
348}
349
350
351static int display_find_keystroke(int fd, void *data)
352{
353 int keystroke = getch();
354
355 switch (keystroke) {
356
357 case '\e':
358 return display_switch_to_main(fd);
359 default:
360 break;
361 }
362
363 return 0;
364}
365
Daniel Lezcanodb145802011-06-21 00:57:08 +0200366int display_init(int wdefault)
367{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200368 int i, maxx, maxy;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200369 size_t array_size = sizeof(windata) / sizeof(windata[0]);
370
371 current_win = wdefault;
372
373 if (mainloop_add(0, display_keystroke, NULL))
374 return -1;
375
376 if (!initscr())
377 return -1;
378
379 start_color();
380 use_default_colors();
381
382 keypad(stdscr, TRUE);
383 noecho();
384 cbreak();
385 curs_set(0);
386 nonl();
387
388 if (init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK) ||
389 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED) ||
390 init_pair(PT_COLOR_HEADER_BAR, COLOR_WHITE, COLOR_BLACK) ||
391 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW) ||
392 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN) ||
393 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK) ||
394 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE) ||
395 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED))
396 return -1;
397
398 if (atexit(display_fini))
399 return -1;
400
401 getmaxyx(stdscr, maxy, maxx);
402
403 for (i = 0; i < array_size; i++) {
404
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200405 main_win = subwin(stdscr, maxy - 2, maxx, 1, 0);
406 if (!main_win)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200407 return -1;
408
409 windata[i].pad = newpad(maxrows, maxx);
410 if (!windata[i].pad)
411 return -1;
412
413 }
414
415 header_win = subwin(stdscr, 1, maxx, 0, 0);
416 if (!header_win)
417 return -1;
418
419 footer_win = subwin(stdscr, 1, maxx, maxy-1, 0);
420 if (!footer_win)
421 return -1;
422
Daniel Lezcano653cb4a2011-06-21 00:57:08 +0200423 if (display_show_header(wdefault))
424 return -1;
425
426 if (display_show_footer(wdefault))
Daniel Lezcanodb145802011-06-21 00:57:08 +0200427 return -1;
428
429 return display_refresh(wdefault);
430}
431
Daniel Lezcanofa453332011-06-21 00:57:08 +0200432int display_header_footer(int win, const char *line)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200433{
Daniel Lezcano653cb4a2011-06-21 00:57:08 +0200434 int ret;
435
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200436 werase(main_win);
437 wattron(main_win, A_BOLD);
Daniel Lezcanofa453332011-06-21 00:57:08 +0200438 mvwprintw(main_win, 0, 0, "%s", line);
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200439 wattroff(main_win, A_BOLD);
440 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200441
Daniel Lezcano653cb4a2011-06-21 00:57:08 +0200442 ret = display_show_header(win);
443 if (ret)
444 return ret;
445
446 return display_show_footer(win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200447}
448
449int display_register(int win, struct display_ops *ops)
450{
451 size_t array_size = sizeof(windata) / sizeof(windata[0]);
452
453 if (win < 0 || win >= array_size)
454 return -1;
455
456 windata[win].ops = ops;
457
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200458 return 0;
459}