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.


6d7e5229572d5dbcaf074c888ff0003af7057c37
[palacios.git] / linux_usr / v3_cons_sc.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  * (c) Peter Dinda, 2011 (Scan code encoding)
6  */
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/ioctl.h> 
12 #include <errno.h>
13 #include <assert.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <curses.h>
18 #include <termios.h>
19 #include <linux/kd.h>
20 #include <linux/keyboard.h>
21
22 #include "v3_ctrl.h"
23
24 static int use_curses = 0;
25 static int debug_enable = 0;
26
27
28 typedef enum { CONSOLE_CURS_SET = 1,
29                CONSOLE_CHAR_SET = 2,
30                CONSOLE_SCROLL = 3,
31                CONSOLE_UPDATE = 4,
32                CONSOLE_RESOLUTION = 5 } console_op_t;
33
34
35
36 static struct {
37     WINDOW * win;
38     int x;
39     int y;
40     int rows;
41     int cols;
42     struct termios termios_old;
43     unsigned char old_kbd_mode;
44 } console;
45
46
47 struct cursor_msg {
48     int x;
49     int y;
50 } __attribute__((packed));
51
52 struct character_msg {
53     int x;
54     int y;
55     char c;
56     unsigned char style;
57 } __attribute__((packed));
58
59 struct scroll_msg {
60     int lines;
61 } __attribute__((packed));
62
63 struct resolution_msg {
64     int cols;
65     int rows;
66 } __attribute__((packed));
67
68
69 struct cons_msg {
70     unsigned char op;
71     union {
72         struct cursor_msg cursor;
73         struct character_msg  character;
74         struct scroll_msg scroll;
75         struct resolution_msg resolution;
76     };
77 } __attribute__((packed)); 
78
79
80
81
82 static int handle_char_set(struct character_msg * msg) {
83     char c = msg->c;
84
85     if (debug_enable) {
86         fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
87     }
88
89     if (c == 0) {
90         c = ' ';
91     }
92
93
94     if ((c < ' ') || (c >= 127)) {
95         if (debug_enable) { 
96             fprintf(stderr, "unexpected control character %d\n", c);
97         }
98         c = '?';
99     }
100
101     if (use_curses) {
102         /* clip whatever falls outside the visible area to avoid errors */
103         if ((msg->x < 0) || (msg->y < 0) ||
104             (msg->x > console.win->_maxx) || 
105             (msg->y > console.win->_maxy)) {
106
107             if (debug_enable) { 
108                 fprintf(stderr, "Char out of range (x=%d,y=%d) MAX:(x=%d,y=%d)\n",
109                         msg->x, msg->y, console.win->_maxx, console.win->_maxy);
110             }
111
112             return -1;
113         }
114
115         if ((msg->x == console.win->_maxx) &&
116             (msg->y == console.win->_maxy)) {
117             return -1;
118         }
119
120         mvwaddch(console.win, msg->y, msg->x, c);
121
122     } else {
123         //stdout text display
124         while (console.y < msg->y) {
125             printf("\n");
126             console.x = 0;
127             console.y++;
128         }
129
130         while (console.x < msg->x) {
131             printf(" ");
132             console.x++;
133         }
134
135         printf("%c", c);
136         console.x++;
137
138         assert(console.x <= console.cols); 
139
140         if (console.x == console.cols) {
141             printf("\n");
142             console.x = 0;
143             console.y++;
144         }
145     }
146
147     return 0;
148 }
149
150 int handle_curs_set(struct cursor_msg * msg) {
151     if (debug_enable) {
152         fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
153     }
154
155     if (use_curses) {
156         /* nothing to do now, cursor is set before update to make sure it isn't 
157          * affected by character_set
158          */
159
160         console.x = msg->x;
161         console.y = msg->y;
162     }
163     
164     return 0;
165 }
166
167
168 int handle_scroll(struct scroll_msg * msg) {
169     int lines = msg->lines;
170
171     if (debug_enable) {
172         fprintf(stderr, "scroll: %d lines\n", lines);
173     }
174
175
176     assert(lines >= 0);
177
178     if (use_curses) {
179         while (lines > 0) {
180             scroll(console.win);
181             lines--;
182         }
183     } else {
184         console.y -= lines;     
185     }
186 }
187
188 int handle_text_resolution(struct resolution_msg * msg) {
189     if (debug_enable) {
190         fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
191     }
192
193
194     console.rows = msg->rows;
195     console.cols = msg->cols;
196
197     return 0;
198 }
199
200 int handle_update( void ) {
201     if (debug_enable) {
202         fprintf(stderr, "update\n");
203     }    
204
205     if (use_curses) {
206
207         if ( (console.x >= 0) && (console.y >= 0) &&
208              (console.x <= console.win->_maxx) &&
209              (console.y <= console.win->_maxy) ) {
210
211             wmove(console.win, console.y, console.x);
212
213         }
214
215         wrefresh(console.win);
216     } else {
217         fflush(stdout);
218     }
219 }
220
221
222 int handle_console_msg(int cons_fd) {
223     int ret = 0;
224     struct cons_msg msg;
225
226     ret = read(cons_fd, &msg, sizeof(struct cons_msg));
227
228     switch (msg.op) {
229         case CONSOLE_CURS_SET:
230             //      printf("Console cursor set (x=%d, y=%d)\n", msg.cursor.x, msg.cursor.y);
231             handle_curs_set(&(msg.cursor));
232             break;
233         case CONSOLE_CHAR_SET:
234             handle_char_set(&(msg.character));
235             /*      printf("Console character set (x=%d, y=%d, c=%c, style=%c)\n", 
236               msg.character.x, msg.character.y, msg.character.c, msg.character.style);*/
237             break;
238         case CONSOLE_SCROLL:
239             //  printf("Console scroll (lines=%d)\n", msg.scroll.lines);
240             handle_scroll(&(msg.scroll));
241             break;
242         case CONSOLE_UPDATE:
243             // printf("Console update\n");
244             handle_update();
245             break;
246         case CONSOLE_RESOLUTION:
247             handle_text_resolution(&(msg.resolution));
248             break;
249         default:
250             printf("Invalid console message operation (%d)\n", msg.op);
251             break;
252     }
253
254     return 0;
255 }
256
257
258 int send_key(int cons_fd, char scan_code) {
259
260     return 0;
261 }
262
263
264
265 void handle_exit(void) {
266     if ( debug_enable ) {
267         fprintf(stderr, "Exiting from console terminal\n");
268     }
269
270     if (use_curses) {
271         endwin();
272     }
273
274     //    tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
275
276     // ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
277 }
278
279
280 #define NO_KEY { 0, 0 }
281
282 struct key_code {
283     unsigned char scan_code;
284     unsigned char capital;
285 };
286
287 static const struct key_code ascii_to_key_code[] = {             // ASCII Value Serves as Index
288     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x00 - 0x03
289     NO_KEY,         NO_KEY,         NO_KEY,         { 0x0E, 0 }, // 0x04 - 0x07
290     { 0x0E, 0 },    { 0x0F, 0 },    { 0x1C, 0 },    NO_KEY,      // 0x08 - 0x0B
291     NO_KEY,         { 0x1C, 0 },    NO_KEY,         NO_KEY,      // 0x0C - 0x0F
292     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x10 - 0x13
293     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x14 - 0x17
294     NO_KEY,         NO_KEY,         NO_KEY,         { 0x01, 0 }, // 0x18 - 0x1B
295     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x1C - 0x1F
296     { 0x39, 0 },    { 0x02, 1 },    { 0x28, 1 },    { 0x04, 1 }, // 0x20 - 0x23
297     { 0x05, 1 },    { 0x06, 1 },    { 0x08, 1 },    { 0x28, 0 }, // 0x24 - 0x27
298     { 0x0A, 1 },    { 0x0B, 1 },    { 0x09, 1 },    { 0x0D, 1 }, // 0x28 - 0x2B
299     { 0x33, 0 },    { 0x0C, 0 },    { 0x34, 0 },    { 0x35, 0 }, // 0x2C - 0x2F
300     { 0x0B, 0 },    { 0x02, 0 },    { 0x03, 0 },    { 0x04, 0 }, // 0x30 - 0x33
301     { 0x05, 0 },    { 0x06, 0 },    { 0x07, 0 },    { 0x08, 0 }, // 0x34 - 0x37
302     { 0x09, 0 },    { 0x0A, 0 },    { 0x27, 1 },    { 0x27, 0 }, // 0x38 - 0x3B
303     { 0x33, 1 },    { 0x0D, 0 },    { 0x34, 1 },    { 0x35, 1 }, // 0x3C - 0x3F
304     { 0x03, 1 },    { 0x1E, 1 },    { 0x30, 1 },    { 0x2E, 1 }, // 0x40 - 0x43
305     { 0x20, 1 },    { 0x12, 1 },    { 0x21, 1 },    { 0x22, 1 }, // 0x44 - 0x47
306     { 0x23, 1 },    { 0x17, 1 },    { 0x24, 1 },    { 0x25, 1 }, // 0x48 - 0x4B
307     { 0x26, 1 },    { 0x32, 1 },    { 0x31, 1 },    { 0x18, 1 }, // 0x4C - 0x4F
308     { 0x19, 1 },    { 0x10, 1 },    { 0x13, 1 },    { 0x1F, 1 }, // 0x50 - 0x53
309     { 0x14, 1 },    { 0x16, 1 },    { 0x2F, 1 },    { 0x11, 1 }, // 0x54 - 0x57
310     { 0x2D, 1 },    { 0x15, 1 },    { 0x2C, 1 },    { 0x1A, 0 }, // 0x58 - 0x5B
311     { 0x2B, 0 },    { 0x1B, 0 },    { 0x07, 1 },    { 0x0C, 1 }, // 0x5C - 0x5F
312     { 0x29, 0 },    { 0x1E, 0 },    { 0x30, 0 },    { 0x2E, 0 }, // 0x60 - 0x63
313     { 0x20, 0 },    { 0x12, 0 },    { 0x21, 0 },    { 0x22, 0 }, // 0x64 - 0x67
314     { 0x23, 0 },    { 0x17, 0 },    { 0x24, 0 },    { 0x25, 0 }, // 0x68 - 0x6B
315     { 0x26, 0 },    { 0x32, 0 },    { 0x31, 0 },    { 0x18, 0 }, // 0x6C - 0x6F
316     { 0x19, 0 },    { 0x10, 0 },    { 0x13, 0 },    { 0x1F, 0 }, // 0x70 - 0x73
317     { 0x14, 0 },    { 0x16, 0 },    { 0x2F, 0 },    { 0x11, 0 }, // 0x74 - 0x77
318     { 0x2D, 0 },    { 0x15, 0 },    { 0x2C, 0 },    { 0x1A, 1 }, // 0x78 - 0x7B
319     { 0x2B, 1 },    { 0x1B, 1 },    { 0x29, 1 },    { 0x0E, 0 }  // 0x7C - 0x7F
320 };
321
322
323
324 #define writeit(fd,c)  do { if (debug_enable) { fprintf(stderr,"scancode 0x%x\n",(c));} if (write((fd),&(c),1)!=1) { return -1; } } while (0)
325
326 int send_char_to_palacios_as_scancodes(int fd, unsigned char c)
327 {
328     unsigned char sc;
329
330     if (debug_enable) {
331         fprintf(stderr,"key '%c'\n",c);
332     }
333
334     if (c<0x80) { 
335         struct key_code k = ascii_to_key_code[c];
336         
337         if (k.scan_code==0 && k.capital==0) { 
338             if (debug_enable) { 
339                 fprintf(stderr,"Cannot send key '%c' to palacios as it maps to no scancode\n",c);
340             }
341         } else {
342             if (k.capital) { 
343                 //shift down
344                 sc = 0x2a ; // left shift down
345                 writeit(fd,sc);
346             }
347             
348             
349             sc = k.scan_code;
350             
351             writeit(fd,sc);  // key down
352             
353             sc |= 0x80;      // key up
354             
355             writeit(fd,sc);
356             
357             if (k.capital) { 
358                 sc = 0x2a | 0x80;
359                 writeit(fd,sc);
360             }
361         }
362             
363     } else {
364
365         
366         if (debug_enable) { 
367             fprintf(stderr,"Cannot send key '%c' to palacios because it is >=0x80\n",c);
368         }
369
370         
371     }
372     return 0;
373 }
374
375
376 #define MIN_TTY_COLS  80
377 #define MIN_TTY_ROWS  25
378 int check_terminal_size (void)
379 {
380     unsigned short n_cols = 0;
381     unsigned short n_rows = 0;
382     struct winsize winsz; 
383
384     ioctl (fileno(stdin), TIOCGWINSZ, &winsz);
385     n_cols = winsz.ws_col;
386     n_rows = winsz.ws_row;
387
388     if (n_cols < MIN_TTY_COLS || n_rows < MIN_TTY_ROWS) {
389         printf ("Your window is not large enough.\n");
390         printf ("It must be at least %dx%d, but yours is %dx%d\n",
391                 MIN_TTY_COLS, MIN_TTY_ROWS, n_cols, n_rows);
392     return (-1);
393     }
394
395     /* SUCCESS */
396     return (0);
397 }
398
399
400 int main(int argc, char* argv[]) {
401     int vm_fd;
402     int cons_fd;
403     char * vm_dev = NULL;
404     struct termios termios;
405
406     use_curses = 1;
407
408     if (argc < 2) {
409         printf("usage: v3_cons_sc <vm_device>\n");
410         return -1;
411     }
412
413     /* Check for minimum Terminal size at start */
414     if (0 != check_terminal_size()) {
415         printf ("Error: terminal too small!\n");
416         return -1;
417     }
418
419     vm_dev = argv[1];
420
421     vm_fd = open(vm_dev, O_RDONLY);
422
423     if (vm_fd == -1) {
424         printf("Error opening VM device: %s\n", vm_dev);
425         return -1;
426     }
427
428     cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL); 
429
430     /* Close the file descriptor.  */ 
431     close(vm_fd); 
432
433     if (cons_fd < 0) {
434         printf("Error opening stream Console\n");
435         return -1;
436     }
437
438     tcgetattr(STDIN_FILENO, &console.termios_old);
439     atexit(handle_exit);
440
441     console.x = 0;
442     console.y = 0;
443
444
445     if (use_curses) {
446         gettmode();
447         console.win = initscr();
448         
449         if (console.win == NULL) {
450             fprintf(stderr, "Error initialization curses screen\n");
451             exit(-1);
452         }
453
454         scrollok(console.win, 1);
455
456         erase();
457     }
458
459     /*
460     termios = console.termios_old;
461     termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
462     termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK); 
463     //termios.c_iflag &= ~(ICRNL | INLCR );    
464
465     //  termios.c_iflag |= SCANCODES; 
466     //    termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 
467     //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
468     termios.c_lflag &= ~(ICANON | ECHO);
469
470     termios.c_cc[VMIN] = 1;
471     termios.c_cc[VTIME] = 0;
472
473     tcflush(STDIN_FILENO, TCIFLUSH);
474     tcsetattr(STDIN_FILENO, TCSANOW, &termios);
475     */    
476
477     raw();
478     cbreak();
479     noecho();
480     keypad(console.win, TRUE);
481
482     //ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
483
484     while (1) {
485         int ret; 
486         int bytes_read = 0;
487         fd_set rset;
488
489         FD_ZERO(&rset);
490         FD_SET(cons_fd, &rset);
491         FD_SET(STDIN_FILENO, &rset);
492
493         ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
494         
495         //      printf("Returned from select...\n");
496
497         if (ret == 0) {
498             continue;
499         } else if (ret == -1) {
500             perror("Select returned error...\n");
501             return -1;
502         }
503
504         if (FD_ISSET(cons_fd, &rset)) {
505             if (handle_console_msg(cons_fd) == -1) {
506                 printf("Console Error\n");
507                 return -1;
508             }
509         }
510
511         if (FD_ISSET(STDIN_FILENO, &rset)) {
512             unsigned char key = getch();
513
514             if (key == '\\') { // ESC
515                 break;
516             } else if (key == '`') {
517                 unsigned char sc = 0x44; // F10
518                 writeit(cons_fd,sc);
519                 sc |= 0x80;
520                 writeit(cons_fd,sc);
521             } else if (key == '~') {  // CTRL-C 
522                 unsigned char sc;
523                 sc = 0x1d;  // left ctrl down
524                 writeit(cons_fd,sc);
525                 sc = 0x2e; // c down
526                 writeit(cons_fd,sc);
527                 sc = 0x2e | 0x80;   // c up
528                 writeit(cons_fd,sc);
529                 sc = 0x1d | 0x80;   // left ctrl up
530                 writeit(cons_fd,sc);
531             } else {
532                 if (send_char_to_palacios_as_scancodes(cons_fd,key)) {
533                     printf("Error sending key to console\n");
534                     return -1;
535                 }
536             }
537             
538         }
539     } 
540
541     erase();
542
543     printf("Console terminated\n");
544
545     close(cons_fd);
546
547     return 0; 
548 }
549
550