qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 16/22] Serial ports replay and stdio monitor for


From: Pavel Dovgaluk
Subject: [Qemu-devel] [RFC PATCH 16/22] Serial ports replay and stdio monitor for Win32
Date: Tue, 1 Jul 2014 15:29:45 +0400

These files include the following changes:
 - Record/replay functions for COM ports added by -serial command-line option.
 - Implementation of stdio monitor for Win32.

Signed-off-by: Pavel Dovgalyuk <address@hidden>
---

diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index c8b15f9..5e13fab
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -86,6 +86,7 @@ struct CharDriverState {
     guint fd_in_tag;
     guint fd_hup_tag;
     QemuOpts *opts;
+    bool replay;
     QTAILQ_ENTRY(CharDriverState) next;
 };
 
@@ -125,6 +126,8 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
  */
 CharDriverState *qemu_chr_new(const char *label, const char *filename,
                               void (*init)(struct CharDriverState *s));
+CharDriverState *qemu_chr_new_replay(const char *label, const char *filename,
+                              void (*init)(struct CharDriverState *s));
 
 /**
  * @qemu_chr_delete:
@@ -320,6 +323,7 @@ int qemu_chr_be_can_write(CharDriverState *s);
  * @len the number of bytes to receive from the front end
  */
 void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
+void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
 
 
 /**

diff --git a/qemu-char.c b/qemu-char.c
index 51917de..4627eef
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -81,6 +81,7 @@
 
 #include "qemu/sockets.h"
 #include "ui/qemu-spice.h"
+#include "replay/replay.h"
 
 #define READ_BUF_LEN 4096
 #define READ_RETRIES 10
@@ -126,6 +127,9 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t 
*buf, int len)
 
     qemu_mutex_lock(&s->chr_write_lock);
     ret = s->chr_write(s, buf, len);
+    if (s->replay) {
+        replay_data_int(&ret);
+    }
     qemu_mutex_unlock(&s->chr_write_lock);
     return ret;
 }
@@ -195,9 +199,18 @@ int qemu_chr_fe_read_all(CharDriverState *s, uint8_t *buf, 
int len)
 
 int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg)
 {
-    if (!s->chr_ioctl)
-        return -ENOTSUP;
-    return s->chr_ioctl(s, cmd, arg);
+    int res;
+    if (!s->chr_ioctl) {
+        res = -ENOTSUP;
+    } else {
+        res = s->chr_ioctl(s, cmd, arg);
+        if (s->replay) {
+            fprintf(stderr, "Replay: ioctl is not supported for serial devices 
yet\n");
+            exit(1);
+        }
+    }
+
+    return res;
 }
 
 int qemu_chr_be_can_write(CharDriverState *s)
@@ -207,17 +220,34 @@ int qemu_chr_be_can_write(CharDriverState *s)
     return s->chr_can_read(s->handler_opaque);
 }
 
-void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
+void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len)
 {
     if (s->chr_read) {
         s->chr_read(s->handler_opaque, buf, len);
     }
 }
 
+void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
+{
+    if (s->replay) {
+        if (replay_mode == REPLAY_PLAY) {
+            fprintf(stderr, "Replay: calling qemu_chr_be_write in play 
mode\n");
+            exit(1);
+        }
+        replay_chr_be_write(s, buf, len);
+    } else {
+        qemu_chr_be_write_impl(s, buf, len);
+    }
+}
+
 int qemu_chr_fe_get_msgfd(CharDriverState *s)
 {
     int fd;
-    return (qemu_chr_fe_get_msgfds(s, &fd, 1) == 1) ? fd : -1;
+    int res = (qemu_chr_fe_get_msgfds(s, &fd, 1) == 1) ? fd : -1;
+    if (s->replay) {
+        replay_data_int(&res);
+    }
+    return res;
 }
 
 int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int len)
@@ -1923,6 +1953,8 @@ static int win_chr_pipe_poll(void *opaque)
     if (size > 0) {
         s->len = size;
         win_chr_read_poll(chr);
+        if (s->max_size == 0)
+            return 0;
         win_chr_read(chr);
         return 1;
     }
@@ -2034,19 +2066,41 @@ static int win_stdio_write(CharDriverState *chr, const 
uint8_t *buf, int
len)
 {
     HANDLE  hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
     DWORD   dwSize;
-    int     len1;
+    int     ret = 0;
+    CONSOLE_SCREEN_BUFFER_INFO info;
 
-    len1 = len;
-
-    while (len1 > 0) {
-        if (!WriteFile(hStdOut, buf, len1, &dwSize, NULL)) {
-            break;
+    while (len > 0) {
+        if (len > 2 && buf[0] == '\033' && buf[1] == '[') {
+            switch (buf[2]) {
+            case 'D':
+                if (!WriteFile(hStdOut, "\b", 1, &dwSize, NULL)) {
+                    return ret;
+                }
+                break;
+            case 'K':
+                if (!GetConsoleScreenBufferInfo(hStdOut, &info)) {
+                    return ret;
+                }
+                if (!FillConsoleOutputCharacter(hStdOut, ' ', 
+                    info.dwSize.X - info.dwCursorPosition.X, 
+                    info.dwCursorPosition, &dwSize)) {
+                    return ret;
+                }
+                break;
+            }
+            dwSize = 3;
+        } else {
+            if (!WriteFile(hStdOut, buf, 1, &dwSize, NULL)) {
+                return ret;
+            }
         }
-        buf  += dwSize;
-        len1 -= dwSize;
+
+        buf += dwSize;
+        len -= dwSize;
+        ret += dwSize;
     }
 
-    return len - len1;
+    return ret;
 }
 
 static void win_stdio_wait_func(void *opaque)
@@ -2170,19 +2224,24 @@ static CharDriverState 
*qemu_chr_open_stdio(ChardevStdio *opts)
 {
     CharDriverState   *chr;
     WinStdioCharState *stdio;
+    HANDLE             hStdOut;
     DWORD              dwMode;
+    DWORD              dwOutMode;
     int                is_console = 0;
 
     chr   = qemu_chr_alloc();
     stdio = g_malloc0(sizeof(WinStdioCharState));
 
     stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
-    if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
+    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+    if (stdio->hStdIn == INVALID_HANDLE_VALUE
+        || hStdOut == INVALID_HANDLE_VALUE) {
         fprintf(stderr, "cannot open stdio: invalid handle\n");
         exit(1);
     }
 
     is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
+    GetConsoleMode(hStdOut, &dwOutMode);
 
     chr->opaque    = stdio;
     chr->chr_write = win_stdio_write;
@@ -2219,9 +2278,11 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio 
*opts)
         /* set the terminal in raw mode */
         /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
         dwMode |= ENABLE_PROCESSED_INPUT;
+        dwOutMode |= ENABLE_PROCESSED_OUTPUT;
     }
 
     SetConsoleMode(stdio->hStdIn, dwMode);
+    SetConsoleMode(hStdOut, dwOutMode);
 
     chr->chr_set_echo = qemu_chr_set_echo_win_stdio;
     qemu_chr_fe_set_echo(chr, false);
@@ -3615,6 +3676,18 @@ CharDriverState *qemu_chr_new(const char *label, const 
char *filename, void
(*in
     return chr;
 }
 
+CharDriverState *qemu_chr_new_replay(const char *label, const char *filename, 
void (*init)(struct
CharDriverState *s))
+{   
+    if (replay_mode == REPLAY_PLAY && (strcmp(filename, "null") && 
strcmp(filename, "vc:80Cx24C")))
{
+        fprintf(stderr, "Only \"-serial null\" can be used with replay\n");
+        exit(1);
+    }
+    CharDriverState *chr = qemu_chr_new(label, filename, init);
+    if (strcmp(filename, "vc:80Cx24C"))
+        replay_register_char_driver(chr);
+    return chr;
+}
+
 void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo)
 {
     if (chr->chr_set_echo) {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]