#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"
+#include "qemu-objects.h"
#include <unistd.h>
#include <fcntl.h>
#else
#include <util.h>
#endif
+#else
#ifdef __linux__
#include <pty.h>
static void qemu_chr_event(CharDriverState *s, int event)
{
+ /* Keep track if the char device is open */
+ switch (event) {
+ case CHR_EVENT_OPENED:
+ s->opened = 1;
+ break;
+ case CHR_EVENT_CLOSED:
+ s->opened = 0;
+ break;
+ }
+
if (!s->chr_event)
return;
s->chr_event(s->handler_opaque, event);
}
void qemu_chr_add_handlers(CharDriverState *s,
- IOCanRWHandler *fd_can_read,
+ IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque)
s->handler_opaque = opaque;
if (s->chr_update_read_handler)
s->chr_update_read_handler(s);
+
+ /* We're connecting to an already opened device, so let's make sure we
+ also get the open event */
+ if (s->opened) {
+ qemu_chr_generic_open(s);
+ }
}
static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
typedef struct {
- IOCanRWHandler *chr_can_read[MAX_MUX];
+ IOCanReadHandler *chr_can_read[MAX_MUX];
IOReadHandler *chr_read[MAX_MUX];
IOEventHandler *chr_event[MAX_MUX];
void *ext_opaque[MAX_MUX];
break;
}
case 's':
- {
- DriveInfo *dinfo;
- QTAILQ_FOREACH(dinfo, &drives, next) {
- bdrv_commit(dinfo->bdrv);
- }
- }
+ bdrv_commit_all();
break;
case 'b':
qemu_chr_event(chr, CHR_EVENT_BREAK);
chr->chr_write = mux_chr_write;
chr->chr_update_read_handler = mux_chr_update_read_handler;
chr->chr_accept_input = mux_chr_accept_input;
+
+ /* Muxes are always open on creation */
+ qemu_chr_generic_open(chr);
+
return chr;
}
{
int fd_out;
- TFR(fd_out = open(qemu_opt_get(opts, "path"),
+ TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
if (fd_out < 0)
return NULL;
snprintf(filename_in, 256, "%s.in", filename);
snprintf(filename_out, 256, "%s.out", filename);
- TFR(fd_in = open(filename_in, O_RDWR | O_BINARY));
- TFR(fd_out = open(filename_out, O_RDWR | O_BINARY));
+ TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY));
+ TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY));
if (fd_in < 0 || fd_out < 0) {
if (fd_in >= 0)
close(fd_in);
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;
return 0;
}
+static void tty_exit(void)
+{
+ tcsetattr(0, TCSANOW, &oldtty);
+}
+
+static void qemu_chr_close_tty(CharDriverState *chr)
+{
+ FDCharDriver *s = chr->opaque;
+ int fd = -1;
+
+ if (s) {
+ fd = s->fd_in;
+ }
+
+ fd_chr_close(chr);
+
+ if (fd >= 0) {
+ close(fd);
+ }
+}
+
static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
{
const char *filename = qemu_opt_get(opts, "path");
int fd;
TFR(fd = open(filename, O_RDWR | O_NONBLOCK));
+ if (fd < 0) {
+ return NULL;
+ }
tty_serial_init(fd, 115200, 'N', 8, 1);
chr = qemu_chr_open_fd(fd, fd);
if (!chr) {
return NULL;
}
chr->chr_ioctl = tty_serial_ioctl;
- qemu_chr_generic_open(chr);
+ chr->chr_close = qemu_chr_close_tty;
+ if (!term_atexit_done++)
+ atexit(tty_exit);
return chr;
}
#else /* ! __linux__ && ! __sun__ */
-static CharDriverState *qemu_chr_open_pty(void)
+static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
{
return NULL;
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
{
- int fd = (int)chr->opaque;
+ int fd = (int)(long)chr->opaque;
uint8_t b;
switch(cmd) {
return NULL;
chr = qemu_mallocz(sizeof(CharDriverState));
- chr->opaque = (void *)fd;
+ chr->opaque = (void *)(long)fd;
chr->chr_write = null_chr_write;
chr->chr_ioctl = pp_ioctl;
return chr;
static int tcp_get_msgfd(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
-
- return s->msgfd;
+ int fd = s->msgfd;
+ s->msgfd = -1;
+ return fd;
}
#ifndef _WIN32
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
if (size > 0)
qemu_chr_read(chr, buf, size);
- if (s->msgfd != -1) {
- close(s->msgfd);
- s->msgfd = -1;
- }
}
}
len = sizeof(saddr);
addr = (struct sockaddr *)&saddr;
}
- fd = accept(s->listen_fd, addr, &len);
+ fd = qemu_accept(s->listen_fd, addr, &len);
if (fd < 0 && errno != EINTR) {
return;
} else if (fd >= 0) {
return NULL;
}
-static QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
+QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
char host[65], port[33], width[8], height[8];
int pos;
qemu_opt_set(opts, "backend", "udp");
if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) {
host[0] = 0;
- if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) {
- fprintf(stderr, "udp #1\n");
+ if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) {
goto fail;
}
}
if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
host[0] = 0;
if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) {
- fprintf(stderr, "udp #2\n");
goto fail;
}
}
}
fail:
- fprintf(stderr, "%s: fail on \"%s\"\n", __FUNCTION__, filename);
qemu_opts_del(opts);
return NULL;
}
qemu_free(chr);
}
-void qemu_chr_info(Monitor *mon)
+static void qemu_chr_qlist_iter(QObject *obj, void *opaque)
+{
+ QDict *chr_dict;
+ Monitor *mon = opaque;
+
+ chr_dict = qobject_to_qdict(obj);
+ monitor_printf(mon, "%s: filename=%s\n", qdict_get_str(chr_dict, "label"),
+ qdict_get_str(chr_dict, "filename"));
+}
+
+void qemu_chr_info_print(Monitor *mon, const QObject *ret_data)
+{
+ qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon);
+}
+
+void qemu_chr_info(Monitor *mon, QObject **ret_data)
{
+ QList *chr_list;
CharDriverState *chr;
+ chr_list = qlist_new();
+
QTAILQ_FOREACH(chr, &chardevs, next) {
- monitor_printf(mon, "%s: filename=%s\n", chr->label, chr->filename);
+ QObject *obj = qobject_from_jsonf("{ 'label': %s, 'filename': %s }",
+ chr->label, chr->filename);
+ qlist_append_obj(chr_list, obj);
}
+
+ *ret_data = QOBJECT(chr_list);
}
CharDriverState *qemu_chr_find(const char *name)