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