blob: 80663a794c0a1fc1ebf6ce65ee4b137ee2798312 [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
25#define print(w, x, y, fmt, args...) do { mvwprintw(w, y, x, fmt, ##args); } while (0)
Amit Arora47fd9182010-08-24 13:26:06 +053026
Daniel Lezcanoeeb13762011-03-26 22:06:17 +010027enum { PT_COLOR_DEFAULT = 1,
28 PT_COLOR_HEADER_BAR,
29 PT_COLOR_ERROR,
30 PT_COLOR_RED,
31 PT_COLOR_YELLOW,
32 PT_COLOR_GREEN,
33 PT_COLOR_BRIGHT,
34 PT_COLOR_BLUE,
35};
36
Amit Arora47fd9182010-08-24 13:26:06 +053037static WINDOW *header_win;
Amit Arora47fd9182010-08-24 13:26:06 +053038static WINDOW *footer_win;
Daniel Lezcanoc196d432011-06-21 00:57:08 +020039static WINDOW *main_win;
Daniel Lezcanod96731a2011-06-15 15:45:12 +020040static int current_win;
Amit Arora47fd9182010-08-24 13:26:06 +053041
42int maxx, maxy;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020043
44/* Number of lines in the virtual window */
45static const int maxrows = 1024;
46
Daniel Lezcano7b3da502011-06-15 15:45:12 +020047#define footer_label " Q (Quit) R (Refresh) Other Keys: 'Left', " \
48 "'Right' , 'Up', 'Down', 'enter', , 'Esc'"
Amit Arora47fd9182010-08-24 13:26:06 +053049
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020050struct rowdata {
51 int attr;
52 void *data;
53};
54
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020055struct windata {
Daniel Lezcanof6656822011-06-15 15:45:12 +020056 WINDOW *pad;
Daniel Lezcanob301b082011-06-15 15:45:12 +020057 struct display_ops *ops;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020058 struct rowdata *rowdata;
59 char *name;
60 int nrdata;
61 int scrolling;
62 int cursor;
63};
64
Daniel Lezcano4120e262011-06-15 15:45:12 +020065/* Warning this is linked with the enum { CLOCK, REGULATOR, ... } */
Daniel Lezcano176e69d2011-06-15 15:45:12 +020066struct windata windata[] = {
Daniel Lezcano4120e262011-06-15 15:45:12 +020067 [CLOCK] = { .name = "Clocks" },
68 [REGULATOR] = { .name = "Regulators" },
69 [SENSOR] = { .name = "Sensors" },
Daniel Lezcanob3e6e812011-06-15 15:45:12 +020070};
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020071
Daniel Lezcano3abd8b12011-03-26 22:06:15 +010072static void display_fini(void)
73{
74 endwin();
75}
76
Daniel Lezcano7b3da502011-06-15 15:45:12 +020077static int show_header_footer(int win)
78{
79 int i;
80 int curr_pointer = 0;
Daniel Lezcano4120e262011-06-15 15:45:12 +020081 size_t array_size = sizeof(windata) / sizeof(windata[0]);
Daniel Lezcano7b3da502011-06-15 15:45:12 +020082
83 wattrset(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
84 wbkgd(header_win, COLOR_PAIR(PT_COLOR_HEADER_BAR));
85 werase(header_win);
86
87 print(header_win, curr_pointer, 0, "PowerDebug %s", VERSION);
88 curr_pointer += 20;
89
Daniel Lezcano4120e262011-06-15 15:45:12 +020090 for (i = 0; i < array_size; i++) {
Daniel Lezcano7b3da502011-06-15 15:45:12 +020091 if (win == i)
92 wattron(header_win, A_REVERSE);
93 else
94 wattroff(header_win, A_REVERSE);
95
96 print(header_win, curr_pointer, 0, " %s ", windata[i].name);
97 curr_pointer += strlen(windata[i].name) + 2;
98 }
99 wrefresh(header_win);
100 werase(footer_win);
101
102 wattron(footer_win, A_REVERSE);
103 print(footer_win, 0, 0, "%s", footer_label);
104 wattroff(footer_win, A_REVERSE);
105 wrefresh(footer_win);
106
107 return 0;
108}
109
Daniel Lezcanodb145802011-06-21 00:57:08 +0200110int display_refresh(int win)
Amit Arora47fd9182010-08-24 13:26:06 +0530111{
Daniel Lezcanodb145802011-06-21 00:57:08 +0200112 /* we are trying to refresh a window which is not showed */
113 if (win != current_win)
114 return 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200115
Daniel Lezcanodb145802011-06-21 00:57:08 +0200116 if (windata[win].ops && windata[win].ops->display)
117 return windata[win].ops->display();
Daniel Lezcano971515a2011-06-15 15:45:12 +0200118
119 return 0;
120}
121
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200122int display_refresh_pad(int win)
Amit Arora728e0c92010-09-14 12:06:09 +0530123{
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{
173 int cursor = windata[current_win].cursor;
174 int nrdata = windata[current_win].nrdata;
175 int scrolling = windata[current_win].scrolling;
176 struct rowdata *rowdata = windata[current_win].rowdata;
177
178 if (cursor >= nrdata)
179 return cursor;
180
181 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
182 if (cursor < nrdata - 1) {
183 if (cursor >= (maxy - 4 + scrolling))
184 scrolling++;
185 cursor++;
186 }
187
188 windata[current_win].scrolling = scrolling;
189 windata[current_win].cursor = cursor;
190
191 return cursor;
192}
193
194static int display_prev_line(void)
195{
196 int cursor = windata[current_win].cursor;
197 int nrdata = windata[current_win].nrdata;
198 int scrolling = windata[current_win].scrolling;
199 struct rowdata *rowdata = windata[current_win].rowdata;
200
201 if (cursor >= nrdata)
202 return cursor;
203
204 display_show_unselection(current_win, cursor, rowdata[cursor].attr);
205 if (cursor > 0) {
206 if (cursor <= scrolling)
207 scrolling--;
208 cursor--;
209 }
210
211 windata[current_win].scrolling = scrolling;
212 windata[current_win].cursor = cursor;
213
214 return cursor;
215}
216
217static int display_set_row_data(int win, int line, void *data, int attr)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200218{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200219 struct rowdata *rowdata = windata[win].rowdata;
220
221 if (line >= windata[win].nrdata) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200222 rowdata = realloc(rowdata, sizeof(struct rowdata) * (line + 1));
223 if (!rowdata)
224 return -1;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200225 windata[win].nrdata = line + 1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200226 }
227
228 rowdata[line].data = data;
229 rowdata[line].attr = attr;
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200230 windata[win].rowdata = rowdata;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200231
232 return 0;
233}
234
Daniel Lezcanof6656822011-06-15 15:45:12 +0200235int display_reset_cursor(int win)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200236{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200237 windata[win].nrdata = 0;
Daniel Lezcanof6656822011-06-15 15:45:12 +0200238 werase(windata[win].pad);
239 return wmove(windata[win].pad, 0, 0);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200240}
241
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200242int display_print_line(int win, int line, char *str, int bold, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200243{
244 int attr = 0;
245
Amit Arora031263a2010-11-09 11:12:41 +0530246 if (bold)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200247 attr |= WA_BOLD;
248
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200249 if (line == windata[win].cursor)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200250 attr |= WA_STANDOUT;
251
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200252 if (display_set_row_data(win, line, data, attr))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200253 return -1;
254
255 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200256 wattron(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200257
Daniel Lezcanof6656822011-06-15 15:45:12 +0200258 wprintw(windata[win].pad, "%s\n", str);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200259
260 if (attr)
Daniel Lezcanof6656822011-06-15 15:45:12 +0200261 wattroff(windata[win].pad, attr);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200262
263 return 0;
264}
265
Daniel Lezcanodb145802011-06-21 00:57:08 +0200266static int display_keystroke(int fd, void *data)
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200267{
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200268 int keystroke = getch();
269
270 switch (keystroke) {
271
272 case KEY_RIGHT:
273 case '\t':
274 display_next_panel();
275 break;
276
277 case KEY_LEFT:
278 case KEY_BTAB:
279 display_prev_panel();
280 break;
281
282 case KEY_DOWN:
283 display_next_line();
284 break;
285
286 case KEY_UP:
287 display_prev_line();
288 break;
289
290 case '\r':
291 display_select();
292 break;
293
294 case EOF:
295 case 'q':
296 case 'Q':
297 return 1;
298
299 case 'r':
300 case 'R':
Daniel Lezcanodb145802011-06-21 00:57:08 +0200301 /* refresh will be done after */
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200302 break;
Daniel Lezcanodb145802011-06-21 00:57:08 +0200303 default:
304 return 0;
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200305 }
306
Daniel Lezcanodb145802011-06-21 00:57:08 +0200307 display_refresh(current_win);
308
309 return 0;
310}
311
312int display_init(int wdefault)
313{
314 int i;
315 size_t array_size = sizeof(windata) / sizeof(windata[0]);
316
317 current_win = wdefault;
318
319 if (mainloop_add(0, display_keystroke, NULL))
320 return -1;
321
322 if (!initscr())
323 return -1;
324
325 start_color();
326 use_default_colors();
327
328 keypad(stdscr, TRUE);
329 noecho();
330 cbreak();
331 curs_set(0);
332 nonl();
333
334 if (init_pair(PT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK) ||
335 init_pair(PT_COLOR_ERROR, COLOR_BLACK, COLOR_RED) ||
336 init_pair(PT_COLOR_HEADER_BAR, COLOR_WHITE, COLOR_BLACK) ||
337 init_pair(PT_COLOR_YELLOW, COLOR_WHITE, COLOR_YELLOW) ||
338 init_pair(PT_COLOR_GREEN, COLOR_WHITE, COLOR_GREEN) ||
339 init_pair(PT_COLOR_BRIGHT, COLOR_WHITE, COLOR_BLACK) ||
340 init_pair(PT_COLOR_BLUE, COLOR_WHITE, COLOR_BLUE) ||
341 init_pair(PT_COLOR_RED, COLOR_WHITE, COLOR_RED))
342 return -1;
343
344 if (atexit(display_fini))
345 return -1;
346
347 getmaxyx(stdscr, maxy, maxx);
348
349 for (i = 0; i < array_size; i++) {
350
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200351 main_win = subwin(stdscr, maxy - 2, maxx, 1, 0);
352 if (!main_win)
Daniel Lezcanodb145802011-06-21 00:57:08 +0200353 return -1;
354
355 windata[i].pad = newpad(maxrows, maxx);
356 if (!windata[i].pad)
357 return -1;
358
359 }
360
361 header_win = subwin(stdscr, 1, maxx, 0, 0);
362 if (!header_win)
363 return -1;
364
365 footer_win = subwin(stdscr, 1, maxx, maxy-1, 0);
366 if (!footer_win)
367 return -1;
368
369 if (show_header_footer(wdefault))
370 return -1;
371
372 return display_refresh(wdefault);
373}
374
375void print_regulator_header(void)
376{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200377 werase(main_win);
378 wattron(main_win, A_BOLD);
379 print(main_win, 0, 0, "Name");
380 print(main_win, 12, 0, "Status");
381 print(main_win, 24, 0, "State");
382 print(main_win, 36, 0, "Type");
383 print(main_win, 48, 0, "Users");
384 print(main_win, 60, 0, "Microvolts");
385 print(main_win, 72, 0, "Min u-volts");
386 print(main_win, 84, 0, "Max u-volts");
387 wattroff(main_win, A_BOLD);
388 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200389
390 show_header_footer(REGULATOR);
391}
392
393void print_clock_header(void)
394{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200395 werase(main_win);
396 wattron(main_win, A_BOLD);
397 print(main_win, 0, 0, "Name");
398 print(main_win, 56, 0, "Flags");
399 print(main_win, 75, 0, "Rate");
400 print(main_win, 88, 0, "Usecount");
401 print(main_win, 98, 0, "Children");
402 wattroff(main_win, A_BOLD);
403 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200404
405 show_header_footer(CLOCK);
406}
407
408void print_sensor_header(void)
409{
Daniel Lezcanoc196d432011-06-21 00:57:08 +0200410 werase(main_win);
411 wattron(main_win, A_BOLD);
412 print(main_win, 0, 0, "Name");
413 print(main_win, 36, 0, "Value");
414 wattroff(main_win, A_BOLD);
415 wrefresh(main_win);
Daniel Lezcanodb145802011-06-21 00:57:08 +0200416
417 show_header_footer(SENSOR);
418}
419
420int display_register(int win, struct display_ops *ops)
421{
422 size_t array_size = sizeof(windata) / sizeof(windata[0]);
423
424 if (win < 0 || win >= array_size)
425 return -1;
426
427 windata[win].ops = ops;
428
Daniel Lezcano176e69d2011-06-15 15:45:12 +0200429 return 0;
430}