aboutsummaryrefslogtreecommitdiffstats
path: root/qemu-char.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-05-10 10:55:21 +0200
committerDavid 'Digit' Turner <digit@android.com>2011-06-01 17:08:17 +0200
commit17410ee4539bb5216421bb9f9dc287b1f678b6cd (patch)
tree3651570420faac7bed11775c7f1f4d483424ac0e /qemu-char.c
parent5973c775c853e26f684de58ad28c267281aaffd6 (diff)
downloadexternal_qemu-17410ee4539bb5216421bb9f9dc287b1f678b6cd.zip
external_qemu-17410ee4539bb5216421bb9f9dc287b1f678b6cd.tar.gz
external_qemu-17410ee4539bb5216421bb9f9dc287b1f678b6cd.tar.bz2
qemu-char.h, console.h: upstream integration
Change-Id: Ibd11e84a4d48c1d6c4a168056869a7480bc89930
Diffstat (limited to 'qemu-char.c')
-rw-r--r--qemu-char.c178
1 files changed, 129 insertions, 49 deletions
diff --git a/qemu-char.c b/qemu-char.c
index a087813..591ca2d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,7 +28,6 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
-#include "block.h"
#include "hw/usb.h"
#include "hw/baum.h"
#include "hw/msmouse.h"
@@ -52,22 +51,19 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
-#ifdef __NetBSD__
-#include <net/if_tap.h>
-#endif
-#ifdef __linux__
-#include <linux/if_tun.h>
-#endif
#include <arpa/inet.h>
#include <dirent.h>
#include <netdb.h>
#include <sys/select.h>
#ifdef CONFIG_BSD
#include <sys/stat.h>
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <libutil.h>
#include <dev/ppbus/ppi.h>
#include <dev/ppbus/ppbconf.h>
+#if defined(__GLIBC__)
+#include <pty.h>
+#endif
#elif defined(__DragonFly__)
#include <libutil.h>
#include <dev/misc/ppi/ppi.h>
@@ -75,8 +71,6 @@
#else
#include <util.h>
#endif
-#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
-#include <freebsd/stdlib.h>
#else
#ifdef __linux__
#include <pty.h>
@@ -221,6 +215,10 @@ void qemu_chr_add_handlers(CharDriverState *s,
IOEventHandler *fd_event,
void *opaque)
{
+ if (!opaque && !fd_can_read && !fd_read && !fd_event) {
+ /* chr driver being released. */
+ ++s->avail_connections;
+ }
s->chr_can_read = fd_can_read;
s->chr_read = fd_read;
s->chr_event = fd_event;
@@ -376,12 +374,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
break;
}
case 's':
- {
- int i;
- for (i = 0; i < nb_drives; i++) {
- bdrv_commit(drives_table[i].bdrv);
- }
- }
+ bdrv_commit_all();
break;
case 'b':
qemu_chr_event(chr, CHR_EVENT_BREAK);
@@ -505,6 +498,9 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
chr->chr_write = mux_chr_write;
chr->chr_update_read_handler = mux_chr_update_read_handler;
chr->chr_accept_input = mux_chr_accept_input;
+ /* Frontend guest-open / -close notification is not support with muxes */
+ chr->chr_guest_open = NULL;
+ chr->chr_guest_close = NULL;
/* Muxes are always open on creation */
qemu_chr_generic_open(chr);
@@ -538,9 +534,10 @@ int send_all(int fd, const void *buf, int len1)
#else
-static int unix_write(int fd, const uint8_t *buf, int len1)
+int send_all(int fd, const void *_buf, int len1)
{
int ret, len;
+ const uint8_t *buf = _buf;
len = len1;
while (len > 0) {
@@ -557,11 +554,6 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
}
return len1 - len;
}
-
-int send_all(int fd, const void *buf, int len1)
-{
- return unix_write(fd, buf, len1);
-}
#endif /* !_WIN32 */
#ifndef _WIN32
@@ -749,7 +741,7 @@ static void stdio_read(void *opaque)
/* init terminal so that we can grab keys */
static struct termios oldtty;
static int old_fd0_flags;
-static int term_atexit_done;
+static bool stdio_allow_signal;
static void term_exit(void)
{
@@ -757,32 +749,26 @@ static void term_exit(void)
fcntl(0, F_SETFL, old_fd0_flags);
}
-static void term_init(QemuOpts *opts)
+static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
{
struct termios tty;
- tcgetattr (0, &tty);
- oldtty = tty;
- old_fd0_flags = fcntl(0, F_GETFL);
-
+ tty = oldtty;
+ if (!echo) {
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
tty.c_oflag |= OPOST;
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
- /* if graphical mode, we allow Ctrl-C handling */
- if (!qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC))
- tty.c_lflag &= ~ISIG;
tty.c_cflag &= ~(CSIZE|PARENB);
tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
+ }
+ /* if graphical mode, we allow Ctrl-C handling */
+ if (!stdio_allow_signal)
+ tty.c_lflag &= ~ISIG;
tcsetattr (0, TCSANOW, &tty);
-
- if (!term_atexit_done++)
- atexit(term_exit);
-
- fcntl(0, F_SETFL, O_NONBLOCK);
}
static void qemu_chr_close_stdio(struct CharDriverState *chr)
@@ -799,11 +785,21 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
return NULL;
+ if (stdio_nb_clients == 0) {
+ old_fd0_flags = fcntl(0, F_GETFL);
+ tcgetattr (0, &oldtty);
+ fcntl(0, F_SETFL, O_NONBLOCK);
+ atexit(term_exit);
+ }
+
chr = qemu_chr_open_fd(0, 1);
chr->chr_close = qemu_chr_close_stdio;
+ chr->chr_set_echo = qemu_chr_set_echo_stdio;
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
stdio_nb_clients++;
- term_init(opts);
+ stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
+ display_type != DT_NOGRAPHIC);
+ qemu_chr_set_echo(chr, false);
return chr;
}
@@ -1046,9 +1042,6 @@ static void tty_serial_init(int fd, int speed,
speed, parity, data_bits, stop_bits);
#endif
tcgetattr (fd, &tty);
- if (!term_atexit_done) {
- oldtty = tty;
- }
#define check_speed(val) if (speed <= val) { spd = B##val; break; }
speed = speed * 10 / 11;
@@ -1220,11 +1213,6 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
return 0;
}
-static void tty_exit(void)
-{
- tcsetattr(0, TCSANOW, &oldtty);
-}
-
static void qemu_chr_close_tty(CharDriverState *chr)
{
FDCharDriver *s = chr->opaque;
@@ -1259,8 +1247,6 @@ static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
}
chr->chr_ioctl = tty_serial_ioctl;
chr->chr_close = qemu_chr_close_tty;
- if (!term_atexit_done++)
- atexit(tty_exit);
return chr;
}
#else /* ! __linux__ && ! __sun__ */
@@ -1415,7 +1401,7 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
{
- int fd = (int)(long)chr->opaque;
+ int fd = (int)(intptr_t)chr->opaque;
uint8_t b;
switch(cmd) {
@@ -1461,7 +1447,7 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
return NULL;
chr = qemu_mallocz(sizeof(CharDriverState));
- chr->opaque = (void *)(long)fd;
+ chr->opaque = (void *)(intptr_t)fd;
chr->chr_write = null_chr_write;
chr->chr_ioctl = pp_ioctl;
return chr;
@@ -2309,6 +2295,70 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
return NULL;
}
+/***********************************************************/
+/* Memory chardev */
+typedef struct {
+ size_t outbuf_size;
+ size_t outbuf_capacity;
+ uint8_t *outbuf;
+} MemoryDriver;
+
+static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+ MemoryDriver *d = chr->opaque;
+
+ /* TODO: the QString implementation has the same code, we should
+ * introduce a generic way to do this in cutils.c */
+ if (d->outbuf_capacity < d->outbuf_size + len) {
+ /* grow outbuf */
+ d->outbuf_capacity += len;
+ d->outbuf_capacity *= 2;
+ d->outbuf = qemu_realloc(d->outbuf, d->outbuf_capacity);
+ }
+
+ memcpy(d->outbuf + d->outbuf_size, buf, len);
+ d->outbuf_size += len;
+
+ return len;
+}
+
+void qemu_chr_init_mem(CharDriverState *chr)
+{
+ MemoryDriver *d;
+
+ d = qemu_malloc(sizeof(*d));
+ d->outbuf_size = 0;
+ d->outbuf_capacity = 4096;
+ d->outbuf = qemu_mallocz(d->outbuf_capacity);
+
+ memset(chr, 0, sizeof(*chr));
+ chr->opaque = d;
+ chr->chr_write = mem_chr_write;
+}
+
+QString *qemu_chr_mem_to_qs(CharDriverState *chr)
+{
+ MemoryDriver *d = chr->opaque;
+ return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1);
+}
+
+/* NOTE: this driver can not be closed with qemu_chr_close()! */
+void qemu_chr_close_mem(CharDriverState *chr)
+{
+ MemoryDriver *d = chr->opaque;
+
+ qemu_free(d->outbuf);
+ qemu_free(chr->opaque);
+ chr->opaque = NULL;
+ chr->chr_write = NULL;
+}
+
+size_t qemu_chr_mem_osize(const CharDriverState *chr)
+{
+ const MemoryDriver *d = chr->opaque;
+ return d->outbuf_size;
+}
+
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
char host[65], port[33], width[8], height[8];
@@ -2481,6 +2531,11 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
return NULL;
}
+ if (qemu_opt_get(opts, "backend") == NULL) {
+ fprintf(stderr, "chardev: \"%s\" missing backend\n",
+ qemu_opts_id(opts));
+ return NULL;
+ }
for (i = 0; i < ARRAY_SIZE(backend_table); i++) {
if (strcmp(backend_table[i].name, qemu_opt_get(opts, "backend")) == 0)
break;
@@ -2510,7 +2565,10 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
snprintf(base->label, len, "%s-base", qemu_opts_id(opts));
chr = qemu_chr_open_mux(base);
chr->filename = base->filename;
+ chr->avail_connections = MAX_MUX;
QTAILQ_INSERT_TAIL(&chardevs, chr, next);
+ } else {
+ chr->avail_connections = 1;
}
chr->label = qemu_strdup(qemu_opts_id(opts));
return chr;
@@ -2534,9 +2592,31 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
monitor_init(chr, MONITOR_USE_READLINE);
}
+ qemu_opts_del(opts);
return chr;
}
+void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
+{
+ if (chr->chr_set_echo) {
+ chr->chr_set_echo(chr, echo);
+ }
+}
+
+void qemu_chr_guest_open(struct CharDriverState *chr)
+{
+ if (chr->chr_guest_open) {
+ chr->chr_guest_open(chr);
+ }
+}
+
+void qemu_chr_guest_close(struct CharDriverState *chr)
+{
+ if (chr->chr_guest_close) {
+ chr->chr_guest_close(chr);
+ }
+}
+
void qemu_chr_close(CharDriverState *chr)
{
QTAILQ_REMOVE(&chardevs, chr, next);