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, 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IOCanRWHandler *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 { 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IOCanRWHandler *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