3 * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe )
10 #include <sys/ioctl.h>
19 #include <linux/keyboard.h>
23 static int use_curses = 0;
24 static int debug_enable = 1;
27 typedef enum { CONSOLE_CURS_SET = 1,
31 CONSOLE_RESOLUTION = 5 } console_op_t;
41 struct termios termios_old;
42 unsigned char old_kbd_mode;
49 } __attribute__((packed));
51 struct character_msg {
56 } __attribute__((packed));
60 } __attribute__((packed));
62 struct resolution_msg {
65 } __attribute__((packed));
71 struct cursor_msg cursor;
72 struct character_msg character;
73 struct scroll_msg scroll;
74 struct resolution_msg resolution;
76 } __attribute__((packed));
81 static int handle_char_set(struct character_msg * msg) {
85 fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
93 if ((c < ' ') || (c >= 127)) {
94 fprintf(stderr, "unexpected control character %d\n", c);
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)) {
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);
109 if ((msg->x == console.win->_maxx) &&
110 (msg->y == console.win->_maxy)) {
114 mvwaddch(console.win, msg->y, msg->x, c);
117 //stdout text display
118 while (console.y < msg->y) {
124 while (console.x < msg->x) {
132 assert(console.x <= console.cols);
134 if (console.x == console.cols) {
144 int handle_curs_set(struct cursor_msg * msg) {
146 fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
150 /* nothing to do now, cursor is set before update to make sure it isn't
151 * affected by character_set
162 int handle_scroll(struct scroll_msg * msg) {
163 int lines = msg->lines;
166 fprintf(stderr, "scroll: %d lines\n", lines);
182 int handle_text_resolution(struct resolution_msg * msg) {
184 fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
188 console.rows = msg->rows;
189 console.cols = msg->cols;
194 int handle_update( void ) {
196 fprintf(stderr, "update\n");
201 if ( (console.x >= 0) && (console.y >= 0) &&
202 (console.x <= console.win->_maxx) &&
203 (console.y <= console.win->_maxy) ) {
205 wmove(console.win, console.y, console.x);
209 wrefresh(console.win);
216 int handle_console_msg(int cons_fd) {
220 ret = read(cons_fd, &msg, sizeof(struct cons_msg));
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));
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);*/
233 // printf("Console scroll (lines=%d)\n", msg.scroll.lines);
234 handle_scroll(&(msg.scroll));
237 // printf("Console update\n");
240 case CONSOLE_RESOLUTION:
241 handle_text_resolution(&(msg.resolution));
244 printf("Invalid console message operation (%d)\n", msg.op);
252 int send_key(int cons_fd, char scan_code) {
259 void handle_exit(void) {
260 fprintf(stderr, "Exiting from console terminal\n");
266 // tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
268 // ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
272 #define NO_KEY { 0, 0 }
275 unsigned char scan_code;
276 unsigned char capital;
279 static const struct key_code ascii_to_key_code[] = { // ASCII Value Serves as Index
280 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x00 - 0x03
281 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x04 - 0x07
282 { 0x0E, 0 }, { 0x0F, 0 }, { 0x1C, 0 }, NO_KEY, // 0x08 - 0x0B
283 NO_KEY, { 0x1C, 0 }, NO_KEY, NO_KEY, // 0x0C - 0x0F
284 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x10 - 0x13
285 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x14 - 0x17
286 NO_KEY, NO_KEY, NO_KEY, { 0x01, 0 }, // 0x18 - 0x1B
287 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x1C - 0x1F
288 { 0x39, 0 }, { 0x02, 1 }, { 0x28, 1 }, { 0x04, 1 }, // 0x20 - 0x23
289 { 0x05, 1 }, { 0x06, 1 }, { 0x08, 1 }, { 0x28, 0 }, // 0x24 - 0x27
290 { 0x0A, 1 }, { 0x0B, 1 }, { 0x09, 1 }, { 0x0D, 1 }, // 0x28 - 0x2B
291 { 0x33, 0 }, { 0x0C, 0 }, { 0x34, 0 }, { 0x35, 0 }, // 0x2C - 0x2F
292 { 0x0B, 0 }, { 0x02, 0 }, { 0x03, 0 }, { 0x04, 0 }, // 0x30 - 0x33
293 { 0x05, 0 }, { 0x06, 0 }, { 0x07, 0 }, { 0x08, 0 }, // 0x34 - 0x37
294 { 0x09, 0 }, { 0x0A, 0 }, { 0x27, 1 }, { 0x27, 0 }, // 0x38 - 0x3B
295 { 0x33, 1 }, { 0x0D, 0 }, { 0x34, 1 }, { 0x35, 1 }, // 0x3C - 0x3F
296 { 0x03, 1 }, { 0x1E, 1 }, { 0x30, 1 }, { 0x2E, 1 }, // 0x40 - 0x43
297 { 0x20, 1 }, { 0x12, 1 }, { 0x21, 1 }, { 0x22, 1 }, // 0x44 - 0x47
298 { 0x23, 1 }, { 0x17, 1 }, { 0x24, 1 }, { 0x25, 1 }, // 0x48 - 0x4B
299 { 0x26, 1 }, { 0x32, 1 }, { 0x31, 1 }, { 0x18, 1 }, // 0x4C - 0x4F
300 { 0x19, 1 }, { 0x10, 1 }, { 0x13, 1 }, { 0x1F, 1 }, // 0x50 - 0x53
301 { 0x14, 1 }, { 0x16, 1 }, { 0x2F, 1 }, { 0x11, 1 }, // 0x54 - 0x57
302 { 0x2D, 1 }, { 0x15, 1 }, { 0x2C, 1 }, { 0x1A, 0 }, // 0x58 - 0x5B
303 { 0x2B, 0 }, { 0x1B, 0 }, { 0x07, 1 }, { 0x0C, 1 }, // 0x5C - 0x5F
304 { 0x29, 0 }, { 0x1E, 0 }, { 0x30, 0 }, { 0x2E, 0 }, // 0x60 - 0x63
305 { 0x20, 0 }, { 0x12, 0 }, { 0x21, 0 }, { 0x22, 0 }, // 0x64 - 0x67
306 { 0x23, 0 }, { 0x17, 0 }, { 0x24, 0 }, { 0x25, 0 }, // 0x68 - 0x6B
307 { 0x26, 0 }, { 0x32, 0 }, { 0x31, 0 }, { 0x18, 0 }, // 0x6C - 0x6F
308 { 0x19, 0 }, { 0x10, 0 }, { 0x13, 0 }, { 0x1F, 0 }, // 0x70 - 0x73
309 { 0x14, 0 }, { 0x16, 0 }, { 0x2F, 0 }, { 0x11, 0 }, // 0x74 - 0x77
310 { 0x2D, 0 }, { 0x15, 0 }, { 0x2C, 0 }, { 0x1A, 1 }, // 0x78 - 0x7B
311 { 0x2B, 1 }, { 0x1B, 1 }, { 0x29, 1 }, { 0x0E, 0 } // 0x7C - 0x7F
316 #define writeit(fd,c) do { fprintf(stderr,"scancode 0x%x\n",(c)); if (write((fd),&(c),1)!=1) { return -1; } } while (0)
318 int send_char_to_palacios_as_scancodes(int fd, unsigned char c)
322 fprintf(stderr,"key '%c'\n",c);
325 struct key_code k = ascii_to_key_code[c];
327 if (k.scan_code==0 && k.capital==0) {
328 fprintf(stderr,"Cannot send key '%c' to palacios as it maps to no scancode\n",c);
332 sc = 0x2a ; // left shift down
339 writeit(fd,sc); // key down
341 sc |= 0x80; // key up
354 fprintf(stderr,"Cannot send key '%c' to palacios because it is >=0x80\n",c);
357 /* case 0xffe1: //left shift */
358 /* scancode = 0x2a; */
361 /* case 0xffe2: //right shift */
362 /* scancode = 0x36; */
365 /* case 0xffe3: //left ctrl */
366 /* case 0xffe4: //right ctrl */
367 /* scancode = 0x1d; // translated as left ctrl */
370 /* case 0xffe7: //left meta */
371 /* case 0xffe8: //right meta */
372 /* case 0xffe9: //left alt */
373 /* case 0xffea: //right alt */
374 /* scancode = 0x38; // translated as a left alt */
377 /* case 0xff08: // backspace */
378 /* scancode = 0x0e; */
381 /* case 0xff09: // tab */
382 /* scancode = 0x0f; */
385 /* case 0xff0d: // return */
386 /* scancode = 0x1c; */
389 /* case 0xff1b: // escape */
390 /* scancode = 0x01; */
393 /* case 0xff63: // insert */
394 /* scancode = 0x52; */
397 /* case 0xffff: // delete */
398 /* scancode = 0x53; */
401 /* case 0xff50: // home */
402 /* scancode = 0x47; */
405 /* case 0xff57: // end */
406 /* scancode = 0x4f; */
409 /* case 0xff55: // pageup */
410 /* scancode = 0x49; */
413 /* case 0xff56: // pagedown */
414 /* scancode = 0x51; */
417 /* case 0xff51: // left */
418 /* scancode = 0x4b; */
421 /* case 0xff52: // up */
422 /* scancode = 0x48; */
425 /* case 0xff53: // right */
426 /* scancode = 0x4d; */
429 /* case 0xff54: // down */
430 /* scancode = 0x50; */
433 /* case 0xffbe: // f1 */
434 /* scancode = 0x3b; */
436 /* case 0xffbf: // f2 */
437 /* scancode = 0x3c; */
439 /* case 0xffc0: // f3 */
440 /* scancode = 0x3d; */
442 /* case 0xffc1: // f4 */
443 /* scancode = 0x3e; */
445 /* case 0xffc2: // f5 */
446 /* scancode = 0x3f; */
448 /* case 0xffc3: // f6 */
449 /* scancode = 0x40; */
451 /* case 0xffc4: // f7 */
452 /* scancode = 0x41; */
454 /* case 0xffc5: // f8 */
455 /* scancode = 0x42; */
457 /* case 0xffc6: // f9 */
458 /* scancode = 0x43; */
460 /* case 0xffc7: // f10 */
461 /* scancode = 0x44; */
463 /* case 0xffc8: // f11 */
464 /* scancode = 0x57; */
466 /* case 0xffc9: // f12 */
467 /* scancode = 0x58; */
473 /* fprintf(stderr,"Ignoring key 0x%x (down=%d)\n", key, down); */
477 /* if (scancode==0) { */
482 /* return scancode; */
488 int main(int argc, char* argv[]) {
491 char * vm_dev = NULL;
492 struct termios termios;
497 printf("Usage: ./v3_cons <vm_device>\n");
505 vm_fd = open(vm_dev, O_RDONLY);
508 printf("Error opening VM device: %s\n", vm_dev);
512 cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL);
514 /* Close the file descriptor. */
518 printf("Error opening stream Console\n");
522 tcgetattr(STDIN_FILENO, &console.termios_old);
531 console.win = initscr();
533 if (console.win == NULL) {
534 fprintf(stderr, "Error initialization curses screen\n");
538 scrollok(console.win, 1);
542 termios = console.termios_old;
543 termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
544 termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK);
545 //termios.c_iflag &= ~(ICRNL | INLCR );
547 // termios.c_iflag |= SCANCODES;
548 // termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
549 //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
550 termios.c_lflag &= ~(ICANON | ECHO);
552 termios.c_cc[VMIN] = 1;
553 termios.c_cc[VTIME] = 0;
555 tcflush(STDIN_FILENO, TCIFLUSH);
556 tcsetattr(STDIN_FILENO, TCSANOW, &termios);
562 keypad(console.win, TRUE);
564 //ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
572 FD_SET(cons_fd, &rset);
573 FD_SET(STDIN_FILENO, &rset);
575 ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
577 // printf("Returned from select...\n");
581 } else if (ret == -1) {
582 perror("Select returned error...\n");
586 if (FD_ISSET(cons_fd, &rset)) {
587 if (handle_console_msg(cons_fd) == -1) {
588 printf("Console Error\n");
593 if (FD_ISSET(STDIN_FILENO, &rset)) {
594 unsigned char key = getch();
596 if (key == '\\') { // ESC
598 } else if (key == '`') {
599 unsigned char sc = 0x44; // F10
604 if (send_char_to_palacios_as_scancodes(cons_fd,key)) {
605 fprintf(stderr, "Error sendign key to console\n");