blob: 758d17edea30fe15547c9abaf00f03ed78b5fa73 [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 Lezcano7b3da502011-06-15 15:45:12 +020044#define footer_label " Q (Quit) R (Refresh) Other Keys: 'Left', " \
45 "'Right' , 'Up', 'Down', 'enter', , 'Esc'"
Amit Arora47fd9182010-08-24 13:26:06 +053046
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020047struct rowdata {
48 int attr;
49 void *data;
50};
51
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020052struct windata {
Daniel Lezcanof6656822011-06-15 15:45:12 +020053 WINDOW *pad;
Daniel Lezcanob301b082011-06-15 15:45:12 +020054 struct display_ops *ops;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020055 struct rowdata *rowdata;
56 char *name;
57 int nrdata;
58 int scrolling;
59 int cursor;
60};
61
Daniel Lezcano4120e262011-06-15 15:45:12 +020062/* Warning this is linked with the enum { CLOCK, REGULATOR, ... } */
Daniel Lezcano176e69d2011-06-15 15:45:12 +020063struct windata windata[] = {
Daniel Lezcano4120e262011-06-15 15:45:12 +020064 [CLOCK] = { .name = "Clocks" },
65 [REGULATOR] = { .name = "Regulators" },
66 [SENSOR] = { .name = "Sensors" },
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020067};
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020068
Daniel Lezcano3abd8b12011-03-26 22:06:15 +010069static void display_fini(void)
70{
71 endwin();
72}
73
Daniel Lezcano7b3da502011-06-15 15:45:12 +020074static int show_header_footer(int win)
75{
76 int i;
77 int curr_pointer = 0;
Daniel Lezcano4120e262011-06-15 15:45:12 +020078 size_t array_size = sizeof(windata) / sizeof(windata[0]);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020079
80 wattrset(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
81 wbkgd(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
82 werase(header_win);
83
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020084 mvwprintw(header_win, 0, curr_pointer, "PowerDebug %s", VERSION);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020085 curr_pointer += 20;
86
Daniel Lezcano4120e262011-06-15 15:45:12 +020087 for (i = 0; i < array_size; i++) {
Daniel Lezcano7b3da502011-06-15 15:45:12 +020088 if (win == i)
89 wattron(header_win, A_REVERSE);
90 else
91 wattroff(header_win, A_REVERSE);
92
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +020093 mvwprintw(header_win, 0, curr_pointer, " %s ", windata[i].name);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020094 curr_pointer += strlen(windata[i].name) + 2;
95 }
96 wrefresh(header_win);
97 werase(footer_win);
98
99 wattron(footer_win, A_REVERSE);
Daniel Lezcanoc757e6d2011-06-21 00:57:08 +0200100 mvwprintw(footer_win, 0, 0, "%s", footer_label);
Daniel Lezcano7b3da502011-06-15 15:45:12 +0200101 wattroff(footer_win, A_REVERSE);
102 wrefresh(footer_win);
103
104 return 0;
105}
106
Daniel Lezcanodb145802011-06-21 00:57:08 +0200107int display_refresh(int win)
Amit Arora47fd9182010-08-24 13:26:06 +0530108{
Daniel Lezcanodb145802011-06-21 00:57:08 +0200109 /* we are trying to refresh a window which is not showed */
110 if (win != current_win)
111 return 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200112
Daniel Lezcanodb145802011-06-21 00:57:08 +0200113 if (windata[win].ops && windata[win].ops->display)
114 return windata[win].ops->display();
Daniel Lezcano971515a2011-06-15 15:45:12 +0200115
116 return 0;
117}
118
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200119int display_refresh_pad(int win)
Amit Arora728e0c92010-09-14 12:06:09 +0530120{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200121 int maxx, maxy;
122
123 getmaxyx(stdscr, maxy, maxx);
124
Daniel Lezcanof6656822011-06-15 15:45:12 +0200125 return prefresh(windata[win].pad, windata[win].scrolling,
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200126 0, 2, 0, maxy - 2, maxx);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200127}
Amit Aroraac4e8652010-11-09 11:16:53 +0530128
Daniel Lezcano28203df2011-06-15 15:45:12 +0200129static int display_show_unselection(int win, int line, bool bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200130{
Daniel Lezcanof6656822011-06-15 15:45:12 +0200131 if (mvwchgat(windata[win].pad, line, 0, -1,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200132 bold ? WA_BOLD: WA_NORMAL, 0, NULL) < 0)
133 return -1;
134
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200135 return display_refresh_pad(win);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200136}
137
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200138void *display_get_row_data(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200139{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200140 return windata[win].rowdata[windata[win].cursor].data;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200141}
142
Daniel Lezcano28203df2011-06-15 15:45:12 +0200143static int display_select(void)
144{
145 if (windata[current_win].ops && windata[current_win].ops->select)
146 return windata[current_win].ops->select();
147
148 return 0;
149}
150
151static int display_next_panel(void)
152{
153 size_t array_size = sizeof(windata) / sizeof(windata[0]);
154
155 current_win++;
156 current_win %= array_size;
157
158 return current_win;
159}
160
161static int display_prev_panel(void)
162{
163 size_t array_size = sizeof(windata) / sizeof(windata[0]);
164
165 current_win--;
166 if (current_win < 0)
167 current_win = array_size - 1;
168
169 return current_win;
170}
171
172static int display_next_line(void)
173{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200174 int maxx, maxy;
Daniel Lezcano28203df2011-06-15 15:45:12 +0200175 int cursor = windata[current_win].cursor;
176 int nrdata = windata[current_win].nrdata;
177 int scrolling = windata[current_win].scrolling;
178 struct rowdata *rowdata = windata[current_win].rowdata;
179
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200180 getmaxyx(stdscr, maxy, maxx);
181
Daniel Lezcano28203df2011-06-15 15:45:12 +0200182 if (cursor >= nrdata)
183 return cursor;
184
185 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
186 if (cursor < nrdata - 1) {
187 if (cursor >= (maxy - 4 + scrolling))
188 scrolling++;
189 cursor++;
190 }
191
192 windata[current_win].scrolling = scrolling;
193 windata[current_win].cursor = cursor;
194
195 return cursor;
196}
197
198static int display_prev_line(void)
199{
200 int cursor = windata[current_win].cursor;
201 int nrdata = windata[current_win].nrdata;
202 int scrolling = windata[current_win].scrolling;
203 struct rowdata *rowdata = windata[current_win].rowdata;
204
205 if (cursor >= nrdata)
206 return cursor;
207
208 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
209 if (cursor > 0) {
210 if (cursor <= scrolling)
211 scrolling--;
212 cursor--;
213 }
214
215 windata[current_win].scrolling = scrolling;
216 windata[current_win].cursor = cursor;
217
218 return cursor;
219}
220
221static int display_set_row_data(int win, int line, void *data, int attr)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200222{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200223 struct rowdata *rowdata = windata[win].rowdata;
224
225 if (line >= windata[win].nrdata) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200226 rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1));
227 if (!rowdata)
228 return -1;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200229 windata[win].nrdata = line + 1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200230 }
231
232 rowdata[line].data = data;
233 rowdata[line].attr = attr;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200234 windata[win].rowdata = rowdata;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200235
236 return 0;
237}
238
Daniel Lezcanof6656822011-06-15 15:45:12 +0200239int display_reset_cursor(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200240{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200241 windata[win].nrdata = 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200242 werase(windata[win].pad);
243 return wmove(windata[win].pad, 0, 0);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200244}
245
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200246int display_print_line(int win, int line, char *str, int bold, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200247{
248 int attr = 0;
249
Amit Arora031263a2010-11-09 11:12:41 +0530250 if (bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200251 attr |= WA_BOLD;
252
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200253 if (line == windata[win].cursor)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200254 attr |= WA_STANDOUT;
255
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200256 if (display_set_row_data(win, line, data, attr))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200257 return -1;
258
259 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200260 wattron(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200261
Daniel Lezcanof6656822011-06-15 15:45:12 +0200262 wprintw(windata[win].pad, "%s\n", str);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200263
264 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200265 wattroff(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200266
267 return 0;
268}
269
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +0200270static int display_find_keystroke(int fd, void *data);
271
272static int display_switch_to_find(int fd)
273{
274 if (mainloop_del(fd))
275 return -1;
276
277 if (mainloop_add(fd, display_find_keystroke, NULL))
278 return -1;
279
280 return 0;
281}
282
Daniel Lezcanodb145802011-06-21 00:57:08 +0200283static int display_keystroke(int fd, void *data)
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200284{
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200285 int keystroke = getch();
286
287 switch (keystroke) {
288
289 case KEY_RIGHT:
290 case '\t':
291 display_next_panel();
292 break;
293
294 case KEY_LEFT:
295 case KEY_BTAB:
296 display_prev_panel();
297 break;
298
299 case KEY_DOWN:
300 display_next_line();
301 break;
302
303 case KEY_UP:
304 display_prev_line();
305 break;
306
307 case '\r':
308 display_select();
309 break;
310
311 case EOF:
312 case 'q':
313 case 'Q':
314 return 1;
315
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +0200316 case '/':
317 return display_switch_to_find(fd);
318
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200319 case 'r':
320 case 'R':
Daniel Lezcanodb145802011-06-21 00:57:08 +0200321 /* refresh will be done after */
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200322 break;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200323 default:
324 return 0;
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200325 }
326
Daniel Lezcanodb145802011-06-21 00:57:08 +0200327 display_refresh(current_win);
328
329 return 0;
330}
331
Daniel Lezcanoe64c48e2011-06-21 00:57:08 +0200332static int display_switch_to_main(int fd)
333{
334 if (mainloop_del(fd))
335 return -1;
336
337 if (mainloop_add(fd, display_keystroke, NULL))
338 return -1;
339
340 display_refresh(current_win);
341
342 return 0;
343}
344
345
346static int display_find_keystroke(int fd, void *data)
347{
348 int keystroke = getch();
349
350 switch (keystroke) {
351
352 case '\e':
353 return display_switch_to_main(fd);
354 default:
355 break;
356 }
357
358 return 0;
359}
360
Daniel Lezcanodb145802011-06-21 00:57:08 +0200361int display_init(int wdefault)
362{
Daniel Lezcano0a8cc582011-06-21 00:57:08 +0200363 int i, maxx, maxy;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200364 size_t array_size = sizeof(windata) / sizeof(windata[0]);
365
366 current_win = wdefault;
367
368 if (mainloop_add(0, display_keystroke, NULL))
369 return -1;
370
371 if (!initscr())
372 return -1;
373
374 start_color();
375 use_default_colors();
376
377 keypad(stdscr, TRUE);
378 noecho();
379 cbreak();
380 curs_set(0);
381 nonl();
382
383 if (init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK) ||
384 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED) ||
385 init_pair(PT_COLOR_HEADER_BAR, COLOR_WHITE, COLOR_BLACK) ||
386 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW) ||
387 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN) ||
388 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK) ||
389 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE) ||
390 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED))
391 return -1;
392
393 if (atexit(display_fini))
394 return -1;
395
396 getmaxyx(stdscr, maxy, maxx);
397
398 for (i = 0; i < array_size; i++) {
399
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200400 main_win = subwin(stdscr, maxy - 2, maxx, 1, 0);
401 if (!main_win)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200402 return -1;
403
404 windata[i].pad = newpad(maxrows, maxx);
405 if (!windata[i].pad)
406 return -1;
407
408 }
409
410 header_win = subwin(stdscr, 1, maxx, 0, 0);
411 if (!header_win)
412 return -1;
413
414 footer_win = subwin(stdscr, 1, maxx, maxy-1, 0);
415 if (!footer_win)
416 return -1;
417
418 if (show_header_footer(wdefault))
419 return -1;
420
421 return display_refresh(wdefault);
422}
423
Daniel Lezcanofa453332011-06-21 00:57:08 +0200424int display_header_footer(int win, const char *line)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200425{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200426 werase(main_win);
427 wattron(main_win, A_BOLD);
Daniel Lezcanofa453332011-06-21 00:57:08 +0200428 mvwprintw(main_win, 0, 0, "%s", line);
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200429 wattroff(main_win, A_BOLD);
430 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200431
Daniel Lezcanofa453332011-06-21 00:57:08 +0200432 return show_header_footer(win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200433}
434
435int display_register(int win, struct display_ops *ops)
436{
437 size_t array_size = sizeof(windata) / sizeof(windata[0]);
438
439 if (win < 0 || win >= array_size)
440 return -1;
441
442 windata[win].ops = ops;
443
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200444 return 0;
445}