qemu-char.c revision 4143d8f4c302878923bde0cb2420f4ca27245bcd
15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * QEMU System Emulator
35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard
55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in the Software without restriction, including without limitation the rights
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is
115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * furnished to do so, subject to the following conditions:
125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The above copyright notice and this permission notice shall be included in
145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * all copies or substantial portions of the Software.
155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE.
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h"
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "monitor.h"
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "console.h"
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sysemu.h"
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-timer.h"
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-char.h"
315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "block.h"
325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/usb.h"
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/baum.h"
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/msmouse.h"
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <unistd.h>
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <fcntl.h>
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <signal.h>
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <time.h>
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <errno.h>
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/time.h>
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <zlib.h>
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/times.h>
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/wait.h>
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <termios.h>
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/mman.h>
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ioctl.h>
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/resource.h>
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/socket.h>
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h>
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h>
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __NetBSD__
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if_tap.h>
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/if_tun.h>
595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <arpa/inet.h>
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dirent.h>
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netdb.h>
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/select.h>
642c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h>
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __FreeBSD__
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libutil.h>
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dev/ppbus/ppi.h>
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dev/ppbus/ppbconf.h>
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__DragonFly__)
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libutil.h>
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dev/misc/ppi/ppi.h>
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <bus/ppbus/ppbconf.h>
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <util.h>
765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <freebsd/stdlib.h>
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <pty.h>
825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/ppdev.h>
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/parport.h>
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __sun__
875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h>
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ethernet.h>
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/sockio.h>
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/arp.h>
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h>
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in_systm.h>
935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/ip.h>
945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/ip_icmp.h> // must come after ip.h
955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/udp.h>
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/tcp.h>
975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h>
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <syslog.h>
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stropts.h>
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu_socket.h"
1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/
1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* character device */
1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TAILQ_HEAD_INITIALIZER(chardevs);
1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int initial_reset_issued;
1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_chr_event(CharDriverState *s, int event)
1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->chr_event)
1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->chr_event(s->handler_opaque, event);
1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_chr_reset_bh(void *opaque)
1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *s = opaque;
123a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    qemu_chr_event(s, CHR_EVENT_OPENED);
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(s->bh);
1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->bh = NULL;
1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_reset(CharDriverState *s)
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->bh == NULL && initial_reset_issued) {
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	s->bh = qemu_bh_new(qemu_chr_reset_bh, s);
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	qemu_bh_schedule(s->bh);
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_initial_reset(void)
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    initial_reset_issued = 1;
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
142a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH(chr, &chardevs, next) {
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_reset(chr);
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->chr_write(s, buf, len);
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->chr_ioctl)
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->chr_ioctl(s, cmd, arg);
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_chr_can_read(CharDriverState *s)
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->chr_can_read)
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->chr_can_read(s->handler_opaque);
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->chr_read(s->handler_opaque, buf, len);
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_accept_input(CharDriverState *s)
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->chr_accept_input)
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->chr_accept_input(s);
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char buf[4096];
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    va_list ap;
1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    va_start(ap, fmt);
1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vsnprintf(buf, sizeof(buf), fmt, ap);
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_write(s, (uint8_t *)buf, strlen(buf));
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    va_end(ap);
1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_send_event(CharDriverState *s, int event)
1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->chr_send_event)
1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->chr_send_event(s, event);
1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_add_handlers(CharDriverState *s,
1944143d8f4c302878923bde0cb2420f4ca27245bcdDavid Turner                           IOCanReadHandler *fd_can_read,
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           IOReadHandler *fd_read,
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           IOEventHandler *fd_event,
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           void *opaque)
1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->chr_can_read = fd_can_read;
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->chr_read = fd_read;
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->chr_event = fd_event;
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->handler_opaque = opaque;
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->chr_update_read_handler)
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->chr_update_read_handler(s);
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return len;
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_null(void)
2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = null_chr_write;
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* MUX driver for serial I/O splitting */
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MAX_MUX 4
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MUX_BUFFER_SIZE 32	/* Must be a power of 2.  */
2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
2264143d8f4c302878923bde0cb2420f4ca27245bcdDavid Turner    IOCanReadHandler *chr_can_read[MAX_MUX];
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IOReadHandler *chr_read[MAX_MUX];
2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IOEventHandler *chr_event[MAX_MUX];
2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *ext_opaque[MAX_MUX];
2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *drv;
2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int mux_cnt;
2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int term_got_escape;
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int max_size;
2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Intermediate input buffer allows to catch escape sequences even if the
2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       currently active device is not accepting any input - but only until it
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       is full as well. */
2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int prod[MAX_MUX];
2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int cons[MAX_MUX];
2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int timestamps;
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int linestart;
2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t timestamps_start;
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} MuxDriver;
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d = chr->opaque;
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!d->timestamps) {
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = d->drv->chr_write(d->drv, buf, len);
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int i;
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = 0;
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        for (i = 0; i < len; i++) {
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (d->linestart) {
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                char buf1[64];
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int64_t ti;
2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int secs;
2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ti = qemu_get_clock(rt_clock);
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (d->timestamps_start == -1)
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    d->timestamps_start = ti;
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ti -= d->timestamps_start;
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                secs = ti / 1000;
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                snprintf(buf1, sizeof(buf1),
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         "[%02d:%02d:%02d.%03d] ",
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         secs / 3600,
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         (secs / 60) % 60,
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         secs % 60,
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         (int)(ti % 1000));
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1));
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->linestart = 0;
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret += d->drv->chr_write(d->drv, buf+i, 1);
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (buf[i] == '\n') {
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->linestart = 1;
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char * const mux_help[] = {
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% h    print this help\n\r",
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% x    exit emulator\n\r",
2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% s    save disk data back to file (if -snapshot)\n\r",
2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% t    toggle console timestamps\n\r"
2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% b    send break (magic sysrq)\n\r",
2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% c    switch between console and monitor\n\r",
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    "% %  sends %\n\r",
2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NULL
2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint term_escape_char = 0x01; /* ctrl-a is used for escape */
2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_print_help(CharDriverState *chr)
2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i, j;
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char ebuf[15] = "Escape-Char";
3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char cbuf[50] = "\n\r";
3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (term_escape_char > 0 && term_escape_char < 26) {
3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        snprintf(cbuf, sizeof(cbuf), "\n\r");
3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a');
3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        snprintf(cbuf, sizeof(cbuf),
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 term_escape_char);
3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf));
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; mux_help[i] != NULL; i++) {
3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        for (j=0; mux_help[i][j] != '\0'; j++) {
3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (mux_help[i][j] == '%')
3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf));
3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else
3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1);
3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_send_event(MuxDriver *d, int mux_nr, int event)
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (d->chr_event[mux_nr])
3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        d->chr_event[mux_nr](d->ext_opaque[mux_nr], event);
3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (d->term_got_escape) {
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        d->term_got_escape = 0;
3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ch == term_escape_char)
3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto send_char;
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch(ch) {
3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case '?':
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 'h':
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            mux_print_help(chr);
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 'x':
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            {
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 const char *term =  "QEMU: Terminated\n\r";
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 chr->chr_write(chr,(uint8_t *)term,strlen(term));
3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 exit(0);
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 break;
3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 's':
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            {
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int i;
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                for (i = 0; i < nb_drives; i++) {
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        bdrv_commit(drives_table[i].bdrv);
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 'b':
3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_chr_event(chr, CHR_EVENT_BREAK);
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 'c':
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Switch to the next registered device */
3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_OUT);
3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            chr->focus++;
3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (chr->focus >= d->mux_cnt)
3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                chr->focus = 0;
3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_IN);
3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 't':
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            d->timestamps = !d->timestamps;
3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            d->timestamps_start = -1;
3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            d->linestart = 0;
3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (ch == term_escape_char) {
3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        d->term_got_escape = 1;
3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    send_char:
3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_accept_input(CharDriverState *chr)
3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int m = chr->focus;
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d = chr->opaque;
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (d->prod[m] != d->cons[m] &&
3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           d->chr_can_read[m] &&
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           d->chr_can_read[m](d->ext_opaque[m])) {
3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        d->chr_read[m](d->ext_opaque[m],
3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int mux_chr_can_read(void *opaque)
3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d = chr->opaque;
3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int m = chr->focus;
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE)
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (d->chr_can_read[m])
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return d->chr_can_read[m](d->ext_opaque[m]);
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_read(void *opaque, const uint8_t *buf, int size)
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d = chr->opaque;
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int m = chr->focus;
4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    mux_chr_accept_input (opaque);
4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < size; i++)
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (mux_proc_byte(chr, d, buf[i])) {
4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (d->prod[m] == d->cons[m] &&
4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->chr_can_read[m] &&
4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->chr_can_read[m](d->ext_opaque[m]))
4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else
4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_event(void *opaque, int event)
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d = chr->opaque;
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Send the event to all registered listeners */
4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < d->mux_cnt; i++)
4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        mux_chr_send_event(d, i, event);
4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_update_read_handler(CharDriverState *chr)
4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d = chr->opaque;
4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (d->mux_cnt >= MAX_MUX) {
4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d->chr_read[d->mux_cnt] = chr->chr_read;
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d->chr_event[d->mux_cnt] = chr->chr_event;
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Fix up the real driver with mux routines */
4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (d->mux_cnt == 0) {
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              mux_chr_event, chr);
4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->focus = d->mux_cnt;
4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d->mux_cnt++;
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MuxDriver *d;
4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d = qemu_mallocz(sizeof(MuxDriver));
4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = d;
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    d->drv = drv;
4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->focus = -1;
4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = mux_chr_write;
4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_update_read_handler = mux_chr_update_read_handler;
4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_accept_input = mux_chr_accept_input;
4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint send_all(int fd, const void *buf, int len1)
4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret, len;
4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = len1;
4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (len > 0) {
4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = send(fd, buf, len, 0);
4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            errno = WSAGetLastError();
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (errno != WSAEWOULDBLOCK) {
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return -1;
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (ret == 0) {
4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            buf += ret;
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            len -= ret;
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return len1 - len;
4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int unix_write(int fd, const uint8_t *buf, int len1)
5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret, len;
5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = len1;
5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (len > 0) {
5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = write(fd, buf, len);
5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (errno != EINTR && errno != EAGAIN)
5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return -1;
5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (ret == 0) {
5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            buf += ret;
5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            len -= ret;
5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return len1 - len;
5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint send_all(int fd, const void *buf, int len1)
5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return unix_write(fd, buf, len1);
5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* !_WIN32 */
5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32
5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd_in, fd_out;
5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int max_size;
5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} FDCharDriver;
5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define STDIO_MAX_CLIENTS 1
5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int stdio_nb_clients = 0;
5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s = chr->opaque;
5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return send_all(s->fd_out, buf, len);
5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int fd_chr_read_poll(void *opaque)
5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s = chr->opaque;
5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->max_size = qemu_chr_can_read(chr);
5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->max_size;
5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void fd_chr_read(void *opaque)
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s = chr->opaque;
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int size, len;
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[1024];
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = sizeof(buf);
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len > s->max_size)
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = s->max_size;
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len == 0)
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    size = read(s->fd_in, buf, len);
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size == 0) {
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* FD has been closed. Remove it from the active list.  */
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size > 0) {
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_read(chr, buf, size);
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void fd_chr_update_read_handler(CharDriverState *chr)
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s = chr->opaque;
5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->fd_in >= 0) {
5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 fd_chr_read, NULL, chr);
5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void fd_chr_close(struct CharDriverState *chr)
5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s = chr->opaque;
5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->fd_in >= 0) {
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* open a character device to a unix fd */
6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s;
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(FDCharDriver));
6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fd_in = fd_in;
6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fd_out = fd_out;
6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = fd_chr_write;
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_update_read_handler = fd_chr_update_read_handler;
6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = fd_chr_close;
6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_file_out(const char *file_out)
6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd_out;
6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TFR(fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd_out < 0)
6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_chr_open_fd(-1, fd_out);
6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_pipe(const char *filename)
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd_in, fd_out;
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char filename_in[256], filename_out[256];
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    snprintf(filename_in, 256, "%s.in", filename);
6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    snprintf(filename_out, 256, "%s.out", filename);
6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TFR(fd_in = open(filename_in, O_RDWR | O_BINARY));
6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TFR(fd_out = open(filename_out, O_RDWR | O_BINARY));
6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd_in < 0 || fd_out < 0) {
6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (fd_in >= 0)
6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    close(fd_in);
6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (fd_out >= 0)
6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    close(fd_out);
6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY));
6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (fd_in < 0)
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return NULL;
6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_chr_open_fd(fd_in, fd_out);
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* for STDIO, we handle the case where several clients use it
6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   (nographic mode) */
6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TERM_FIFO_MAX_SIZE 1
6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int term_fifo_size;
6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int stdio_read_poll(void *opaque)
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* try to flush the queue if needed */
6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_read(chr, term_fifo, 1);
6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        term_fifo_size = 0;
6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* see if we can absorb more chars */
6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (term_fifo_size == 0)
6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void stdio_read(void *opaque)
6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int size;
6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[1];
6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    size = read(0, buf, 1);
6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size == 0) {
6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* stdin has been closed. Remove it from the active list.  */
6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size > 0) {
6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (qemu_chr_can_read(chr) > 0) {
6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_chr_read(chr, buf, 1);
6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (term_fifo_size == 0) {
6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            term_fifo[term_fifo_size++] = buf[0];
6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* init terminal so that we can grab keys */
7005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct termios oldtty;
7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int old_fd0_flags;
7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int term_atexit_done;
7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void term_exit(void)
7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcsetattr (0, TCSANOW, &oldtty);
7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fcntl(0, F_SETFL, old_fd0_flags);
7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void term_init(void)
7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct termios tty;
7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcgetattr (0, &tty);
7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    oldtty = tty;
7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    old_fd0_flags = fcntl(0, F_GETFL);
7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          |INLCR|IGNCR|ICRNL|IXON);
7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_oflag |= OPOST;
7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* if graphical mode, we allow Ctrl-C handling */
7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (display_type == DT_NOGRAPHIC)
7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_lflag &= ~ISIG;
7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_cflag &= ~(CSIZE|PARENB);
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_cflag |= CS8;
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_cc[VMIN] = 1;
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_cc[VTIME] = 0;
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcsetattr (0, TCSANOW, &tty);
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!term_atexit_done++)
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        atexit(term_exit);
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fcntl(0, F_SETFL, O_NONBLOCK);
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_chr_close_stdio(struct CharDriverState *chr)
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    term_exit();
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    stdio_nb_clients--;
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fd_chr_close(chr);
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_stdio(void)
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_chr_open_fd(0, 1);
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = qemu_chr_close_stdio;
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    stdio_nb_clients++;
7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    term_init();
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __sun__
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Once Solaris has openpty(), this is going to be removed. */
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int openpty(int *amaster, int *aslave, char *name,
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   struct termios *termp, struct winsize *winp)
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        const char *slave;
7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int mfd = -1, sfd = -1;
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *amaster = *aslave = -1;
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (mfd < 0)
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto err;
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (grantpt(mfd) == -1 || unlockpt(mfd) == -1)
7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto err;
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if ((slave = ptsname(mfd)) == NULL)
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto err;
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1)
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto err;
7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(sfd, I_PUSH, "ptem") == -1 ||
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (termp != NULL && tcgetattr(sfd, termp) < 0))
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto err;
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (amaster)
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *amaster = mfd;
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (aslave)
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *aslave = sfd;
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (winp)
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ioctl(sfd, TIOCSWINSZ, winp);
7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr:
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (sfd != -1)
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                close(sfd);
8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        close(mfd);
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void cfmakeraw (struct termios *termios_p)
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_iflag &=
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_oflag &= ~OPOST;
8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_cflag &= ~(CSIZE|PARENB);
8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_cflag |= CS8;
8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_cc[VMIN] = 0;
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        termios_p->c_cc[VTIME] = 0;
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int connected;
8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int polling;
8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int read_bytes;
8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUTimer *timer;
8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} PtyCharDriver;
8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_update_read_handler(CharDriverState *chr);
8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_state(CharDriverState *chr, int connected);
8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->connected) {
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* guest sends data, check for (re-)connect */
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pty_chr_update_read_handler(chr);
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return send_all(s->fd, buf, len);
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pty_chr_read_poll(void *opaque)
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->read_bytes = qemu_chr_can_read(chr);
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->read_bytes;
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_read(void *opaque)
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int size, len;
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[1024];
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = sizeof(buf);
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len > s->read_bytes)
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = s->read_bytes;
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len == 0)
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    size = read(s->fd, buf, len);
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((size == -1 && errno == EIO) ||
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        (size == 0)) {
8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pty_chr_state(chr, 0);
8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size > 0) {
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pty_chr_state(chr, 1);
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_read(chr, buf, size);
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_update_read_handler(CharDriverState *chr)
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         pty_chr_read, NULL, chr);
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->polling = 1;
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /*
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * Short timeout here: just need wait long enougth that qemu makes
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * it through the poll loop once.  When reconnected we want a
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * short timeout so we notice it almost instantly.  Otherwise
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * read() gives us -EIO instantly, making pty_chr_state() reset the
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * timeout to the normal (much longer) poll interval before the
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * timer triggers.
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     */
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10);
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_state(CharDriverState *chr, int connected)
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!connected) {
9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->connected = 0;
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->polling = 0;
9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* (re-)connect poll interval for idle guests: once per second.
9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * We check more frequently in case the guests sends data to
9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * the virtual device linked to our pty. */
9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!s->connected)
9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_chr_reset(chr);
9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->connected = 1;
9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_timer(void *opaque)
9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct CharDriverState *chr = opaque;
9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->connected)
9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->polling) {
9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* If we arrive here without polling being cleared due
9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * read returning -EIO, then we are (re-)connected */
9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pty_chr_state(chr, 1);
9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Next poll ... */
9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pty_chr_update_read_handler(chr);
9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_close(struct CharDriverState *chr)
9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s = chr->opaque;
9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    close(s->fd);
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_del_timer(s->timer);
9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free_timer(s->timer);
9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_pty(void)
9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PtyCharDriver *s;
9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct termios tty;
9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int slave_fd, len;
9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__OpenBSD__) || defined(__DragonFly__)
9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char pty_name[PATH_MAX];
9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define q_ptsname(x) pty_name
9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char *pty_name = NULL;
9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define q_ptsname(x) ptsname(x)
9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(PtyCharDriver));
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) {
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Set raw attributes on the pty. */
9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcgetattr(slave_fd, &tty);
9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cfmakeraw(&tty);
9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcsetattr(slave_fd, TCSAFLUSH, &tty);
9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    close(slave_fd);
9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = strlen(q_ptsname(s->fd)) + 5;
9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->filename = qemu_malloc(len);
9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd));
9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd));
9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = pty_chr_write;
9775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_update_read_handler = pty_chr_update_read_handler;
9785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = pty_chr_close;
9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tty_serial_init(int fd, int speed,
9865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            int parity, int data_bits, int stop_bits)
9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct termios tty;
9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    speed_t spd;
9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           speed, parity, data_bits, stop_bits);
9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcgetattr (fd, &tty);
9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MARGIN 1.1
9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (speed <= 50 * MARGIN)
9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B50;
10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 75 * MARGIN)
10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B75;
10025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 300 * MARGIN)
10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B300;
10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 600 * MARGIN)
10055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B600;
10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 1200 * MARGIN)
10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B1200;
10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 2400 * MARGIN)
10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B2400;
10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 4800 * MARGIN)
10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B4800;
10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 9600 * MARGIN)
10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B9600;
10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 19200 * MARGIN)
10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B19200;
10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 38400 * MARGIN)
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B38400;
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 57600 * MARGIN)
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B57600;
10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (speed <= 115200 * MARGIN)
10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B115200;
10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        spd = B115200;
10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cfsetispeed(&tty, spd);
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cfsetospeed(&tty, spd);
10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          |INLCR|IGNCR|ICRNL|IXON);
10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_oflag |= OPOST;
10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB);
10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch(data_bits) {
10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 8:
10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= CS8;
10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 7:
10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= CS7;
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 6:
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= CS6;
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 5:
10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= CS5;
10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch(parity) {
10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 'N':
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 'E':
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= PARENB;
10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 'O':
10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= PARENB | PARODD;
10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (stop_bits == 2)
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tty.c_cflag |= CSTOPB;
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcsetattr (fd, TCSANOW, &tty);
10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FDCharDriver *s = chr->opaque;
10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch(cmd) {
10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_SERIAL_SET_PARAMS:
10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        {
10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            QEMUSerialSetParams *ssp = arg;
10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tty_serial_init(s->fd_in, ssp->speed, ssp->parity,
10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            ssp->data_bits, ssp->stop_bits);
10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_SERIAL_SET_BREAK:
10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        {
10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            int enable = *(int *)arg;
10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (enable)
10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcsendbreak(s->fd_in, 1);
10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_SERIAL_GET_TIOCM:
10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        {
10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            int sarg = 0;
10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            int *targ = (int *)arg;
10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ioctl(s->fd_in, TIOCMGET, &sarg);
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *targ = 0;
10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & TIOCM_CTS)
10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *targ |= CHR_TIOCM_CTS;
10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & TIOCM_CAR)
10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *targ |= CHR_TIOCM_CAR;
10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & TIOCM_DSR)
10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *targ |= CHR_TIOCM_DSR;
10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & TIOCM_RI)
10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *targ |= CHR_TIOCM_RI;
10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & TIOCM_DTR)
10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *targ |= CHR_TIOCM_DTR;
11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & TIOCM_RTS)
11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *targ |= CHR_TIOCM_RTS;
11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_SERIAL_SET_TIOCM:
11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        {
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            int sarg = *(int *)arg;
11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            int targ = 0;
11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ioctl(s->fd_in, TIOCMGET, &targ);
11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                     | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & CHR_TIOCM_CTS)
11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                targ |= TIOCM_CTS;
11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & CHR_TIOCM_CAR)
11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                targ |= TIOCM_CAR;
11155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & CHR_TIOCM_DSR)
11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                targ |= TIOCM_DSR;
11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & CHR_TIOCM_RI)
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                targ |= TIOCM_RI;
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & CHR_TIOCM_DTR)
11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                targ |= TIOCM_DTR;
11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sarg & CHR_TIOCM_RTS)
11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                targ |= TIOCM_RTS;
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ioctl(s->fd_in, TIOCMSET, &targ);
11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_tty(const char *filename)
11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
11355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tty_serial_init(fd, 115200, 'N', 8, 1);
11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_chr_open_fd(fd, fd);
11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!chr) {
11415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        close(fd);
11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_ioctl = tty_serial_ioctl;
11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else  /* ! __linux__ && ! __sun__ */
11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_pty(void)
11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* __linux__ || __sun__ */
11545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__linux__)
11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int mode;
11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} ParallelCharDriver;
11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pp_hw_mode(ParallelCharDriver *s, uint16_t mode)
11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->mode != mode) {
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int m = mode;
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(s->fd, PPSETMODE, &m) < 0)
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	s->mode = mode;
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 1;
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ParallelCharDriver *drv = chr->opaque;
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd = drv->fd;
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t b;
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch(cmd) {
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_READ_DATA:
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPRDATA, &b) < 0)
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *(uint8_t *)arg = b;
11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_WRITE_DATA:
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        b = *(uint8_t *)arg;
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPWDATA, &b) < 0)
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_READ_CONTROL:
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPRCONTROL, &b) < 0)
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/* Linux gives only the lowest bits, and no way to know data
11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   direction! For better compatibility set the fixed upper
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   bits. */
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *(uint8_t *)arg = b | 0xc0;
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_WRITE_CONTROL:
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        b = *(uint8_t *)arg;
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPWCONTROL, &b) < 0)
12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_READ_STATUS:
12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPRSTATUS, &b) < 0)
12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *(uint8_t *)arg = b;
12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_DATA_DIR:
12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPDATADIR, (int *)arg) < 0)
12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_EPP_READ_ADDR:
12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
12135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    struct ParallelIOArg *parg = arg;
12145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    int n = read(fd, parg->buffer, parg->count);
12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    if (n != parg->count) {
12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return -EIO;
12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    }
12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_EPP_READ:
12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    struct ParallelIOArg *parg = arg;
12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    int n = read(fd, parg->buffer, parg->count);
12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    if (n != parg->count) {
12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return -EIO;
12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    }
12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_EPP_WRITE_ADDR:
12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    struct ParallelIOArg *parg = arg;
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    int n = write(fd, parg->buffer, parg->count);
12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    if (n != parg->count) {
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return -EIO;
12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    }
12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_EPP_WRITE:
12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    struct ParallelIOArg *parg = arg;
12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    int n = write(fd, parg->buffer, parg->count);
12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    if (n != parg->count) {
12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return -EIO;
12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    }
12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pp_close(CharDriverState *chr)
12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ParallelCharDriver *drv = chr->opaque;
12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd = drv->fd;
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ioctl(fd, PPRELEASE);
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    close(fd);
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(drv);
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_pp(const char *filename)
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ParallelCharDriver *drv;
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TFR(fd = open(filename, O_RDWR));
12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd < 0)
12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ioctl(fd, PPCLAIM) < 0) {
12755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        close(fd);
12765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
12775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    drv = qemu_mallocz(sizeof(ParallelCharDriver));
12805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    drv->fd = fd;
12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    drv->mode = IEEE1284_MODE_COMPAT;
12825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
12845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = null_chr_write;
12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_ioctl = pp_ioctl;
12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = pp_close;
12875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = drv;
12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* __linux__ */
12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__FreeBSD__) || defined(__DragonFly__)
12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
12975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd = (int)chr->opaque;
12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t b;
13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch(cmd) {
13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_READ_DATA:
13035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPIGDATA, &b) < 0)
13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *(uint8_t *)arg = b;
13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
13075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_WRITE_DATA:
13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        b = *(uint8_t *)arg;
13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPISDATA, &b) < 0)
13105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
13115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
13125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_READ_CONTROL:
13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPIGCTRL, &b) < 0)
13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
13155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *(uint8_t *)arg = b;
13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_WRITE_CONTROL:
13185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        b = *(uint8_t *)arg;
13195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPISCTRL, &b) < 0)
13205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
13215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
13225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case CHR_IOCTL_PP_READ_STATUS:
13235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ioctl(fd, PPIGSTATUS, &b) < 0)
13245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return -ENOTSUP;
13255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *(uint8_t *)arg = b;
13265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
13275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
13315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_pp(const char *filename)
13345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
13375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fd = open(filename, O_RDWR);
13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd < 0)
13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = (void *)fd;
13445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = null_chr_write;
13455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_ioctl = pp_ioctl;
13465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
13475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
13495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else /* _WIN32 */
13515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
13535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int max_size;
13545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    HANDLE hcom, hrecv, hsend;
13555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    OVERLAPPED orecv, osend;
13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BOOL fpipe;
13575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD len;
13585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} WinCharState;
13595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NSENDBUF 2048
13615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NRECVBUF 2048
13625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MAXCONNECT 1
13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NTIMEOUT 5000
13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_poll(void *opaque);
13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_pipe_poll(void *opaque);
13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void win_chr_close(CharDriverState *chr)
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->hsend) {
13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        CloseHandle(s->hsend);
13745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->hsend = NULL;
13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->hrecv) {
13775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        CloseHandle(s->hrecv);
13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->hrecv = NULL;
13795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->hcom) {
13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        CloseHandle(s->hcom);
13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->hcom = NULL;
13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->fpipe)
13855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_del_polling_cb(win_chr_pipe_poll, chr);
13865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
13875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_del_polling_cb(win_chr_poll, chr);
13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_init(CharDriverState *chr, const char *filename)
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    COMMCONFIG comcfg;
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    COMSTAT comstat;
13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD size;
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD err;
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->hsend) {
14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed CreateEvent\n");
14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->hrecv) {
14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed CreateEvent\n");
14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                      OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->hcom == INVALID_HANDLE_VALUE) {
14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError());
14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->hcom = NULL;
14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed SetupComm\n");
14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ZeroMemory(&comcfg, sizeof(COMMCONFIG));
14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    size = sizeof(COMMCONFIG);
14255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    GetDefaultCommConfig(filename, &comcfg, &size);
14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    comcfg.dcb.DCBlength = sizeof(DCB);
14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CommConfigDialog(filename, NULL, &comcfg);
14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!SetCommState(s->hcom, &comcfg.dcb)) {
14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed SetCommState\n");
14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!SetCommMask(s->hcom, EV_ERR)) {
14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed SetCommMask\n");
14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cto.ReadIntervalTimeout = MAXDWORD;
14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!SetCommTimeouts(s->hcom, &cto)) {
14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed SetCommTimeouts\n");
14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!ClearCommError(s->hcom, &err, &comstat)) {
14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed ClearCommError\n");
14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_add_polling_cb(win_chr_poll, chr);
14505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
14515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail:
14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    win_chr_close(chr);
14545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
14555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1)
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
14605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD len, ret, size, err;
14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = len1;
14635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ZeroMemory(&s->osend, sizeof(s->osend));
14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->osend.hEvent = s->hsend;
14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (len > 0) {
14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (s->hsend)
14675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = WriteFile(s->hcom, buf, len, &size, &s->osend);
14685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
14695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = WriteFile(s->hcom, buf, len, &size, NULL);
14705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!ret) {
14715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            err = GetLastError();
14725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (err == ERROR_IO_PENDING) {
14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE);
14745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (ret) {
14755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    buf += size;
14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    len -= size;
14775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
14785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
14795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
14845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            buf += size;
14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            len -= size;
14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return len1 - len;
14895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_read_poll(CharDriverState *chr)
14925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
14945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->max_size = qemu_chr_can_read(chr);
14965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->max_size;
14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void win_chr_readfile(CharDriverState *chr)
15005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
15025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret, err;
15035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[1024];
15045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD size;
15055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ZeroMemory(&s->orecv, sizeof(s->orecv));
15075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->orecv.hEvent = s->hrecv;
15085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv);
15095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!ret) {
15105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        err = GetLastError();
15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (err == ERROR_IO_PENDING) {
15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE);
15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size > 0) {
15175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_read(chr, buf, size);
15185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
15205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void win_chr_read(CharDriverState *chr)
15225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
15245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->len > s->max_size)
15265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->len = s->max_size;
15275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->len == 0)
15285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
15295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    win_chr_readfile(chr);
15315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
15325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_poll(void *opaque)
15345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
15365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
15375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    COMSTAT status;
15385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD comerr;
15395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ClearCommError(s->hcom, &comerr, &status);
15415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (status.cbInQue > 0) {
15425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->len = status.cbInQue;
15435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        win_chr_read_poll(chr);
15445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        win_chr_read(chr);
15455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
15465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
15485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
15495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_win(const char *filename)
15515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
15535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s;
15545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
15565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(WinCharState));
15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = win_chr_write;
15595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = win_chr_close;
15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (win_chr_init(chr, filename) < 0) {
15625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        free(s);
15635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        free(chr);
15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_pipe_poll(void *opaque)
15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD size;
15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size > 0) {
15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->len = size;
15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        win_chr_read_poll(chr);
15805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        win_chr_read(chr);
15815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
15825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
15845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
15855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_pipe_init(CharDriverState *chr, const char *filename)
15875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s = chr->opaque;
15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    OVERLAPPED ov;
15905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
15915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD size;
15925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char openname[256];
15935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fpipe = TRUE;
15955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
15975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->hsend) {
15985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed CreateEvent\n");
15995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
16005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->hrecv) {
16035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed CreateEvent\n");
16045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
16055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename);
16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
16105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              PIPE_WAIT,
16115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
16125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->hcom == INVALID_HANDLE_VALUE) {
16135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError());
16145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->hcom = NULL;
16155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ZeroMemory(&ov, sizeof(ov));
16195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
16205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = ConnectNamedPipe(s->hcom, &ov);
16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret) {
16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed ConnectNamedPipe\n");
16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
16275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!ret) {
16285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Failed GetOverlappedResult\n");
16295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ov.hEvent) {
16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            CloseHandle(ov.hEvent);
16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ov.hEvent = NULL;
16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
16345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ov.hEvent) {
16375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        CloseHandle(ov.hEvent);
16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ov.hEvent = NULL;
16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_add_polling_cb(win_chr_pipe_poll, chr);
16415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail:
16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    win_chr_close(chr);
16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
16465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_win_pipe(const char *filename)
16505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
16525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s;
16535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
16555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(WinCharState));
16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = win_chr_write;
16585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = win_chr_close;
16595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (win_chr_pipe_init(chr, filename) < 0) {
16615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        free(s);
16625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        free(chr);
16635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
16645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
16705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
16725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    WinCharState *s;
16735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(WinCharState));
16765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->hcom = fd_out;
16775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
16785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = win_chr_write;
16795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
16805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
16815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_win_con(const char *filename)
16845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
16865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
16895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    HANDLE fd_out;
16915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
16935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
16945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd_out == INVALID_HANDLE_VALUE)
16955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
16965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_chr_open_win_file(fd_out);
16985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* !_WIN32 */
17005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/
17025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* UDP Net console */
17035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
17055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr_in daddr;
17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[1024];
17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int bufcnt;
17095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int bufptr;
17105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int max_size;
17115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} NetCharDriver;
17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NetCharDriver *s = chr->opaque;
17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return sendto(s->fd, (const void *)buf, len, 0,
17185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  (struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in));
17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int udp_chr_read_poll(void *opaque)
17225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
17245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NetCharDriver *s = chr->opaque;
17255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->max_size = qemu_chr_can_read(chr);
17275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* If there were any stray characters in the queue process them
17295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * first
17305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     */
17315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (s->max_size > 0 && s->bufptr < s->bufcnt) {
17325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_read(chr, &s->buf[s->bufptr], 1);
17335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->bufptr++;
17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->max_size = qemu_chr_can_read(chr);
17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->max_size;
17375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_chr_read(void *opaque)
17405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
17425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NetCharDriver *s = chr->opaque;
17435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->max_size == 0)
17455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
17465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->bufcnt = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
17475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->bufptr = s->bufcnt;
17485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->bufcnt <= 0)
17495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
17505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->bufptr = 0;
17525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (s->max_size > 0 && s->bufptr < s->bufcnt) {
17535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_chr_read(chr, &s->buf[s->bufptr], 1);
17545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->bufptr++;
17555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->max_size = qemu_chr_can_read(chr);
17565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_chr_update_read_handler(CharDriverState *chr)
17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NetCharDriver *s = chr->opaque;
17625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->fd >= 0) {
17645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
17655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             udp_chr_read, NULL, chr);
17665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_chr_close(CharDriverState *chr)
17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NetCharDriver *s = chr->opaque;
17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->fd >= 0) {
17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
17745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        closesocket(s->fd);
17755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
17775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_udp(const char *def)
17805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = NULL;
17825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    NetCharDriver *s = NULL;
17835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd = -1;
17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr_in saddr;
17855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
17875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(NetCharDriver));
17885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fd = socket(PF_INET, SOCK_DGRAM, 0);
17905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd < 0) {
17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        perror("socket(PF_INET, SOCK_DGRAM)");
17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto return_err;
17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (parse_host_src_port(&s->daddr, &saddr, def) < 0) {
17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        printf("Could not parse: %s\n", def);
17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto return_err;
17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
18015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    {
18025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        perror("bind");
18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto return_err;
18045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fd = fd;
18075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->bufcnt = 0;
18085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->bufptr = 0;
18095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = udp_chr_write;
18115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_update_read_handler = udp_chr_update_read_handler;
18125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = udp_chr_close;
18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerreturn_err:
18165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (chr)
18175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        free(chr);
18185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s)
18195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        free(s);
18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd >= 0)
18215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        closesocket(fd);
18225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
18245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/
18265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* TCP Net console */
18275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
18295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd, listen_fd;
18305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int connected;
18315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int max_size;
18325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int do_telnetopt;
18335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int do_nodelay;
18345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_unix;
18355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} TCPCharDriver;
18365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_accept(void *opaque);
18385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
18405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
18415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = chr->opaque;
18425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->connected) {
18435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return send_all(s->fd, buf, len);
18445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
18455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* XXX: indicate an error ? */
18465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return len;
18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
18495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tcp_chr_read_poll(void *opaque)
18515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
18525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
18535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = chr->opaque;
18545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->connected)
18555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
18565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->max_size = qemu_chr_can_read(chr);
18575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->max_size;
18585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
18595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IAC 255
18615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IAC_BREAK 243
18625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_process_IAC_bytes(CharDriverState *chr,
18635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                      TCPCharDriver *s,
18645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                      uint8_t *buf, int *size)
18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
18665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Handle any telnet client's basic IAC options to satisfy char by
18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * char mode with no echo.  All IAC options will be removed from
18685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * the buf and the do_telnetopt variable will be used to track the
18695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * state of the width of the IAC information.
18705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     *
18715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * IAC commands come in sets of 3 bytes with the exception of the
18725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * "IAC BREAK" command and the double IAC.
18735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     */
18745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
18765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int j = 0;
18775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < *size; i++) {
18795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (s->do_telnetopt > 1) {
18805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
18815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* Double IAC means send an IAC */
18825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (j != i)
18835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    buf[j] = buf[i];
18845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                j++;
18855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                s->do_telnetopt = 1;
18865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
18875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
18885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    /* Handle IAC break commands by sending a serial break */
18895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qemu_chr_event(chr, CHR_EVENT_BREAK);
18905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    s->do_telnetopt++;
18915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
18925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                s->do_telnetopt++;
18935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
18945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (s->do_telnetopt >= 4) {
18955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                s->do_telnetopt = 1;
18965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
18975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
18985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if ((unsigned char)buf[i] == IAC) {
18995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                s->do_telnetopt = 2;
19005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
19015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (j != i)
19025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    buf[j] = buf[i];
19035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                j++;
19045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
19055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
19065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
19075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    *size = j;
19085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_read(void *opaque)
19115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
19135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = chr->opaque;
19145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[1024];
19155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int len, size;
19165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!s->connected || s->max_size <= 0)
19185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
19195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = sizeof(buf);
19205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len > s->max_size)
19215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = s->max_size;
19225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    size = recv(s->fd, (void *)buf, len, 0);
19235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (size == 0) {
19245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* connection closed */
19255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->connected = 0;
19265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (s->listen_fd >= 0) {
19275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
19285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
19295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
19305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        closesocket(s->fd);
19315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->fd = -1;
19325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (size > 0) {
19335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (s->do_telnetopt)
19345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcp_chr_process_IAC_bytes(chr, s, buf, &size);
19355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (size > 0)
19365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_chr_read(chr, buf, size);
19375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
19385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_connect(void *opaque)
19415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
19435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = chr->opaque;
19445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->connected = 1;
19465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
19475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         tcp_chr_read, NULL, chr);
19485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_chr_reset(chr);
19495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
19525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_telnet_init(int fd)
19535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char buf[3];
19555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Send the telnet negotion to put telnet in binary, no echo, single char mode */
19565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IACSET(buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
19575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    send(fd, (char *)buf, 3, 0);
19585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IACSET(buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
19595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    send(fd, (char *)buf, 3, 0);
19605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IACSET(buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
19615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    send(fd, (char *)buf, 3, 0);
19625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    IACSET(buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
19635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    send(fd, (char *)buf, 3, 0);
19645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void socket_set_nodelay(int fd)
19675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int val = 1;
19695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
19705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_accept(void *opaque)
19735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = opaque;
19755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = chr->opaque;
19765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr_in saddr;
19775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32
19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr_un uaddr;
19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr *addr;
19815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socklen_t len;
19825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
19835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(;;) {
19855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32
19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (s->is_unix) {
19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    len = sizeof(uaddr);
19885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    addr = (struct sockaddr *)&uaddr;
19895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	} else
19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
19915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	{
19925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    len = sizeof(saddr);
19935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    addr = (struct sockaddr *)&saddr;
19945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
19955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fd = accept(s->listen_fd, addr, &len);
19965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (fd < 0 && errno != EINTR) {
19975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return;
19985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (fd >= 0) {
19995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (s->do_telnetopt)
20005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcp_chr_telnet_init(fd);
20015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
20025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socket_set_nonblock(fd);
20055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->do_nodelay)
20065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        socket_set_nodelay(fd);
20075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fd = fd;
20085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
20095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcp_chr_connect(chr);
20105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_close(CharDriverState *chr)
20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = chr->opaque;
20155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->fd >= 0) {
20165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
20175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        closesocket(s->fd);
20185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s->listen_fd >= 0) {
20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
20215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        closesocket(s->listen_fd);
20225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
20245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_tcp(const char *host_str,
20275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                          int is_telnet,
20285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					  int is_unix)
20295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr = NULL;
20315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCPCharDriver *s = NULL;
20325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd = -1, offset = 0;
20335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_listen = 0;
20345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_waitconnect = 1;
20355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int do_nodelay = 0;
20365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const char *ptr;
20375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ptr = host_str;
20395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while((ptr = strchr(ptr,','))) {
20405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ptr++;
20415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!strncmp(ptr,"server",6)) {
20425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            is_listen = 1;
20435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (!strncmp(ptr,"nowait",6)) {
20445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            is_waitconnect = 0;
20455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (!strncmp(ptr,"nodelay",6)) {
20465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            do_nodelay = 1;
20475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (!strncmp(ptr,"to=",3)) {
20485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* nothing, inet_listen() parses this one */;
20495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (!strncmp(ptr,"ipv4",4)) {
20505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* nothing, inet_connect() and inet_listen() parse this one */;
20515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (!strncmp(ptr,"ipv6",4)) {
20525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* nothing, inet_connect() and inet_listen() parse this one */;
20535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
20545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            printf("Unknown option: %s\n", ptr);
20555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto fail;
20565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!is_listen)
20595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        is_waitconnect = 0;
20605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr = qemu_mallocz(sizeof(CharDriverState));
20625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(TCPCharDriver));
20635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_listen) {
20655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr->filename = qemu_malloc(256);
20665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (is_unix) {
20675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pstrcpy(chr->filename, 256, "unix:");
20685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (is_telnet) {
20695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pstrcpy(chr->filename, 256, "telnet:");
20705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
20715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pstrcpy(chr->filename, 256, "tcp:");
20725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        offset = strlen(chr->filename);
20745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_unix) {
20765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (is_listen) {
20775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fd = unix_listen(host_str, chr->filename + offset, 256 - offset);
20785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
20795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fd = unix_connect(host_str);
20805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
20825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (is_listen) {
20835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fd = inet_listen(host_str, chr->filename + offset, 256 - offset,
20845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             SOCK_STREAM, 0);
20855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
20865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fd = inet_connect(host_str, SOCK_STREAM);
20875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd < 0)
20905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
20915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!is_waitconnect)
20935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        socket_set_nonblock(fd);
20945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->connected = 0;
20965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fd = -1;
20975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->listen_fd = -1;
20985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->is_unix = is_unix;
20995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->do_nodelay = do_nodelay && !is_unix;
21005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->opaque = s;
21025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_write = tcp_chr_write;
21035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    chr->chr_close = tcp_chr_close;
21045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_listen) {
21065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->listen_fd = fd;
21075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
21085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (is_telnet)
21095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            s->do_telnetopt = 1;
21105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
21115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->connected = 1;
21125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        s->fd = fd;
21135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        socket_set_nodelay(fd);
21145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tcp_chr_connect(chr);
21155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
21165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_listen && is_waitconnect) {
21185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        printf("QEMU waiting for connection on: %s\n",
21195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               chr->filename ? chr->filename : host_str);
21205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tcp_chr_accept(chr);
21215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        socket_set_nonblock(s->listen_fd);
21225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
21235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
21255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail:
21265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (fd >= 0)
21275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        closesocket(fd);
21285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
21295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(chr);
21305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
21315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerCharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s))
21345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const char *p;
21365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
21375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!strcmp(filename, "vc")) {
21395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = text_console_init(0);
21405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "vc:", &p)) {
21425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = text_console_init(p);
21435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!strcmp(filename, "null")) {
21455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_null();
21465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "tcp:", &p)) {
21485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_tcp(p, 0, 0);
21495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "telnet:", &p)) {
21515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_tcp(p, 1, 0);
21525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "udp:", &p)) {
21545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_udp(p);
21555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "mon:", &p)) {
21575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open(label, p, NULL);
21585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (chr) {
21595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            chr = qemu_chr_open_mux(chr);
21605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_init(chr, MONITOR_USE_READLINE);
21615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
21625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            printf("Unable to open driver: %s\n", p);
21635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
21645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!strcmp(filename, "msmouse")) {
21655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_msmouse();
21665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32
21685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "unix:", &p)) {
21695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	chr = qemu_chr_open_tcp(p, 0, 1);
21705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (strstart(filename, "file:", &p)) {
21715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_file_out(p);
21725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (strstart(filename, "pipe:", &p)) {
21735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_pipe(p);
21745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!strcmp(filename, "pty")) {
21755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_pty();
21765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!strcmp(filename, "stdio")) {
21775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_stdio();
21785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__linux__)
21805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "/dev/parport", NULL)) {
21815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_pp(filename);
21825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__FreeBSD__) || defined(__DragonFly__)
21845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "/dev/ppi", NULL)) {
21855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_pp(filename);
21865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
21885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
21895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
21905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "/dev/", NULL)) {
21915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_tty(filename);
21925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
21945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else /* !_WIN32 */
21955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "COM", NULL)) {
21965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_win(filename);
21975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
21985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "pipe:", &p)) {
21995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_win_pipe(p);
22005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
22015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "con:", NULL)) {
22025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_win_con(filename);
22035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
22045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (strstart(filename, "file:", &p)) {
22055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = qemu_chr_open_win_file_out(p);
22065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
22075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
22085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_BRLAPI
22095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!strcmp(filename, "braille")) {
22105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = chr_baum_init();
22115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
22125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
22135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    {
22145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr = NULL;
22155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
22165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (chr) {
22185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!chr->filename)
22195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            chr->filename = qemu_strdup(filename);
22205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr->init = init;
22215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr->label = qemu_strdup(label);
22225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        TAILQ_INSERT_TAIL(&chardevs, chr, next);
22235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
22245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return chr;
22255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
22265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_close(CharDriverState *chr)
22285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
22295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TAILQ_REMOVE(&chardevs, chr, next);
22305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (chr->chr_close)
22315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        chr->chr_close(chr);
22325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(chr->filename);
22335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(chr->label);
22345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(chr);
22355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
22365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_info(Monitor *mon)
22385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
22395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CharDriverState *chr;
22405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2241a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH(chr, &chardevs, next) {
22425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        monitor_printf(mon, "%s: filename=%s\n", chr->label, chr->filename);
22435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
22445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2245