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