Re: [Qemu-devel] [PATCH V5] Add stdio char device on windows

2011-10-23 Thread Blue Swirl
Thanks, applied.

On Thu, Oct 6, 2011 at 14:37, Fabien Chouteau chout...@adacore.com wrote:
 Simple implementation of an stdio char device on Windows.

 Signed-off-by: Fabien Chouteau chout...@adacore.com
 ---
  qemu-char.c |  227 
 ++-
  1 files changed, 225 insertions(+), 2 deletions(-)

 diff --git a/qemu-char.c b/qemu-char.c
 index 09d2309..b9381be 100644
 --- a/qemu-char.c
 +++ b/qemu-char.c
 @@ -538,6 +538,9 @@ int send_all(int fd, const void *_buf, int len1)
  }
  #endif /* !_WIN32 */

 +#define STDIO_MAX_CLIENTS 1
 +static int stdio_nb_clients;
 +
  #ifndef _WIN32

  typedef struct {
 @@ -545,8 +548,6 @@ typedef struct {
     int max_size;
  } FDCharDriver;

 -#define STDIO_MAX_CLIENTS 1
 -static int stdio_nb_clients = 0;

  static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
  {
 @@ -1451,6 +1452,8 @@ static int qemu_chr_open_pp(QemuOpts *opts, 
 CharDriverState **_chr)

  #else /* _WIN32 */

 +static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
 +
  typedef struct {
     int max_size;
     HANDLE hcom, hrecv, hsend;
 @@ -1459,6 +1462,14 @@ typedef struct {
     DWORD len;
  } WinCharState;

 +typedef struct {
 +    HANDLE  hStdIn;
 +    HANDLE  hInputReadyEvent;
 +    HANDLE  hInputDoneEvent;
 +    HANDLE  hInputThread;
 +    uint8_t win_stdio_buf;
 +} WinStdioCharState;
 +
  #define NSENDBUF 2048
  #define NRECVBUF 2048
  #define MAXCONNECT 1
 @@ -1809,6 +1820,217 @@ static int qemu_chr_open_win_file_out(QemuOpts *opts, 
 CharDriverState **_chr)

     return qemu_chr_open_win_file(fd_out, _chr);
  }
 +
 +static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
 +{
 +    HANDLE  hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
 +    DWORD   dwSize;
 +    int     len1;
 +
 +    len1 = len;
 +
 +    while (len1  0) {
 +        if (!WriteFile(hStdOut, buf, len1, dwSize, NULL)) {
 +            break;
 +        }
 +        buf  += dwSize;
 +        len1 -= dwSize;
 +    }
 +
 +    return len - len1;
 +}
 +
 +static void win_stdio_wait_func(void *opaque)
 +{
 +    CharDriverState   *chr   = opaque;
 +    WinStdioCharState *stdio = chr-opaque;
 +    INPUT_RECORD       buf[4];
 +    int                ret;
 +    DWORD              dwSize;
 +    int                i;
 +
 +    ret = ReadConsoleInput(stdio-hStdIn, buf, sizeof(buf) / sizeof(*buf),
 +                           dwSize);
 +
 +    if (!ret) {
 +        /* Avoid error storm */
 +        qemu_del_wait_object(stdio-hStdIn, NULL, NULL);
 +        return;
 +    }
 +
 +    for (i = 0; i  dwSize; i++) {
 +        KEY_EVENT_RECORD *kev = buf[i].Event.KeyEvent;
 +
 +        if (buf[i].EventType == KEY_EVENT  kev-bKeyDown) {
 +            int j;
 +            if (kev-uChar.AsciiChar != 0) {
 +                for (j = 0; j  kev-wRepeatCount; j++) {
 +                    if (qemu_chr_be_can_write(chr)) {
 +                        uint8_t c = kev-uChar.AsciiChar;
 +                        qemu_chr_be_write(chr, c, 1);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +static DWORD WINAPI win_stdio_thread(LPVOID param)
 +{
 +    CharDriverState   *chr   = param;
 +    WinStdioCharState *stdio = chr-opaque;
 +    int                ret;
 +    DWORD              dwSize;
 +
 +    while (1) {
 +
 +        /* Wait for one byte */
 +        ret = ReadFile(stdio-hStdIn, stdio-win_stdio_buf, 1, dwSize, 
 NULL);
 +
 +        /* Exit in case of error, continue if nothing read */
 +        if (!ret) {
 +            break;
 +        }
 +        if (!dwSize) {
 +            continue;
 +        }
 +
 +        /* Some terminal emulator returns \r\n for Enter, just pass \n */
 +        if (stdio-win_stdio_buf == '\r') {
 +            continue;
 +        }
 +
 +        /* Signal the main thread and wait until the byte was eaten */
 +        if (!SetEvent(stdio-hInputReadyEvent)) {
 +            break;
 +        }
 +        if (WaitForSingleObject(stdio-hInputDoneEvent, INFINITE)
 +            != WAIT_OBJECT_0) {
 +            break;
 +        }
 +    }
 +
 +    qemu_del_wait_object(stdio-hInputReadyEvent, NULL, NULL);
 +    return 0;
 +}
 +
 +static void win_stdio_thread_wait_func(void *opaque)
 +{
 +    CharDriverState   *chr   = opaque;
 +    WinStdioCharState *stdio = chr-opaque;
 +
 +    if (qemu_chr_be_can_write(chr)) {
 +        qemu_chr_be_write(chr, stdio-win_stdio_buf, 1);
 +    }
 +
 +    SetEvent(stdio-hInputDoneEvent);
 +}
 +
 +static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool echo)
 +{
 +    WinStdioCharState *stdio  = chr-opaque;
 +    DWORD              dwMode = 0;
 +
 +    GetConsoleMode(stdio-hStdIn, dwMode);
 +
 +    if (echo) {
 +        SetConsoleMode(stdio-hStdIn, dwMode | ENABLE_ECHO_INPUT);
 +    } else {
 +        SetConsoleMode(stdio-hStdIn, dwMode  ~ENABLE_ECHO_INPUT);
 +    }
 +}
 +
 +static void win_stdio_close(CharDriverState *chr)
 +{
 +    WinStdioCharState *stdio = chr-opaque;
 +
 +    if 

Re: [Qemu-devel] [PATCH V5] Add stdio char device on windows

2011-10-20 Thread Fabien Chouteau
On 12/10/2011 16:47, Fabien Chouteau wrote:
 On 06/10/2011 16:37, Fabien Chouteau wrote:
 Simple implementation of an stdio char device on Windows.

 
 Any comments?
 

Anthony, can you apply this patch please?

Thanks in advance,

-- 
Fabien Chouteau



Re: [Qemu-devel] [PATCH V5] Add stdio char device on windows

2011-10-12 Thread Fabien Chouteau
On 06/10/2011 16:37, Fabien Chouteau wrote:
 Simple implementation of an stdio char device on Windows.
 

Any comments?

-- 
Fabien Chouteau



[Qemu-devel] [PATCH V5] Add stdio char device on windows

2011-10-06 Thread Fabien Chouteau
Simple implementation of an stdio char device on Windows.

Signed-off-by: Fabien Chouteau chout...@adacore.com
---
 qemu-char.c |  227 ++-
 1 files changed, 225 insertions(+), 2 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 09d2309..b9381be 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -538,6 +538,9 @@ int send_all(int fd, const void *_buf, int len1)
 }
 #endif /* !_WIN32 */
 
+#define STDIO_MAX_CLIENTS 1
+static int stdio_nb_clients;
+
 #ifndef _WIN32
 
 typedef struct {
@@ -545,8 +548,6 @@ typedef struct {
 int max_size;
 } FDCharDriver;
 
-#define STDIO_MAX_CLIENTS 1
-static int stdio_nb_clients = 0;
 
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
@@ -1451,6 +1452,8 @@ static int qemu_chr_open_pp(QemuOpts *opts, 
CharDriverState **_chr)
 
 #else /* _WIN32 */
 
+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
 typedef struct {
 int max_size;
 HANDLE hcom, hrecv, hsend;
@@ -1459,6 +1462,14 @@ typedef struct {
 DWORD len;
 } WinCharState;
 
+typedef struct {
+HANDLE  hStdIn;
+HANDLE  hInputReadyEvent;
+HANDLE  hInputDoneEvent;
+HANDLE  hInputThread;
+uint8_t win_stdio_buf;
+} WinStdioCharState;
+
 #define NSENDBUF 2048
 #define NRECVBUF 2048
 #define MAXCONNECT 1
@@ -1809,6 +1820,217 @@ static int qemu_chr_open_win_file_out(QemuOpts *opts, 
CharDriverState **_chr)
 
 return qemu_chr_open_win_file(fd_out, _chr);
 }
+
+static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+HANDLE  hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+DWORD   dwSize;
+int len1;
+
+len1 = len;
+
+while (len1  0) {
+if (!WriteFile(hStdOut, buf, len1, dwSize, NULL)) {
+break;
+}
+buf  += dwSize;
+len1 -= dwSize;
+}
+
+return len - len1;
+}
+
+static void win_stdio_wait_func(void *opaque)
+{
+CharDriverState   *chr   = opaque;
+WinStdioCharState *stdio = chr-opaque;
+INPUT_RECORD   buf[4];
+intret;
+DWORD  dwSize;
+inti;
+
+ret = ReadConsoleInput(stdio-hStdIn, buf, sizeof(buf) / sizeof(*buf),
+   dwSize);
+
+if (!ret) {
+/* Avoid error storm */
+qemu_del_wait_object(stdio-hStdIn, NULL, NULL);
+return;
+}
+
+for (i = 0; i  dwSize; i++) {
+KEY_EVENT_RECORD *kev = buf[i].Event.KeyEvent;
+
+if (buf[i].EventType == KEY_EVENT  kev-bKeyDown) {
+int j;
+if (kev-uChar.AsciiChar != 0) {
+for (j = 0; j  kev-wRepeatCount; j++) {
+if (qemu_chr_be_can_write(chr)) {
+uint8_t c = kev-uChar.AsciiChar;
+qemu_chr_be_write(chr, c, 1);
+}
+}
+}
+}
+}
+}
+
+static DWORD WINAPI win_stdio_thread(LPVOID param)
+{
+CharDriverState   *chr   = param;
+WinStdioCharState *stdio = chr-opaque;
+intret;
+DWORD  dwSize;
+
+while (1) {
+
+/* Wait for one byte */
+ret = ReadFile(stdio-hStdIn, stdio-win_stdio_buf, 1, dwSize, NULL);
+
+/* Exit in case of error, continue if nothing read */
+if (!ret) {
+break;
+}
+if (!dwSize) {
+continue;
+}
+
+/* Some terminal emulator returns \r\n for Enter, just pass \n */
+if (stdio-win_stdio_buf == '\r') {
+continue;
+}
+
+/* Signal the main thread and wait until the byte was eaten */
+if (!SetEvent(stdio-hInputReadyEvent)) {
+break;
+}
+if (WaitForSingleObject(stdio-hInputDoneEvent, INFINITE)
+!= WAIT_OBJECT_0) {
+break;
+}
+}
+
+qemu_del_wait_object(stdio-hInputReadyEvent, NULL, NULL);
+return 0;
+}
+
+static void win_stdio_thread_wait_func(void *opaque)
+{
+CharDriverState   *chr   = opaque;
+WinStdioCharState *stdio = chr-opaque;
+
+if (qemu_chr_be_can_write(chr)) {
+qemu_chr_be_write(chr, stdio-win_stdio_buf, 1);
+}
+
+SetEvent(stdio-hInputDoneEvent);
+}
+
+static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool echo)
+{
+WinStdioCharState *stdio  = chr-opaque;
+DWORD  dwMode = 0;
+
+GetConsoleMode(stdio-hStdIn, dwMode);
+
+if (echo) {
+SetConsoleMode(stdio-hStdIn, dwMode | ENABLE_ECHO_INPUT);
+} else {
+SetConsoleMode(stdio-hStdIn, dwMode  ~ENABLE_ECHO_INPUT);
+}
+}
+
+static void win_stdio_close(CharDriverState *chr)
+{
+WinStdioCharState *stdio = chr-opaque;
+
+if (stdio-hInputReadyEvent != INVALID_HANDLE_VALUE) {
+CloseHandle(stdio-hInputReadyEvent);
+}
+if (stdio-hInputDoneEvent != INVALID_HANDLE_VALUE) {
+CloseHandle(stdio-hInputDoneEvent);
+}
+if (stdio-hInputThread !=