1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include "qemu/osdep.h" 25 #include "qemu/sockets.h" 26 #include "io/channel-file.h" 27 #include "qapi/error.h" 28 29 #ifdef _WIN32 30 #include "char-win.h" 31 #else 32 #include <sys/ioctl.h> 33 #include <termios.h> 34 #include "char-fd.h" 35 #endif 36 37 #include "char-serial.h" 38 39 #ifdef _WIN32 40 41 static void qmp_chardev_open_serial(Chardev *chr, 42 ChardevBackend *backend, 43 bool *be_opened, 44 Error **errp) 45 { 46 ChardevHostdev *serial = backend->u.serial.data; 47 48 win_chr_init(chr, serial->device, errp); 49 } 50 51 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ 52 || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ 53 || defined(__GLIBC__) 54 55 static void tty_serial_init(int fd, int speed, 56 int parity, int data_bits, int stop_bits) 57 { 58 struct termios tty; 59 speed_t spd; 60 61 #if 0 62 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", 63 speed, parity, data_bits, stop_bits); 64 #endif 65 tcgetattr(fd, &tty); 66 67 #define check_speed(val) if (speed <= val) { spd = B##val; break; } 68 speed = speed * 10 / 11; 69 do { 70 check_speed(50); 71 check_speed(75); 72 check_speed(110); 73 check_speed(134); 74 check_speed(150); 75 check_speed(200); 76 check_speed(300); 77 check_speed(600); 78 check_speed(1200); 79 check_speed(1800); 80 check_speed(2400); 81 check_speed(4800); 82 check_speed(9600); 83 check_speed(19200); 84 check_speed(38400); 85 /* Non-Posix values follow. They may be unsupported on some systems. */ 86 check_speed(57600); 87 check_speed(115200); 88 #ifdef B230400 89 check_speed(230400); 90 #endif 91 #ifdef B460800 92 check_speed(460800); 93 #endif 94 #ifdef B500000 95 check_speed(500000); 96 #endif 97 #ifdef B576000 98 check_speed(576000); 99 #endif 100 #ifdef B921600 101 check_speed(921600); 102 #endif 103 #ifdef B1000000 104 check_speed(1000000); 105 #endif 106 #ifdef B1152000 107 check_speed(1152000); 108 #endif 109 #ifdef B1500000 110 check_speed(1500000); 111 #endif 112 #ifdef B2000000 113 check_speed(2000000); 114 #endif 115 #ifdef B2500000 116 check_speed(2500000); 117 #endif 118 #ifdef B3000000 119 check_speed(3000000); 120 #endif 121 #ifdef B3500000 122 check_speed(3500000); 123 #endif 124 #ifdef B4000000 125 check_speed(4000000); 126 #endif 127 spd = B115200; 128 } while (0); 129 130 cfsetispeed(&tty, spd); 131 cfsetospeed(&tty, spd); 132 133 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP 134 | INLCR | IGNCR | ICRNL | IXON); 135 tty.c_oflag |= OPOST; 136 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); 137 tty.c_cflag &= ~(CSIZE | PARENB | PARODD | CRTSCTS | CSTOPB); 138 switch (data_bits) { 139 default: 140 case 8: 141 tty.c_cflag |= CS8; 142 break; 143 case 7: 144 tty.c_cflag |= CS7; 145 break; 146 case 6: 147 tty.c_cflag |= CS6; 148 break; 149 case 5: 150 tty.c_cflag |= CS5; 151 break; 152 } 153 switch (parity) { 154 default: 155 case 'N': 156 break; 157 case 'E': 158 tty.c_cflag |= PARENB; 159 break; 160 case 'O': 161 tty.c_cflag |= PARENB | PARODD; 162 break; 163 } 164 if (stop_bits == 2) { 165 tty.c_cflag |= CSTOPB; 166 } 167 168 tcsetattr(fd, TCSANOW, &tty); 169 } 170 171 static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg) 172 { 173 FDChardev *s = FD_CHARDEV(chr); 174 QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in); 175 176 switch (cmd) { 177 case CHR_IOCTL_SERIAL_SET_PARAMS: 178 { 179 QEMUSerialSetParams *ssp = arg; 180 tty_serial_init(fioc->fd, 181 ssp->speed, ssp->parity, 182 ssp->data_bits, ssp->stop_bits); 183 } 184 break; 185 case CHR_IOCTL_SERIAL_SET_BREAK: 186 { 187 int enable = *(int *)arg; 188 if (enable) { 189 tcsendbreak(fioc->fd, 1); 190 } 191 } 192 break; 193 case CHR_IOCTL_SERIAL_GET_TIOCM: 194 { 195 int sarg = 0; 196 int *targ = (int *)arg; 197 ioctl(fioc->fd, TIOCMGET, &sarg); 198 *targ = 0; 199 if (sarg & TIOCM_CTS) { 200 *targ |= CHR_TIOCM_CTS; 201 } 202 if (sarg & TIOCM_CAR) { 203 *targ |= CHR_TIOCM_CAR; 204 } 205 if (sarg & TIOCM_DSR) { 206 *targ |= CHR_TIOCM_DSR; 207 } 208 if (sarg & TIOCM_RI) { 209 *targ |= CHR_TIOCM_RI; 210 } 211 if (sarg & TIOCM_DTR) { 212 *targ |= CHR_TIOCM_DTR; 213 } 214 if (sarg & TIOCM_RTS) { 215 *targ |= CHR_TIOCM_RTS; 216 } 217 } 218 break; 219 case CHR_IOCTL_SERIAL_SET_TIOCM: 220 { 221 int sarg = *(int *)arg; 222 int targ = 0; 223 ioctl(fioc->fd, TIOCMGET, &targ); 224 targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR 225 | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS); 226 if (sarg & CHR_TIOCM_CTS) { 227 targ |= TIOCM_CTS; 228 } 229 if (sarg & CHR_TIOCM_CAR) { 230 targ |= TIOCM_CAR; 231 } 232 if (sarg & CHR_TIOCM_DSR) { 233 targ |= TIOCM_DSR; 234 } 235 if (sarg & CHR_TIOCM_RI) { 236 targ |= TIOCM_RI; 237 } 238 if (sarg & CHR_TIOCM_DTR) { 239 targ |= TIOCM_DTR; 240 } 241 if (sarg & CHR_TIOCM_RTS) { 242 targ |= TIOCM_RTS; 243 } 244 ioctl(fioc->fd, TIOCMSET, &targ); 245 } 246 break; 247 default: 248 return -ENOTSUP; 249 } 250 return 0; 251 } 252 253 static void qmp_chardev_open_serial(Chardev *chr, 254 ChardevBackend *backend, 255 bool *be_opened, 256 Error **errp) 257 { 258 ChardevHostdev *serial = backend->u.serial.data; 259 int fd; 260 261 fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp); 262 if (fd < 0) { 263 return; 264 } 265 qemu_set_nonblock(fd); 266 tty_serial_init(fd, 115200, 'N', 8, 1); 267 268 qemu_chr_open_fd(chr, fd, fd); 269 } 270 #endif /* __linux__ || __sun__ */ 271 272 #ifdef HAVE_CHARDEV_SERIAL 273 static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend, 274 Error **errp) 275 { 276 const char *device = qemu_opt_get(opts, "path"); 277 ChardevHostdev *serial; 278 279 if (device == NULL) { 280 error_setg(errp, "chardev: serial/tty: no device path given"); 281 return; 282 } 283 backend->type = CHARDEV_BACKEND_KIND_SERIAL; 284 serial = backend->u.serial.data = g_new0(ChardevHostdev, 1); 285 qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial)); 286 serial->device = g_strdup(device); 287 } 288 289 static void char_serial_class_init(ObjectClass *oc, void *data) 290 { 291 ChardevClass *cc = CHARDEV_CLASS(oc); 292 293 cc->parse = qemu_chr_parse_serial; 294 cc->open = qmp_chardev_open_serial; 295 #ifndef _WIN32 296 cc->chr_ioctl = tty_serial_ioctl; 297 #endif 298 } 299 300 301 static const TypeInfo char_serial_type_info = { 302 .name = TYPE_CHARDEV_SERIAL, 303 #ifdef _WIN32 304 .parent = TYPE_CHARDEV_WIN, 305 #else 306 .parent = TYPE_CHARDEV_FD, 307 #endif 308 .class_init = char_serial_class_init, 309 }; 310 311 static void register_types(void) 312 { 313 type_register_static(&char_serial_type_info); 314 } 315 316 type_init(register_types); 317 318 #endif 319