1 /* $NetBSD: tipsy.c,v 1.2 2010/02/18 16:14:55 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Experimental proof-of-concept program: 30 * 31 * tip-on-booze. Uses rump kernel for ucom driver + underlying 32 * hardware. Just shovels bits back and forth between the user 33 * terminal and the ucom device. 34 * 35 * Seems to drop an occasional character for output here and there. 36 * Haven't pinpointed the problem yet. It happens commonly for certain 37 * patterns such as ctrl-U followed by immediate typing. Tipsy is quite 38 * sober despite this "feature". 39 */ 40 41 #include <sys/types.h> 42 #include <sys/ioctl.h> 43 44 #include <rump/rump.h> 45 #include <rump/rump_syscalls.h> 46 47 #include <err.h> 48 #include <errno.h> 49 #include <fcntl.h> 50 #include <pthread.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 #include <termios.h> 56 57 /* 58 * We use a shovel thread to get the bits from the rump kernel and 59 * print them on the terminal. The reason for a thread instead of 60 * polling is that we currently have no way to poll two fd's when 61 * they are in different kernels (stdin in the host, ucom in rump). 62 */ 63 static void * 64 shovel(void *arg) 65 { 66 char buf[64]; 67 ssize_t n; 68 int fd = (int)(intptr_t)arg; 69 70 for (;;) { 71 n = rump_sys_read(fd, buf, sizeof(buf)); 72 if (__predict_false(n <= 0)) { 73 if (n == 0) 74 errx(1, "ucom EOF"); 75 if (n == -1) 76 err(1, "ucom read"); 77 } 78 if (write(STDOUT_FILENO, buf, n) != n) 79 err(1, "write to console"); 80 } 81 } 82 83 int 84 main(int argc, char *argv[]) 85 { 86 pthread_t pt; 87 struct termios tios; 88 int probeonly = 0; 89 int com; 90 91 if (argc > 1) { 92 if (argc == 2 && strcmp(argv[1], "probe") == 0) { 93 probeonly = 1; 94 } else { 95 fprintf(stderr, "mind the usage\n"); 96 exit(1); 97 } 98 } 99 100 if (probeonly) 101 rump_boot_sethowto(RUMP_AB_VERBOSE); 102 rump_init(); 103 if (probeonly) { 104 pause(); 105 exit(0); 106 } 107 108 com = rump_sys_open("/dev/dtyU0", O_RDWR); 109 if (com == -1) 110 err(1, "rump ucom open failed"); 111 112 /* 113 * Setup the com port. You might need to tweak this. 114 */ 115 if (rump_sys_ioctl(com, TIOCGETA, &tios) == -1) 116 err(1, "rump get term"); 117 tios.c_cflag &= ~(CSIZE|PARENB); 118 tios.c_cflag |= CS8; 119 tios.c_cflag |= CLOCAL; 120 tios.c_iflag &= ~(ISTRIP|ICRNL); 121 tios.c_oflag &= ~OPOST; 122 tios.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO); 123 tios.c_cc[VMIN] = 1; 124 tios.c_cc[VTIME] = 0; 125 if (rump_sys_ioctl(com, TIOCSETA, &tios) == -1) 126 err(1, "rump set term"); 127 128 /* setup stdin */ 129 if (tcgetattr(STDIN_FILENO, &tios) == -1) 130 err(1, "host get term"); 131 tios.c_oflag &= ~OPOST; 132 tios.c_iflag &= ~(INPCK|ICRNL); 133 tios.c_lflag &= ~(ICANON|IEXTEN|ECHO); 134 tios.c_cc[VINTR] = tios.c_cc[VQUIT] = tios.c_cc[VSUSP] 135 = tios.c_cc[VDSUSP] = tios.c_cc[VDISCARD] = tios.c_cc[VREPRINT] 136 = tios.c_cc[VLNEXT] = _POSIX_VDISABLE; 137 tios.c_cc[VMIN] = 1; 138 tios.c_cc[VTIME] = 0; 139 if (tcsetattr(STDIN_FILENO, TCSADRAIN, &tios) == -1) 140 err(1, "host set term"); 141 142 if (pthread_create(&pt, NULL, shovel, (void *)(intptr_t)com) == -1) 143 err(1, "pthread create"); 144 145 /* read stdin, feed that into the rump kernel */ 146 for (;;) { 147 char ch; 148 149 ch = getchar(); 150 if (rump_sys_write(com, &ch, 1) != 1) 151 err(1, "rump write"); 152 } 153 } 154