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
24 #include "qemu/osdep.h"
25 #include "qemu/sockets.h"
26 #include "io/channel-file.h"
27 #include "qapi/error.h"
30 #include "chardev/char-win.h"
32 #include <sys/ioctl.h>
34 #include "chardev/char-fd.h"
37 #include "chardev/char-serial.h"
41 static void qmp_chardev_open_serial(Chardev
*chr
,
42 ChardevBackend
*backend
,
46 ChardevHostdev
*serial
= backend
->u
.serial
.data
;
48 win_chr_serial_init(chr
, serial
->device
, errp
);
51 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
52 || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
55 static void tty_serial_init(int fd
, int speed
,
56 int parity
, int data_bits
, int stop_bits
)
62 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
63 speed
, parity
, data_bits
, stop_bits
);
67 #define check_speed(val) \
73 speed
= speed
* 10 / 11;
89 /* Non-Posix values follow. They may be unsupported on some systems. */
108 check_speed(1000000);
111 check_speed(1152000);
114 check_speed(1500000);
117 check_speed(2000000);
120 check_speed(2500000);
123 check_speed(3000000);
126 check_speed(3500000);
129 check_speed(4000000);
135 cfsetispeed(&tty
, spd
);
136 cfsetospeed(&tty
, spd
);
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
);
163 tty
.c_cflag
|= PARENB
;
166 tty
.c_cflag
|= PARENB
| PARODD
;
169 if (stop_bits
== 2) {
170 tty
.c_cflag
|= CSTOPB
;
173 tcsetattr(fd
, TCSANOW
, &tty
);
176 static int tty_serial_ioctl(Chardev
*chr
, int cmd
, void *arg
)
178 FDChardev
*s
= FD_CHARDEV(chr
);
179 QIOChannelFile
*fioc
= QIO_CHANNEL_FILE(s
->ioc_in
);
182 case CHR_IOCTL_SERIAL_SET_PARAMS
:
184 QEMUSerialSetParams
*ssp
= arg
;
185 tty_serial_init(fioc
->fd
,
186 ssp
->speed
, ssp
->parity
,
187 ssp
->data_bits
, ssp
->stop_bits
);
190 case CHR_IOCTL_SERIAL_SET_BREAK
:
192 int enable
= *(int *)arg
;
194 tcsendbreak(fioc
->fd
, 1);
198 case CHR_IOCTL_SERIAL_GET_TIOCM
:
201 int *targ
= (int *)arg
;
202 ioctl(fioc
->fd
, TIOCMGET
, &sarg
);
204 if (sarg
& TIOCM_CTS
) {
205 *targ
|= CHR_TIOCM_CTS
;
207 if (sarg
& TIOCM_CAR
) {
208 *targ
|= CHR_TIOCM_CAR
;
210 if (sarg
& TIOCM_DSR
) {
211 *targ
|= CHR_TIOCM_DSR
;
213 if (sarg
& TIOCM_RI
) {
214 *targ
|= CHR_TIOCM_RI
;
216 if (sarg
& TIOCM_DTR
) {
217 *targ
|= CHR_TIOCM_DTR
;
219 if (sarg
& TIOCM_RTS
) {
220 *targ
|= CHR_TIOCM_RTS
;
224 case CHR_IOCTL_SERIAL_SET_TIOCM
:
226 int sarg
= *(int *)arg
;
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
) {
234 if (sarg
& CHR_TIOCM_CAR
) {
237 if (sarg
& CHR_TIOCM_DSR
) {
240 if (sarg
& CHR_TIOCM_RI
) {
243 if (sarg
& CHR_TIOCM_DTR
) {
246 if (sarg
& CHR_TIOCM_RTS
) {
249 ioctl(fioc
->fd
, TIOCMSET
, &targ
);
258 static void qmp_chardev_open_serial(Chardev
*chr
,
259 ChardevBackend
*backend
,
263 ChardevHostdev
*serial
= backend
->u
.serial
.data
;
266 fd
= qmp_chardev_open_file_source(serial
->device
, O_RDWR
, errp
);
270 qemu_set_nonblock(fd
);
271 tty_serial_init(fd
, 115200, 'N', 8, 1);
273 qemu_chr_open_fd(chr
, fd
, fd
);
275 #endif /* __linux__ || __sun__ */
277 #ifdef HAVE_CHARDEV_SERIAL
278 static void qemu_chr_parse_serial(QemuOpts
*opts
, ChardevBackend
*backend
,
281 const char *device
= qemu_opt_get(opts
, "path");
282 ChardevHostdev
*serial
;
284 if (device
== NULL
) {
285 error_setg(errp
, "chardev: serial/tty: no device path given");
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
);
294 static void char_serial_class_init(ObjectClass
*oc
, void *data
)
296 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
298 cc
->parse
= qemu_chr_parse_serial
;
299 cc
->open
= qmp_chardev_open_serial
;
301 cc
->chr_ioctl
= tty_serial_ioctl
;
306 static const TypeInfo char_serial_type_info
= {
307 .name
= TYPE_CHARDEV_SERIAL
,
309 .parent
= TYPE_CHARDEV_WIN
,
311 .parent
= TYPE_CHARDEV_FD
,
313 .class_init
= char_serial_class_init
,
316 static void register_types(void)
318 type_register_static(&char_serial_type_info
);
321 type_init(register_types
);