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 25 #include "qemu/osdep.h" 26 #include "qemu/option.h" 27 #include "qemu/sockets.h" 28 #include "io/channel-file.h" 29 #include "qapi/error.h" 30 31 #ifdef _WIN32 32 #include "chardev/char-win.h" 33 #else 34 #include <sys/ioctl.h> 35 #include <termios.h> 36 #include "chardev/char-fd.h" 37 #endif 38 39 #include "chardev/char-serial.h" 40 41 #ifdef _WIN32 42 43 static void qmp_chardev_open_serial(Chardev *chr, 44 ChardevBackend *backend, 45 bool *be_opened, 46 Error **errp) 47 { 48 ChardevHostdev *serial = backend->u.serial.data; 49 50 win_chr_serial_init(chr, serial->device, errp); 51 } 52 53 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ 54 || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ 55 || defined(__GLIBC__) 56 57 static void tty_serial_init(int fd, int speed, 58 int parity, int data_bits, int stop_bits) 59 { 60 struct termios tty = {0}; 61 speed_t spd; 62 63 #if 0 64 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", 65 speed, parity, data_bits, stop_bits); 66 #endif 67 tcgetattr(fd, &tty); 68 69 #define check_speed(val) \ 70 if (speed <= val) { \ 71 spd = B##val; \ 72 goto done; \ 73 } 74 75 speed = speed * 10 / 11; 76 check_speed(50); 77 check_speed(75); 78 check_speed(110); 79 check_speed(134); 80 check_speed(150); 81 check_speed(200); 82 check_speed(300); 83 check_speed(600); 84 check_speed(1200); 85 check_speed(1800); 86 check_speed(2400); 87 check_speed(4800); 88 check_speed(9600); 89 check_speed(19200); 90 check_speed(38400); 91 /* Non-Posix values follow. They may be unsupported on some systems. */ 92 check_speed(57600); 93 check_speed(115200); 94 #ifdef B230400 95 check_speed(230400); 96 #endif 97 #ifdef B460800 98 check_speed(460800); 99 #endif 100 #ifdef B500000 101 check_speed(500000); 102 #endif 103 #ifdef B576000 104 check_speed(576000); 105 #endif 106 #ifdef B921600 107 check_speed(921600); 108 #endif 109 #ifdef B1000000 110 check_speed(1000000); 111 #endif 112 #ifdef B1152000 113 check_speed(1152000); 114 #endif 115 #ifdef B1500000 116 check_speed(1500000); 117 #endif 118 #ifdef B2000000 119 check_speed(2000000); 120 #endif 121 #ifdef B2500000 122 check_speed(2500000); 123 #endif 124 #ifdef B3000000 125 check_speed(3000000); 126 #endif 127 #ifdef B3500000 128 check_speed(3500000); 129 #endif 130 #ifdef B4000000 131 check_speed(4000000); 132 #endif 133 spd = B115200; 134 135 #undef check_speed 136 done: 137 cfsetispeed(&tty, spd); 138 cfsetospeed(&tty, spd); 139 140 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP 141 | INLCR | IGNCR | ICRNL | IXON); 142 tty.c_oflag &= ~OPOST; 143 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); 144 tty.c_cflag &= ~(CSIZE | PARENB | PARODD | CRTSCTS | CSTOPB); 145 switch (data_bits) { 146 default: 147 case 8: 148 tty.c_cflag |= CS8; 149 break; 150 case 7: 151 tty.c_cflag |= CS7; 152 break; 153 case 6: 154 tty.c_cflag |= CS6; 155 break; 156 case 5: 157 tty.c_cflag |= CS5; 158 break; 159 } 160 switch (parity) { 161 default: 162 case 'N': 163 break; 164 case 'E': 165 tty.c_cflag |= PARENB; 166 break; 167 case 'O': 168 tty.c_cflag |= PARENB | PARODD; 169 break; 170 } 171 if (stop_bits == 2) { 172 tty.c_cflag |= CSTOPB; 173 } 174 175 tcsetattr(fd, TCSANOW, &tty); 176 } 177 178 static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg) 179 { 180 FDChardev *s = FD_CHARDEV(chr); 181 QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in); 182 183 switch (cmd) { 184 case CHR_IOCTL_SERIAL_SET_PARAMS: 185 { 186 QEMUSerialSetParams *ssp = arg; 187 tty_serial_init(fioc->fd, 188 ssp->speed, ssp->parity, 189 ssp->data_bits, ssp->stop_bits); 190 } 191 break; 192 case CHR_IOCTL_SERIAL_SET_BREAK: 193 { 194 int enable = *(int *)arg; 195 if (enable) { 196 tcsendbreak(fioc->fd, 1); 197 } 198 } 199 break; 200 case CHR_IOCTL_SERIAL_GET_TIOCM: 201 { 202 int sarg = 0; 203 int *targ = (int *)arg; 204 ioctl(fioc->fd, TIOCMGET, &sarg); 205 *targ = 0; 206 if (sarg & TIOCM_CTS) { 207 *targ |= CHR_TIOCM_CTS; 208 } 209 if (sarg & TIOCM_CAR) { 210 *targ |= CHR_TIOCM_CAR; 211 } 212 if (sarg & TIOCM_DSR) { 213 *targ |= CHR_TIOCM_DSR; 214 } 215 if (sarg & TIOCM_RI) { 216 *targ |= CHR_TIOCM_RI; 217 } 218 if (sarg & TIOCM_DTR) { 219 *targ |= CHR_TIOCM_DTR; 220 } 221 if (sarg & TIOCM_RTS) { 222 *targ |= CHR_TIOCM_RTS; 223 } 224 } 225 break; 226 case CHR_IOCTL_SERIAL_SET_TIOCM: 227 { 228 int sarg = *(int *)arg; 229 int targ = 0; 230 ioctl(fioc->fd, TIOCMGET, &targ); 231 targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR 232 | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS); 233 if (sarg & CHR_TIOCM_CTS) { 234 targ |= TIOCM_CTS; 235 } 236 if (sarg & CHR_TIOCM_CAR) { 237 targ |= TIOCM_CAR; 238 } 239 if (sarg & CHR_TIOCM_DSR) { 240 targ |= TIOCM_DSR; 241 } 242 if (sarg & CHR_TIOCM_RI) { 243 targ |= TIOCM_RI; 244 } 245 if (sarg & CHR_TIOCM_DTR) { 246 targ |= TIOCM_DTR; 247 } 248 if (sarg & CHR_TIOCM_RTS) { 249 targ |= TIOCM_RTS; 250 } 251 ioctl(fioc->fd, TIOCMSET, &targ); 252 } 253 break; 254 default: 255 return -ENOTSUP; 256 } 257 return 0; 258 } 259 260 static void qmp_chardev_open_serial(Chardev *chr, 261 ChardevBackend *backend, 262 bool *be_opened, 263 Error **errp) 264 { 265 ChardevHostdev *serial = backend->u.serial.data; 266 int fd; 267 268 fd = qmp_chardev_open_file_source(serial->device, O_RDWR | O_NONBLOCK, 269 errp); 270 if (fd < 0) { 271 return; 272 } 273 qemu_set_nonblock(fd); 274 tty_serial_init(fd, 115200, 'N', 8, 1); 275 276 qemu_chr_open_fd(chr, fd, fd); 277 } 278 #endif /* __linux__ || __sun__ */ 279 280 #ifdef HAVE_CHARDEV_SERIAL 281 static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend, 282 Error **errp) 283 { 284 const char *device = qemu_opt_get(opts, "path"); 285 ChardevHostdev *serial; 286 287 if (device == NULL) { 288 error_setg(errp, "chardev: serial/tty: no device path given"); 289 return; 290 } 291 backend->type = CHARDEV_BACKEND_KIND_SERIAL; 292 serial = backend->u.serial.data = g_new0(ChardevHostdev, 1); 293 qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial)); 294 serial->device = g_strdup(device); 295 } 296 297 static void char_serial_class_init(ObjectClass *oc, void *data) 298 { 299 ChardevClass *cc = CHARDEV_CLASS(oc); 300 301 cc->parse = qemu_chr_parse_serial; 302 cc->open = qmp_chardev_open_serial; 303 #ifndef _WIN32 304 cc->chr_ioctl = tty_serial_ioctl; 305 #endif 306 } 307 308 309 static const TypeInfo char_serial_type_info = { 310 .name = TYPE_CHARDEV_SERIAL, 311 #ifdef _WIN32 312 .parent = TYPE_CHARDEV_WIN, 313 #else 314 .parent = TYPE_CHARDEV_FD, 315 #endif 316 .class_init = char_serial_class_init, 317 }; 318 319 static void register_types(void) 320 { 321 type_register_static(&char_serial_type_info); 322 } 323 324 type_init(register_types); 325 326 #endif 327