X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=qemu-char.c;h=1c0c9f5dffec287150dabab4400e73101d11d391;hb=d55ebf5539139b26b9c6412a834cb493f008a8a9;hp=2cf8644542916d60ce25d74920d4083988f9948e;hpb=c3b972c30d9052df7eb535a14b4e2c8c6bb12743;p=qemu diff --git a/qemu-char.c b/qemu-char.c index 2cf8644..1c0c9f5 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -23,6 +23,7 @@ */ #include "qemu-common.h" #include "net.h" +#include "monitor.h" #include "console.h" #include "sysemu.h" #include "qemu-timer.h" @@ -30,6 +31,7 @@ #include "block.h" #include "hw/usb.h" #include "hw/baum.h" +#include "hw/msmouse.h" #include #include @@ -59,10 +61,16 @@ #include #include #include -#ifdef _BSD +#ifdef HOST_BSD #include #ifdef __FreeBSD__ #include +#include +#include +#elif defined(__DragonFly__) +#include +#include +#include #else #include #endif @@ -98,6 +106,10 @@ /***********************************************************/ /* character device */ +static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = + TAILQ_HEAD_INITIALIZER(chardevs); +static int initial_reset_issued; + static void qemu_chr_event(CharDriverState *s, int event) { if (!s->chr_event) @@ -115,12 +127,23 @@ static void qemu_chr_reset_bh(void *opaque) void qemu_chr_reset(CharDriverState *s) { - if (s->bh == NULL) { + if (s->bh == NULL && initial_reset_issued) { s->bh = qemu_bh_new(qemu_chr_reset_bh, s); qemu_bh_schedule(s->bh); } } +void qemu_chr_initial_reset(void) +{ + CharDriverState *chr; + + initial_reset_issued = 1; + + TAILQ_FOREACH(chr, &chardevs, next) { + qemu_chr_reset(chr); + } +} + int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) { return s->chr_write(s, buf, len); @@ -191,8 +214,6 @@ static CharDriverState *qemu_chr_open_null(void) CharDriverState *chr; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; chr->chr_write = null_chr_write; return chr; } @@ -209,12 +230,15 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; - unsigned char buffer[MUX_BUFFER_SIZE]; - int prod; - int cons; int mux_cnt; int term_got_escape; int max_size; + /* Intermediate input buffer allows to catch escape sequences even if the + currently active device is not accepting any input - but only until it + is full as well. */ + unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE]; + int prod[MAX_MUX]; + int cons[MAX_MUX]; } MuxDriver; @@ -239,13 +263,13 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) if (term_timestamps_start == -1) term_timestamps_start = ti; ti -= term_timestamps_start; - secs = ti / 1000000000; + secs = ti / 1000; snprintf(buf1, sizeof(buf1), "[%02d:%02d:%02d.%03d] ", secs / 3600, (secs / 60) % 60, secs % 60, - (int)((ti / 1000000) % 1000)); + (int)(ti % 1000)); d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1)); } } @@ -290,6 +314,12 @@ static void mux_print_help(CharDriverState *chr) } } +static void mux_chr_send_event(MuxDriver *d, int mux_nr, int event) +{ + if (d->chr_event[mux_nr]) + d->chr_event[mux_nr](d->ext_opaque[mux_nr], event); +} + static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) { if (d->term_got_escape) { @@ -321,9 +351,11 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) break; case 'c': /* Switch to the next registered device */ + mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_OUT); chr->focus++; if (chr->focus >= d->mux_cnt) chr->focus = 0; + mux_chr_send_event(d, chr->focus, CHR_EVENT_MUX_IN); break; case 't': term_timestamps = !term_timestamps; @@ -344,11 +376,11 @@ static void mux_chr_accept_input(CharDriverState *chr) int m = chr->focus; MuxDriver *d = chr->opaque; - while (d->prod != d->cons && + while (d->prod[m] != d->cons[m] && d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) { d->chr_read[m](d->ext_opaque[m], - &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1); + &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); } } @@ -356,11 +388,12 @@ static int mux_chr_can_read(void *opaque) { CharDriverState *chr = opaque; MuxDriver *d = chr->opaque; + int m = chr->focus; - if ((d->prod - d->cons) < MUX_BUFFER_SIZE) + if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) return 1; - if (d->chr_can_read[chr->focus]) - return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); + if (d->chr_can_read[m]) + return d->chr_can_read[m](d->ext_opaque[m]); return 0; } @@ -375,12 +408,12 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) for(i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) { - if (d->prod == d->cons && + if (d->prod[m] == d->cons[m] && d->chr_can_read[m] && d->chr_can_read[m](d->ext_opaque[m])) d->chr_read[m](d->ext_opaque[m], &buf[i], 1); else - d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i]; + d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i]; } } @@ -392,8 +425,7 @@ static void mux_chr_event(void *opaque, int event) /* Send the event to all registered listeners */ for (i = 0; i < d->mux_cnt; i++) - if (d->chr_event[i]) - d->chr_event[i](d->ext_opaque[i], event); + mux_chr_send_event(d, i, event); } static void mux_chr_update_read_handler(CharDriverState *chr) @@ -423,13 +455,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) MuxDriver *d; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; d = qemu_mallocz(sizeof(MuxDriver)); - if (!d) { - free(chr); - return NULL; - } chr->opaque = d; d->drv = drv; @@ -450,7 +476,6 @@ int send_all(int fd, const void *buf, int len1) while (len > 0) { ret = send(fd, buf, len, 0); if (ret < 0) { - int errno; errno = WSAGetLastError(); if (errno != WSAEWOULDBLOCK) { return -1; @@ -546,7 +571,7 @@ static void fd_chr_update_read_handler(CharDriverState *chr) FDCharDriver *s = chr->opaque; if (s->fd_in >= 0) { - if (nographic && s->fd_in == 0) { + if (display_type == DT_NOGRAPHIC && s->fd_in == 0) { } else { qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, fd_chr_read, NULL, chr); @@ -559,7 +584,7 @@ static void fd_chr_close(struct CharDriverState *chr) FDCharDriver *s = chr->opaque; if (s->fd_in >= 0) { - if (nographic && s->fd_in == 0) { + if (display_type == DT_NOGRAPHIC && s->fd_in == 0) { } else { qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); } @@ -575,13 +600,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) FDCharDriver *s; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(FDCharDriver)); - if (!s) { - free(chr); - return NULL; - } s->fd_in = fd_in; s->fd_out = fd_out; chr->opaque = s; @@ -695,7 +714,7 @@ static void term_init(void) tty.c_oflag |= OPOST; tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); /* if graphical mode, we allow Ctrl-C handling */ - if (nographic) + if (display_type == DT_NOGRAPHIC) tty.c_lflag &= ~ISIG; tty.c_cflag &= ~(CSIZE|PARENB); tty.c_cflag |= CS8; @@ -735,8 +754,8 @@ static CharDriverState *qemu_chr_open_stdio(void) #ifdef __sun__ /* Once Solaris has openpty(), this is going to be removed. */ -int openpty(int *amaster, int *aslave, char *name, - struct termios *termp, struct winsize *winp) +static int openpty(int *amaster, int *aslave, char *name, + struct termios *termp, struct winsize *winp) { const char *slave; int mfd = -1, sfd = -1; @@ -776,7 +795,7 @@ err: return -1; } -void cfmakeraw (struct termios *termios_p) +static void cfmakeraw (struct termios *termios_p) { termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); @@ -791,7 +810,7 @@ void cfmakeraw (struct termios *termios_p) #endif #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ - || defined(__NetBSD__) || defined(__OpenBSD__) + || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) typedef struct { int fd; @@ -910,6 +929,8 @@ static void pty_chr_close(struct CharDriverState *chr) qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); close(s->fd); + qemu_del_timer(s->timer); + qemu_free_timer(s->timer); qemu_free(s); } @@ -919,7 +940,7 @@ static CharDriverState *qemu_chr_open_pty(void) PtyCharDriver *s; struct termios tty; int slave_fd, len; -#if defined(__OpenBSD__) +#if defined(__OpenBSD__) || defined(__DragonFly__) char pty_name[PATH_MAX]; #define q_ptsname(x) pty_name #else @@ -928,13 +949,7 @@ static CharDriverState *qemu_chr_open_pty(void) #endif chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(PtyCharDriver)); - if (!s) { - qemu_free(chr); - return NULL; - } if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) { return NULL; @@ -1066,17 +1081,17 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) int *targ = (int *)arg; ioctl(s->fd_in, TIOCMGET, &sarg); *targ = 0; - if (sarg | TIOCM_CTS) + if (sarg & TIOCM_CTS) *targ |= CHR_TIOCM_CTS; - if (sarg | TIOCM_CAR) + if (sarg & TIOCM_CAR) *targ |= CHR_TIOCM_CAR; - if (sarg | TIOCM_DSR) + if (sarg & TIOCM_DSR) *targ |= CHR_TIOCM_DSR; - if (sarg | TIOCM_RI) + if (sarg & TIOCM_RI) *targ |= CHR_TIOCM_RI; - if (sarg | TIOCM_DTR) + if (sarg & TIOCM_DTR) *targ |= CHR_TIOCM_DTR; - if (sarg | TIOCM_RTS) + if (sarg & TIOCM_RTS) *targ |= CHR_TIOCM_RTS; } break; @@ -1084,9 +1099,20 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) { int sarg = *(int *)arg; int targ = 0; - if (sarg | CHR_TIOCM_DTR) + ioctl(s->fd_in, TIOCMGET, &targ); + targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR + | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS); + if (sarg & CHR_TIOCM_CTS) + targ |= TIOCM_CTS; + if (sarg & CHR_TIOCM_CAR) + targ |= TIOCM_CAR; + if (sarg & CHR_TIOCM_DSR) + targ |= TIOCM_DSR; + if (sarg & CHR_TIOCM_RI) + targ |= TIOCM_RI; + if (sarg & CHR_TIOCM_DTR) targ |= TIOCM_DTR; - if (sarg | CHR_TIOCM_RTS) + if (sarg & CHR_TIOCM_RTS) targ |= TIOCM_RTS; ioctl(s->fd_in, TIOCMSET, &targ); } @@ -1245,19 +1271,10 @@ static CharDriverState *qemu_chr_open_pp(const char *filename) } drv = qemu_mallocz(sizeof(ParallelCharDriver)); - if (!drv) { - close(fd); - return NULL; - } drv->fd = fd; drv->mode = IEEE1284_MODE_COMPAT; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) { - qemu_free(drv); - close(fd); - return NULL; - } chr->chr_write = null_chr_write; chr->chr_ioctl = pp_ioctl; chr->chr_close = pp_close; @@ -1269,6 +1286,61 @@ static CharDriverState *qemu_chr_open_pp(const char *filename) } #endif /* __linux__ */ +#if defined(__FreeBSD__) || defined(__DragonFly__) +static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) +{ + int fd = (int)chr->opaque; + uint8_t b; + + switch(cmd) { + case CHR_IOCTL_PP_READ_DATA: + if (ioctl(fd, PPIGDATA, &b) < 0) + return -ENOTSUP; + *(uint8_t *)arg = b; + break; + case CHR_IOCTL_PP_WRITE_DATA: + b = *(uint8_t *)arg; + if (ioctl(fd, PPISDATA, &b) < 0) + return -ENOTSUP; + break; + case CHR_IOCTL_PP_READ_CONTROL: + if (ioctl(fd, PPIGCTRL, &b) < 0) + return -ENOTSUP; + *(uint8_t *)arg = b; + break; + case CHR_IOCTL_PP_WRITE_CONTROL: + b = *(uint8_t *)arg; + if (ioctl(fd, PPISCTRL, &b) < 0) + return -ENOTSUP; + break; + case CHR_IOCTL_PP_READ_STATUS: + if (ioctl(fd, PPIGSTATUS, &b) < 0) + return -ENOTSUP; + *(uint8_t *)arg = b; + break; + default: + return -ENOTSUP; + } + return 0; +} + +static CharDriverState *qemu_chr_open_pp(const char *filename) +{ + CharDriverState *chr; + int fd; + + fd = open(filename, O_RDWR); + if (fd < 0) + return NULL; + + chr = qemu_mallocz(sizeof(CharDriverState)); + chr->opaque = (void *)fd; + chr->chr_write = null_chr_write; + chr->chr_ioctl = pp_ioctl; + return chr; +} +#endif + #else /* _WIN32 */ typedef struct { @@ -1475,13 +1547,7 @@ static CharDriverState *qemu_chr_open_win(const char *filename) WinCharState *s; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(WinCharState)); - if (!s) { - free(chr); - return NULL; - } chr->opaque = s; chr->chr_write = win_chr_write; chr->chr_close = win_chr_close; @@ -1580,13 +1646,7 @@ static CharDriverState *qemu_chr_open_win_pipe(const char *filename) WinCharState *s; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(WinCharState)); - if (!s) { - free(chr); - return NULL; - } chr->opaque = s; chr->chr_write = win_chr_write; chr->chr_close = win_chr_close; @@ -1606,13 +1666,7 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) WinCharState *s; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - return NULL; s = qemu_mallocz(sizeof(WinCharState)); - if (!s) { - free(chr); - return NULL; - } s->hcom = fd_out; chr->opaque = s; chr->chr_write = win_chr_write; @@ -1706,6 +1760,16 @@ static void udp_chr_update_read_handler(CharDriverState *chr) } } +static void udp_chr_close(CharDriverState *chr) +{ + NetCharDriver *s = chr->opaque; + if (s->fd >= 0) { + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + closesocket(s->fd); + } + qemu_free(s); +} + static CharDriverState *qemu_chr_open_udp(const char *def) { CharDriverState *chr = NULL; @@ -1714,11 +1778,7 @@ static CharDriverState *qemu_chr_open_udp(const char *def) struct sockaddr_in saddr; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - goto return_err; s = qemu_mallocz(sizeof(NetCharDriver)); - if (!s) - goto return_err; fd = socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { @@ -1743,6 +1803,7 @@ static CharDriverState *qemu_chr_open_udp(const char *def) chr->opaque = s; chr->chr_write = udp_chr_write; chr->chr_update_read_handler = udp_chr_update_read_handler; + chr->chr_close = udp_chr_close; return chr; return_err: @@ -1945,10 +2006,14 @@ static void tcp_chr_accept(void *opaque) static void tcp_chr_close(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; - if (s->fd >= 0) + if (s->fd >= 0) { + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); closesocket(s->fd); - if (s->listen_fd >= 0) + } + if (s->listen_fd >= 0) { + qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); closesocket(s->listen_fd); + } qemu_free(s); } @@ -1975,6 +2040,10 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, do_nodelay = 1; } else if (!strncmp(ptr,"to=",3)) { /* nothing, inet_listen() parses this one */; + } else if (!strncmp(ptr,"ipv4",4)) { + /* nothing, inet_connect() and inet_listen() parse this one */; + } else if (!strncmp(ptr,"ipv6",4)) { + /* nothing, inet_connect() and inet_listen() parse this one */; } else { printf("Unknown option: %s\n", ptr); goto fail; @@ -1984,20 +2053,16 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, is_waitconnect = 0; chr = qemu_mallocz(sizeof(CharDriverState)); - if (!chr) - goto fail; s = qemu_mallocz(sizeof(TCPCharDriver)); - if (!s) - goto fail; if (is_listen) { chr->filename = qemu_malloc(256); if (is_unix) { - strcpy(chr->filename, "unix:"); + pstrcpy(chr->filename, 256, "unix:"); } else if (is_telnet) { - strcpy(chr->filename, "telnet:"); + pstrcpy(chr->filename, 256, "telnet:"); } else { - strcpy(chr->filename, "tcp:"); + pstrcpy(chr->filename, 256, "tcp:"); } offset = strlen(chr->filename); } @@ -2059,19 +2124,16 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, return NULL; } -static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs -= TAILQ_HEAD_INITIALIZER(chardevs); - -CharDriverState *qemu_chr_open(const char *label, const char *filename) +CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s)) { const char *p; CharDriverState *chr; if (!strcmp(filename, "vc")) { - chr = text_console_init(&display_state, 0); + chr = text_console_init(0); } else if (strstart(filename, "vc:", &p)) { - chr = text_console_init(&display_state, p); + chr = text_console_init(p); } else if (!strcmp(filename, "null")) { chr = qemu_chr_open_null(); @@ -2086,13 +2148,15 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename) chr = qemu_chr_open_udp(p); } else if (strstart(filename, "mon:", &p)) { - chr = qemu_chr_open(label, p); + chr = qemu_chr_open(label, p, NULL); if (chr) { chr = qemu_chr_open_mux(chr); - monitor_init(chr, !nographic); + monitor_init(chr, MONITOR_USE_READLINE); } else { printf("Unable to open driver: %s\n", p); } + } else if (!strcmp(filename, "msmouse")) { + chr = qemu_chr_open_msmouse(); } else #ifndef _WIN32 if (strstart(filename, "unix:", &p)) { @@ -2110,9 +2174,13 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename) if (strstart(filename, "/dev/parport", NULL)) { chr = qemu_chr_open_pp(filename); } else +#elif defined(__FreeBSD__) || defined(__DragonFly__) + if (strstart(filename, "/dev/ppi", NULL)) { + chr = qemu_chr_open_pp(filename); + } else #endif #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ - || defined(__NetBSD__) || defined(__OpenBSD__) + || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) if (strstart(filename, "/dev/", NULL)) { chr = qemu_chr_open_tty(filename); } else @@ -2143,6 +2211,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename) if (chr) { if (!chr->filename) chr->filename = qemu_strdup(filename); + chr->init = init; chr->label = qemu_strdup(label); TAILQ_INSERT_TAIL(&chardevs, chr, next); } @@ -2159,11 +2228,11 @@ void qemu_chr_close(CharDriverState *chr) qemu_free(chr); } -void qemu_chr_info(void) +void qemu_chr_info(Monitor *mon) { CharDriverState *chr; TAILQ_FOREACH(chr, &chardevs, next) { - term_printf("%s: filename=%s\n", chr->label, chr->filename); + monitor_printf(mon, "%s: filename=%s\n", chr->label, chr->filename); } }