3 * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe )
5 * (c) Peter Dinda, 2011 (Scan code encoding)
11 #include <sys/ioctl.h>
20 #include <linux/keyboard.h>
24 static int use_curses = 0;
25 static int debug_enable = 0;
28 typedef enum { CONSOLE_CURS_SET = 1,
32 CONSOLE_RESOLUTION = 5 } console_op_t;
42 struct termios termios_old;
43 unsigned char old_kbd_mode;
50 } __attribute__((packed));
52 struct character_msg {
57 } __attribute__((packed));
61 } __attribute__((packed));
63 struct resolution_msg {
66 } __attribute__((packed));
72 struct cursor_msg cursor;
73 struct character_msg character;
74 struct scroll_msg scroll;
75 struct resolution_msg resolution;
77 } __attribute__((packed));
82 static int handle_char_set(struct character_msg * msg) {
86 fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
94 if ((c < ' ') || (c >= 127)) {
96 fprintf(stderr, "unexpected control character %d\n", c);
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)) {
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);
115 if ((msg->x == console.win->_maxx) &&
116 (msg->y == console.win->_maxy)) {
120 wattron(console.win, COLOR_PAIR(msg->style));
121 mvwaddch(console.win, msg->y, msg->x, c);
122 wattroff(console.win, COLOR_PAIR(msg->style));
125 //stdout text display
126 while (console.y < msg->y) {
132 while (console.x < msg->x) {
140 assert(console.x <= console.cols);
142 if (console.x == console.cols) {
152 int handle_curs_set(struct cursor_msg * msg) {
154 fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
158 /* nothing to do now, cursor is set before update to make sure it isn't
159 * affected by character_set
170 int handle_scroll(struct scroll_msg * msg) {
171 int lines = msg->lines;
174 fprintf(stderr, "scroll: %d lines\n", lines);
190 int handle_text_resolution(struct resolution_msg * msg) {
192 fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
196 console.rows = msg->rows;
197 console.cols = msg->cols;
202 int handle_update( void ) {
204 fprintf(stderr, "update\n");
209 if ( (console.x >= 0) && (console.y >= 0) &&
210 (console.x <= console.win->_maxx) &&
211 (console.y <= console.win->_maxy) ) {
213 wmove(console.win, console.y, console.x);
217 wrefresh(console.win);
224 int handle_console_msg(int cons_fd) {
228 ret = read(cons_fd, &msg, sizeof(struct cons_msg));
231 case CONSOLE_CURS_SET:
232 // printf("Console cursor set (x=%d, y=%d)\n", msg.cursor.x, msg.cursor.y);
233 handle_curs_set(&(msg.cursor));
235 case CONSOLE_CHAR_SET:
236 handle_char_set(&(msg.character));
237 /* printf("Console character set (x=%d, y=%d, c=%c, style=%c)\n",
238 msg.character.x, msg.character.y, msg.character.c, msg.character.style);*/
241 // printf("Console scroll (lines=%d)\n", msg.scroll.lines);
242 handle_scroll(&(msg.scroll));
245 // printf("Console update\n");
248 case CONSOLE_RESOLUTION:
249 handle_text_resolution(&(msg.resolution));
252 printf("Invalid console message operation (%d)\n", msg.op);
260 int send_key(int cons_fd, char scan_code) {
267 void handle_exit(void) {
268 if ( debug_enable ) {
269 fprintf(stderr, "Exiting from console terminal\n");
276 // tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
278 // ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
282 #define NO_KEY { 0, 0 }
285 unsigned char scan_code;
286 unsigned char capital;
289 static const struct key_code ascii_to_key_code[] = { // ASCII Value Serves as Index
290 NO_KEY, NO_KEY, {0x50, 0}, {0x48, 0}, // 0x00 - 0x03
291 {0x4B, 0}, {0x4D, 0}, NO_KEY, { 0x0E, 0 }, // 0x04 - 0x07
292 { 0x0E, 0 }, { 0x0F, 0 }, { 0x1C, 0 }, NO_KEY, // 0x08 - 0x0B
293 NO_KEY, { 0x1C, 0 }, NO_KEY, NO_KEY, // 0x0C - 0x0F
294 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x10 - 0x13
295 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x14 - 0x17
296 NO_KEY, NO_KEY, NO_KEY, { 0x01, 0 }, // 0x18 - 0x1B
297 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x1C - 0x1F
298 { 0x39, 0 }, { 0x02, 1 }, { 0x28, 1 }, { 0x04, 1 }, // 0x20 - 0x23
299 { 0x05, 1 }, { 0x06, 1 }, { 0x08, 1 }, { 0x28, 0 }, // 0x24 - 0x27
300 { 0x0A, 1 }, { 0x0B, 1 }, { 0x09, 1 }, { 0x0D, 1 }, // 0x28 - 0x2B
301 { 0x33, 0 }, { 0x0C, 0 }, { 0x34, 0 }, { 0x35, 0 }, // 0x2C - 0x2F
302 { 0x0B, 0 }, { 0x02, 0 }, { 0x03, 0 }, { 0x04, 0 }, // 0x30 - 0x33
303 { 0x05, 0 }, { 0x06, 0 }, { 0x07, 0 }, { 0x08, 0 }, // 0x34 - 0x37
304 { 0x09, 0 }, { 0x0A, 0 }, { 0x27, 1 }, { 0x27, 0 }, // 0x38 - 0x3B
305 { 0x33, 1 }, { 0x0D, 0 }, { 0x34, 1 }, { 0x35, 1 }, // 0x3C - 0x3F
306 { 0x03, 1 }, { 0x1E, 1 }, { 0x30, 1 }, { 0x2E, 1 }, // 0x40 - 0x43
307 { 0x20, 1 }, { 0x12, 1 }, { 0x21, 1 }, { 0x22, 1 }, // 0x44 - 0x47
308 { 0x23, 1 }, { 0x17, 1 }, { 0x24, 1 }, { 0x25, 1 }, // 0x48 - 0x4B
309 { 0x26, 1 }, { 0x32, 1 }, { 0x31, 1 }, { 0x18, 1 }, // 0x4C - 0x4F
310 { 0x19, 1 }, { 0x10, 1 }, { 0x13, 1 }, { 0x1F, 1 }, // 0x50 - 0x53
311 { 0x14, 1 }, { 0x16, 1 }, { 0x2F, 1 }, { 0x11, 1 }, // 0x54 - 0x57
312 { 0x2D, 1 }, { 0x15, 1 }, { 0x2C, 1 }, { 0x1A, 0 }, // 0x58 - 0x5B
313 { 0x2B, 0 }, { 0x1B, 0 }, { 0x07, 1 }, { 0x0C, 1 }, // 0x5C - 0x5F
314 { 0x29, 0 }, { 0x1E, 0 }, { 0x30, 0 }, { 0x2E, 0 }, // 0x60 - 0x63
315 { 0x20, 0 }, { 0x12, 0 }, { 0x21, 0 }, { 0x22, 0 }, // 0x64 - 0x67
316 { 0x23, 0 }, { 0x17, 0 }, { 0x24, 0 }, { 0x25, 0 }, // 0x68 - 0x6B
317 { 0x26, 0 }, { 0x32, 0 }, { 0x31, 0 }, { 0x18, 0 }, // 0x6C - 0x6F
318 { 0x19, 0 }, { 0x10, 0 }, { 0x13, 0 }, { 0x1F, 0 }, // 0x70 - 0x73
319 { 0x14, 0 }, { 0x16, 0 }, { 0x2F, 0 }, { 0x11, 0 }, // 0x74 - 0x77
320 { 0x2D, 0 }, { 0x15, 0 }, { 0x2C, 0 }, { 0x1A, 1 }, // 0x78 - 0x7B
321 { 0x2B, 1 }, { 0x1B, 1 }, { 0x29, 1 }, { 0x0E, 0 } // 0x7C - 0x7F
326 #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)
328 int send_char_to_palacios_as_scancodes(int fd, unsigned char c)
333 fprintf(stderr,"key '%c'\n",c);
337 struct key_code k = ascii_to_key_code[c];
339 if (k.scan_code==0 && k.capital==0) {
341 fprintf(stderr,"Cannot send key '%c' to palacios as it maps to no scancode\n",c);
346 sc = 0x2a ; // left shift down
353 writeit(fd,sc); // key down
355 sc |= 0x80; // key up
369 fprintf(stderr,"Cannot send key '%c' to palacios because it is >=0x80\n",c);
378 #define MIN_TTY_COLS 80
379 #define MIN_TTY_ROWS 25
380 int check_terminal_size (void)
382 unsigned short n_cols = 0;
383 unsigned short n_rows = 0;
384 struct winsize winsz;
386 ioctl (fileno(stdin), TIOCGWINSZ, &winsz);
387 n_cols = winsz.ws_col;
388 n_rows = winsz.ws_row;
390 if (n_cols < MIN_TTY_COLS || n_rows < MIN_TTY_ROWS) {
391 printf ("Your window is not large enough.\n");
392 printf ("It must be at least %dx%d, but yours is %dx%d\n",
393 MIN_TTY_COLS, MIN_TTY_ROWS, n_cols, n_rows);
408 for (i = 0; i < 0x100; i++) {
409 init_pair(i, i & 0xf, (i >> 4) & 0xf);
414 int main(int argc, char* argv[]) {
417 char * vm_dev = NULL;
418 struct termios termios;
423 printf("usage: v3_cons_sc <vm_device>\n");
427 /* Check for minimum Terminal size at start */
428 if (0 != check_terminal_size()) {
429 printf ("Error: terminal too small!\n");
435 vm_fd = open(vm_dev, O_RDONLY);
438 printf("Error opening VM device: %s\n", vm_dev);
442 cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL);
444 /* Close the file descriptor. */
448 printf("Error opening stream Console\n");
452 tcgetattr(STDIN_FILENO, &console.termios_old);
461 console.win = initscr();
463 if (console.win == NULL) {
464 fprintf(stderr, "Error initialization curses screen\n");
468 scrollok(console.win, 1);
475 termios = console.termios_old;
476 termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
477 termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK);
478 //termios.c_iflag &= ~(ICRNL | INLCR );
480 // termios.c_iflag |= SCANCODES;
481 // termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
482 //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
483 termios.c_lflag &= ~(ICANON | ECHO);
485 termios.c_cc[VMIN] = 1;
486 termios.c_cc[VTIME] = 0;
488 tcflush(STDIN_FILENO, TCIFLUSH);
489 tcsetattr(STDIN_FILENO, TCSANOW, &termios);
495 keypad(console.win, TRUE);
497 //ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
505 FD_SET(cons_fd, &rset);
506 FD_SET(STDIN_FILENO, &rset);
508 ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
510 // printf("Returned from select...\n");
514 } else if (ret == -1) {
515 perror("Select returned error...\n");
519 if (FD_ISSET(cons_fd, &rset)) {
520 if (handle_console_msg(cons_fd) == -1) {
521 printf("Console Error\n");
526 if (FD_ISSET(STDIN_FILENO, &rset)) {
527 unsigned char key = getch();
529 if (key == '\\') { // ESC
531 } else if (key == '`') {
532 unsigned char sc = 0x44; // F10
536 } else if (key == '~') { // CTRL-C
538 sc = 0x1d; // left ctrl down
542 sc = 0x2e | 0x80; // c up
544 sc = 0x1d | 0x80; // left ctrl up
547 if (send_char_to_palacios_as_scancodes(cons_fd,key)) {
548 printf("Error sending key to console\n");
558 printf("Console terminated\n");