4 * Copyright (c) 2003-2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
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"
33 #include "chardev/char-win.h"
35 #include <sys/ioctl.h>
37 #include "chardev/char-fd.h"
40 #include "chardev/char-serial.h"
44 static void qmp_chardev_open_serial(Chardev
*chr
,
45 ChardevBackend
*backend
,
49 ChardevHostdev
*serial
= backend
->u
.serial
.data
;
51 win_chr_serial_init(chr
, serial
->device
, errp
);
54 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
55 || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
56 || defined(__GLIBC__) || defined(__APPLE__)
58 static void tty_serial_init(int fd
, int speed
,
59 int parity
, int data_bits
, int stop_bits
)
61 struct termios tty
= {0};
65 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
66 speed
, parity
, data_bits
, stop_bits
);
70 #define check_speed(val) \
76 speed
= speed
* 10 / 11;
92 /* Non-Posix values follow. They may be unsupported on some systems. */
111 check_speed(1000000);
114 check_speed(1152000);
117 check_speed(1500000);
120 check_speed(2000000);
123 check_speed(2500000);
126 check_speed(3000000);
129 check_speed(3500000);
132 check_speed(4000000);
138 cfsetispeed(&tty
, spd
);
139 cfsetospeed(&tty
, spd
);
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
);
166 tty
.c_cflag
|= PARENB
;
169 tty
.c_cflag
|= PARENB
| PARODD
;
172 if (stop_bits
== 2) {
173 tty
.c_cflag
|= CSTOPB
;
176 tcsetattr(fd
, TCSANOW
, &tty
);
179 static int tty_serial_ioctl(Chardev
*chr
, int cmd
, void *arg
)
181 FDChardev
*s
= FD_CHARDEV(chr
);
182 QIOChannelFile
*fioc
= QIO_CHANNEL_FILE(s
->ioc_in
);
185 case CHR_IOCTL_SERIAL_SET_PARAMS
:
187 QEMUSerialSetParams
*ssp
= arg
;
188 tty_serial_init(fioc
->fd
,
189 ssp
->speed
, ssp
->parity
,
190 ssp
->data_bits
, ssp
->stop_bits
);
193 case CHR_IOCTL_SERIAL_SET_BREAK
:
195 int enable
= *(int *)arg
;
197 tcsendbreak(fioc
->fd
, 1);
201 case CHR_IOCTL_SERIAL_GET_TIOCM
:
204 int *targ
= (int *)arg
;
205 ioctl(fioc
->fd
, TIOCMGET
, &sarg
);
207 if (sarg
& TIOCM_CTS
) {
208 *targ
|= CHR_TIOCM_CTS
;
210 if (sarg
& TIOCM_CAR
) {
211 *targ
|= CHR_TIOCM_CAR
;
213 if (sarg
& TIOCM_DSR
) {
214 *targ
|= CHR_TIOCM_DSR
;
216 if (sarg
& TIOCM_RI
) {
217 *targ
|= CHR_TIOCM_RI
;
219 if (sarg
& TIOCM_DTR
) {
220 *targ
|= CHR_TIOCM_DTR
;
222 if (sarg
& TIOCM_RTS
) {
223 *targ
|= CHR_TIOCM_RTS
;
227 case CHR_IOCTL_SERIAL_SET_TIOCM
:
229 int sarg
= *(int *)arg
;
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
) {
237 if (sarg
& CHR_TIOCM_CAR
) {
240 if (sarg
& CHR_TIOCM_DSR
) {
243 if (sarg
& CHR_TIOCM_RI
) {
246 if (sarg
& CHR_TIOCM_DTR
) {
249 if (sarg
& CHR_TIOCM_RTS
) {
252 ioctl(fioc
->fd
, TIOCMSET
, &targ
);
261 static void qmp_chardev_open_serial(Chardev
*chr
,
262 ChardevBackend
*backend
,
266 ChardevHostdev
*serial
= backend
->u
.serial
.data
;
269 fd
= qmp_chardev_open_file_source(serial
->device
, O_RDWR
| O_NONBLOCK
,
274 if (!g_unix_set_fd_nonblocking(fd
, true, NULL
)) {
275 error_setg_errno(errp
, errno
, "Failed to set FD nonblocking");
278 tty_serial_init(fd
, 115200, 'N', 8, 1);
280 qemu_chr_open_fd(chr
, fd
, fd
);
282 #endif /* __linux__ || __sun__ */
284 #ifdef HAVE_CHARDEV_SERIAL
285 static void qemu_chr_parse_serial(QemuOpts
*opts
, ChardevBackend
*backend
,
288 const char *device
= qemu_opt_get(opts
, "path");
289 ChardevHostdev
*serial
;
291 if (device
== NULL
) {
292 error_setg(errp
, "chardev: serial/tty: no device path given");
295 backend
->type
= CHARDEV_BACKEND_KIND_SERIAL
;
296 serial
= backend
->u
.serial
.data
= g_new0(ChardevHostdev
, 1);
297 qemu_chr_parse_common(opts
, qapi_ChardevHostdev_base(serial
));
298 serial
->device
= g_strdup(device
);
301 static void char_serial_class_init(ObjectClass
*oc
, void *data
)
303 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
305 cc
->parse
= qemu_chr_parse_serial
;
306 cc
->open
= qmp_chardev_open_serial
;
308 cc
->chr_ioctl
= tty_serial_ioctl
;
313 static const TypeInfo char_serial_type_info
= {
314 .name
= TYPE_CHARDEV_SERIAL
,
316 .parent
= TYPE_CHARDEV_WIN
,
318 .parent
= TYPE_CHARDEV_FD
,
320 .class_init
= char_serial_class_init
,
323 static void register_types(void)
325 type_register_static(&char_serial_type_info
);
328 type_init(register_types
);