Re: [Qemu-devel] [PATCH V5] Add stdio char device on windows
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
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
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
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 !=