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" 253b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "sockets.h" 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h" 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "monitor.h" 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "console.h" 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sysemu.h" 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-timer.h" 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-char.h" 323b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "block.h" 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/usb.h" 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/baum.h" 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/msmouse.h" 369d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#include "qemu-objects.h" 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <unistd.h> 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <fcntl.h> 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <signal.h> 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <time.h> 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <errno.h> 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/time.h> 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <zlib.h> 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/times.h> 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/wait.h> 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <termios.h> 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/mman.h> 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ioctl.h> 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/resource.h> 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/socket.h> 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h> 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h> 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <arpa/inet.h> 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dirent.h> 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netdb.h> 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/select.h> 602c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h> 6217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libutil.h> 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dev/ppbus/ppi.h> 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dev/ppbus/ppbconf.h> 6617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner#if defined(__GLIBC__) 6717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner#include <pty.h> 6817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner#endif 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__DragonFly__) 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libutil.h> 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dev/misc/ppi/ppi.h> 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <bus/ppbus/ppbconf.h> 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <util.h> 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__ 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <pty.h> 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/ppdev.h> 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/parport.h> 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __sun__ 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h> 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ethernet.h> 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/sockio.h> 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/arp.h> 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h> 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in_systm.h> 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/ip.h> 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/ip_icmp.h> // must come after ip.h 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/udp.h> 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/tcp.h> 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h> 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <syslog.h> 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stropts.h> 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu_socket.h" 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1039d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#define READ_BUF_LEN 4096 1049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 1053b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#ifdef CONFIG_ANDROID 1063b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "charpipe.h" 1073b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "modem_driver.h" 1083b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "android/gps.h" 1093b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "android/hw-kmsg.h" 1103b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#include "android/hw-qemud.h" 1113b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#endif /* CONFIG_ANDROID */ 1123b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/ 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* character device */ 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1169d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = 1179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QTAILQ_HEAD_INITIALIZER(chardevs); 1183b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turnerstatic int initial_reset_issued; 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_chr_event(CharDriverState *s, int event) 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1229d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* Keep track if the char device is open */ 1239d1188280fa5294f9438424e5e8eae91f645bfd8David Turner switch (event) { 1249d1188280fa5294f9438424e5e8eae91f645bfd8David Turner case CHR_EVENT_OPENED: 1259d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->opened = 1; 1269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner break; 1279d1188280fa5294f9438424e5e8eae91f645bfd8David Turner case CHR_EVENT_CLOSED: 1289d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->opened = 0; 1299d1188280fa5294f9438424e5e8eae91f645bfd8David Turner break; 1309d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 1319d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->chr_event) 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_event(s->handler_opaque, event); 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1379d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic void qemu_chr_generic_open_bh(void *opaque) 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *s = opaque; 140a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner qemu_chr_event(s, CHR_EVENT_OPENED); 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_bh_delete(s->bh); 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bh = NULL; 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1459d1188280fa5294f9438424e5e8eae91f645bfd8David Turnervoid qemu_chr_generic_open(CharDriverState *s) 1469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 1479d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (s->bh == NULL) { 1489d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->bh = qemu_bh_new(qemu_chr_generic_open_bh, s); 1499d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_bh_schedule(s->bh); 1509d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 1519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 1529d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_reset(CharDriverState *s) 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->bh == NULL && initial_reset_issued) { 1569d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->bh = qemu_bh_new(qemu_chr_generic_open_bh, s); 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_bh_schedule(s->bh); 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_initial_reset(void) 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner initial_reset_issued = 1; 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 167a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QTAILQ_FOREACH(chr, &chardevs, next) { 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_reset(chr); 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->chr_write(s, buf, len); 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg) 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->chr_ioctl) 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->chr_ioctl(s, cmd, arg); 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_chr_can_read(CharDriverState *s) 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->chr_can_read) 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->chr_can_read(s->handler_opaque); 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_read(s->handler_opaque, buf, len); 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1969d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerint qemu_chr_get_msgfd(CharDriverState *s) 1979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 1989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return s->get_msgfd ? s->get_msgfd(s) : -1; 1999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 2009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_accept_input(CharDriverState *s) 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->chr_accept_input) 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_accept_input(s); 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_printf(CharDriverState *s, const char *fmt, ...) 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner char buf[READ_BUF_LEN]; 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner va_list ap; 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner va_start(ap, fmt); 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vsnprintf(buf, sizeof(buf), fmt, ap); 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_write(s, (uint8_t *)buf, strlen(buf)); 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner va_end(ap); 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_send_event(CharDriverState *s, int event) 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->chr_send_event) 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_send_event(s, event); 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_add_handlers(CharDriverState *s, 2244143d8f4c302878923bde0cb2420f4ca27245bcdDavid Turner IOCanReadHandler *fd_can_read, 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IOReadHandler *fd_read, 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IOEventHandler *fd_event, 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *opaque) 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 22917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (!opaque && !fd_can_read && !fd_read && !fd_event) { 23017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner /* chr driver being released. */ 23117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner ++s->avail_connections; 23217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_can_read = fd_can_read; 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_read = fd_read; 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_event = fd_event; 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->handler_opaque = opaque; 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->chr_update_read_handler) 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->chr_update_read_handler(s); 2399d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 2409d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* We're connecting to an already opened device, so let's make sure we 2419d1188280fa5294f9438424e5e8eae91f645bfd8David Turner also get the open event */ 2429d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (s->opened) { 2439d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(s); 2449d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len; 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2529d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_null(QemuOpts *opts) 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = null_chr_write; 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* MUX driver for serial I/O splitting */ 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MAX_MUX 4 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 2664143d8f4c302878923bde0cb2420f4ca27245bcdDavid Turner IOCanReadHandler *chr_can_read[MAX_MUX]; 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IOReadHandler *chr_read[MAX_MUX]; 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IOEventHandler *chr_event[MAX_MUX]; 2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *ext_opaque[MAX_MUX]; 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *drv; 2719d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int focus; 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int mux_cnt; 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int term_got_escape; 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_size; 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Intermediate input buffer allows to catch escape sequences even if the 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner currently active device is not accepting any input - but only until it 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is full as well. */ 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE]; 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int prod[MAX_MUX]; 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int cons[MAX_MUX]; 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int timestamps; 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int linestart; 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int64_t timestamps_start; 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} MuxDriver; 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d = chr->opaque; 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!d->timestamps) { 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = d->drv->chr_write(d->drv, buf, len); 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = 0; 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < len; i++) { 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->linestart) { 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf1[64]; 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int64_t ti; 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int secs; 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3035973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner ti = qemu_get_clock_ms(rt_clock); 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->timestamps_start == -1) 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->timestamps_start = ti; 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ti -= d->timestamps_start; 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner secs = ti / 1000; 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(buf1, sizeof(buf1), 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "[%02d:%02d:%02d.%03d] ", 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner secs / 3600, 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (secs / 60) % 60, 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner secs % 60, 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (int)(ti % 1000)); 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1)); 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->linestart = 0; 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret += d->drv->chr_write(d->drv, buf+i, 1); 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (buf[i] == '\n') { 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->linestart = 1; 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char * const mux_help[] = { 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% h print this help\n\r", 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% x exit emulator\n\r", 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% s save disk data back to file (if -snapshot)\n\r", 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% t toggle console timestamps\n\r" 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% b send break (magic sysrq)\n\r", 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% c switch between console and monitor\n\r", 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "% % sends %\n\r", 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint term_escape_char = 0x01; /* ctrl-a is used for escape */ 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_print_help(CharDriverState *chr) 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i, j; 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char ebuf[15] = "Escape-Char"; 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char cbuf[50] = "\n\r"; 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (term_escape_char > 0 && term_escape_char < 26) { 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(cbuf, sizeof(cbuf), "\n\r"); 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a'); 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(cbuf, sizeof(cbuf), 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner term_escape_char); 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf)); 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; mux_help[i] != NULL; i++) { 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (j=0; mux_help[i][j] != '\0'; j++) { 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (mux_help[i][j] == '%') 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf)); 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1); 3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_send_event(MuxDriver *d, int mux_nr, int event) 3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->chr_event[mux_nr]) 3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_event[mux_nr](d->ext_opaque[mux_nr], event); 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) 3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->term_got_escape) { 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->term_got_escape = 0; 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ch == term_escape_char) 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto send_char; 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(ch) { 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case '?': 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'h': 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner mux_print_help(chr); 3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'x': 3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *term = "QEMU: Terminated\n\r"; 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write(chr,(uint8_t *)term,strlen(term)); 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(0); 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 's': 38817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner bdrv_commit_all(); 3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'b': 3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_event(chr, CHR_EVENT_BREAK); 3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'c': 3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Switch to the next registered device */ 3959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); 3969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner d->focus++; 3979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (d->focus >= d->mux_cnt) 3989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner d->focus = 0; 3999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); 4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 't': 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->timestamps = !d->timestamps; 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->timestamps_start = -1; 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->linestart = 0; 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (ch == term_escape_char) { 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->term_got_escape = 1; 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_char: 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_accept_input(CharDriverState *chr) 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d = chr->opaque; 4199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int m = d->focus; 4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (d->prod[m] != d->cons[m] && 4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_can_read[m] && 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_can_read[m](d->ext_opaque[m])) { 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_read[m](d->ext_opaque[m], 4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); 4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int mux_chr_can_read(void *opaque) 4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d = chr->opaque; 4339d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int m = d->focus; 4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) 4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->chr_can_read[m]) 4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return d->chr_can_read[m](d->ext_opaque[m]); 4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_read(void *opaque, const uint8_t *buf, int size) 4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d = chr->opaque; 4469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int m = d->focus; 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner mux_chr_accept_input (opaque); 4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(i = 0; i < size; i++) 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (mux_proc_byte(chr, d, buf[i])) { 4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->prod[m] == d->cons[m] && 4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_can_read[m] && 4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_can_read[m](d->ext_opaque[m])) 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_read[m](d->ext_opaque[m], &buf[i], 1); 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i]; 4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_event(void *opaque, int event) 4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d = chr->opaque; 4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Send the event to all registered listeners */ 4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < d->mux_cnt; i++) 4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner mux_chr_send_event(d, i, event); 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void mux_chr_update_read_handler(CharDriverState *chr) 4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d = chr->opaque; 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->mux_cnt >= MAX_MUX) { 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n"); 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->ext_opaque[d->mux_cnt] = chr->handler_opaque; 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_can_read[d->mux_cnt] = chr->chr_can_read; 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_read[d->mux_cnt] = chr->chr_read; 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->chr_event[d->mux_cnt] = chr->chr_event; 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Fix up the real driver with mux routines */ 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (d->mux_cnt == 0) { 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, 4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner mux_chr_event, chr); 4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (d->focus != -1) { 4919d1188280fa5294f9438424e5e8eae91f645bfd8David Turner mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); 4929d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 4939d1188280fa5294f9438424e5e8eae91f645bfd8David Turner d->focus = d->mux_cnt; 4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->mux_cnt++; 4959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); 4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_mux(CharDriverState *drv) 4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MuxDriver *d; 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d = qemu_mallocz(sizeof(MuxDriver)); 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = d; 5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d->drv = drv; 5089d1188280fa5294f9438424e5e8eae91f645bfd8David Turner d->focus = -1; 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = mux_chr_write; 5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_update_read_handler = mux_chr_update_read_handler; 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_accept_input = mux_chr_accept_input; 51217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner /* Frontend guest-open / -close notification is not support with muxes */ 51317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_guest_open = NULL; 51417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_guest_close = NULL; 5159d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 5169d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* Muxes are always open on creation */ 5179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 5189d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint send_all(int fd, const void *buf, int len1) 5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5263b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#if 1 5273b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return socket_send(fd, buf, len1); 5283b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#else 5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret, len; 5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = len1; 5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (len > 0) { 5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = send(fd, buf, len, 0); 5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = WSAGetLastError(); 5363b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (errno != WSAEWOULDBLOCK && errno != WSAEAGAIN) { 5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (ret == 0) { 5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += ret; 5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len -= ret; 5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len1 - len; 5473b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#endif 5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 55217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnerint send_all(int fd, const void *_buf, int len1) 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret, len; 55517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner const uint8_t *buf = _buf; 5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = len1; 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (len > 0) { 5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = write(fd, buf, len); 5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (errno != EINTR && errno != EAGAIN) 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (ret == 0) { 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += ret; 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len -= ret; 5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len1 - len; 5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* !_WIN32 */ 5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5743b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_android_modem(QemuOpts* opts) 5753b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner{ 5763b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner CharDriverState* cs; 5773b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_chr_open_charpipe( &cs, &android_modem_cs ); 5783b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return cs; 5793b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner} 5803b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_android_gps(QemuOpts* opts) 5813b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner{ 5823b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner CharDriverState* cs; 5833b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_chr_open_charpipe( &cs, &android_gps_cs ); 5843b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return cs; 5853b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner} 5863b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 5873b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_android_kmsg(QemuOpts* opts) 5883b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner{ 5893b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return android_kmsg_get_cs(); 5903b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner} 5913b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 5923b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_android_qemud(QemuOpts* opts) 5933b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner{ 5943b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return android_qemud_get_cs(); 5953b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner} 5963b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 5973b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd_in, fd_out; 6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_size; 6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} FDCharDriver; 6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define STDIO_MAX_CLIENTS 1 6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int stdio_nb_clients = 0; 6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s = chr->opaque; 6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return send_all(s->fd_out, buf, len); 6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int fd_chr_read_poll(void *opaque) 6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s = chr->opaque; 6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->max_size = qemu_chr_can_read(chr); 6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->max_size; 6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void fd_chr_read(void *opaque) 6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s = chr->opaque; 6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size, len; 6289d1188280fa5294f9438424e5e8eae91f645bfd8David Turner uint8_t buf[READ_BUF_LEN]; 6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = sizeof(buf); 6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len > s->max_size) 6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = s->max_size; 6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 0) 6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = read(s->fd_in, buf, len); 6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size == 0) { 6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* FD has been closed. Remove it from the active list. */ 6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); 6399d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) { 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, buf, size); 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void fd_chr_update_read_handler(CharDriverState *chr) 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s = chr->opaque; 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd_in >= 0) { 6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (display_type == DT_NOGRAPHIC && s->fd_in == 0) { 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_chr_read, NULL, chr); 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void fd_chr_close(struct CharDriverState *chr) 6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s = chr->opaque; 6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd_in >= 0) { 6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (display_type == DT_NOGRAPHIC && s->fd_in == 0) { 6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); 6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 6729d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* open a character device to a unix fd */ 6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) 6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s; 6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(FDCharDriver)); 6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd_in = fd_in; 6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd_out = fd_out; 6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = fd_chr_write; 6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_update_read_handler = fd_chr_update_read_handler; 6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = fd_chr_close; 6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6959d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_file_out(QemuOpts *opts) 6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd_out; 6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"), 7009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666)); 7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd_out < 0) 7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_chr_open_fd(-1, fd_out); 7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7069d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_pipe(QemuOpts *opts) 7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd_in, fd_out; 7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char filename_in[256], filename_out[256]; 7109d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *filename = qemu_opt_get(opts, "path"); 7119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 7129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (filename == NULL) { 7139d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fprintf(stderr, "chardev: pipe: no filename given\n"); 7149d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 7159d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(filename_in, 256, "%s.in", filename); 7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(filename_out, 256, "%s.out", filename); 7199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY)); 7209d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY)); 7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd_in < 0 || fd_out < 0) { 7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd_in >= 0) 7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd_in); 7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd_out >= 0) 7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd_out); 7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY)); 7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd_in < 0) 7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_chr_open_fd(fd_in, fd_out); 7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7333b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#ifdef CONFIG_ANDROID 7343b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_fdpair(QemuOpts* opts) 7353b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner{ 7363b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner int fd_in = qemu_opt_get_number(opts, "fdin",-1); 7373b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner int fd_out = qemu_opt_get_number(opts, "fdout",-1); 7383b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 7393b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (fd_in < 0 || fd_out < 0) 7403b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return NULL; 7413b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner 7423b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return qemu_chr_open_fd(fd_in, fd_out); 7433b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner} 7443b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#endif /* CONFIG_ANDROID */ 7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* for STDIO, we handle the case where several clients use it 7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (nographic mode) */ 7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TERM_FIFO_MAX_SIZE 1 7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic uint8_t term_fifo[TERM_FIFO_MAX_SIZE]; 7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int term_fifo_size; 7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int stdio_read_poll(void *opaque) 7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* try to flush the queue if needed */ 7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) { 7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, term_fifo, 1); 7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner term_fifo_size = 0; 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* see if we can absorb more chars */ 7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (term_fifo_size == 0) 7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void stdio_read(void *opaque) 7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size; 7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buf[1]; 7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = read(0, buf, 1); 7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size == 0) { 7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* stdin has been closed. Remove it from the active list. */ 7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); 7809d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) { 7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (qemu_chr_can_read(chr) > 0) { 7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, buf, 1); 7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (term_fifo_size == 0) { 7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner term_fifo[term_fifo_size++] = buf[0]; 7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* init terminal so that we can grab keys */ 7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct termios oldtty; 7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int old_fd0_flags; 79517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnerstatic bool stdio_allow_signal; 7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void term_exit(void) 7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcsetattr (0, TCSANOW, &oldtty); 8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fcntl(0, F_SETFL, old_fd0_flags); 8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 80317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnerstatic void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo) 8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct termios tty; 8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 80717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner tty = oldtty; 80817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (!echo) { 8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP 8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner |INLCR|IGNCR|ICRNL|IXON); 8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_oflag |= OPOST; 8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); 8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag &= ~(CSIZE|PARENB); 8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= CS8; 8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cc[VMIN] = 1; 8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cc[VTIME] = 0; 81717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 81817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner /* if graphical mode, we allow Ctrl-C handling */ 81917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (!stdio_allow_signal) 82017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner tty.c_lflag &= ~ISIG; 8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcsetattr (0, TCSANOW, &tty); 8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_chr_close_stdio(struct CharDriverState *chr) 8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner term_exit(); 8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner stdio_nb_clients--; 8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); 8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_chr_close(chr); 8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8339d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_stdio(QemuOpts *opts) 8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (stdio_nb_clients >= STDIO_MAX_CLIENTS) 8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 83917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (stdio_nb_clients == 0) { 84017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner old_fd0_flags = fcntl(0, F_GETFL); 84117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner tcgetattr (0, &oldtty); 84217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner fcntl(0, F_SETFL, O_NONBLOCK); 84317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner atexit(term_exit); 84417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 84517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_chr_open_fd(0, 1); 8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = qemu_chr_close_stdio; 84817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_set_echo = qemu_chr_set_echo_stdio; 8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr); 8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner stdio_nb_clients++; 85117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner stdio_allow_signal = qemu_opt_get_bool(opts, "signal", 85217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner display_type != DT_NOGRAPHIC); 85317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner qemu_chr_set_echo(chr, false); 8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __sun__ 8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Once Solaris has openpty(), this is going to be removed. */ 8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int openpty(int *amaster, int *aslave, char *name, 8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct termios *termp, struct winsize *winp) 8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *slave; 8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int mfd = -1, sfd = -1; 8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *amaster = *aslave = -1; 8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY); 8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (mfd < 0) 8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (grantpt(mfd) == -1 || unlockpt(mfd) == -1) 8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((slave = ptsname(mfd)) == NULL) 8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1) 8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(sfd, I_PUSH, "ptem") == -1 || 8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (termp != NULL && tcgetattr(sfd, termp) < 0)) 8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (amaster) 8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *amaster = mfd; 8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (aslave) 8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *aslave = sfd; 8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (winp) 8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl(sfd, TIOCSWINSZ, winp); 8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr: 8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sfd != -1) 8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(sfd); 8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(mfd); 8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void cfmakeraw (struct termios *termios_p) 9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_iflag &= 9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); 9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_oflag &= ~OPOST; 9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); 9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_cflag &= ~(CSIZE|PARENB); 9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_cflag |= CS8; 9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_cc[VMIN] = 0; 9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner termios_p->c_cc[VTIME] = 0; 9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9153b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#ifndef _WIN32 9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int connected; 9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int polling; 9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int read_bytes; 9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner QEMUTimer *timer; 9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} PtyCharDriver; 9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_update_read_handler(CharDriverState *chr); 9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_state(CharDriverState *chr, int connected); 9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->connected) { 9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* guest sends data, check for (re-)connect */ 9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pty_chr_update_read_handler(chr); 9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return send_all(s->fd, buf, len); 9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pty_chr_read_poll(void *opaque) 9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->read_bytes = qemu_chr_can_read(chr); 9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->read_bytes; 9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_read(void *opaque) 9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size, len; 9549d1188280fa5294f9438424e5e8eae91f645bfd8David Turner uint8_t buf[READ_BUF_LEN]; 9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = sizeof(buf); 9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len > s->read_bytes) 9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = s->read_bytes; 9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len == 0) 9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = read(s->fd, buf, len); 9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((size == -1 && errno == EIO) || 9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (size == 0)) { 9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pty_chr_state(chr, 0); 9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) { 9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pty_chr_state(chr, 1); 9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, buf, size); 9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_update_read_handler(CharDriverState *chr) 9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, pty_chr_read_poll, 9785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pty_chr_read, NULL, chr); 9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->polling = 1; 9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Short timeout here: just need wait long enougth that qemu makes 9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * it through the poll loop once. When reconnected we want a 9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * short timeout so we notice it almost instantly. Otherwise 9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * read() gives us -EIO instantly, making pty_chr_state() reset the 9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * timeout to the normal (much longer) poll interval before the 9865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * timer triggers. 9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 9885973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 10); 9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_state(CharDriverState *chr, int connected) 9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!connected) { 9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->connected = 0; 9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->polling = 0; 9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* (re-)connect poll interval for idle guests: once per second. 10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * We check more frequently in case the guests sends data to 10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the virtual device linked to our pty. */ 10025973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 1000); 10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->connected) 10059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->connected = 1; 10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_timer(void *opaque) 10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct CharDriverState *chr = opaque; 10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->connected) 10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->polling) { 10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* If we arrive here without polling being cleared due 10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * read returning -EIO, then we are (re-)connected */ 10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pty_chr_state(chr, 1); 10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Next poll ... */ 10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pty_chr_update_read_handler(chr); 10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pty_chr_close(struct CharDriverState *chr) 10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s = chr->opaque; 10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_del_timer(s->timer); 10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free_timer(s->timer); 10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 10379d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10409d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_pty(QemuOpts *opts) 10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PtyCharDriver *s; 10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct termios tty; 10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int slave_fd, len; 10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__OpenBSD__) || defined(__DragonFly__) 10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char pty_name[PATH_MAX]; 10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define q_ptsname(x) pty_name 10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *pty_name = NULL; 10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define q_ptsname(x) ptsname(x) 10523b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner //extern char* ptsname(int); 10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(PtyCharDriver)); 10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) { 10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Set raw attributes on the pty. */ 10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcgetattr(slave_fd, &tty); 10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cfmakeraw(&tty); 10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcsetattr(slave_fd, TCSAFLUSH, &tty); 10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(slave_fd); 10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = strlen(q_ptsname(s->fd)) + 5; 10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->filename = qemu_malloc(len); 10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd)); 10719d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "path", q_ptsname(s->fd)); 10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd)); 10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = pty_chr_write; 10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_update_read_handler = pty_chr_update_read_handler; 10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = pty_chr_close; 10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10795973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr); 10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tty_serial_init(int fd, int speed, 10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int parity, int data_bits, int stop_bits) 10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct termios tty; 10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner speed_t spd; 10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", 10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner speed, parity, data_bits, stop_bits); 10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcgetattr (fd, &tty); 10959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 10969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#define check_speed(val) if (speed <= val) { spd = B##val; break; } 10979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner speed = speed * 10 / 11; 10989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner do { 10999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(50); 11009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(75); 11019d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(110); 11029d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(134); 11039d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(150); 11049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(200); 11059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(300); 11069d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(600); 11079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(1200); 11089d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(1800); 11099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(2400); 11109d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(4800); 11119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(9600); 11129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(19200); 11139d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(38400); 11149d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* Non-Posix values follow. They may be unsupported on some systems. */ 11159d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(57600); 11169d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(115200); 11179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B230400 11189d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(230400); 11199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11209d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B460800 11219d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(460800); 11229d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11239d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B500000 11249d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(500000); 11259d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B576000 11279d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(576000); 11289d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11299d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B921600 11309d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(921600); 11319d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11329d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B1000000 11339d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(1000000); 11349d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11359d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B1152000 11369d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(1152000); 11379d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11389d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B1500000 11399d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(1500000); 11409d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11419d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B2000000 11429d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(2000000); 11439d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11449d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B2500000 11459d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(2500000); 11469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11479d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B3000000 11489d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(3000000); 11499d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11509d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B3500000 11519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(3500000); 11529d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11539d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef B4000000 11549d1188280fa5294f9438424e5e8eae91f645bfd8David Turner check_speed(4000000); 11559d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner spd = B115200; 11579d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } while (0); 11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cfsetispeed(&tty, spd); 11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cfsetospeed(&tty, spd); 11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP 11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner |INLCR|IGNCR|ICRNL|IXON); 11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_oflag |= OPOST; 11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); 11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB); 11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(data_bits) { 11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 8: 11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= CS8; 11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 7: 11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= CS7; 11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 6: 11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= CS6; 11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 5: 11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= CS5; 11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(parity) { 11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'N': 11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'E': 11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= PARENB; 11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'O': 11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= PARENB | PARODD; 11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (stop_bits == 2) 11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty.c_cflag |= CSTOPB; 11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcsetattr (fd, TCSANOW, &tty); 11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) 12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FDCharDriver *s = chr->opaque; 12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(cmd) { 12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_SERIAL_SET_PARAMS: 12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner QEMUSerialSetParams *ssp = arg; 12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty_serial_init(s->fd_in, ssp->speed, ssp->parity, 12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssp->data_bits, ssp->stop_bits); 12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_SERIAL_SET_BREAK: 12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 12135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int enable = *(int *)arg; 12145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (enable) 12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcsendbreak(s->fd_in, 1); 12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_SERIAL_GET_TIOCM: 12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int sarg = 0; 12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int *targ = (int *)arg; 12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl(s->fd_in, TIOCMGET, &sarg); 12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ = 0; 12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & TIOCM_CTS) 12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ |= CHR_TIOCM_CTS; 12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & TIOCM_CAR) 12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ |= CHR_TIOCM_CAR; 12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & TIOCM_DSR) 12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ |= CHR_TIOCM_DSR; 12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & TIOCM_RI) 12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ |= CHR_TIOCM_RI; 12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & TIOCM_DTR) 12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ |= CHR_TIOCM_DTR; 12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & TIOCM_RTS) 12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *targ |= CHR_TIOCM_RTS; 12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_SERIAL_SET_TIOCM: 12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int sarg = *(int *)arg; 12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int targ = 0; 12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl(s->fd_in, TIOCMGET, &targ); 12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR 12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS); 12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & CHR_TIOCM_CTS) 12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ |= TIOCM_CTS; 12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & CHR_TIOCM_CAR) 12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ |= TIOCM_CAR; 12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & CHR_TIOCM_DSR) 12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ |= TIOCM_DSR; 12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & CHR_TIOCM_RI) 12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ |= TIOCM_RI; 12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & CHR_TIOCM_DTR) 12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ |= TIOCM_DTR; 12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sarg & CHR_TIOCM_RTS) 12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner targ |= TIOCM_RTS; 12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl(s->fd_in, TIOCMSET, &targ); 12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12669d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic void qemu_chr_close_tty(CharDriverState *chr) 12679d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 12689d1188280fa5294f9438424e5e8eae91f645bfd8David Turner FDCharDriver *s = chr->opaque; 12699d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int fd = -1; 12709d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 12719d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (s) { 12729d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = s->fd_in; 12739d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 12749d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 12759d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd_chr_close(chr); 12769d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 12779d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (fd >= 0) { 12789d1188280fa5294f9438424e5e8eae91f645bfd8David Turner close(fd); 12799d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 12809d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 12819d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 12829d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_tty(QemuOpts *opts) 12835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 12849d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *filename = qemu_opt_get(opts, "path"); 12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 12875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(fd = open(filename, O_RDWR | O_NONBLOCK)); 12899d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (fd < 0) { 12909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 12919d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tty_serial_init(fd, 115200, 'N', 8, 1); 12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_chr_open_fd(fd, fd); 12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!chr) { 12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd); 12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 12975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_ioctl = tty_serial_ioctl; 12999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->chr_close = qemu_chr_close_tty; 13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 13023b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#else /* _WIN32 */ 13039d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_pty(QemuOpts *opts) 13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 13073b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#endif /* _WIN32 */ 13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__linux__) 13105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 13115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 13125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int mode; 13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} ParallelCharDriver; 13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pp_hw_mode(ParallelCharDriver *s, uint16_t mode) 13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->mode != mode) { 13185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int m = mode; 13195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(s->fd, PPSETMODE, &m) < 0) 13205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 13215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->mode = mode; 13225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 13245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 13255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pp_ioctl(CharDriverState *chr, int cmd, void *arg) 13275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ParallelCharDriver *drv = chr->opaque; 13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd = drv->fd; 13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t b; 13315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(cmd) { 13335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_READ_DATA: 13345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPRDATA, &b) < 0) 13355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(uint8_t *)arg = b; 13375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_WRITE_DATA: 13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner b = *(uint8_t *)arg; 13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPWDATA, &b) < 0) 13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_READ_CONTROL: 13445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPRCONTROL, &b) < 0) 13455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 13465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Linux gives only the lowest bits, and no way to know data 13475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner direction! For better compatibility set the fixed upper 13485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bits. */ 13495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(uint8_t *)arg = b | 0xc0; 13505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_WRITE_CONTROL: 13525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner b = *(uint8_t *)arg; 13535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPWCONTROL, &b) < 0) 13545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 13555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_READ_STATUS: 13575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPRSTATUS, &b) < 0) 13585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 13595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(uint8_t *)arg = b; 13605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_DATA_DIR: 13625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPDATADIR, (int *)arg) < 0) 13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_EPP_READ_ADDR: 13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { 13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ParallelIOArg *parg = arg; 13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n = read(fd, parg->buffer, parg->count); 13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (n != parg->count) { 13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -EIO; 13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_EPP_READ: 13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) { 13765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ParallelIOArg *parg = arg; 13775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n = read(fd, parg->buffer, parg->count); 13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (n != parg->count) { 13795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -EIO; 13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_EPP_WRITE_ADDR: 13845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { 13855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ParallelIOArg *parg = arg; 13865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n = write(fd, parg->buffer, parg->count); 13875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (n != parg->count) { 13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -EIO; 13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_EPP_WRITE: 13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) { 13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ParallelIOArg *parg = arg; 13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n = write(fd, parg->buffer, parg->count); 13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (n != parg->count) { 13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -EIO; 13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void pp_close(CharDriverState *chr) 14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ParallelCharDriver *drv = chr->opaque; 14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd = drv->fd; 14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pp_hw_mode(drv, IEEE1284_MODE_COMPAT); 14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl(fd, PPRELEASE); 14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd); 14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(drv); 14169d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14199d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_pp(QemuOpts *opts) 14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14219d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *filename = qemu_opt_get(opts, "path"); 14225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 14235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ParallelCharDriver *drv; 14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 14255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(fd = open(filename, O_RDWR)); 14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) 14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPCLAIM) < 0) { 14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd); 14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner drv = qemu_mallocz(sizeof(ParallelCharDriver)); 14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner drv->fd = fd; 14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner drv->mode = IEEE1284_MODE_COMPAT; 14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = null_chr_write; 14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_ioctl = pp_ioctl; 14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = pp_close; 14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = drv; 14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14459d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* __linux__ */ 14505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int pp_ioctl(CharDriverState *chr, int cmd, void *arg) 14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 145417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner int fd = (int)(intptr_t)chr->opaque; 14555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t b; 14565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(cmd) { 14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_READ_DATA: 14595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPIGDATA, &b) < 0) 14605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(uint8_t *)arg = b; 14625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_WRITE_DATA: 14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner b = *(uint8_t *)arg; 14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPISDATA, &b) < 0) 14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_READ_CONTROL: 14695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPIGCTRL, &b) < 0) 14705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(uint8_t *)arg = b; 14725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_WRITE_CONTROL: 14745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner b = *(uint8_t *)arg; 14755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPISCTRL, &b) < 0) 14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CHR_IOCTL_PP_READ_STATUS: 14795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(fd, PPIGSTATUS, &b) < 0) 14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *(uint8_t *)arg = b; 14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 14845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOTSUP; 14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14899d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_pp(QemuOpts *opts) 14905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14919d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *filename = qemu_opt_get(opts, "path"); 14925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 14935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 14945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = open(filename, O_RDWR); 14965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) 14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 150017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->opaque = (void *)(intptr_t)fd; 15015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = null_chr_write; 15025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_ioctl = pp_ioctl; 15035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 15045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 15065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else /* _WIN32 */ 15085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 15105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_size; 15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner HANDLE hcom, hrecv, hsend; 15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OVERLAPPED orecv, osend; 15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BOOL fpipe; 15145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD len; 15155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} WinCharState; 15165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NSENDBUF 2048 15185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NRECVBUF 2048 15195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MAXCONNECT 1 15205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define NTIMEOUT 5000 15215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_poll(void *opaque); 15235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_pipe_poll(void *opaque); 15245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void win_chr_close(CharDriverState *chr) 15265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 15285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->hsend) { 15305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CloseHandle(s->hsend); 15315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hsend = NULL; 15325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->hrecv) { 15345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CloseHandle(s->hrecv); 15355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hrecv = NULL; 15365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->hcom) { 15385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CloseHandle(s->hcom); 15395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hcom = NULL; 15405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fpipe) 15425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_del_polling_cb(win_chr_pipe_poll, chr); 15435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 15445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_del_polling_cb(win_chr_poll, chr); 15459d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 15469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 15475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_init(CharDriverState *chr, const char *filename) 15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 15525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner COMMCONFIG comcfg; 15535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; 15545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner COMSTAT comstat; 15555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD size; 15565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD err; 15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); 15595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->hsend) { 15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed CreateEvent\n"); 15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 15625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); 15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->hrecv) { 15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed CreateEvent\n"); 15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, 15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); 15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->hcom == INVALID_HANDLE_VALUE) { 15725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError()); 15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hcom = NULL; 15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { 15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed SetupComm\n"); 15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 15805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ZeroMemory(&comcfg, sizeof(COMMCONFIG)); 15835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = sizeof(COMMCONFIG); 15845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GetDefaultCommConfig(filename, &comcfg, &size); 15855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner comcfg.dcb.DCBlength = sizeof(DCB); 15865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CommConfigDialog(filename, NULL, &comcfg); 15875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!SetCommState(s->hcom, &comcfg.dcb)) { 15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed SetCommState\n"); 15905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 15915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!SetCommMask(s->hcom, EV_ERR)) { 15945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed SetCommMask\n"); 15955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cto.ReadIntervalTimeout = MAXDWORD; 15995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!SetCommTimeouts(s->hcom, &cto)) { 16005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed SetCommTimeouts\n"); 16015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ClearCommError(s->hcom, &err, &comstat)) { 16055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed ClearCommError\n"); 16065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 16075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_add_polling_cb(win_chr_poll, chr); 16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 16105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail: 16125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_close(chr); 16135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 16145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1) 16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 16195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD len, ret, size, err; 16205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = len1; 16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ZeroMemory(&s->osend, sizeof(s->osend)); 16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->osend.hEvent = s->hsend; 16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (len > 0) { 16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->hsend) 16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = WriteFile(s->hcom, buf, len, &size, &s->osend); 16275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 16285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = WriteFile(s->hcom, buf, len, &size, NULL); 16295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) { 16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner err = GetLastError(); 16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (err == ERROR_IO_PENDING) { 16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE); 16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret) { 16345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += size; 16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len -= size; 16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 16375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 16415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 16435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += size; 16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len -= size; 16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len1 - len; 16485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_read_poll(CharDriverState *chr) 16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 16535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->max_size = qemu_chr_can_read(chr); 16555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->max_size; 16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void win_chr_readfile(CharDriverState *chr) 16595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 16615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret, err; 16629d1188280fa5294f9438424e5e8eae91f645bfd8David Turner uint8_t buf[READ_BUF_LEN]; 16635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD size; 16645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ZeroMemory(&s->orecv, sizeof(s->orecv)); 16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->orecv.hEvent = s->hrecv; 16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); 16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) { 16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner err = GetLastError(); 16705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (err == ERROR_IO_PENDING) { 16715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE); 16725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) { 16765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, buf, size); 16775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void win_chr_read(CharDriverState *chr) 16815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 16835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->len > s->max_size) 16855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->len = s->max_size; 16865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->len == 0) 16875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 16885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_readfile(chr); 16905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_poll(void *opaque) 16935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 16955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 16965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner COMSTAT status; 16975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD comerr; 16985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ClearCommError(s->hcom, &comerr, &status); 17005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (status.cbInQue > 0) { 17015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->len = status.cbInQue; 17025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_read_poll(chr); 17035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_read(chr); 17045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 17055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17099d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_win(QemuOpts *opts) 17105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *filename = qemu_opt_get(opts, "path"); 17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s; 17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(WinCharState)); 17175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 17185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = win_chr_write; 17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = win_chr_close; 17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (win_chr_init(chr, filename) < 0) { 17225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(s); 17235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(chr); 17245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 17255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 17275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 17285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_pipe_poll(void *opaque) 17315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 17335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD size; 17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); 17375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) { 17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->len = size; 17395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_read_poll(chr); 17405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_read(chr); 17415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 17425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 17445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int win_chr_pipe_init(CharDriverState *chr, const char *filename) 17475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s = chr->opaque; 17495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OVERLAPPED ov; 17505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 17515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD size; 17525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char openname[256]; 17535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fpipe = TRUE; 17555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); 17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->hsend) { 17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed CreateEvent\n"); 17595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); 17625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->hrecv) { 17635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed CreateEvent\n"); 17645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 17655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename); 17685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 17695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | 17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner PIPE_WAIT, 17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); 17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->hcom == INVALID_HANDLE_VALUE) { 17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError()); 17745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hcom = NULL; 17755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 17765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ZeroMemory(&ov, sizeof(ov)); 17795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 17805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = ConnectNamedPipe(s->hcom, &ov); 17815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret) { 17825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed ConnectNamedPipe\n"); 17835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE); 17875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ret) { 17885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Failed GetOverlappedResult\n"); 17895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ov.hEvent) { 17905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CloseHandle(ov.hEvent); 17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ov.hEvent = NULL; 17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 17945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ov.hEvent) { 17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CloseHandle(ov.hEvent); 17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ov.hEvent = NULL; 17995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_add_polling_cb(win_chr_pipe_poll, chr); 18015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 18025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail: 18045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner win_chr_close(chr); 18055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18099d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts) 18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *filename = qemu_opt_get(opts, "path"); 18125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s; 18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 18165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(WinCharState)); 18175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 18185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = win_chr_write; 18195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = win_chr_close; 18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (win_chr_pipe_init(chr, filename) < 0) { 18225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(s); 18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(chr); 18245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 18255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 18275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 18285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) 18315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 18335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WinCharState *s; 18345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 18365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(WinCharState)); 18375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->hcom = fd_out; 18385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 18395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = win_chr_write; 18409d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 18415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 18425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18449d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_win_con(QemuOpts *opts) 18455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE)); 18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18499d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts) 18505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *file_out = qemu_opt_get(opts, "path"); 18525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner HANDLE fd_out; 18535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL, 18555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 18565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd_out == INVALID_HANDLE_VALUE) 18575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 18585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_chr_open_win_file(fd_out); 18605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* !_WIN32 */ 18625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/ 18645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* UDP Net console */ 18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 18683b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner SockAddress daddr; 18699d1188280fa5294f9438424e5e8eae91f645bfd8David Turner uint8_t buf[READ_BUF_LEN]; 18705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int bufcnt; 18715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int bufptr; 18725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_size; 18735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} NetCharDriver; 18745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 18765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCharDriver *s = chr->opaque; 18785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18793b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return socket_sendto(s->fd, (const void *)buf, len, &s->daddr); 18805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int udp_chr_read_poll(void *opaque) 18835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 18855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCharDriver *s = chr->opaque; 18865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->max_size = qemu_chr_can_read(chr); 18885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* If there were any stray characters in the queue process them 18905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * first 18915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 18925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (s->max_size > 0 && s->bufptr < s->bufcnt) { 18935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, &s->buf[s->bufptr], 1); 18945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bufptr++; 18955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->max_size = qemu_chr_can_read(chr); 18965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->max_size; 18985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_chr_read(void *opaque) 19015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 19035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCharDriver *s = chr->opaque; 19045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->max_size == 0) 19065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 19073b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner s->bufcnt = socket_recv(s->fd, (void *)s->buf, sizeof(s->buf)); 19085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bufptr = s->bufcnt; 19095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->bufcnt <= 0) 19105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 19115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bufptr = 0; 19135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (s->max_size > 0 && s->bufptr < s->bufcnt) { 19145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, &s->buf[s->bufptr], 1); 19155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bufptr++; 19165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->max_size = qemu_chr_can_read(chr); 19175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_chr_update_read_handler(CharDriverState *chr) 19215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCharDriver *s = chr->opaque; 19235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd >= 0) { 19255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, udp_chr_read_poll, 19265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udp_chr_read, NULL, chr); 19275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_chr_close(CharDriverState *chr) 19315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCharDriver *s = chr->opaque; 19335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd >= 0) { 19345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 19353b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner socket_close(s->fd); 19365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 19385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19409d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_udp(QemuOpts *opts) 19415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = NULL; 19435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCharDriver *s = NULL; 19445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd = -1; 19455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 19473b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner s = qemu_mallocz(sizeof(NetCharDriver)); 19485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19499d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = inet_dgram_opts(opts); 19505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) { 19519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fprintf(stderr, "inet_dgram_opts failed\n"); 19525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto return_err; 19535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 19565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bufcnt = 0; 19575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bufptr = 0; 19585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 19595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = udp_chr_write; 19605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_update_read_handler = udp_chr_update_read_handler; 19615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = udp_chr_close; 19625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 19635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerreturn_err: 19655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (chr) 19665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(chr); 19675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s) 19685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(s); 19695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) 19705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(fd); 19715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 19725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/ 19755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* TCP Net console */ 19765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct { 19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, listen_fd; 19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int connected; 19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int max_size; 19815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int do_telnetopt; 19825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int do_nodelay; 19835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int is_unix; 19849d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int msgfd; 19855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} TCPCharDriver; 19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_accept(void *opaque); 19885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = chr->opaque; 19925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->connected) { 19935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return send_all(s->fd, buf, len); 19945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 19955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX: indicate an error ? */ 19965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len; 19975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tcp_chr_read_poll(void *opaque) 20015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 20035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = chr->opaque; 20045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->connected) 20055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 20065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->max_size = qemu_chr_can_read(chr); 20075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->max_size; 20085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IAC 255 20115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IAC_BREAK 243 20125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_process_IAC_bytes(CharDriverState *chr, 20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s, 20145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *buf, int *size) 20155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Handle any telnet client's basic IAC options to satisfy char by 20175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * char mode with no echo. All IAC options will be removed from 20185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the buf and the do_telnetopt variable will be used to track the 20195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * state of the width of the IAC information. 20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 20215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IAC commands come in sets of 3 bytes with the exception of the 20225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * "IAC BREAK" command and the double IAC. 20235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 20245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 20265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int j = 0; 20275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < *size; i++) { 20295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->do_telnetopt > 1) { 20305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) { 20315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Double IAC means send an IAC */ 20325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (j != i) 20335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf[j] = buf[i]; 20345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner j++; 20355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_telnetopt = 1; 20365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 20375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) { 20385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Handle IAC break commands by sending a serial break */ 20395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_event(chr, CHR_EVENT_BREAK); 20405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_telnetopt++; 20415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_telnetopt++; 20435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->do_telnetopt >= 4) { 20455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_telnetopt = 1; 20465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 20485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((unsigned char)buf[i] == IAC) { 20495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_telnetopt = 2; 20505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 20515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (j != i) 20525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf[j] = buf[i]; 20535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner j++; 20545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *size = j; 20585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20609d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic int tcp_get_msgfd(CharDriverState *chr) 20619d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 20629d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TCPCharDriver *s = chr->opaque; 20639d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int fd = s->msgfd; 20649d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->msgfd = -1; 20659d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return fd; 20669d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 20679d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 20689d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifndef _WIN32 20699d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) 20709d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 20719d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TCPCharDriver *s = chr->opaque; 20729d1188280fa5294f9438424e5e8eae91f645bfd8David Turner struct cmsghdr *cmsg; 20739d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 20749d1188280fa5294f9438424e5e8eae91f645bfd8David Turner for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { 20759d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int fd; 20769d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 20779d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || 20789d1188280fa5294f9438424e5e8eae91f645bfd8David Turner cmsg->cmsg_level != SOL_SOCKET || 20799d1188280fa5294f9438424e5e8eae91f645bfd8David Turner cmsg->cmsg_type != SCM_RIGHTS) 20809d1188280fa5294f9438424e5e8eae91f645bfd8David Turner continue; 20819d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 20829d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = *((int *)CMSG_DATA(cmsg)); 20839d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (fd < 0) 20849d1188280fa5294f9438424e5e8eae91f645bfd8David Turner continue; 20859d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 20869d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (s->msgfd != -1) 20879d1188280fa5294f9438424e5e8eae91f645bfd8David Turner close(s->msgfd); 20889d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->msgfd = fd; 20899d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 20909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 20919d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 20929d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) 20939d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 20949d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TCPCharDriver *s = chr->opaque; 20959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner struct msghdr msg = { NULL, }; 20969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner struct iovec iov[1]; 20979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner union { 20989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner struct cmsghdr cmsg; 20999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner char control[CMSG_SPACE(sizeof(int))]; 21009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } msg_control; 21019d1188280fa5294f9438424e5e8eae91f645bfd8David Turner ssize_t ret; 21029d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 21039d1188280fa5294f9438424e5e8eae91f645bfd8David Turner iov[0].iov_base = buf; 21049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner iov[0].iov_len = len; 21059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 21069d1188280fa5294f9438424e5e8eae91f645bfd8David Turner msg.msg_iov = iov; 21079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner msg.msg_iovlen = 1; 21089d1188280fa5294f9438424e5e8eae91f645bfd8David Turner msg.msg_control = &msg_control; 21099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner msg.msg_controllen = sizeof(msg_control); 21109d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 21119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner ret = recvmsg(s->fd, &msg, 0); 21129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (ret > 0 && s->is_unix) 21139d1188280fa5294f9438424e5e8eae91f645bfd8David Turner unix_process_msgfd(chr, &msg); 21149d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 21159d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return ret; 21169d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 21179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#else 21189d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) 21199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 21209d1188280fa5294f9438424e5e8eae91f645bfd8David Turner TCPCharDriver *s = chr->opaque; 21219d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return recv(s->fd, buf, len, 0); 21229d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 21239d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 21249d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 21255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_read(void *opaque) 21265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 21275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 21285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = chr->opaque; 21299d1188280fa5294f9438424e5e8eae91f645bfd8David Turner uint8_t buf[READ_BUF_LEN]; 21305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len, size; 21315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->connected || s->max_size <= 0) 21335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 21345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = sizeof(buf); 21355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len > s->max_size) 21365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = s->max_size; 21379d1188280fa5294f9438424e5e8eae91f645bfd8David Turner size = tcp_chr_recv(chr, (void *)buf, len); 21385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size == 0) { 21395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* connection closed */ 21405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->connected = 0; 21415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->listen_fd >= 0) { 21425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); 21435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 21453b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner socket_close(s->fd); 21465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = -1; 21479d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 21485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (size > 0) { 21495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->do_telnetopt) 21505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_chr_process_IAC_bytes(chr, s, buf, &size); 21515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) 21525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_read(chr, buf, size); 21535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 21555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21569d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifndef _WIN32 21579d1188280fa5294f9438424e5e8eae91f645bfd8David TurnerCharDriverState *qemu_chr_open_eventfd(int eventfd) 21589d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 21599d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return qemu_chr_open_fd(eventfd, eventfd); 21609d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 21619d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 21629d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 21635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_connect(void *opaque) 21645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 21655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 21665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = chr->opaque; 21675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->connected = 1; 21695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, tcp_chr_read_poll, 21705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_chr_read, NULL, chr); 21719d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_generic_open(chr); 21725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 21735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c; 21755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_telnet_init(int fd) 21765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 21775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[3]; 21785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Send the telnet negotion to put telnet in binary, no echo, single char mode */ 21795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IACSET(buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */ 21803b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner socket_send(fd, (char *)buf, 3); 21815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IACSET(buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */ 21823b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner socket_send(fd, (char *)buf, 3); 21835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IACSET(buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */ 21843b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner socket_send(fd, (char *)buf, 3); 21855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IACSET(buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */ 21863b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner socket_send(fd, (char *)buf, 3); 21875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 21885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_accept(void *opaque) 21905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 21915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = opaque; 21925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = chr->opaque; 21935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 21945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(;;) { 21963b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner fd = socket_accept(s->listen_fd, NULL); 21973b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (fd < 0) { 21985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 21995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (fd >= 0) { 22005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->do_telnetopt) 22015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_chr_telnet_init(fd); 22025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 22035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nonblock(fd); 22065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->do_nodelay) 22075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nodelay(fd); 22085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 22095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); 22105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_chr_connect(chr); 22115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 22125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tcp_chr_close(CharDriverState *chr) 22145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 22155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = chr->opaque; 22165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd >= 0) { 22175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 22185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(s->fd); 22195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->listen_fd >= 0) { 22215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); 22225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(s->listen_fd); 22235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 22259d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_chr_event(chr, CHR_EVENT_CLOSED); 22265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 22275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22289d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic CharDriverState *qemu_chr_open_socket(QemuOpts *opts) 22295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 22305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr = NULL; 22315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCPCharDriver *s = NULL; 22329d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int fd = -1; 22339d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int is_listen; 22349d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int is_waitconnect; 22359d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int do_nodelay; 22369d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int is_unix; 22379d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int is_telnet; 22389d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 22399d1188280fa5294f9438424e5e8eae91f645bfd8David Turner is_listen = qemu_opt_get_bool(opts, "server", 0); 22409d1188280fa5294f9438424e5e8eae91f645bfd8David Turner is_waitconnect = qemu_opt_get_bool(opts, "wait", 1); 22419d1188280fa5294f9438424e5e8eae91f645bfd8David Turner is_telnet = qemu_opt_get_bool(opts, "telnet", 0); 22429d1188280fa5294f9438424e5e8eae91f645bfd8David Turner do_nodelay = !qemu_opt_get_bool(opts, "delay", 1); 22439d1188280fa5294f9438424e5e8eae91f645bfd8David Turner is_unix = qemu_opt_get(opts, "path") != NULL; 22445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!is_listen) 22455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is_waitconnect = 0; 22465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr = qemu_mallocz(sizeof(CharDriverState)); 22485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(TCPCharDriver)); 22495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_unix) { 22515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_listen) { 22529d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = unix_listen_opts(opts); 22535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22549d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = unix_connect_opts(opts); 22555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_listen) { 22589d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = inet_listen_opts(opts, 0); 22595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22609d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fd = inet_connect_opts(opts); 22615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) 22645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 22655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!is_waitconnect) 22675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nonblock(fd); 22685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->connected = 0; 22705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = -1; 22715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->listen_fd = -1; 22729d1188280fa5294f9438424e5e8eae91f645bfd8David Turner s->msgfd = -1; 22735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->is_unix = is_unix; 22745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_nodelay = do_nodelay && !is_unix; 22755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->opaque = s; 22775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_write = tcp_chr_write; 22785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close = tcp_chr_close; 22799d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->get_msgfd = tcp_get_msgfd; 22805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_listen) { 22825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->listen_fd = fd; 22835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); 22845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_telnet) 22855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->do_telnetopt = 1; 22869d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 22875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->connected = 1; 22895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 22905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nodelay(fd); 22915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_chr_connect(chr); 22925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22949d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* for "info chardev" monitor command */ 22959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->filename = qemu_malloc(256); 22969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (is_unix) { 22979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner snprintf(chr->filename, 256, "unix:%s%s", 22989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get(opts, "path"), 22999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get_bool(opts, "server", 0) ? ",server" : ""); 23009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } else if (is_telnet) { 23019d1188280fa5294f9438424e5e8eae91f645bfd8David Turner snprintf(chr->filename, 256, "telnet:%s:%s%s", 23029d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), 23039d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get_bool(opts, "server", 0) ? ",server" : ""); 23049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } else { 23059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner snprintf(chr->filename, 256, "tcp:%s:%s%s", 23069d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), 23079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get_bool(opts, "server", 0) ? ",server" : ""); 23089d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 23099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 23105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_listen && is_waitconnect) { 23115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("QEMU waiting for connection on: %s\n", 23129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->filename); 23135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_chr_accept(chr); 23145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nonblock(s->listen_fd); 23155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 23179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 23185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail: 23195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) 23205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(fd); 23215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 23225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(chr); 23235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 23245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 23255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 232617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner/***********************************************************/ 232717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner/* Memory chardev */ 232817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnertypedef struct { 232917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner size_t outbuf_size; 233017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner size_t outbuf_capacity; 233117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner uint8_t *outbuf; 233217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} MemoryDriver; 233317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 233417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnerstatic int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 233517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 233617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner MemoryDriver *d = chr->opaque; 233717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 233817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner /* TODO: the QString implementation has the same code, we should 233917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner * introduce a generic way to do this in cutils.c */ 234017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (d->outbuf_capacity < d->outbuf_size + len) { 234117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner /* grow outbuf */ 234217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf_capacity += len; 234317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf_capacity *= 2; 234417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf = qemu_realloc(d->outbuf, d->outbuf_capacity); 234517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 234617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 234717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner memcpy(d->outbuf + d->outbuf_size, buf, len); 234817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf_size += len; 234917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 235017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner return len; 235117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 235217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 235317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnervoid qemu_chr_init_mem(CharDriverState *chr) 235417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 235517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner MemoryDriver *d; 235617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 235717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d = qemu_malloc(sizeof(*d)); 235817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf_size = 0; 235917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf_capacity = 4096; 236017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner d->outbuf = qemu_mallocz(d->outbuf_capacity); 236117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 236217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner memset(chr, 0, sizeof(*chr)); 236317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->opaque = d; 236417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_write = mem_chr_write; 236517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 236617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 236717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' TurnerQString *qemu_chr_mem_to_qs(CharDriverState *chr) 236817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 236917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner MemoryDriver *d = chr->opaque; 237017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1); 237117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 237217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 237317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner/* NOTE: this driver can not be closed with qemu_chr_close()! */ 237417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnervoid qemu_chr_close_mem(CharDriverState *chr) 237517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 237617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner MemoryDriver *d = chr->opaque; 237717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 237817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner qemu_free(d->outbuf); 237917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner qemu_free(chr->opaque); 238017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->opaque = NULL; 238117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_write = NULL; 238217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 238317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 238417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnersize_t qemu_chr_mem_osize(const CharDriverState *chr) 238517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 238617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner const MemoryDriver *d = chr->opaque; 238717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner return d->outbuf_size; 238817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 238917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 23909d1188280fa5294f9438424e5e8eae91f645bfd8David TurnerQemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) 23915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 23929d1188280fa5294f9438424e5e8eae91f645bfd8David Turner char host[65], port[33], width[8], height[8]; 23939d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int pos; 23945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p; 23959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QemuOpts *opts; 23969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 23979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1); 23989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (NULL == opts) 23999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 24005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strstart(filename, "mon:", &p)) { 24029d1188280fa5294f9438424e5e8eae91f645bfd8David Turner filename = p; 24039d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "mux", "on"); 24049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 24069d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strcmp(filename, "null") == 0 || 24079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner strcmp(filename, "pty") == 0 || 24089d1188280fa5294f9438424e5e8eae91f645bfd8David Turner strcmp(filename, "msmouse") == 0 || 24099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner strcmp(filename, "braille") == 0 || 24109d1188280fa5294f9438424e5e8eae91f645bfd8David Turner strcmp(filename, "stdio") == 0) { 24119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", filename); 24129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24139d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24149d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "vc", &p)) { 24159d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "vc"); 24169d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (*p == ':') { 24179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p+1, "%8[0-9]x%8[0-9]", width, height) == 2) { 24189d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* pixels */ 24199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "width", width); 24209d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "height", height); 24219d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } else if (sscanf(p+1, "%8[0-9]Cx%8[0-9]C", width, height) == 2) { 24229d1188280fa5294f9438424e5e8eae91f645bfd8David Turner /* chars */ 24239d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "cols", width); 24249d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "rows", height); 24259d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } else { 24269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner goto fail; 24279d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24299d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24309d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24319d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strcmp(filename, "con:") == 0) { 24329d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "console"); 24339d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24349d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24359d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "COM", NULL)) { 24369d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "serial"); 24379d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "path", filename); 24389d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24399d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24409d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "file:", &p)) { 24419d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "file"); 24429d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "path", p); 24439d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24449d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24459d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "pipe:", &p)) { 24469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "pipe"); 24479d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "path", p); 24489d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24499d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24509d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "tcp:", &p) || 24519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner strstart(filename, "telnet:", &p)) { 24529d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { 24539d1188280fa5294f9438424e5e8eae91f645bfd8David Turner host[0] = 0; 24549d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) 24559d1188280fa5294f9438424e5e8eae91f645bfd8David Turner goto fail; 24569d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24579d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "socket"); 24589d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "host", host); 24599d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "port", port); 24609d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (p[pos] == ',') { 24619d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (qemu_opts_do_parse(opts, p+pos+1, NULL) != 0) 24629d1188280fa5294f9438424e5e8eae91f645bfd8David Turner goto fail; 24639d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24649d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "telnet:", &p)) 24659d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "telnet", "on"); 24669d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24679d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24689d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "udp:", &p)) { 24699d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "udp"); 24709d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) { 24719d1188280fa5294f9438424e5e8eae91f645bfd8David Turner host[0] = 0; 24729d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) { 24739d1188280fa5294f9438424e5e8eae91f645bfd8David Turner goto fail; 24749d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24759d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24769d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "host", host); 24779d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "port", port); 24789d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (p[pos] == '@') { 24799d1188280fa5294f9438424e5e8eae91f645bfd8David Turner p += pos + 1; 24809d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { 24819d1188280fa5294f9438424e5e8eae91f645bfd8David Turner host[0] = 0; 24829d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) { 24839d1188280fa5294f9438424e5e8eae91f645bfd8David Turner goto fail; 24849d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24859d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24869d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "localaddr", host); 24879d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "localport", port); 24889d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24899d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strstart(filename, "unix:", &p)) { 24929d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "socket"); 24939d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (qemu_opts_do_parse(opts, p, "path") != 0) 24949d1188280fa5294f9438424e5e8eae91f645bfd8David Turner goto fail; 24959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 24969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 24979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "/dev/parport", NULL) || 24989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner strstart(filename, "/dev/ppi", NULL)) { 24999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "parport"); 25009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "path", filename); 25019d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 25029d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 25035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strstart(filename, "/dev/", NULL)) { 25049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "backend", "tty"); 25059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_set(opts, "path", filename); 25069d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return opts; 25079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 25083b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#ifdef CONFIG_ANDROID 25093b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (strstart(filename, "fdpair:", &p)) { 25103b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner int fdin, fdout; 25113b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner char temp[8]; 25123b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "backend", "fdpair"); 25133b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (sscanf(p, "%d,%d", &fdin, &fdout) != 2) { 25143b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner goto fail; 25153b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25163b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (fdin < 0 || fdout < 0) { 25173b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner goto fail; 25183b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25193b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner snprintf(temp, sizeof temp, "%d", fdin); 25203b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "fdin", temp); 25213b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner snprintf(temp, sizeof temp, "%d", fdout); 25223b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "fdout", temp); 25233b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return opts; 25243b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25253b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (!strcmp(filename, "android-kmsg")) { 25263b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "backend", "android-kmsg"); 25273b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return opts; 25283b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25293b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (!strcmp(filename, "android-qemud")) { 25303b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "backend", "android-qemud"); 25313b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return opts; 25323b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25333b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (!strcmp(filename, "android-modem")) { 25343b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "backend", "android-modem"); 25353b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return opts; 25363b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25373b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner if (!strcmp(filename, "android-gps")) { 25383b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner qemu_opt_set(opts, "backend", "android-gps"); 25393b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner return opts; 25403b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner } 25413b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#endif /* CONFIG_ANDROID */ 25429d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 25439d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerfail: 25449d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opts_del(opts); 25459d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 25469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 25479d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 25489d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic const struct { 25499d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *name; 25509d1188280fa5294f9438424e5e8eae91f645bfd8David Turner CharDriverState *(*open)(QemuOpts *opts); 25519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} backend_table[] = { 25529d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "null", .open = qemu_chr_open_null }, 25539d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "socket", .open = qemu_chr_open_socket }, 25549d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "udp", .open = qemu_chr_open_udp }, 25559d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "msmouse", .open = qemu_chr_open_msmouse }, 25563b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner { .name = "vc", .open = text_console_init }, 25579d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef _WIN32 25589d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "file", .open = qemu_chr_open_win_file_out }, 25599d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "pipe", .open = qemu_chr_open_win_pipe }, 25609d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "console", .open = qemu_chr_open_win_con }, 25619d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "serial", .open = qemu_chr_open_win }, 25629d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#else 25639d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "file", .open = qemu_chr_open_file_out }, 25649d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "pipe", .open = qemu_chr_open_pipe }, 25659d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "pty", .open = qemu_chr_open_pty }, 25669d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "stdio", .open = qemu_chr_open_stdio }, 25675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 25689d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#ifdef CONFIG_ANDROID 25693b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#ifndef _WIN32 25709d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "fdpair", .open = qemu_chr_open_fdpair }, 25715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 25723b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner { .name = "android-qemud", .open = qemu_chr_open_android_qemud }, 25733b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner { .name = "android-kmsg", .open = qemu_chr_open_android_kmsg }, 25743b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner { .name = "android-modem", .open = qemu_chr_open_android_modem }, 25753b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner { .name = "android-gps", .open = qemu_chr_open_android_gps }, 25763b2846ad9f156e62574a0abc5ec489f8f13f1121David 'Digit' Turner#endif 25775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_BRLAPI 25789d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "braille", .open = chr_baum_init }, 25799d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 25809d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ 25819d1188280fa5294f9438424e5e8eae91f645bfd8David Turner || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ 25829d1188280fa5294f9438424e5e8eae91f645bfd8David Turner || defined(__FreeBSD_kernel__) 25839d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "tty", .open = qemu_chr_open_tty }, 25849d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#endif 25859d1188280fa5294f9438424e5e8eae91f645bfd8David Turner#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) \ 25869d1188280fa5294f9438424e5e8eae91f645bfd8David Turner || defined(__FreeBSD_kernel__) 25879d1188280fa5294f9438424e5e8eae91f645bfd8David Turner { .name = "parport", .open = qemu_chr_open_pp }, 25885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 25899d1188280fa5294f9438424e5e8eae91f645bfd8David Turner}; 25909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 25919d1188280fa5294f9438424e5e8eae91f645bfd8David TurnerCharDriverState *qemu_chr_open_opts(QemuOpts *opts, 25929d1188280fa5294f9438424e5e8eae91f645bfd8David Turner void (*init)(struct CharDriverState *s)) 25939d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 25949d1188280fa5294f9438424e5e8eae91f645bfd8David Turner CharDriverState *chr; 25959d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int i; 25969d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 25979d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (qemu_opts_id(opts) == NULL) { 25989d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fprintf(stderr, "chardev: no id specified\n"); 25999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 26009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 26019d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 260217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (qemu_opt_get(opts, "backend") == NULL) { 260317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner fprintf(stderr, "chardev: \"%s\" missing backend\n", 260417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner qemu_opts_id(opts)); 260517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner return NULL; 260617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 26079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner for (i = 0; i < ARRAY_SIZE(backend_table); i++) { 26089d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strcmp(backend_table[i].name, qemu_opt_get(opts, "backend")) == 0) 26099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner break; 26109d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 26119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (i == ARRAY_SIZE(backend_table)) { 26129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fprintf(stderr, "chardev: backend \"%s\" not found\n", 26139d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get(opts, "backend")); 26149d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 26155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 26165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 26179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr = backend_table[i].open(opts); 26189d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (!chr) { 26199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner fprintf(stderr, "chardev: opening backend \"%s\" failed\n", 26209d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qemu_opt_get(opts, "backend")); 26219d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 26229d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 26239d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 26249d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (!chr->filename) 26259d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->filename = qemu_strdup(qemu_opt_get(opts, "backend")); 26269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->init = init; 26279d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QTAILQ_INSERT_TAIL(&chardevs, chr, next); 26289d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 26299d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (qemu_opt_get_bool(opts, "mux", 0)) { 26309d1188280fa5294f9438424e5e8eae91f645bfd8David Turner CharDriverState *base = chr; 26319d1188280fa5294f9438424e5e8eae91f645bfd8David Turner int len = strlen(qemu_opts_id(opts)) + 6; 26329d1188280fa5294f9438424e5e8eae91f645bfd8David Turner base->label = qemu_malloc(len); 26339d1188280fa5294f9438424e5e8eae91f645bfd8David Turner snprintf(base->label, len, "%s-base", qemu_opts_id(opts)); 26349d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr = qemu_chr_open_mux(base); 26359d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->filename = base->filename; 263617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->avail_connections = MAX_MUX; 26379d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QTAILQ_INSERT_TAIL(&chardevs, chr, next); 263817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } else { 263917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->avail_connections = 1; 26409d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 26419d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->label = qemu_strdup(qemu_opts_id(opts)); 26429d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return chr; 26439d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 26449d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 26459d1188280fa5294f9438424e5e8eae91f645bfd8David TurnerCharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s)) 26469d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 26479d1188280fa5294f9438424e5e8eae91f645bfd8David Turner const char *p; 26489d1188280fa5294f9438424e5e8eae91f645bfd8David Turner CharDriverState *chr; 26499d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QemuOpts *opts; 26509d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 26519d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strstart(filename, "chardev:", &p)) { 26529d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return qemu_chr_find(p); 26539d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 26549d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 26559d1188280fa5294f9438424e5e8eae91f645bfd8David Turner opts = qemu_chr_parse_compat(label, filename); 26569d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (!opts) 26579d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 26589d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 26599d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr = qemu_chr_open_opts(opts, init); 26609d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (chr && qemu_opt_get_bool(opts, "mux", 0)) { 26619d1188280fa5294f9438424e5e8eae91f645bfd8David Turner monitor_init(chr, MONITOR_USE_READLINE); 26625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 266317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner qemu_opts_del(opts); 26645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return chr; 26655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 26665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 266717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnervoid qemu_chr_set_echo(struct CharDriverState *chr, bool echo) 266817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 266917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (chr->chr_set_echo) { 267017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_set_echo(chr, echo); 267117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 267217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 267317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 267417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnervoid qemu_chr_guest_open(struct CharDriverState *chr) 267517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 267617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (chr->chr_guest_open) { 267717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_guest_open(chr); 267817410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 267917410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 268017410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 268117410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turnervoid qemu_chr_guest_close(struct CharDriverState *chr) 268217410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner{ 268317410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner if (chr->chr_guest_close) { 268417410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner chr->chr_guest_close(chr); 268517410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner } 268617410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner} 268717410ee4539bb5216421bb9f9dc287b1f678b6cdDavid 'Digit' Turner 26885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_chr_close(CharDriverState *chr) 26895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 26909d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QTAILQ_REMOVE(&chardevs, chr, next); 26915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (chr->chr_close) 26925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner chr->chr_close(chr); 26935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(chr->filename); 26945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(chr->label); 26955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(chr); 26965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 26975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 26989d1188280fa5294f9438424e5e8eae91f645bfd8David Turnerstatic void qemu_chr_qlist_iter(QObject *obj, void *opaque) 26999d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 27009d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QDict *chr_dict; 27019d1188280fa5294f9438424e5e8eae91f645bfd8David Turner Monitor *mon = opaque; 27029d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27039d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr_dict = qobject_to_qdict(obj); 27049d1188280fa5294f9438424e5e8eae91f645bfd8David Turner monitor_printf(mon, "%s: filename=%s\n", qdict_get_str(chr_dict, "label"), 27059d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qdict_get_str(chr_dict, "filename")); 27069d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 27079d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27089d1188280fa5294f9438424e5e8eae91f645bfd8David Turnervoid qemu_chr_info_print(Monitor *mon, const QObject *ret_data) 27099d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 27109d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon); 27119d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 27129d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27139d1188280fa5294f9438424e5e8eae91f645bfd8David Turnervoid qemu_chr_info(Monitor *mon, QObject **ret_data) 27149d1188280fa5294f9438424e5e8eae91f645bfd8David Turner{ 27159d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QList *chr_list; 27169d1188280fa5294f9438424e5e8eae91f645bfd8David Turner CharDriverState *chr; 27179d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27189d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr_list = qlist_new(); 27199d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27209d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QTAILQ_FOREACH(chr, &chardevs, next) { 27219d1188280fa5294f9438424e5e8eae91f645bfd8David Turner QObject *obj = qobject_from_jsonf("{ 'label': %s, 'filename': %s }", 27229d1188280fa5294f9438424e5e8eae91f645bfd8David Turner chr->label, chr->filename); 27239d1188280fa5294f9438424e5e8eae91f645bfd8David Turner qlist_append_obj(chr_list, obj); 27249d1188280fa5294f9438424e5e8eae91f645bfd8David Turner } 27259d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27269d1188280fa5294f9438424e5e8eae91f645bfd8David Turner *ret_data = QOBJECT(chr_list); 27279d1188280fa5294f9438424e5e8eae91f645bfd8David Turner} 27289d1188280fa5294f9438424e5e8eae91f645bfd8David Turner 27299d1188280fa5294f9438424e5e8eae91f645bfd8David TurnerCharDriverState *qemu_chr_find(const char *name) 27305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 27315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *chr; 27325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2733a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QTAILQ_FOREACH(chr, &chardevs, next) { 27349d1188280fa5294f9438424e5e8eae91f645bfd8David Turner if (strcmp(chr->label, name) != 0) 27359d1188280fa5294f9438424e5e8eae91f645bfd8David Turner continue; 27369d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return chr; 27375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 27389d1188280fa5294f9438424e5e8eae91f645bfd8David Turner return NULL; 27395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2740