@@ -1078,7 +1078,7 @@ void console_select(unsigned int index)
}
}
-static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
+static int console_puts(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
TextConsole *s = chr->opaque;
int i;
@@ -1088,7 +1088,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
s->update_x1 = 0;
s->update_y1 = 0;
console_show_cursor(s, 0);
- for(i = 0; i < len; i++) {
+ for(i = 0; i < *len; i++) {
console_putchar(s, buf[i]);
}
console_show_cursor(s, 1);
@@ -1097,7 +1097,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
s->update_x1 - s->update_x0,
s->update_y1 - s->update_y0);
}
- return len;
+ return *len;
}
static void console_send_event(CharDriverState *chr, int event)
@@ -1498,11 +1498,11 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
if (chr->label) {
char msg[128];
- int len;
+ size_t len;
s->t_attrib.bgcol = COLOR_BLUE;
len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
- console_puts(chr, (uint8_t*)msg, len);
+ console_puts(chr, (uint8_t*)msg, &len);
s->t_attrib = s->t_attrib_default;
}
@@ -376,7 +376,9 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
}
}
#else
- qemu_chr_write(s->chr, buf, len);
+ size_t tmplen = len;
+
+ qemu_chr_write(s->chr, buf, &tmplen);
#endif
}
@@ -2595,22 +2597,23 @@ static void gdb_monitor_output(GDBState *s, const char *msg, int len)
put_packet(s, buf);
}
-static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf,
+ size_t *len)
{
const char *p = (const char *)buf;
int max_sz;
max_sz = (sizeof(gdbserver_state->last_packet) - 2) / 2;
for (;;) {
- if (len <= max_sz) {
- gdb_monitor_output(gdbserver_state, p, len);
+ if (*len <= max_sz) {
+ gdb_monitor_output(gdbserver_state, p, *len);
break;
}
gdb_monitor_output(gdbserver_state, p, max_sz);
p += max_sz;
- len -= max_sz;
+ *len -= max_sz;
}
- return len;
+ return *len;
}
#ifndef _WIN32
@@ -296,7 +296,7 @@ static int csrhci_data_len(const uint8_t *pkt)
}
static int csrhci_write(struct CharDriverState *chr,
- const uint8_t *buf, int len)
+ const uint8_t *buf, size_t *len)
{
struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
int plen = s->in_len;
@@ -304,8 +304,8 @@ static int csrhci_write(struct CharDriverState *chr,
if (!s->enable)
return 0;
- s->in_len += len;
- memcpy(s->inpkt + plen, buf, len);
+ s->in_len += *len;
+ memcpy(s->inpkt + plen, buf, *len);
while (1) {
if (s->in_len >= 2 && plen < 2)
@@ -326,7 +326,7 @@ static int csrhci_write(struct CharDriverState *chr,
break;
}
- return len;
+ return *len;
}
static void csrhci_out_hci_packet_event(void *opaque,
@@ -46,15 +46,16 @@ static void debugcon_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
DebugconState *s = opaque;
unsigned char ch = val;
+ size_t tmplen;
#ifdef DEBUG_DEBUGCON
printf("debugcon: write addr=0x%04x val=0x%02x\n", addr, val);
#endif
- qemu_chr_write(s->chr, &ch, 1);
+ tmplen = 1;
+ qemu_chr_write(s->chr, &ch, &tmplen);
}
-
static uint32_t debugcon_ioport_read(void *opaque, uint32_t addr)
{
DebugconState *s = opaque;
@@ -53,10 +53,11 @@ static void msmouse_event(void *opaque,
qemu_chr_read(chr, bytes, 4);
}
-static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
+static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf,
+ size_t *len)
{
/* Ignore writes to mouse port */
- return len;
+ return *len;
}
static void msmouse_chr_close (struct CharDriverState *chr)
@@ -116,10 +116,13 @@ parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
s->status |= PARA_STS_ERROR;
}
else if (val & PARA_CTR_SELECT) {
+ size_t tmplen;
+
+ tmplen = 1;
if (val & PARA_CTR_STROBE) {
s->status &= ~PARA_STS_BUSY;
if ((s->control & PARA_CTR_STROBE) == 0)
- qemu_chr_write(s->chr, &s->dataw, 1);
+ qemu_chr_write(s->chr, &s->dataw, &tmplen);
} else {
if (s->control & PARA_CTR_INTEN) {
s->irq_pending = 1;
@@ -311,6 +311,7 @@ static void serial_xmit(void *opaque)
{
SerialState *s = opaque;
uint64_t new_xmit_ts = qemu_get_clock(vm_clock);
+ size_t tmplen;
if (s->tsr_retry <= 0) {
if (s->fcr & UART_FCR_FE) {
@@ -323,10 +324,11 @@ static void serial_xmit(void *opaque)
}
}
+ tmplen = 1;
if (s->mcr & UART_MCR_LOOP) {
/* in loopback mode, say that we just received a char */
serial_receive1(s, &s->tsr, 1);
- } else if (qemu_chr_write(s->chr, &s->tsr, 1) != 1) {
+ } else if (qemu_chr_write(s->chr, &s->tsr, &tmplen) != 1) {
if ((s->tsr_retry > 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
s->tsr_retry++;
qemu_mod_timer(s->transmit_timer, new_xmit_ts + s->char_transmit_time);
@@ -426,14 +426,14 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
int ret = 0;
uint8_t devep = p->devep;
uint8_t *data = p->data;
- int len = p->len;
+ size_t len = p->len;
int first_len;
switch (p->pid) {
case USB_TOKEN_OUT:
if (devep != 2)
goto fail;
- qemu_chr_write(s->cs, data, len);
+ qemu_chr_write(s->cs, data, &len);
break;
case USB_TOKEN_IN:
@@ -24,7 +24,7 @@ static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
{
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
- qemu_chr_write(vcon->chr, buf, len);
+ qemu_chr_write(vcon->chr, buf, &len);
}
/* Readiness of the guest to accept data on a port */
@@ -232,7 +232,9 @@ static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
void monitor_flush(Monitor *mon)
{
if (mon && mon->outbuf_index != 0 && !mon->mux_out) {
- qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index);
+ size_t tmplen = mon->outbuf_index;
+
+ qemu_chr_write(mon->chr, mon->outbuf, &tmplen);
mon->outbuf_index = 0;
}
}
@@ -54,10 +54,13 @@ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_
{
NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
uint32_t len;
+ size_t len_len;
+
len = htonl(size);
+ len_len = sizeof(len);
- send_all(s->fd, (const uint8_t *)&len, sizeof(len));
- return send_all(s->fd, buf, size);
+ send_all(s->fd, (const uint8_t *)&len, &len_len);
+ return send_all(s->fd, buf, &size);
}
static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size)
@@ -130,7 +130,7 @@ void qemu_chr_generic_open(CharDriverState *s)
}
}
-int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, size_t *len)
{
return s->chr_write(s, buf, len);
}
@@ -169,9 +169,12 @@ void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
{
char buf[READ_BUF_LEN];
va_list ap;
+ size_t len;
+
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
- qemu_chr_write(s, (uint8_t *)buf, strlen(buf));
+ len = strlen(buf);
+ qemu_chr_write(s, (uint8_t *)buf, &len);
va_end(ap);
}
@@ -195,9 +198,9 @@ void qemu_chr_add_handlers(CharDriverState *s,
s->chr_update_read_handler(s);
}
-static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int null_chr_write(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
- return len;
+ return *len;
}
static CharDriverState *qemu_chr_open_null(QemuOpts *opts)
@@ -235,7 +238,7 @@ typedef struct {
} MuxDriver;
-static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
MuxDriver *d = chr->opaque;
int ret;
@@ -245,7 +248,9 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
int i;
ret = 0;
- for (i = 0; i < len; i++) {
+ for (i = 0; i < *len; i++) {
+ size_t tmplen;
+
if (d->linestart) {
char buf1[64];
int64_t ti;
@@ -262,10 +267,12 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
(secs / 60) % 60,
secs % 60,
(int)(ti % 1000));
- d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1));
+ tmplen = strlen(buf1);
+ d->drv->chr_write(d->drv, (uint8_t *)buf1, &tmplen);
d->linestart = 0;
}
- ret += d->drv->chr_write(d->drv, buf+i, 1);
+ tmplen = 1;
+ ret += d->drv->chr_write(d->drv, buf+i, &tmplen);
if (buf[i] == '\n') {
d->linestart = 1;
}
@@ -291,6 +298,7 @@ static void mux_print_help(CharDriverState *chr)
int i, j;
char ebuf[15] = "Escape-Char";
char cbuf[50] = "\n\r";
+ size_t tmplen;
if (term_escape_char > 0 && term_escape_char < 26) {
snprintf(cbuf, sizeof(cbuf), "\n\r");
@@ -300,13 +308,18 @@ static void mux_print_help(CharDriverState *chr)
"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
term_escape_char);
}
- chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf));
+ tmplen = strlen(cbuf);
+ chr->chr_write(chr, (uint8_t *)cbuf, &tmplen);
for (i = 0; mux_help[i] != NULL; i++) {
for (j=0; mux_help[i][j] != '\0'; j++) {
- if (mux_help[i][j] == '%')
- chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf));
- else
- chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1);
+
+ if (mux_help[i][j] == '%') {
+ tmplen = strlen(ebuf);
+ chr->chr_write(chr, (uint8_t *)ebuf, &tmplen);
+ } else {
+ tmplen = 1;
+ chr->chr_write(chr, (uint8_t *)&mux_help[i][j], &tmplen);
+ }
}
}
}
@@ -331,7 +344,9 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
case 'x':
{
const char *term = "QEMU: Terminated\n\r";
- chr->chr_write(chr,(uint8_t *)term,strlen(term));
+ size_t tmplen = strlen(term);
+
+ chr->chr_write(chr, (uint8_t *)term, &tmplen);
exit(0);
break;
}
@@ -470,13 +485,14 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
#ifdef _WIN32
-int send_all(int fd, const void *buf, int len1)
+int send_all(int fd, const void *buf, size_t *len)
{
- int ret, len;
+ ssize_t tmplen, ret;
- len = len1;
- while (len > 0) {
- ret = send(fd, buf, len, 0);
+ tmplen = *len;
+ *len = 0;
+ while (tmplen > 0) {
+ ret = send(fd, buf, tmplen, 0);
if (ret < 0) {
errno = WSAGetLastError();
if (errno != WSAEWOULDBLOCK) {
@@ -486,7 +502,8 @@ int send_all(int fd, const void *buf, int len1)
break;
} else {
buf += ret;
- len -= ret;
+ *len += ret;
+ tmplen -= ret;
}
}
return len1 - len;
@@ -494,13 +511,14 @@ int send_all(int fd, const void *buf, int len1)
#else
-static int unix_write(int fd, const uint8_t *buf, int len1)
+static int unix_write(int fd, const uint8_t *buf, size_t *len)
{
- int ret, len;
+ ssize_t tmplen, ret;
- len = len1;
- while (len > 0) {
- ret = write(fd, buf, len);
+ tmplen = *len;
+ *len = 0;
+ while (tmplen > 0) {
+ ret = write(fd, buf, tmplen);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return -1;
@@ -508,15 +526,16 @@ static int unix_write(int fd, const uint8_t *buf, int len1)
break;
} else {
buf += ret;
- len -= ret;
+ *len += ret;
+ tmplen -= ret;
}
}
- return len1 - len;
+ return *len;
}
-int send_all(int fd, const void *buf, int len1)
+int send_all(int fd, const void *buf, size_t *len)
{
- return unix_write(fd, buf, len1);
+ return unix_write(fd, buf, len);
}
#endif /* !_WIN32 */
@@ -530,7 +549,7 @@ typedef struct {
#define STDIO_MAX_CLIENTS 1
static int stdio_nb_clients = 0;
-static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
FDCharDriver *s = chr->opaque;
return send_all(s->fd_out, buf, len);
@@ -836,7 +855,7 @@ typedef struct {
static void pty_chr_update_read_handler(CharDriverState *chr);
static void pty_chr_state(CharDriverState *chr, int connected);
-static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
PtyCharDriver *s = chr->opaque;
@@ -1791,11 +1810,11 @@ typedef struct {
int max_size;
} NetCharDriver;
-static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
NetCharDriver *s = chr->opaque;
- return send(s->fd, (const void *)buf, len, 0);
+ return send(s->fd, (const void *)buf, *len, 0);
}
static int udp_chr_read_poll(void *opaque)
@@ -1906,14 +1925,14 @@ typedef struct {
static void tcp_chr_accept(void *opaque);
-static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, size_t *len)
{
TCPCharDriver *s = chr->opaque;
if (s->connected) {
return send_all(s->fd, buf, len);
} else {
/* XXX: indicate an error ? */
- return len;
+ return *len;
}
}
@@ -2201,8 +2220,9 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
if (fd < 0)
goto fail;
- if (!is_waitconnect)
+ if (!is_waitconnect) {
socket_set_nonblock(fd);
+ }
s->connected = 0;
s->fd = -1;
@@ -2225,7 +2245,9 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
} else {
s->connected = 1;
s->fd = fd;
- socket_set_nodelay(fd);
+ if (s->do_nodelay) {
+ socket_set_nodelay(fd);
+ }
tcp_chr_connect(chr);
}
@@ -1,6 +1,8 @@
#ifndef QEMU_CHAR_H
#define QEMU_CHAR_H
+#include <stdbool.h>
+
#include "qemu-common.h"
#include "qemu-queue.h"
#include "qemu-option.h"
@@ -52,7 +54,7 @@ typedef void IOEventHandler(void *opaque, int event);
struct CharDriverState {
void (*init)(struct CharDriverState *s);
- int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
+ int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, size_t *len);
void (*chr_update_read_handler)(struct CharDriverState *s);
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
int (*get_msgfd)(struct CharDriverState *s);
@@ -67,6 +69,7 @@ struct CharDriverState {
QEMUBH *bh;
char *label;
char *filename;
+ bool nonblock;
QTAILQ_ENTRY(CharDriverState) next;
};
@@ -76,7 +79,7 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
void qemu_chr_close(CharDriverState *chr);
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
-int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, size_t *len);
void qemu_chr_send_event(CharDriverState *s, int event);
void qemu_chr_add_handlers(CharDriverState *s,
IOCanReadHandler *fd_can_read,
@@ -35,7 +35,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
int qemu_socket(int domain, int type, int protocol);
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
void socket_set_nonblock(int fd);
-int send_all(int fd, const void *buf, int len1);
+int send_all(int fd, const void *buf, size_t *len);
/* New, ipv6-ready socket helper functions, see qemu-sockets.c */
int inet_listen_opts(QemuOpts *opts, int port_offset);
@@ -798,12 +798,14 @@ int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
{
- if (so->s == -1 && so->extra) {
- qemu_chr_write(so->extra, buf, len);
- return len;
- }
+ if (so->s == -1 && so->extra) {
+ size_t tmplen = len;
+
+ qemu_chr_write(so->extra, buf, &tmplen);
+ return len;
+ }
- return send(so->s, buf, len, flags);
+ return send(so->s, buf, len, flags);
}
static struct socket *
There might be cases where a few bytes would have been sent out to char devices and some not. Currently the return values from qemu_chr_write() to char devs are only -1, indicating an error, or the complete length of the string passed. Make 'len' a pointer instead, and indicate how much of the string was written. The return value will either be the same as 'len' or a negative number indicating an error condition. Signed-off-by: Amit Shah <amit.shah@redhat.com> --- console.c | 10 +++--- gdbstub.c | 15 +++++--- hw/bt-hci-csr.c | 8 ++-- hw/debugcon.c | 5 ++- hw/msmouse.c | 5 ++- hw/parallel.c | 5 ++- hw/serial.c | 4 ++- hw/usb-serial.c | 4 +- hw/virtio-console.c | 2 +- monitor.c | 4 ++- net/socket.c | 7 +++- qemu-char.c | 96 +++++++++++++++++++++++++++++++------------------- qemu-char.h | 7 +++- qemu_socket.h | 2 +- slirp/slirp.c | 12 ++++--- 15 files changed, 114 insertions(+), 72 deletions(-)