Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Avoid strict-aliasing related issues when compiling with optimization
[palacios.git] / linux_usr / v3_cons.c
1 /* 
2  * V3 Console utility
3  * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe )
4  * (c) Jack lange, 2010
5  */
6
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/ioctl.h> 
11 #include <errno.h>
12 #include <assert.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <curses.h>
17 #include <termios.h>
18 #include <linux/kd.h>
19 #include <linux/keyboard.h>
20
21 #include "v3_ctrl.h"
22
23 static int use_curses = 0;
24 static int debug_enable = 0;
25
26
27 typedef enum { CONSOLE_CURS_SET = 1,
28                CONSOLE_CHAR_SET = 2,
29                CONSOLE_SCROLL = 3,
30                CONSOLE_UPDATE = 4,
31                CONSOLE_RESOLUTION = 5 } console_op_t;
32
33
34
35 static struct {
36     WINDOW * win;
37     int x;
38     int y;
39     int rows;
40     int cols;
41     struct termios termios_old;
42     unsigned char old_kbd_mode;
43 } console;
44
45
46 struct cursor_msg {
47     int x;
48     int y;
49 } __attribute__((packed));
50
51 struct character_msg {
52     int x;
53     int y;
54     char c;
55     unsigned char style;
56 } __attribute__((packed));
57
58 struct scroll_msg {
59     int lines;
60 } __attribute__((packed));
61
62 struct resolution_msg {
63     int cols;
64     int rows;
65 } __attribute__((packed));
66
67
68 struct cons_msg {
69     unsigned char op;
70     union {
71         struct cursor_msg cursor;
72         struct character_msg  character;
73         struct scroll_msg scroll;
74         struct resolution_msg resolution;
75     };
76 } __attribute__((packed)); 
77
78
79
80
81 static int handle_char_set(struct character_msg * msg) {
82     char c = msg->c;
83
84     if (debug_enable) {
85         fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
86     }
87
88     if (c == 0) {
89         c = ' ';
90     }
91
92
93     if ((c < ' ') || (c >= 127)) {
94         fprintf(stderr, "unexpected control character %d\n", c);
95         c = '?';
96     }
97
98     if (use_curses) {
99         /* clip whatever falls outside the visible area to avoid errors */
100         if ((msg->x < 0) || (msg->y < 0) ||
101             (msg->x > console.win->_maxx) || 
102             (msg->y > console.win->_maxy)) {
103
104             fprintf(stderr, "Char out of range (x=%d,y=%d) MAX:(x=%d,y=%d)\n",
105                     msg->x, msg->y, console.win->_maxx, console.win->_maxy);
106             return -1;
107         }
108
109         if ((msg->x == console.win->_maxx) &&
110             (msg->y == console.win->_maxy)) {
111             return -1;
112         }
113
114         mvwaddch(console.win, msg->y, msg->x, c);
115
116     } else {
117         //stdout text display
118         while (console.y < msg->y) {
119             printf("\n");
120             console.x = 0;
121             console.y++;
122         }
123
124         while (console.x < msg->x) {
125             printf(" ");
126             console.x++;
127         }
128
129         printf("%c", c);
130         console.x++;
131
132         assert(console.x <= console.cols); 
133
134         if (console.x == console.cols) {
135             printf("\n");
136             console.x = 0;
137             console.y++;
138         }
139     }
140
141     return 0;
142 }
143
144 int handle_curs_set(struct cursor_msg * msg) {
145     if (debug_enable) {
146         fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
147     }
148
149     if (use_curses) {
150         /* nothing to do now, cursor is set before update to make sure it isn't 
151          * affected by character_set
152          */
153
154         console.x = msg->x;
155         console.y = msg->y;
156     }
157     
158     return 0;
159 }
160
161
162 int handle_scroll(struct scroll_msg * msg) {
163     int lines = msg->lines;
164
165     if (debug_enable) {
166         fprintf(stderr, "scroll: %d lines\n", lines);
167     }
168
169
170     assert(lines >= 0);
171
172     if (use_curses) {
173         while (lines > 0) {
174             scroll(console.win);
175             lines--;
176         }
177     } else {
178         console.y -= lines;     
179     }
180 }
181
182 int handle_text_resolution(struct resolution_msg * msg) {
183     if (debug_enable) {
184         fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
185     }
186
187
188     console.rows = msg->rows;
189     console.cols = msg->cols;
190
191     return 0;
192 }
193
194 int handle_update( void ) {
195     if (debug_enable) {
196         fprintf(stderr, "update\n");
197     }    
198
199     if (use_curses) {
200
201         if ( (console.x >= 0) && (console.y >= 0) &&
202              (console.x <= console.win->_maxx) &&
203              (console.y <= console.win->_maxy) ) {
204
205             wmove(console.win, console.y, console.x);
206
207         }
208
209         wrefresh(console.win);
210     } else {
211         fflush(stdout);
212     }
213 }
214
215
216 int handle_console_msg(int cons_fd) {
217     int ret = 0;
218     struct cons_msg msg;
219
220     ret = read(cons_fd, &msg, sizeof(struct cons_msg));
221
222     switch (msg.op) {
223         case CONSOLE_CURS_SET:
224             //      printf("Console cursor set (x=%d, y=%d)\n", msg.cursor.x, msg.cursor.y);
225             handle_curs_set(&(msg.cursor));
226             break;
227         case CONSOLE_CHAR_SET:
228             handle_char_set(&(msg.character));
229             /*      printf("Console character set (x=%d, y=%d, c=%c, style=%c)\n", 
230               msg.character.x, msg.character.y, msg.character.c, msg.character.style);*/
231             break;
232         case CONSOLE_SCROLL:
233             //  printf("Console scroll (lines=%d)\n", msg.scroll.lines);
234             handle_scroll(&(msg.scroll));
235             break;
236         case CONSOLE_UPDATE:
237             // printf("Console update\n");
238             handle_update();
239             break;
240         case CONSOLE_RESOLUTION:
241             handle_text_resolution(&(msg.resolution));
242             break;
243         default:
244             printf("Invalid console message operation (%d)\n", msg.op);
245             break;
246     }
247
248     return 0;
249 }
250
251
252 int send_key(int cons_fd, char scan_code) {
253
254     return 0;
255 }
256
257
258
259 void handle_exit(void) {
260     fprintf(stderr, "Exiting from console terminal\n");
261
262     if (use_curses) {
263         endwin();
264     }
265
266     tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
267
268     ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
269 }
270
271 int main(int argc, char* argv[]) {
272     int vm_fd;
273     int cons_fd;
274     char * vm_dev = NULL;
275     struct termios termios;
276
277     use_curses = 1;
278
279     if (argc < 2) {
280         printf("usage: v3_cons <vm_device>\nThis will only work when run from a real PC console!\n");
281         return -1;
282     }
283
284     vm_dev = argv[1];
285
286
287
288     vm_fd = open(vm_dev, O_RDONLY);
289
290     if (vm_fd == -1) {
291         printf("Error opening VM device: %s\n", vm_dev);
292         return -1;
293     }
294
295     cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL); 
296
297     /* Close the file descriptor.  */ 
298     close(vm_fd); 
299
300     if (cons_fd < 0) {
301         printf("Error opening stream Console\n");
302         return -1;
303     }
304
305     tcgetattr(STDIN_FILENO, &console.termios_old);
306     atexit(handle_exit);
307
308     console.x = 0;
309     console.y = 0;
310
311
312     if (use_curses) {
313         gettmode();
314         console.win = initscr();
315         
316         if (console.win == NULL) {
317             fprintf(stderr, "Error initialization curses screen\n");
318             exit(-1);
319         }
320
321         scrollok(console.win, 1);
322     }
323
324     /*
325     termios = console.termios_old;
326     termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
327     termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK); 
328     //termios.c_iflag &= ~(ICRNL | INLCR );    
329
330     //  termios.c_iflag |= SCANCODES; 
331     //    termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 
332     //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
333     termios.c_lflag &= ~(ICANON | ECHO);
334
335     termios.c_cc[VMIN] = 1;
336     termios.c_cc[VTIME] = 0;
337
338     tcflush(STDIN_FILENO, TCIFLUSH);
339     tcsetattr(STDIN_FILENO, TCSANOW, &termios);
340     */    
341
342     raw();
343         //cbreak();
344     noecho();
345     keypad(console.win, TRUE);
346
347     ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
348
349     while (1) {
350         int ret; 
351         int bytes_read = 0;
352         fd_set rset;
353
354         FD_ZERO(&rset);
355         FD_SET(cons_fd, &rset);
356         FD_SET(STDIN_FILENO, &rset);
357
358         ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
359         
360         //      printf("Returned from select...\n");
361
362         if (ret == 0) {
363             continue;
364         } else if (ret == -1) {
365             perror("Select returned error...\n");
366             return -1;
367         }
368
369         if (FD_ISSET(cons_fd, &rset)) {
370             if (handle_console_msg(cons_fd) == -1) {
371                 printf("Console Error\n");
372                 return -1;
373             }
374         }
375
376         if (FD_ISSET(STDIN_FILENO, &rset)) {
377             unsigned char key = getch();
378
379             if (key == 0x01) { // ESC
380                 break;
381             }
382
383             if (write(cons_fd, &key, 1) != 1) {
384                 fprintf(stderr, "ERrror sendign key to console\n");
385                 return -1;
386             }
387             
388         }
389     } 
390
391     close(cons_fd);
392
393     return 0; 
394 }
395
396