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.


Cleaned up help messages for userspace utils
[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 int main(int argc, char* argv[]) {
376     int vm_fd;
377     int cons_fd;
378     char * vm_dev = NULL;
379     struct termios termios;
380
381     use_curses = 1;
382
383     if (argc < 2) {
384         printf("usage: v3_cons_sc <vm_device>\n");
385         return -1;
386     }
387
388     vm_dev = argv[1];
389
390     vm_fd = open(vm_dev, O_RDONLY);
391
392     if (vm_fd == -1) {
393         printf("Error opening VM device: %s\n", vm_dev);
394         return -1;
395     }
396
397     cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL); 
398
399     /* Close the file descriptor.  */ 
400     close(vm_fd); 
401
402     if (cons_fd < 0) {
403         printf("Error opening stream Console\n");
404         return -1;
405     }
406
407     tcgetattr(STDIN_FILENO, &console.termios_old);
408     atexit(handle_exit);
409
410     console.x = 0;
411     console.y = 0;
412
413
414     if (use_curses) {
415         gettmode();
416         console.win = initscr();
417         
418         if (console.win == NULL) {
419             fprintf(stderr, "Error initialization curses screen\n");
420             exit(-1);
421         }
422
423         scrollok(console.win, 1);
424
425         erase();
426     }
427
428     /*
429     termios = console.termios_old;
430     termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
431     termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK); 
432     //termios.c_iflag &= ~(ICRNL | INLCR );    
433
434     //  termios.c_iflag |= SCANCODES; 
435     //    termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 
436     //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
437     termios.c_lflag &= ~(ICANON | ECHO);
438
439     termios.c_cc[VMIN] = 1;
440     termios.c_cc[VTIME] = 0;
441
442     tcflush(STDIN_FILENO, TCIFLUSH);
443     tcsetattr(STDIN_FILENO, TCSANOW, &termios);
444     */    
445
446     raw();
447     cbreak();
448     noecho();
449     keypad(console.win, TRUE);
450
451     //ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
452
453     if (LINES<25 || COLS<80) { 
454         printf("Your window is not large enough.\nIt must be at least 80x25, but yours is %dx%d\n",COLS,LINES);
455         close(cons_fd);
456         exit(-1);
457     }
458     
459
460     while (1) {
461         int ret; 
462         int bytes_read = 0;
463         fd_set rset;
464
465         FD_ZERO(&rset);
466         FD_SET(cons_fd, &rset);
467         FD_SET(STDIN_FILENO, &rset);
468
469         ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
470         
471         //      printf("Returned from select...\n");
472
473         if (ret == 0) {
474             continue;
475         } else if (ret == -1) {
476             perror("Select returned error...\n");
477             return -1;
478         }
479
480         if (FD_ISSET(cons_fd, &rset)) {
481             if (handle_console_msg(cons_fd) == -1) {
482                 printf("Console Error\n");
483                 return -1;
484             }
485         }
486
487         if (FD_ISSET(STDIN_FILENO, &rset)) {
488             unsigned char key = getch();
489
490             if (key == '\\') { // ESC
491                 break;
492             } else if (key == '`') {
493                 unsigned char sc = 0x44; // F10
494                 writeit(cons_fd,sc);
495                 sc |= 0x80;
496                 writeit(cons_fd,sc);
497             } else if (key == '~') {  // CTRL-C 
498                 unsigned char sc;
499                 sc = 0x1d;  // left ctrl down
500                 writeit(cons_fd,sc);
501                 sc = 0x2e; // c down
502                 writeit(cons_fd,sc);
503                 sc = 0x2e | 0x80;   // c up
504                 writeit(cons_fd,sc);
505                 sc = 0x1d | 0x80;   // left ctrl up
506                 writeit(cons_fd,sc);
507             } else {
508                 if (send_char_to_palacios_as_scancodes(cons_fd,key)) {
509                     printf("Error sending key to console\n");
510                     return -1;
511                 }
512             }
513             
514         }
515     } 
516
517     erase();
518
519     printf("Console terminated\n");
520
521     close(cons_fd);
522
523     return 0; 
524 }
525
526