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/option.h"
27 #include "qemu/sockets.h"
28 #include "io/channel-file.h"
29 #include "qapi/error.h"
32 #include "chardev/char-win.h"
34 #include <sys/ioctl.h>
36 #include "chardev/char-fd.h"
39 #include "chardev/char-serial.h"
43 static void qmp_chardev_open_serial(Chardev
*chr
,
44 ChardevBackend
*backend
,
48 ChardevHostdev
*serial
= backend
->u
.serial
.data
;
50 win_chr_serial_init(chr
, serial
->device
, errp
);
53 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
54 || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
57 static void tty_serial_init(int fd
, int speed
,
58 int parity
, int data_bits
, int stop_bits
)
64 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
65 speed
, parity
, data_bits
, stop_bits
);
69 #define check_speed(val) \
75 speed
= speed
* 10 / 11;
91 /* Non-Posix values follow. They may be unsupported on some systems. */
110 check_speed(1000000);
113 check_speed(1152000);
116 check_speed(1500000);
119 check_speed(2000000);
122 check_speed(2500000);
125 check_speed(3000000);
128 check_speed(3500000);
131 check_speed(4000000);
137 cfsetispeed(&tty
, spd
);
138 cfsetospeed(&tty
, spd
);
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
);
165 tty
.c_cflag
|= PARENB
;
168 tty
.c_cflag
|= PARENB
| PARODD
;
171 if (stop_bits
== 2) {
172 tty
.c_cflag
|= CSTOPB
;
175 tcsetattr(fd
, TCSANOW
, &tty
);
178 static int tty_serial_ioctl(Chardev
*chr
, int cmd
, void *arg
)
180 FDChardev
*s
= FD_CHARDEV(chr
);
181 QIOChannelFile
*fioc
= QIO_CHANNEL_FILE(s
->ioc_in
);
184 case CHR_IOCTL_SERIAL_SET_PARAMS
:
186 QEMUSerialSetParams
*ssp
= arg
;
187 tty_serial_init(fioc
->fd
,
188 ssp
->speed
, ssp
->parity
,
189 ssp
->data_bits
, ssp
->stop_bits
);
192 case CHR_IOCTL_SERIAL_SET_BREAK
:
194 int enable
= *(int *)arg
;
196 tcsendbreak(fioc
->fd
, 1);
200 case CHR_IOCTL_SERIAL_GET_TIOCM
:
203 int *targ
= (int *)arg
;
204 ioctl(fioc
->fd
, TIOCMGET
, &sarg
);
206 if (sarg
& TIOCM_CTS
) {
207 *targ
|= CHR_TIOCM_CTS
;
209 if (sarg
& TIOCM_CAR
) {
210 *targ
|= CHR_TIOCM_CAR
;
212 if (sarg
& TIOCM_DSR
) {
213 *targ
|= CHR_TIOCM_DSR
;
215 if (sarg
& TIOCM_RI
) {
216 *targ
|= CHR_TIOCM_RI
;
218 if (sarg
& TIOCM_DTR
) {
219 *targ
|= CHR_TIOCM_DTR
;
221 if (sarg
& TIOCM_RTS
) {
222 *targ
|= CHR_TIOCM_RTS
;
226 case CHR_IOCTL_SERIAL_SET_TIOCM
:
228 int sarg
= *(int *)arg
;
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
) {
236 if (sarg
& CHR_TIOCM_CAR
) {
239 if (sarg
& CHR_TIOCM_DSR
) {
242 if (sarg
& CHR_TIOCM_RI
) {
245 if (sarg
& CHR_TIOCM_DTR
) {
248 if (sarg
& CHR_TIOCM_RTS
) {
251 ioctl(fioc
->fd
, TIOCMSET
, &targ
);
260 static void qmp_chardev_open_serial(Chardev
*chr
,
261 ChardevBackend
*backend
,
265 ChardevHostdev
*serial
= backend
->u
.serial
.data
;
268 fd
= qmp_chardev_open_file_source(serial
->device
, O_RDWR
| O_NONBLOCK
,
273 qemu_set_nonblock(fd
);
274 tty_serial_init(fd
, 115200, 'N', 8, 1);
276 qemu_chr_open_fd(chr
, fd
, fd
);
278 #endif /* __linux__ || __sun__ */
280 #ifdef HAVE_CHARDEV_SERIAL
281 static void qemu_chr_parse_serial(QemuOpts
*opts
, ChardevBackend
*backend
,
284 const char *device
= qemu_opt_get(opts
, "path");
285 ChardevHostdev
*serial
;
287 if (device
== NULL
) {
288 error_setg(errp
, "chardev: serial/tty: no device path given");
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
);
297 static void char_serial_class_init(ObjectClass
*oc
, void *data
)
299 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
301 cc
->parse
= qemu_chr_parse_serial
;
302 cc
->open
= qmp_chardev_open_serial
;
304 cc
->chr_ioctl
= tty_serial_ioctl
;
309 static const TypeInfo char_serial_type_info
= {
310 .name
= TYPE_CHARDEV_SERIAL
,
312 .parent
= TYPE_CHARDEV_WIN
,
314 .parent
= TYPE_CHARDEV_FD
,
316 .class_init
= char_serial_class_init
,
319 static void register_types(void)
321 type_register_static(&char_serial_type_info
);
324 type_init(register_types
);