From c7e47c63e0362ffded57db38684b88c270cff65f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 30 May 2017 09:09:19 -0300 Subject: char: cast ARRAY_SIZE() as signed to silent warning on empty array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chardev/char.c: In function 'chardev_name_foreach': chardev/char.c:546:19: error: comparison of unsigned expression < 0 is always false [-Werror=type-limits] for (i = 0; i < ARRAY_SIZE(chardev_alias_table); i++) { ^ Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20170530120919.8874-1-f4bug@amsat.org> Reviewed-by: Marc-André Lureau --- chardev/char.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chardev/char.c b/chardev/char.c index 4e24dc39af..26607c1c6b 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -841,7 +841,7 @@ chardev_name_foreach(void (*fn)(const char *name, void *opaque), void *opaque) object_class_foreach(chardev_class_foreach, TYPE_CHARDEV, false, &fe); - for (i = 0; i < ARRAY_SIZE(chardev_alias_table); i++) { + for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) { fn(chardev_alias_table[i].alias, opaque); } } @@ -887,7 +887,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts, return NULL; } - for (i = 0; i < ARRAY_SIZE(chardev_alias_table); i++) { + for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) { if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) { name = chardev_alias_table[i].typename; break; -- cgit v1.2.3 From b88ee025942d1ed67232700ef8befa5e52a9f7bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Jan 2017 19:37:19 +0100 Subject: char-win: simplify win_chr_read() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit win_chr_read_poll() is always used before win_chr_read(). We can easily fold win_chr_readfile() too. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char-win.c | 35 +++++++++-------------------------- chardev/char-win.h | 2 +- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/chardev/char-win.c b/chardev/char-win.c index e4b6957ded..a46d878ef8 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -26,14 +26,21 @@ #include "qapi/error.h" #include "char-win.h" -static void win_chr_readfile(Chardev *chr) +static void win_chr_read(Chardev *chr) { WinChardev *s = WIN_CHARDEV(chr); - + int max_size = qemu_chr_be_can_write(chr); int ret, err; uint8_t buf[CHR_READ_BUF_LEN]; DWORD size; + if (s->len > max_size) { + s->len = max_size; + } + if (s->len == 0) { + return; + } + ZeroMemory(&s->orecv, sizeof(s->orecv)); s->orecv.hEvent = s->hrecv; ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); @@ -49,28 +56,6 @@ static void win_chr_readfile(Chardev *chr) } } -static void win_chr_read(Chardev *chr) -{ - WinChardev *s = WIN_CHARDEV(chr); - - if (s->len > s->max_size) { - s->len = s->max_size; - } - if (s->len == 0) { - return; - } - - win_chr_readfile(chr); -} - -static int win_chr_read_poll(Chardev *chr) -{ - WinChardev *s = WIN_CHARDEV(chr); - - s->max_size = qemu_chr_be_can_write(chr); - return s->max_size; -} - static int win_chr_poll(void *opaque) { Chardev *chr = CHARDEV(opaque); @@ -81,7 +66,6 @@ static int win_chr_poll(void *opaque) ClearCommError(s->hcom, &comerr, &status); if (status.cbInQue > 0) { s->len = status.cbInQue; - win_chr_read_poll(chr); win_chr_read(chr); return 1; } @@ -163,7 +147,6 @@ int win_chr_pipe_poll(void *opaque) PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); if (size > 0) { s->len = size; - win_chr_read_poll(chr); win_chr_read(chr); return 1; } diff --git a/chardev/char-win.h b/chardev/char-win.h index d78a7d7972..73a0e3caef 100644 --- a/chardev/char-win.h +++ b/chardev/char-win.h @@ -28,7 +28,7 @@ typedef struct { Chardev parent; - int max_size; + HANDLE hcom, hrecv, hsend; OVERLAPPED orecv; BOOL fpipe; -- cgit v1.2.3 From 6ce8e0eb587782e26a05a57134529cc598febd56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Jan 2017 20:03:08 +0100 Subject: char-win: remove WinChardev.len MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "len" argument can be passed directly to win_chr_read() Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char-win.c | 16 +++++++--------- chardev/char-win.h | 1 - 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/chardev/char-win.c b/chardev/char-win.c index a46d878ef8..5e7daeeae1 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -26,7 +26,7 @@ #include "qapi/error.h" #include "char-win.h" -static void win_chr_read(Chardev *chr) +static void win_chr_read(Chardev *chr, DWORD len) { WinChardev *s = WIN_CHARDEV(chr); int max_size = qemu_chr_be_can_write(chr); @@ -34,16 +34,16 @@ static void win_chr_read(Chardev *chr) uint8_t buf[CHR_READ_BUF_LEN]; DWORD size; - if (s->len > max_size) { - s->len = max_size; + if (len > max_size) { + len = max_size; } - if (s->len == 0) { + if (len == 0) { return; } ZeroMemory(&s->orecv, sizeof(s->orecv)); s->orecv.hEvent = s->hrecv; - ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); + ret = ReadFile(s->hcom, buf, len, &size, &s->orecv); if (!ret) { err = GetLastError(); if (err == ERROR_IO_PENDING) { @@ -65,8 +65,7 @@ static int win_chr_poll(void *opaque) ClearCommError(s->hcom, &comerr, &status); if (status.cbInQue > 0) { - s->len = status.cbInQue; - win_chr_read(chr); + win_chr_read(chr, status.cbInQue); return 1; } return 0; @@ -146,8 +145,7 @@ int win_chr_pipe_poll(void *opaque) PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); if (size > 0) { - s->len = size; - win_chr_read(chr); + win_chr_read(chr, size); return 1; } return 0; diff --git a/chardev/char-win.h b/chardev/char-win.h index 73a0e3caef..70215e04c2 100644 --- a/chardev/char-win.h +++ b/chardev/char-win.h @@ -32,7 +32,6 @@ typedef struct { HANDLE hcom, hrecv, hsend; OVERLAPPED orecv; BOOL fpipe; - DWORD len; /* Protected by the Chardev chr_write_lock. */ OVERLAPPED osend; -- cgit v1.2.3 From 221e659c3f37251b4312e0ac8ccf7799c67600b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Jan 2017 19:51:46 +0100 Subject: char-win: rename win_chr_init/poll win_chr_serial_init/poll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those 2 functions are specific to serial chardev, make it more clear. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char-serial.c | 2 +- chardev/char-win.c | 8 ++++---- chardev/char-win.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/chardev/char-serial.c b/chardev/char-serial.c index 094e08dca5..fef3a91c77 100644 --- a/chardev/char-serial.c +++ b/chardev/char-serial.c @@ -45,7 +45,7 @@ static void qmp_chardev_open_serial(Chardev *chr, { ChardevHostdev *serial = backend->u.serial.data; - win_chr_init(chr, serial->device, errp); + win_chr_serial_init(chr, serial->device, errp); } #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ diff --git a/chardev/char-win.c b/chardev/char-win.c index 5e7daeeae1..11abad1521 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -56,7 +56,7 @@ static void win_chr_read(Chardev *chr, DWORD len) } } -static int win_chr_poll(void *opaque) +static int win_chr_serial_poll(void *opaque) { Chardev *chr = CHARDEV(opaque); WinChardev *s = WIN_CHARDEV(opaque); @@ -71,7 +71,7 @@ static int win_chr_poll(void *opaque) return 0; } -int win_chr_init(Chardev *chr, const char *filename, Error **errp) +int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp) { WinChardev *s = WIN_CHARDEV(chr); COMMCONFIG comcfg; @@ -130,7 +130,7 @@ int win_chr_init(Chardev *chr, const char *filename, Error **errp) error_setg(errp, "Failed ClearCommError"); goto fail; } - qemu_add_polling_cb(win_chr_poll, chr); + qemu_add_polling_cb(win_chr_serial_poll, chr); return 0; fail: @@ -208,7 +208,7 @@ static void char_win_finalize(Object *obj) if (s->fpipe) { qemu_del_polling_cb(win_chr_pipe_poll, chr); } else { - qemu_del_polling_cb(win_chr_poll, chr); + qemu_del_polling_cb(win_chr_serial_poll, chr); } qemu_chr_be_event(chr, CHR_EVENT_CLOSED); diff --git a/chardev/char-win.h b/chardev/char-win.h index 70215e04c2..e0b3839a77 100644 --- a/chardev/char-win.h +++ b/chardev/char-win.h @@ -46,7 +46,7 @@ typedef struct { #define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN) void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out); -int win_chr_init(Chardev *chr, const char *filename, Error **errp); +int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp); int win_chr_pipe_poll(void *opaque); #endif /* CHAR_WIN_H */ -- cgit v1.2.3 From ef0f272f38e1e534dd05a5a611aa0eb15dc60cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Jan 2017 21:37:01 +0100 Subject: char-win: rename hcom->file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hcom is the name of the file handle, regardless of the actual chardev driver (serial, file, console etc..). Rename it to be more explicit. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char-pipe.c | 10 +++++----- chardev/char-win.c | 36 ++++++++++++++++++------------------ chardev/char-win.h | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c index 54240c863d..aae950a22b 100644 --- a/chardev/char-pipe.c +++ b/chardev/char-pipe.c @@ -58,27 +58,27 @@ static int win_chr_pipe_init(Chardev *chr, const char *filename, } openname = g_strdup_printf("\\\\.\\pipe\\%s", filename); - s->hcom = CreateNamedPipe(openname, + s->file = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); g_free(openname); - if (s->hcom == INVALID_HANDLE_VALUE) { + if (s->file == INVALID_HANDLE_VALUE) { error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError()); - s->hcom = NULL; + s->file = NULL; goto fail; } ZeroMemory(&ov, sizeof(ov)); ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - ret = ConnectNamedPipe(s->hcom, &ov); + ret = ConnectNamedPipe(s->file, &ov); if (ret) { error_setg(errp, "Failed ConnectNamedPipe"); goto fail; } - ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE); + ret = GetOverlappedResult(s->file, &ov, &size, TRUE); if (!ret) { error_setg(errp, "Failed GetOverlappedResult"); if (ov.hEvent) { diff --git a/chardev/char-win.c b/chardev/char-win.c index 11abad1521..a7e3296909 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -43,11 +43,11 @@ static void win_chr_read(Chardev *chr, DWORD len) ZeroMemory(&s->orecv, sizeof(s->orecv)); s->orecv.hEvent = s->hrecv; - ret = ReadFile(s->hcom, buf, len, &size, &s->orecv); + ret = ReadFile(s->file, buf, len, &size, &s->orecv); if (!ret) { err = GetLastError(); if (err == ERROR_IO_PENDING) { - ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE); + ret = GetOverlappedResult(s->file, &s->orecv, &size, TRUE); } } @@ -63,7 +63,7 @@ static int win_chr_serial_poll(void *opaque) COMSTAT status; DWORD comerr; - ClearCommError(s->hcom, &comerr, &status); + ClearCommError(s->file, &comerr, &status); if (status.cbInQue > 0) { win_chr_read(chr, status.cbInQue); return 1; @@ -91,15 +91,15 @@ int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp) goto fail; } - s->hcom = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, + s->file = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); - if (s->hcom == INVALID_HANDLE_VALUE) { + if (s->file == INVALID_HANDLE_VALUE) { error_setg(errp, "Failed CreateFile (%lu)", GetLastError()); - s->hcom = NULL; + s->file = NULL; goto fail; } - if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { + if (!SetupComm(s->file, NRECVBUF, NSENDBUF)) { error_setg(errp, "Failed SetupComm"); goto fail; } @@ -110,23 +110,23 @@ int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp) comcfg.dcb.DCBlength = sizeof(DCB); CommConfigDialog(filename, NULL, &comcfg); - if (!SetCommState(s->hcom, &comcfg.dcb)) { + if (!SetCommState(s->file, &comcfg.dcb)) { error_setg(errp, "Failed SetCommState"); goto fail; } - if (!SetCommMask(s->hcom, EV_ERR)) { + if (!SetCommMask(s->file, EV_ERR)) { error_setg(errp, "Failed SetCommMask"); goto fail; } cto.ReadIntervalTimeout = MAXDWORD; - if (!SetCommTimeouts(s->hcom, &cto)) { + if (!SetCommTimeouts(s->file, &cto)) { error_setg(errp, "Failed SetCommTimeouts"); goto fail; } - if (!ClearCommError(s->hcom, &err, &comstat)) { + if (!ClearCommError(s->file, &err, &comstat)) { error_setg(errp, "Failed ClearCommError"); goto fail; } @@ -143,7 +143,7 @@ int win_chr_pipe_poll(void *opaque) WinChardev *s = WIN_CHARDEV(opaque); DWORD size; - PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); + PeekNamedPipe(s->file, NULL, 0, NULL, &size, NULL); if (size > 0) { win_chr_read(chr, size); return 1; @@ -162,14 +162,14 @@ static int win_chr_write(Chardev *chr, const uint8_t *buf, int len1) s->osend.hEvent = s->hsend; while (len > 0) { if (s->hsend) { - ret = WriteFile(s->hcom, buf, len, &size, &s->osend); + ret = WriteFile(s->file, buf, len, &size, &s->osend); } else { - ret = WriteFile(s->hcom, buf, len, &size, NULL); + ret = WriteFile(s->file, buf, len, &size, NULL); } if (!ret) { err = GetLastError(); if (err == ERROR_IO_PENDING) { - ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE); + ret = GetOverlappedResult(s->file, &s->osend, &size, TRUE); if (ret) { buf += size; len -= size; @@ -202,8 +202,8 @@ static void char_win_finalize(Object *obj) if (s->hrecv) { CloseHandle(s->hrecv); } - if (s->hcom) { - CloseHandle(s->hcom); + if (s->file) { + CloseHandle(s->file); } if (s->fpipe) { qemu_del_polling_cb(win_chr_pipe_poll, chr); @@ -219,7 +219,7 @@ void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out) WinChardev *s = WIN_CHARDEV(chr); s->skip_free = true; - s->hcom = fd_out; + s->file = fd_out; } static void char_win_class_init(ObjectClass *oc, void *data) diff --git a/chardev/char-win.h b/chardev/char-win.h index e0b3839a77..888be2b3ca 100644 --- a/chardev/char-win.h +++ b/chardev/char-win.h @@ -29,7 +29,7 @@ typedef struct { Chardev parent; - HANDLE hcom, hrecv, hsend; + HANDLE file, hrecv, hsend; OVERLAPPED orecv; BOOL fpipe; -- cgit v1.2.3 From 541815ff7f54f45a60d058b1c499c4affff094e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Jan 2017 21:34:42 +0100 Subject: char-win: close file handle except with console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the console handle shouldn't be closed, however, the "file" handle should. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char-console.c | 2 +- chardev/char-file.c | 2 +- chardev/char-win.c | 12 ++++-------- chardev/char-win.h | 5 ++--- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/chardev/char-console.c b/chardev/char-console.c index c824937fe6..8d972c1506 100644 --- a/chardev/char-console.c +++ b/chardev/char-console.c @@ -29,7 +29,7 @@ static void qemu_chr_open_win_con(Chardev *chr, bool *be_opened, Error **errp) { - qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE)); + win_chr_set_file(chr, GetStdHandle(STD_OUTPUT_HANDLE), true); } static void char_console_class_init(ObjectClass *oc, void *data) diff --git a/chardev/char-file.c b/chardev/char-file.c index 8bae25350d..aed4ae1569 100644 --- a/chardev/char-file.c +++ b/chardev/char-file.c @@ -65,7 +65,7 @@ static void qmp_chardev_open_file(Chardev *chr, return; } - qemu_chr_open_win_file(chr, out); + win_chr_set_file(chr, out, false); #else int flags, in = -1, out; diff --git a/chardev/char-win.c b/chardev/char-win.c index a7e3296909..ec9a731be9 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -192,17 +192,13 @@ static void char_win_finalize(Object *obj) Chardev *chr = CHARDEV(obj); WinChardev *s = WIN_CHARDEV(chr); - if (s->skip_free) { - return; - } - if (s->hsend) { CloseHandle(s->hsend); } if (s->hrecv) { CloseHandle(s->hrecv); } - if (s->file) { + if (!s->keep_open && s->file) { CloseHandle(s->file); } if (s->fpipe) { @@ -214,12 +210,12 @@ static void char_win_finalize(Object *obj) qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } -void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out) +void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open) { WinChardev *s = WIN_CHARDEV(chr); - s->skip_free = true; - s->file = fd_out; + s->keep_open = keep_open; + s->file = file; } static void char_win_class_init(ObjectClass *oc, void *data) diff --git a/chardev/char-win.h b/chardev/char-win.h index 888be2b3ca..4994425e9e 100644 --- a/chardev/char-win.h +++ b/chardev/char-win.h @@ -29,14 +29,13 @@ typedef struct { Chardev parent; + bool keep_open; /* console do not close file */ HANDLE file, hrecv, hsend; OVERLAPPED orecv; BOOL fpipe; /* Protected by the Chardev chr_write_lock. */ OVERLAPPED osend; - /* FIXME: file/console do not finalize */ - bool skip_free; } WinChardev; #define NSENDBUF 2048 @@ -45,7 +44,7 @@ typedef struct { #define TYPE_CHARDEV_WIN "chardev-win" #define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN) -void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out); +void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open); int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp); int win_chr_pipe_poll(void *opaque); -- cgit v1.2.3 From f664b88247487c4cb020d016bef0f3b1daf9f4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 2 Feb 2017 17:47:00 +0400 Subject: Remove/replace sysemu/char.h inclusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are apparently unnecessary includes. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/arm/bcm2835_peripherals.c | 1 - hw/char/imx_serial.c | 1 - hw/display/xenfb.c | 1 - hw/i386/xen/xen-hvm.c | 1 - hw/mips/mips_fulong2e.c | 1 - hw/mips/mips_malta.c | 1 - hw/net/xgmac.c | 1 - hw/ppc/spapr_events.c | 1 - hw/ppc/spapr_rtas.c | 1 - hw/sparc/leon3.c | 1 - hw/usb/ccid-card-emulated.c | 2 +- hw/xen/xen_backend.c | 1 - util/event_notifier-posix.c | 1 - 13 files changed, 1 insertion(+), 13 deletions(-) diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 369ef1e3bd..502f04c02a 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -13,7 +13,6 @@ #include "hw/arm/bcm2835_peripherals.h" #include "hw/misc/bcm2835_mbox_defs.h" #include "hw/arm/raspi_platform.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" /* Peripheral base address on the VC (GPU) system bus */ diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 52e67f8dc9..af250305be 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -21,7 +21,6 @@ #include "qemu/osdep.h" #include "hw/char/imx_serial.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" #include "qemu/log.h" #ifndef DEBUG_IMX_UART diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index 7a8727aa21..e76c0d805c 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -28,7 +28,6 @@ #include "hw/hw.h" #include "ui/console.h" -#include "sysemu/char.h" #include "hw/xen/xen_backend.h" #include diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 919f09b694..1acd4de405 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -18,7 +18,6 @@ #include "hw/xen/xen_backend.h" #include "qmp-commands.h" -#include "sysemu/char.h" #include "qemu/error-report.h" #include "qemu/range.h" #include "sysemu/xen-mapcache.h" diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index e636c3abaa..dbe2805acb 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -32,7 +32,6 @@ #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" #include "audio/audio.h" #include "qemu/log.h" diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 7814c39654..95cdabb2dd 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -37,7 +37,6 @@ #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" #include "sysemu/arch_init.h" #include "qemu/log.h" diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 46b1aa17fa..0843bf185c 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -26,7 +26,6 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" #include "qemu/log.h" #include "net/net.h" #include "net/checksum.h" diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 73e2a1884f..57acd85a87 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -28,7 +28,6 @@ #include "qapi/error.h" #include "cpu.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 128d993d04..b666a4c15c 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -29,7 +29,6 @@ #include "qemu/log.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" #include "sysemu/cpus.h" diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 6e16478413..f415997649 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -28,7 +28,6 @@ #include "hw/hw.h" #include "qemu/timer.h" #include "hw/ptimer.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" #include "hw/boards.h" diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c index 99627860a3..e646eb243b 100644 --- a/hw/usb/ccid-card-emulated.c +++ b/hw/usb/ccid-card-emulated.c @@ -33,7 +33,7 @@ #include #include "qemu/thread.h" -#include "sysemu/char.h" +#include "qemu/main-loop.h" #include "ccid.h" #define DPRINTF(card, lvl, fmt, ...) \ diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index 3570f37e56..c46cbb0759 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -28,7 +28,6 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/boards.h" -#include "sysemu/char.h" #include "qemu/log.h" #include "qapi/error.h" #include "hw/xen/xen_backend.h" diff --git a/util/event_notifier-posix.c b/util/event_notifier-posix.c index acdbe3b483..73c4046b58 100644 --- a/util/event_notifier-posix.c +++ b/util/event_notifier-posix.c @@ -14,7 +14,6 @@ #include "qemu-common.h" #include "qemu/cutils.h" #include "qemu/event_notifier.h" -#include "sysemu/char.h" #include "qemu/main-loop.h" #ifdef CONFIG_EVENTFD -- cgit v1.2.3 From 8228e353d8906bf43399ca0ef28446c5c48bb686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 26 Jan 2017 17:19:46 +0400 Subject: chardev: move headers to include/chardev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So they are all in one place. The following patch will move serial & parallel declarations to the respective headers. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + backends/baum.c | 2 +- backends/msmouse.c | 2 +- backends/rng-egd.c | 2 +- backends/testdev.c | 2 +- backends/wctablet.c | 2 +- chardev/char-console.c | 2 +- chardev/char-fd.c | 6 +- chardev/char-fd.h | 44 ---- chardev/char-file.c | 6 +- chardev/char-io.c | 2 +- chardev/char-io.h | 46 ---- chardev/char-mux.c | 4 +- chardev/char-mux.h | 63 ----- chardev/char-null.c | 2 +- chardev/char-parallel.c | 6 +- chardev/char-parallel.h | 32 --- chardev/char-pipe.c | 6 +- chardev/char-pty.c | 4 +- chardev/char-ringbuf.c | 2 +- chardev/char-serial.c | 6 +- chardev/char-serial.h | 35 --- chardev/char-socket.c | 4 +- chardev/char-stdio.c | 8 +- chardev/char-udp.c | 4 +- chardev/char-win-stdio.c | 4 +- chardev/char-win-stdio.h | 29 --- chardev/char-win.c | 2 +- chardev/char-win.h | 51 ---- chardev/char.c | 10 +- gdbstub.c | 2 +- hmp.c | 2 +- hw/arm/fsl-imx25.c | 2 +- hw/arm/fsl-imx31.c | 2 +- hw/arm/fsl-imx6.c | 2 +- hw/arm/omap2.c | 2 +- hw/arm/pxa2xx.c | 2 +- hw/arm/strongarm.c | 2 +- hw/bt/hci-csr.c | 2 +- hw/char/cadence_uart.c | 2 +- hw/char/debugcon.c | 2 +- hw/char/digic-uart.c | 2 +- hw/char/escc.c | 2 +- hw/char/etraxfs_ser.c | 2 +- hw/char/exynos4210_uart.c | 2 +- hw/char/grlib_apbuart.c | 2 +- hw/char/ipoctal232.c | 2 +- hw/char/lm32_juart.c | 2 +- hw/char/lm32_uart.c | 2 +- hw/char/mcf_uart.c | 2 +- hw/char/milkymist-uart.c | 2 +- hw/char/omap_uart.c | 2 +- hw/char/parallel.c | 2 +- hw/char/pl011.c | 2 +- hw/char/sclpconsole-lm.c | 2 +- hw/char/sclpconsole.c | 2 +- hw/char/serial.c | 2 +- hw/char/sh_serial.c | 2 +- hw/char/spapr_vty.c | 2 +- hw/char/terminal3270.c | 2 +- hw/char/virtio-console.c | 2 +- hw/char/xen_console.c | 2 +- hw/char/xilinx_uartlite.c | 2 +- hw/core/qdev-properties-system.c | 2 +- hw/core/qdev-properties.c | 2 +- hw/ipmi/ipmi_bmc_extern.c | 2 +- hw/isa/pc87312.c | 2 +- hw/mips/boston.c | 2 +- hw/misc/ivshmem.c | 2 +- hw/usb/ccid-card-passthru.c | 2 +- hw/usb/dev-serial.c | 2 +- hw/usb/redirect.c | 2 +- hw/virtio/vhost-user.c | 2 +- hw/xen/xen-common.c | 2 +- hw/xtensa/xtfpga.c | 2 +- include/chardev/char-fd.h | 44 ++++ include/chardev/char-io.h | 46 ++++ include/chardev/char-mux.h | 63 +++++ include/chardev/char-parallel.h | 32 +++ include/chardev/char-serial.h | 35 +++ include/chardev/char-win-stdio.h | 29 +++ include/chardev/char-win.h | 51 ++++ include/chardev/char.h | 499 ++++++++++++++++++++++++++++++++++++++ include/hw/char/bcm2835_aux.h | 2 +- include/hw/char/cadence_uart.h | 2 +- include/hw/char/digic-uart.h | 2 +- include/hw/char/imx_serial.h | 2 +- include/hw/char/serial.h | 4 +- include/hw/char/stm32f2xx_usart.h | 2 +- include/sysemu/char.h | 499 -------------------------------------- monitor.c | 2 +- net/colo-compare.c | 2 +- net/filter-mirror.c | 2 +- net/slirp.c | 2 +- net/vhost-user.c | 2 +- qmp.c | 2 +- qtest.c | 2 +- replay/replay-char.c | 2 +- slirp/slirp.c | 2 +- spice-qemu-char.c | 2 +- tests/postcopy-test.c | 2 +- tests/test-char.c | 2 +- tests/vhost-user-test.c | 2 +- ui/console.c | 2 +- ui/gtk.c | 2 +- vl.c | 2 +- 106 files changed, 912 insertions(+), 911 deletions(-) delete mode 100644 chardev/char-fd.h delete mode 100644 chardev/char-io.h delete mode 100644 chardev/char-mux.h delete mode 100644 chardev/char-parallel.h delete mode 100644 chardev/char-serial.h delete mode 100644 chardev/char-win-stdio.h delete mode 100644 chardev/char-win.h create mode 100644 include/chardev/char-fd.h create mode 100644 include/chardev/char-io.h create mode 100644 include/chardev/char-mux.h create mode 100644 include/chardev/char-parallel.h create mode 100644 include/chardev/char-serial.h create mode 100644 include/chardev/char-win-stdio.h create mode 100644 include/chardev/char-win.h create mode 100644 include/chardev/char.h delete mode 100644 include/sysemu/char.h diff --git a/MAINTAINERS b/MAINTAINERS index 7df088259b..48e2964ed8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1238,6 +1238,7 @@ M: Paolo Bonzini M: Marc-André Lureau S: Maintained F: chardev/ +F: include/chardev/ F: backends/msmouse.c F: backends/testdev.c diff --git a/backends/baum.c b/backends/baum.c index 2eddcae119..302dd9666c 100644 --- a/backends/baum.c +++ b/backends/baum.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/timer.h" #include "hw/usb.h" #include "ui/console.h" diff --git a/backends/msmouse.c b/backends/msmouse.c index d2c3162f1e..0ffd137ce8 100644 --- a/backends/msmouse.c +++ b/backends/msmouse.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "ui/console.h" #include "ui/input.h" diff --git a/backends/rng-egd.c b/backends/rng-egd.c index 380b19a0a1..5448f6e5f5 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "sysemu/rng.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" diff --git a/backends/testdev.c b/backends/testdev.c index 7df9248a13..031e9a23e8 100644 --- a/backends/testdev.c +++ b/backends/testdev.c @@ -25,7 +25,7 @@ */ #include "qemu/osdep.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #define BUF_SIZE 32 diff --git a/backends/wctablet.c b/backends/wctablet.c index a4d3ae098a..07a4cde956 100644 --- a/backends/wctablet.c +++ b/backends/wctablet.c @@ -32,7 +32,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "ui/console.h" #include "ui/input.h" #include "trace.h" diff --git a/chardev/char-console.c b/chardev/char-console.c index 8d972c1506..535ed65136 100644 --- a/chardev/char-console.c +++ b/chardev/char-console.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "char-win.h" +#include "chardev/char-win.h" static void qemu_chr_open_win_con(Chardev *chr, ChardevBackend *backend, diff --git a/chardev/char-fd.c b/chardev/char-fd.c index 0b182c552c..1584a3de20 100644 --- a/chardev/char-fd.c +++ b/chardev/char-fd.c @@ -25,11 +25,11 @@ #include "qemu/sockets.h" #include "qapi/error.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "io/channel-file.h" -#include "char-fd.h" -#include "char-io.h" +#include "chardev/char-fd.h" +#include "chardev/char-io.h" /* Called with chr_write_lock held. */ static int fd_chr_write(Chardev *chr, const uint8_t *buf, int len) diff --git a/chardev/char-fd.h b/chardev/char-fd.h deleted file mode 100644 index d8327982fb..0000000000 --- a/chardev/char-fd.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_FD_H -#define CHAR_FD_H - -#include "io/channel.h" -#include "sysemu/char.h" - -typedef struct FDChardev { - Chardev parent; - Chardev *chr; - QIOChannel *ioc_in, *ioc_out; - int max_size; -} FDChardev; - -#define TYPE_CHARDEV_FD "chardev-fd" - -#define FD_CHARDEV(obj) OBJECT_CHECK(FDChardev, (obj), TYPE_CHARDEV_FD) - -void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out); -int qmp_chardev_open_file_source(char *src, int flags, Error **errp); - -#endif /* CHAR_FD_H */ diff --git a/chardev/char-file.c b/chardev/char-file.c index aed4ae1569..a57b88aaf2 100644 --- a/chardev/char-file.c +++ b/chardev/char-file.c @@ -24,12 +24,12 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #ifdef _WIN32 -#include "char-win.h" +#include "chardev/char-win.h" #else -#include "char-fd.h" +#include "chardev/char-fd.h" #endif static void qmp_chardev_open_file(Chardev *chr, diff --git a/chardev/char-io.c b/chardev/char-io.c index b5708eef45..f81052481a 100644 --- a/chardev/char-io.c +++ b/chardev/char-io.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "char-io.h" +#include "chardev/char-io.h" typedef struct IOWatchPoll { GSource parent; diff --git a/chardev/char-io.h b/chardev/char-io.h deleted file mode 100644 index 55973a7671..0000000000 --- a/chardev/char-io.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_IO_H -#define CHAR_IO_H - -#include "qemu-common.h" -#include "io/channel.h" -#include "sysemu/char.h" - -/* Can only be used for read */ -GSource *io_add_watch_poll(Chardev *chr, - QIOChannel *ioc, - IOCanReadHandler *fd_can_read, - QIOChannelFunc fd_read, - gpointer user_data, - GMainContext *context); - -void remove_fd_in_watch(Chardev *chr); - -int io_channel_send(QIOChannel *ioc, const void *buf, size_t len); - -int io_channel_send_full(QIOChannel *ioc, const void *buf, size_t len, - int *fds, size_t nfds); - -#endif /* CHAR_IO_H */ diff --git a/chardev/char-mux.c b/chardev/char-mux.c index 37d42c65c6..106c682e7f 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -24,9 +24,9 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/block-backend.h" -#include "char-mux.h" +#include "chardev/char-mux.h" /* MUX driver for serial I/O splitting */ diff --git a/chardev/char-mux.h b/chardev/char-mux.h deleted file mode 100644 index 3f41dfcfd2..0000000000 --- a/chardev/char-mux.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_MUX_H -#define CHAR_MUX_H - -#include "sysemu/char.h" - -extern bool muxes_realized; - -#define MAX_MUX 4 -#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ -#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) -typedef struct MuxChardev { - Chardev parent; - CharBackend *backends[MAX_MUX]; - CharBackend chr; - int focus; - int mux_cnt; - int term_got_escape; - int max_size; - /* Intermediate input buffer catches 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]; - int timestamps; - - /* Protected by the Chardev chr_write_lock. */ - int linestart; - int64_t timestamps_start; -} MuxChardev; - -#define MUX_CHARDEV(obj) OBJECT_CHECK(MuxChardev, (obj), TYPE_CHARDEV_MUX) -#define CHARDEV_IS_MUX(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX) - -void mux_chr_set_handlers(Chardev *chr, GMainContext *context); -void mux_set_focus(Chardev *chr, int focus); -void mux_chr_send_all_event(Chardev *chr, int event); - -#endif /* CHAR_MUX_H */ diff --git a/chardev/char-null.c b/chardev/char-null.c index dc0d68ab2d..90bafe76f4 100644 --- a/chardev/char-null.c +++ b/chardev/char-null.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" static void null_chr_open(Chardev *chr, ChardevBackend *backend, diff --git a/chardev/char-parallel.c b/chardev/char-parallel.c index 3fa22ce29d..bce89f8c36 100644 --- a/chardev/char-parallel.c +++ b/chardev/char-parallel.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qapi/error.h" #include @@ -41,8 +41,8 @@ #endif #endif -#include "char-fd.h" -#include "char-parallel.h" +#include "chardev/char-fd.h" +#include "chardev/char-parallel.h" #if defined(__linux__) diff --git a/chardev/char-parallel.h b/chardev/char-parallel.h deleted file mode 100644 index 26742f9d5c..0000000000 --- a/chardev/char-parallel.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_PARALLEL_H -#define CHAR_PARALLEL_H - -#if defined(__linux__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__DragonFly__) -#define HAVE_CHARDEV_PARPORT 1 -#endif - -#endif /* CHAR_PARALLEL_H */ diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c index aae950a22b..3a95e4c1b2 100644 --- a/chardev/char-pipe.c +++ b/chardev/char-pipe.c @@ -23,12 +23,12 @@ */ #include "qemu/osdep.h" #include "qapi/error.h" -#include "sysemu/char.h" +#include "chardev/char.h" #ifdef _WIN32 -#include "char-win.h" +#include "chardev/char-win.h" #else -#include "char-fd.h" +#include "chardev/char-fd.h" #endif #ifdef _WIN32 diff --git a/chardev/char-pty.c b/chardev/char-pty.c index 35a175d796..e5d20a0e6a 100644 --- a/chardev/char-pty.c +++ b/chardev/char-pty.c @@ -24,12 +24,12 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "io/channel-file.h" #include "qemu/sockets.h" #include "qemu/error-report.h" -#include "char-io.h" +#include "chardev/char-io.h" #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c index d130069e88..df52b04d22 100644 --- a/chardev/char-ringbuf.c +++ b/chardev/char-ringbuf.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qmp-commands.h" #include "qemu/base64.h" diff --git a/chardev/char-serial.c b/chardev/char-serial.c index fef3a91c77..2f8f83821d 100644 --- a/chardev/char-serial.c +++ b/chardev/char-serial.c @@ -27,14 +27,14 @@ #include "qapi/error.h" #ifdef _WIN32 -#include "char-win.h" +#include "chardev/char-win.h" #else #include #include -#include "char-fd.h" +#include "chardev/char-fd.h" #endif -#include "char-serial.h" +#include "chardev/char-serial.h" #ifdef _WIN32 diff --git a/chardev/char-serial.h b/chardev/char-serial.h deleted file mode 100644 index 64a27f63b1..0000000000 --- a/chardev/char-serial.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_SERIAL_H -#define CHAR_SERIAL_H - -#ifdef _WIN32 -#define HAVE_CHARDEV_SERIAL 1 -#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ - || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ - || defined(__GLIBC__) -#define HAVE_CHARDEV_SERIAL 1 -#endif - -#endif diff --git a/chardev/char-socket.c b/chardev/char-socket.c index e2fb7f7cd5..ccc499cfa1 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -22,14 +22,14 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "io/channel-socket.h" #include "io/channel-tls.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "qapi/clone-visitor.h" -#include "char-io.h" +#include "chardev/char-io.h" /***********************************************************/ /* TCP Net console */ diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c index be4a65962c..6f5d798d7b 100644 --- a/chardev/char-stdio.c +++ b/chardev/char-stdio.c @@ -25,14 +25,14 @@ #include "qemu/sockets.h" #include "qapi/error.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #ifdef _WIN32 -#include "char-win.h" -#include "char-win-stdio.h" +#include "chardev/char-win.h" +#include "chardev/char-win-stdio.h" #else #include -#include "char-fd.h" +#include "chardev/char-fd.h" #endif #ifndef _WIN32 diff --git a/chardev/char-udp.c b/chardev/char-udp.c index 607647642a..4ee11d3ebf 100644 --- a/chardev/char-udp.c +++ b/chardev/char-udp.c @@ -22,11 +22,11 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "io/channel-socket.h" #include "qapi/error.h" -#include "char-io.h" +#include "chardev/char-io.h" /***********************************************************/ /* UDP Net console */ diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c index eb44afc17a..efcf7827eb 100644 --- a/chardev/char-win-stdio.c +++ b/chardev/char-win-stdio.c @@ -23,8 +23,8 @@ */ #include "qemu/osdep.h" #include "qapi/error.h" -#include "char-win.h" -#include "char-win-stdio.h" +#include "chardev/char-win.h" +#include "chardev/char-win-stdio.h" typedef struct { Chardev parent; diff --git a/chardev/char-win-stdio.h b/chardev/char-win-stdio.h deleted file mode 100644 index d7314f734d..0000000000 --- a/chardev/char-win-stdio.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_WIN_STDIO_H -#define CHAR_WIN_STDIO_H - -#define TYPE_CHARDEV_WIN_STDIO "chardev-win-stdio" - -#endif /* CHAR_WIN_STDIO_H */ diff --git a/chardev/char-win.c b/chardev/char-win.c index ec9a731be9..05518e0958 100644 --- a/chardev/char-win.c +++ b/chardev/char-win.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qapi/error.h" -#include "char-win.h" +#include "chardev/char-win.h" static void win_chr_read(Chardev *chr, DWORD len) { diff --git a/chardev/char-win.h b/chardev/char-win.h deleted file mode 100644 index 4994425e9e..0000000000 --- a/chardev/char-win.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CHAR_WIN_H -#define CHAR_WIN_H - -#include "sysemu/char.h" - -typedef struct { - Chardev parent; - - bool keep_open; /* console do not close file */ - HANDLE file, hrecv, hsend; - OVERLAPPED orecv; - BOOL fpipe; - - /* Protected by the Chardev chr_write_lock. */ - OVERLAPPED osend; -} WinChardev; - -#define NSENDBUF 2048 -#define NRECVBUF 2048 - -#define TYPE_CHARDEV_WIN "chardev-win" -#define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN) - -void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open); -int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp); -int win_chr_pipe_poll(void *opaque); - -#endif /* CHAR_WIN_H */ diff --git a/chardev/char.c b/chardev/char.c index 26607c1c6b..02142b480e 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -28,16 +28,16 @@ #include "sysemu/sysemu.h" #include "qemu/config-file.h" #include "qemu/error-report.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qmp-commands.h" #include "qapi-visit.h" #include "sysemu/replay.h" #include "qemu/help_option.h" -#include "char-mux.h" -#include "char-io.h" -#include "char-parallel.h" -#include "char-serial.h" +#include "chardev/char-mux.h" +#include "chardev/char-io.h" +#include "chardev/char-parallel.h" +#include "chardev/char-serial.h" /***********************************************************/ /* character device */ diff --git a/gdbstub.c b/gdbstub.c index 86eed4f97c..6515c635dc 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -25,7 +25,7 @@ #include "qemu.h" #else #include "monitor/monitor.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "exec/gdbstub.h" #endif diff --git a/hmp.c b/hmp.c index 20f5daba5e..97d4822e52 100644 --- a/hmp.c +++ b/hmp.c @@ -17,7 +17,7 @@ #include "hmp.h" #include "net/net.h" #include "net/eth.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/block-backend.h" #include "sysemu/sysemu.h" #include "qemu/config-file.h" diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index 9056f27bf8..40666b68a3 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -30,7 +30,7 @@ #include "sysemu/sysemu.h" #include "exec/address-spaces.h" #include "hw/boards.h" -#include "sysemu/char.h" +#include "chardev/char.h" static void fsl_imx25_init(Object *obj) { diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index d7e2d832b2..c30130667e 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -27,7 +27,7 @@ #include "sysemu/sysemu.h" #include "exec/address-spaces.h" #include "hw/boards.h" -#include "sysemu/char.h" +#include "chardev/char.h" static void fsl_imx31_init(Object *obj) { diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index 6969e734ad..27773c9c47 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "hw/arm/fsl-imx6.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" #define NAME_SIZE 20 diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 8afb854c74..9eabbaeea5 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -30,7 +30,7 @@ #include "hw/arm/omap.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/block/flash.h" #include "hw/arm/soc_dma.h" #include "hw/sysbus.h" diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index eea551dc16..0d43cc707c 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -17,7 +17,7 @@ #include "hw/char/serial.h" #include "hw/i2c/i2c.h" #include "hw/ssi/ssi.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qemu/cutils.h" diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 3311cc38a4..66cad198d4 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -34,7 +34,7 @@ #include "strongarm.h" #include "qemu/error-report.h" #include "hw/arm/arm.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "hw/ssi/ssi.h" #include "qemu/cutils.h" diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c index 3c193848fc..cc2087392e 100644 --- a/hw/bt/hci-csr.c +++ b/hw/bt/hci-csr.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/timer.h" #include "qemu/bswap.h" #include "hw/irq.h" diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 4dcee571c0..cf4c1d56ff 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -23,7 +23,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/timer.h" #include "qemu/log.h" #include "hw/char/cadence_uart.h" diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index 80dce07e7f..77d91c8558 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c index 029f5bbf5e..4f1dec7f1d 100644 --- a/hw/char/digic-uart.c +++ b/hw/char/digic-uart.c @@ -29,7 +29,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/log.h" #include "hw/char/digic-uart.h" diff --git a/hw/char/escc.c b/hw/char/escc.c index 9228091cec..df89d58eed 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/char/escc.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "ui/console.h" #include "ui/input.h" #include "trace.h" diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 54383878e0..33e3e16397 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/log.h" #define D(x) diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index bff706ab3a..94952fb90f 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -23,7 +23,7 @@ #include "hw/sysbus.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/arm/exynos4210.h" diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index db686e6a6f..39d1133c61 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "trace.h" diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index 93929c2880..b8a3c92c9e 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "hw/ipack/ipack.h" #include "qemu/bitops.h" -#include "sysemu/char.h" +#include "chardev/char.h" /* #define DEBUG_IPOCTAL */ diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c index f8c1e0d076..6b0633e518 100644 --- a/hw/char/lm32_juart.c +++ b/hw/char/lm32_juart.c @@ -21,7 +21,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/char/lm32_juart.h" diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index 7f3597c4b0..a7610c28ce 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" enum { diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index e69672f4e9..b639b53c83 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -9,7 +9,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/m68k/mcf.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "exec/address-spaces.h" #include "qapi/error.h" diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index ae8e2f3554..5ef847c5eb 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -25,7 +25,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" enum { diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c index 31ebb1592c..6fd1b9cf6b 100644 --- a/hw/char/omap_uart.c +++ b/hw/char/omap_uart.c @@ -18,7 +18,7 @@ * with this program; if not, see . */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/hw.h" #include "hw/arm/omap.h" #include "hw/char/serial.h" diff --git a/hw/char/parallel.c b/hw/char/parallel.c index c71a4a0f4f..c926df0bee 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" #include "sysemu/sysemu.h" diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 24ea9738b6..1757035bb3 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -9,7 +9,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/log.h" #include "trace.h" diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 07d6ebd112..755d514188 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -17,7 +17,7 @@ #include "hw/qdev.h" #include "qemu/thread.h" #include "qemu/error-report.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index b78f240a73..0fd3cb4887 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -19,7 +19,7 @@ #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" -#include "sysemu/char.h" +#include "chardev/char.h" typedef struct ASCIIConsoleData { EventBufferHeader ebh; diff --git a/hw/char/serial.c b/hw/char/serial.c index 03d890ca24..aa336333be 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "hw/char/serial.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qapi/error.h" #include "qemu/timer.h" #include "exec/address-spaces.h" diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 303eb0a678..80c7696d8d 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sh4/sh.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "exec/address-spaces.h" #include "qapi/error.h" diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index e30c8da57c..2317e45404 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/qdev.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c index b2dda01baa..c043104185 100644 --- a/hw/char/terminal3270.c +++ b/hw/char/terminal3270.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/s390x/3270-ccw.h" /* Enough spaces for different window sizes. */ diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 798d9b69fd..8418db6a07 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" #include "trace.h" #include "hw/virtio/virtio-serial.h" diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index c01f41090e..1cdbe59f8a 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -25,7 +25,7 @@ #include "qapi/error.h" #include "hw/hw.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/xen/xen_backend.h" #include "qapi/error.h" diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 37d313b429..bcebdae3da 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #define DUART(x) diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 79c2014135..4da0c6a24e 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -20,7 +20,7 @@ #include "hw/block/block.h" #include "net/hub.h" #include "qapi/visitor.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/iothread.h" static void get_pointer(Object *obj, Visitor *v, Property *prop, diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index fa3617db2d..9f1a497322 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -9,7 +9,7 @@ #include "hw/block/block.h" #include "net/hub.h" #include "qapi/visitor.h" -#include "sysemu/char.h" +#include "chardev/char.h" void qdev_prop_set_after_realize(DeviceState *dev, const char *name, Error **errp) diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index e8e3d250b6..35285383fd 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -30,7 +30,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/timer.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "hw/ipmi/ipmi.h" diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index c707d24db4..5ce9f0a062 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -30,7 +30,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "trace.h" diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 53d1e0ce45..a4677f7da4 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -35,7 +35,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/log.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 475e36a4c7..cd064dcf8c 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -29,7 +29,7 @@ #include "qemu/error-report.h" #include "qemu/event_notifier.h" #include "qom/object_interfaces.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/hostmem.h" #include "sysemu/qtest.h" #include "qapi/visitor.h" diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index a41b0d6ec5..c2096b25ab 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -9,7 +9,7 @@ */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" #include "qemu/sockets.h" #include "ccid.h" diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 76ceca1f5c..4df995109b 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -15,7 +15,7 @@ #include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "sysemu/char.h" +#include "chardev/char.h" //#define DEBUG_Serial diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index ad5ef783a6..c862c1adea 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -33,7 +33,7 @@ #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "qemu/iov.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include #include diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index dde094abb4..44c9d8c954 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -13,7 +13,7 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-backend.h" #include "hw/virtio/virtio-net.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/kvm.h" #include "qemu/error-report.h" #include "qemu/sockets.h" diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c index a9055e9eba..0bed5770c9 100644 --- a/hw/xen/xen-common.c +++ b/hw/xen/xen-common.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "hw/xen/xen_backend.h" #include "qmp-commands.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/accel.h" #include "migration/migration.h" diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 4636f8e934..d5ac080d4a 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -40,7 +40,7 @@ #include "hw/sysbus.h" #include "hw/block/flash.h" #include "sysemu/block-backend.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/device_tree.h" #include "qemu/error-report.h" #include "bootparam.h" diff --git a/include/chardev/char-fd.h b/include/chardev/char-fd.h new file mode 100644 index 0000000000..55ae5b47b0 --- /dev/null +++ b/include/chardev/char-fd.h @@ -0,0 +1,44 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_FD_H +#define CHAR_FD_H + +#include "io/channel.h" +#include "chardev/char.h" + +typedef struct FDChardev { + Chardev parent; + Chardev *chr; + QIOChannel *ioc_in, *ioc_out; + int max_size; +} FDChardev; + +#define TYPE_CHARDEV_FD "chardev-fd" + +#define FD_CHARDEV(obj) OBJECT_CHECK(FDChardev, (obj), TYPE_CHARDEV_FD) + +void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out); +int qmp_chardev_open_file_source(char *src, int flags, Error **errp); + +#endif /* CHAR_FD_H */ diff --git a/include/chardev/char-io.h b/include/chardev/char-io.h new file mode 100644 index 0000000000..9638da5100 --- /dev/null +++ b/include/chardev/char-io.h @@ -0,0 +1,46 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_IO_H +#define CHAR_IO_H + +#include "qemu-common.h" +#include "io/channel.h" +#include "chardev/char.h" + +/* Can only be used for read */ +GSource *io_add_watch_poll(Chardev *chr, + QIOChannel *ioc, + IOCanReadHandler *fd_can_read, + QIOChannelFunc fd_read, + gpointer user_data, + GMainContext *context); + +void remove_fd_in_watch(Chardev *chr); + +int io_channel_send(QIOChannel *ioc, const void *buf, size_t len); + +int io_channel_send_full(QIOChannel *ioc, const void *buf, size_t len, + int *fds, size_t nfds); + +#endif /* CHAR_IO_H */ diff --git a/include/chardev/char-mux.h b/include/chardev/char-mux.h new file mode 100644 index 0000000000..45cdfc7e67 --- /dev/null +++ b/include/chardev/char-mux.h @@ -0,0 +1,63 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_MUX_H +#define CHAR_MUX_H + +#include "chardev/char.h" + +extern bool muxes_realized; + +#define MAX_MUX 4 +#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ +#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) +typedef struct MuxChardev { + Chardev parent; + CharBackend *backends[MAX_MUX]; + CharBackend chr; + int focus; + int mux_cnt; + int term_got_escape; + int max_size; + /* Intermediate input buffer catches 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]; + int timestamps; + + /* Protected by the Chardev chr_write_lock. */ + int linestart; + int64_t timestamps_start; +} MuxChardev; + +#define MUX_CHARDEV(obj) OBJECT_CHECK(MuxChardev, (obj), TYPE_CHARDEV_MUX) +#define CHARDEV_IS_MUX(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX) + +void mux_chr_set_handlers(Chardev *chr, GMainContext *context); +void mux_set_focus(Chardev *chr, int focus); +void mux_chr_send_all_event(Chardev *chr, int event); + +#endif /* CHAR_MUX_H */ diff --git a/include/chardev/char-parallel.h b/include/chardev/char-parallel.h new file mode 100644 index 0000000000..26742f9d5c --- /dev/null +++ b/include/chardev/char-parallel.h @@ -0,0 +1,32 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_PARALLEL_H +#define CHAR_PARALLEL_H + +#if defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#define HAVE_CHARDEV_PARPORT 1 +#endif + +#endif /* CHAR_PARALLEL_H */ diff --git a/include/chardev/char-serial.h b/include/chardev/char-serial.h new file mode 100644 index 0000000000..64a27f63b1 --- /dev/null +++ b/include/chardev/char-serial.h @@ -0,0 +1,35 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_SERIAL_H +#define CHAR_SERIAL_H + +#ifdef _WIN32 +#define HAVE_CHARDEV_SERIAL 1 +#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ + || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ + || defined(__GLIBC__) +#define HAVE_CHARDEV_SERIAL 1 +#endif + +#endif diff --git a/include/chardev/char-win-stdio.h b/include/chardev/char-win-stdio.h new file mode 100644 index 0000000000..d7314f734d --- /dev/null +++ b/include/chardev/char-win-stdio.h @@ -0,0 +1,29 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_WIN_STDIO_H +#define CHAR_WIN_STDIO_H + +#define TYPE_CHARDEV_WIN_STDIO "chardev-win-stdio" + +#endif /* CHAR_WIN_STDIO_H */ diff --git a/include/chardev/char-win.h b/include/chardev/char-win.h new file mode 100644 index 0000000000..fa59e9e423 --- /dev/null +++ b/include/chardev/char-win.h @@ -0,0 +1,51 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CHAR_WIN_H +#define CHAR_WIN_H + +#include "chardev/char.h" + +typedef struct { + Chardev parent; + + bool keep_open; /* console do not close file */ + HANDLE file, hrecv, hsend; + OVERLAPPED orecv; + BOOL fpipe; + + /* Protected by the Chardev chr_write_lock. */ + OVERLAPPED osend; +} WinChardev; + +#define NSENDBUF 2048 +#define NRECVBUF 2048 + +#define TYPE_CHARDEV_WIN "chardev-win" +#define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN) + +void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open); +int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp); +int win_chr_pipe_poll(void *opaque); + +#endif /* CHAR_WIN_H */ diff --git a/include/chardev/char.h b/include/chardev/char.h new file mode 100644 index 0000000000..fffc0f40d4 --- /dev/null +++ b/include/chardev/char.h @@ -0,0 +1,499 @@ +#ifndef QEMU_CHAR_H +#define QEMU_CHAR_H + +#include "qemu-common.h" +#include "qemu/option.h" +#include "qemu/main-loop.h" +#include "qemu/bitmap.h" +#include "qom/object.h" + +#define IAC_EOR 239 +#define IAC_SE 240 +#define IAC_NOP 241 +#define IAC_BREAK 243 +#define IAC_IP 244 +#define IAC_SB 250 +#define IAC 255 + +/* character device */ + +typedef enum { + CHR_EVENT_BREAK, /* serial break char */ + CHR_EVENT_OPENED, /* new connection established */ + CHR_EVENT_MUX_IN, /* mux-focus was set to this terminal */ + CHR_EVENT_MUX_OUT, /* mux-focus will move on */ + CHR_EVENT_CLOSED /* connection closed */ +} QEMUChrEvent; + +#define CHR_READ_BUF_LEN 4096 + +#define CHR_IOCTL_SERIAL_SET_PARAMS 1 +typedef struct { + int speed; + int parity; + int data_bits; + int stop_bits; +} QEMUSerialSetParams; + +#define CHR_IOCTL_SERIAL_SET_BREAK 2 + +#define CHR_IOCTL_PP_READ_DATA 3 +#define CHR_IOCTL_PP_WRITE_DATA 4 +#define CHR_IOCTL_PP_READ_CONTROL 5 +#define CHR_IOCTL_PP_WRITE_CONTROL 6 +#define CHR_IOCTL_PP_READ_STATUS 7 +#define CHR_IOCTL_PP_EPP_READ_ADDR 8 +#define CHR_IOCTL_PP_EPP_READ 9 +#define CHR_IOCTL_PP_EPP_WRITE_ADDR 10 +#define CHR_IOCTL_PP_EPP_WRITE 11 +#define CHR_IOCTL_PP_DATA_DIR 12 + +struct ParallelIOArg { + void *buffer; + int count; +}; + +#define CHR_IOCTL_SERIAL_SET_TIOCM 13 +#define CHR_IOCTL_SERIAL_GET_TIOCM 14 + +#define CHR_TIOCM_CTS 0x020 +#define CHR_TIOCM_CAR 0x040 +#define CHR_TIOCM_DSR 0x100 +#define CHR_TIOCM_RI 0x080 +#define CHR_TIOCM_DTR 0x002 +#define CHR_TIOCM_RTS 0x004 + +typedef void IOEventHandler(void *opaque, int event); + +typedef enum { + /* Whether the chardev peer is able to close and + * reopen the data channel, thus requiring support + * for qemu_chr_wait_connected() to wait for a + * valid connection */ + QEMU_CHAR_FEATURE_RECONNECTABLE, + /* Whether it is possible to send/recv file descriptors + * over the data channel */ + QEMU_CHAR_FEATURE_FD_PASS, + /* Whether replay or record mode is enabled */ + QEMU_CHAR_FEATURE_REPLAY, + + QEMU_CHAR_FEATURE_LAST, +} ChardevFeature; + +/* This is the backend as seen by frontend, the actual backend is + * Chardev */ +typedef struct CharBackend { + Chardev *chr; + IOEventHandler *chr_event; + IOCanReadHandler *chr_can_read; + IOReadHandler *chr_read; + void *opaque; + int tag; + int fe_open; +} CharBackend; + +struct Chardev { + Object parent_obj; + + QemuMutex chr_write_lock; + CharBackend *be; + char *label; + char *filename; + int logfd; + int be_open; + GSource *gsource; + DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST); +}; + +/** + * @qemu_chr_new_from_opts: + * + * Create a new character backend from a QemuOpts list. + * + * @opts see qemu-config.c for a list of valid options + * + * Returns: a new character backend + */ +Chardev *qemu_chr_new_from_opts(QemuOpts *opts, + Error **errp); + +/** + * @qemu_chr_parse_common: + * + * Parse the common options available to all character backends. + * + * @opts the options that still need parsing + * @backend a new backend + */ +void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend); + +/** + * @qemu_chr_new: + * + * Create a new character backend from a URI. + * + * @label the name of the backend + * @filename the URI + * + * Returns: a new character backend + */ +Chardev *qemu_chr_new(const char *label, const char *filename); + + +/** + * @qemu_chr_fe_disconnect: + * + * Close a fd accpeted by character backend. + * Without associated Chardev, do nothing. + */ +void qemu_chr_fe_disconnect(CharBackend *be); + +/** + * @qemu_chr_cleanup: + * + * Delete all chardevs (when leaving qemu) + */ +void qemu_chr_cleanup(void); + +/** + * @qemu_chr_fe_wait_connected: + * + * Wait for characted backend to be connected, return < 0 on error or + * if no assicated Chardev. + */ +int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); + +/** + * @qemu_chr_new_noreplay: + * + * Create a new character backend from a URI. + * Character device communications are not written + * into the replay log. + * + * @label the name of the backend + * @filename the URI + * + * Returns: a new character backend + */ +Chardev *qemu_chr_new_noreplay(const char *label, const char *filename); + +/** + * @qemu_chr_fe_set_echo: + * + * Ask the backend to override its normal echo setting. This only really + * applies to the stdio backend and is used by the QMP server such that you + * can see what you type if you try to type QMP commands. + * Without associated Chardev, do nothing. + * + * @echo true to enable echo, false to disable echo + */ +void qemu_chr_fe_set_echo(CharBackend *be, bool echo); + +/** + * @qemu_chr_fe_set_open: + * + * Set character frontend open status. This is an indication that the + * front end is ready (or not) to begin doing I/O. + * Without associated Chardev, do nothing. + */ +void qemu_chr_fe_set_open(CharBackend *be, int fe_open); + +/** + * @qemu_chr_fe_printf: + * + * Write to a character backend using a printf style interface. This + * function is thread-safe. It does nothing without associated + * Chardev. + * + * @fmt see #printf + */ +void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/** + * @qemu_chr_fe_add_watch: + * + * If the backend is connected, create and add a #GSource that fires + * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP) + * is active; return the #GSource's tag. If it is disconnected, + * or without associated Chardev, return 0. + * + * @cond the condition to poll for + * @func the function to call when the condition happens + * @user_data the opaque pointer to pass to @func + * + * Returns: the source tag + */ +guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, + GIOFunc func, void *user_data); + +/** + * @qemu_chr_fe_write: + * + * Write data to a character backend from the front end. This function + * will send data from the front end to the back end. This function + * is thread-safe. + * + * @buf the data + * @len the number of bytes to send + * + * Returns: the number of bytes consumed (0 if no assicated Chardev) + */ +int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); + +/** + * @qemu_chr_fe_write_all: + * + * Write data to a character backend from the front end. This function will + * send data from the front end to the back end. Unlike @qemu_chr_fe_write, + * this function will block if the back end cannot consume all of the data + * attempted to be written. This function is thread-safe. + * + * @buf the data + * @len the number of bytes to send + * + * Returns: the number of bytes consumed (0 if no assicated Chardev) + */ +int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); + +/** + * @qemu_chr_fe_read_all: + * + * Read data to a buffer from the back end. + * + * @buf the data buffer + * @len the number of bytes to read + * + * Returns: the number of bytes read (0 if no assicated Chardev) + */ +int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); + +/** + * @qemu_chr_fe_ioctl: + * + * Issue a device specific ioctl to a backend. This function is thread-safe. + * + * @cmd see CHR_IOCTL_* + * @arg the data associated with @cmd + * + * Returns: if @cmd is not supported by the backend or there is no + * associated Chardev, -ENOTSUP, otherwise the return + * value depends on the semantics of @cmd + */ +int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); + +/** + * @qemu_chr_fe_get_msgfd: + * + * For backends capable of fd passing, return the latest file descriptor passed + * by a client. + * + * Returns: -1 if fd passing isn't supported or there is no pending file + * descriptor. If a file descriptor is returned, subsequent calls to + * this function will return -1 until a client sends a new file + * descriptor. + */ +int qemu_chr_fe_get_msgfd(CharBackend *be); + +/** + * @qemu_chr_fe_get_msgfds: + * + * For backends capable of fd passing, return the number of file received + * descriptors and fills the fds array up to num elements + * + * Returns: -1 if fd passing isn't supported or there are no pending file + * descriptors. If file descriptors are returned, subsequent calls to + * this function will return -1 until a client sends a new set of file + * descriptors. + */ +int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); + +/** + * @qemu_chr_fe_set_msgfds: + * + * For backends capable of fd passing, set an array of fds to be passed with + * the next send operation. + * A subsequent call to this function before calling a write function will + * result in overwriting the fd array with the new value without being send. + * Upon writing the message the fd array is freed. + * + * Returns: -1 if fd passing isn't supported or no associated Chardev. + */ +int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num); + +/** + * @qemu_chr_be_can_write: + * + * Determine how much data the front end can currently accept. This function + * returns the number of bytes the front end can accept. If it returns 0, the + * front end cannot receive data at the moment. The function must be polled + * to determine when data can be received. + * + * Returns: the number of bytes the front end can receive via @qemu_chr_be_write + */ +int qemu_chr_be_can_write(Chardev *s); + +/** + * @qemu_chr_be_write: + * + * Write data from the back end to the front end. Before issuing this call, + * the caller should call @qemu_chr_be_can_write to determine how much data + * the front end can currently accept. + * + * @buf a buffer to receive data from the front end + * @len the number of bytes to receive from the front end + */ +void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len); + +/** + * @qemu_chr_be_write_impl: + * + * Implementation of back end writing. Used by replay module. + * + * @buf a buffer to receive data from the front end + * @len the number of bytes to receive from the front end + */ +void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len); + +/** + * @qemu_chr_be_event: + * + * Send an event from the back end to the front end. + * + * @event the event to send + */ +void qemu_chr_be_event(Chardev *s, int event); + +/** + * @qemu_chr_fe_init: + * + * Initializes a front end for the given CharBackend and + * Chardev. Call qemu_chr_fe_deinit() to remove the association and + * release the driver. + * + * Returns: false on error. + */ +bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); + +/** + * @qemu_chr_fe_get_driver: + * + * Returns the driver associated with a CharBackend or NULL if no + * associated Chardev. + */ +Chardev *qemu_chr_fe_get_driver(CharBackend *be); + +/** + * @qemu_chr_fe_deinit: + * + * Dissociate the CharBackend from the Chardev. + * + * Safe to call without associated Chardev. + */ +void qemu_chr_fe_deinit(CharBackend *b); + +/** + * @qemu_chr_fe_set_handlers: + * @b: a CharBackend + * @fd_can_read: callback to get the amount of data the frontend may + * receive + * @fd_read: callback to receive data from char + * @fd_event: event callback + * @opaque: an opaque pointer for the callbacks + * @context: a main loop context or NULL for the default + * @set_open: whether to call qemu_chr_fe_set_open() implicitely when + * any of the handler is non-NULL + * + * Set the front end char handlers. The front end takes the focus if + * any of the handler is non-NULL. + * + * Without associated Chardev, nothing is changed. + */ +void qemu_chr_fe_set_handlers(CharBackend *b, + IOCanReadHandler *fd_can_read, + IOReadHandler *fd_read, + IOEventHandler *fd_event, + void *opaque, + GMainContext *context, + bool set_open); + +/** + * @qemu_chr_fe_take_focus: + * + * Take the focus (if the front end is muxed). + * + * Without associated Chardev, nothing is changed. + */ +void qemu_chr_fe_take_focus(CharBackend *b); + +void qemu_chr_fe_accept_input(CharBackend *be); +int qemu_chr_add_client(Chardev *s, int fd); +Chardev *qemu_chr_find(const char *name); + +bool qemu_chr_has_feature(Chardev *chr, + ChardevFeature feature); +void qemu_chr_set_feature(Chardev *chr, + ChardevFeature feature); +QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); +int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len); +int qemu_chr_wait_connected(Chardev *chr, Error **errp); + +#define TYPE_CHARDEV "chardev" +#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV) +#define CHARDEV_CLASS(klass) \ + OBJECT_CLASS_CHECK(ChardevClass, (klass), TYPE_CHARDEV) +#define CHARDEV_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ChardevClass, (obj), TYPE_CHARDEV) + +#define TYPE_CHARDEV_NULL "chardev-null" +#define TYPE_CHARDEV_MUX "chardev-mux" +#define TYPE_CHARDEV_RINGBUF "chardev-ringbuf" +#define TYPE_CHARDEV_PTY "chardev-pty" +#define TYPE_CHARDEV_CONSOLE "chardev-console" +#define TYPE_CHARDEV_STDIO "chardev-stdio" +#define TYPE_CHARDEV_PIPE "chardev-pipe" +#define TYPE_CHARDEV_MEMORY "chardev-memory" +#define TYPE_CHARDEV_PARALLEL "chardev-parallel" +#define TYPE_CHARDEV_FILE "chardev-file" +#define TYPE_CHARDEV_SERIAL "chardev-serial" +#define TYPE_CHARDEV_SOCKET "chardev-socket" +#define TYPE_CHARDEV_UDP "chardev-udp" + +#define CHARDEV_IS_RINGBUF(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_RINGBUF) +#define CHARDEV_IS_PTY(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_PTY) + +typedef struct ChardevClass { + ObjectClass parent_class; + + bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */ + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); + + void (*open)(Chardev *chr, ChardevBackend *backend, + bool *be_opened, Error **errp); + + int (*chr_write)(Chardev *s, const uint8_t *buf, int len); + int (*chr_sync_read)(Chardev *s, const uint8_t *buf, int len); + GSource *(*chr_add_watch)(Chardev *s, GIOCondition cond); + void (*chr_update_read_handler)(Chardev *s, GMainContext *context); + int (*chr_ioctl)(Chardev *s, int cmd, void *arg); + int (*get_msgfds)(Chardev *s, int* fds, int num); + int (*set_msgfds)(Chardev *s, int *fds, int num); + int (*chr_add_client)(Chardev *chr, int fd); + int (*chr_wait_connected)(Chardev *chr, Error **errp); + void (*chr_disconnect)(Chardev *chr); + void (*chr_accept_input)(Chardev *chr); + void (*chr_set_echo)(Chardev *chr, bool echo); + void (*chr_set_fe_open)(Chardev *chr, int fe_open); +} ChardevClass; + +Chardev *qemu_chardev_new(const char *id, const char *typename, + ChardevBackend *backend, Error **errp); + +extern int term_escape_char; + +/* console.c */ +void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp); + +#endif diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h index 6865f154bc..2a051c5646 100644 --- a/include/hw/char/bcm2835_aux.h +++ b/include/hw/char/bcm2835_aux.h @@ -9,7 +9,7 @@ #define BCM2835_AUX_H #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #define TYPE_BCM2835_AUX "bcm2835-aux" #define BCM2835_AUX(obj) OBJECT_CHECK(BCM2835AuxState, (obj), TYPE_BCM2835_AUX) diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h index c836db4b74..eed7d8d358 100644 --- a/include/hw/char/cadence_uart.h +++ b/include/hw/char/cadence_uart.h @@ -19,7 +19,7 @@ #ifndef CADENCE_UART_H #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/timer.h" #define CADENCE_UART_RX_FIFO_SIZE 16 diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h index 340c8e1111..370b48a6c5 100644 --- a/include/hw/char/digic-uart.h +++ b/include/hw/char/digic-uart.h @@ -19,7 +19,7 @@ #define HW_CHAR_DIGIC_UART_H #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #define TYPE_DIGIC_UART "digic-uart" #define DIGIC_UART(obj) \ diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index 4cc3fbc395..05500f5346 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -19,7 +19,7 @@ #define IMX_SERIAL_H #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #define TYPE_IMX_SERIAL "imx.serial" #define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL) diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index daebb076c2..01dcd2a8d2 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -28,10 +28,10 @@ #include "hw/hw.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "exec/memory.h" #include "qemu/fifo8.h" -#include "sysemu/char.h" +#include "chardev/char.h" #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h index 3267523270..4259dbeb1e 100644 --- a/include/hw/char/stm32f2xx_usart.h +++ b/include/hw/char/stm32f2xx_usart.h @@ -26,7 +26,7 @@ #define HW_STM32F2XX_USART_H #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/hw.h" #define USART_SR 0x00 diff --git a/include/sysemu/char.h b/include/sysemu/char.h deleted file mode 100644 index fffc0f40d4..0000000000 --- a/include/sysemu/char.h +++ /dev/null @@ -1,499 +0,0 @@ -#ifndef QEMU_CHAR_H -#define QEMU_CHAR_H - -#include "qemu-common.h" -#include "qemu/option.h" -#include "qemu/main-loop.h" -#include "qemu/bitmap.h" -#include "qom/object.h" - -#define IAC_EOR 239 -#define IAC_SE 240 -#define IAC_NOP 241 -#define IAC_BREAK 243 -#define IAC_IP 244 -#define IAC_SB 250 -#define IAC 255 - -/* character device */ - -typedef enum { - CHR_EVENT_BREAK, /* serial break char */ - CHR_EVENT_OPENED, /* new connection established */ - CHR_EVENT_MUX_IN, /* mux-focus was set to this terminal */ - CHR_EVENT_MUX_OUT, /* mux-focus will move on */ - CHR_EVENT_CLOSED /* connection closed */ -} QEMUChrEvent; - -#define CHR_READ_BUF_LEN 4096 - -#define CHR_IOCTL_SERIAL_SET_PARAMS 1 -typedef struct { - int speed; - int parity; - int data_bits; - int stop_bits; -} QEMUSerialSetParams; - -#define CHR_IOCTL_SERIAL_SET_BREAK 2 - -#define CHR_IOCTL_PP_READ_DATA 3 -#define CHR_IOCTL_PP_WRITE_DATA 4 -#define CHR_IOCTL_PP_READ_CONTROL 5 -#define CHR_IOCTL_PP_WRITE_CONTROL 6 -#define CHR_IOCTL_PP_READ_STATUS 7 -#define CHR_IOCTL_PP_EPP_READ_ADDR 8 -#define CHR_IOCTL_PP_EPP_READ 9 -#define CHR_IOCTL_PP_EPP_WRITE_ADDR 10 -#define CHR_IOCTL_PP_EPP_WRITE 11 -#define CHR_IOCTL_PP_DATA_DIR 12 - -struct ParallelIOArg { - void *buffer; - int count; -}; - -#define CHR_IOCTL_SERIAL_SET_TIOCM 13 -#define CHR_IOCTL_SERIAL_GET_TIOCM 14 - -#define CHR_TIOCM_CTS 0x020 -#define CHR_TIOCM_CAR 0x040 -#define CHR_TIOCM_DSR 0x100 -#define CHR_TIOCM_RI 0x080 -#define CHR_TIOCM_DTR 0x002 -#define CHR_TIOCM_RTS 0x004 - -typedef void IOEventHandler(void *opaque, int event); - -typedef enum { - /* Whether the chardev peer is able to close and - * reopen the data channel, thus requiring support - * for qemu_chr_wait_connected() to wait for a - * valid connection */ - QEMU_CHAR_FEATURE_RECONNECTABLE, - /* Whether it is possible to send/recv file descriptors - * over the data channel */ - QEMU_CHAR_FEATURE_FD_PASS, - /* Whether replay or record mode is enabled */ - QEMU_CHAR_FEATURE_REPLAY, - - QEMU_CHAR_FEATURE_LAST, -} ChardevFeature; - -/* This is the backend as seen by frontend, the actual backend is - * Chardev */ -typedef struct CharBackend { - Chardev *chr; - IOEventHandler *chr_event; - IOCanReadHandler *chr_can_read; - IOReadHandler *chr_read; - void *opaque; - int tag; - int fe_open; -} CharBackend; - -struct Chardev { - Object parent_obj; - - QemuMutex chr_write_lock; - CharBackend *be; - char *label; - char *filename; - int logfd; - int be_open; - GSource *gsource; - DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST); -}; - -/** - * @qemu_chr_new_from_opts: - * - * Create a new character backend from a QemuOpts list. - * - * @opts see qemu-config.c for a list of valid options - * - * Returns: a new character backend - */ -Chardev *qemu_chr_new_from_opts(QemuOpts *opts, - Error **errp); - -/** - * @qemu_chr_parse_common: - * - * Parse the common options available to all character backends. - * - * @opts the options that still need parsing - * @backend a new backend - */ -void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend); - -/** - * @qemu_chr_new: - * - * Create a new character backend from a URI. - * - * @label the name of the backend - * @filename the URI - * - * Returns: a new character backend - */ -Chardev *qemu_chr_new(const char *label, const char *filename); - - -/** - * @qemu_chr_fe_disconnect: - * - * Close a fd accpeted by character backend. - * Without associated Chardev, do nothing. - */ -void qemu_chr_fe_disconnect(CharBackend *be); - -/** - * @qemu_chr_cleanup: - * - * Delete all chardevs (when leaving qemu) - */ -void qemu_chr_cleanup(void); - -/** - * @qemu_chr_fe_wait_connected: - * - * Wait for characted backend to be connected, return < 0 on error or - * if no assicated Chardev. - */ -int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); - -/** - * @qemu_chr_new_noreplay: - * - * Create a new character backend from a URI. - * Character device communications are not written - * into the replay log. - * - * @label the name of the backend - * @filename the URI - * - * Returns: a new character backend - */ -Chardev *qemu_chr_new_noreplay(const char *label, const char *filename); - -/** - * @qemu_chr_fe_set_echo: - * - * Ask the backend to override its normal echo setting. This only really - * applies to the stdio backend and is used by the QMP server such that you - * can see what you type if you try to type QMP commands. - * Without associated Chardev, do nothing. - * - * @echo true to enable echo, false to disable echo - */ -void qemu_chr_fe_set_echo(CharBackend *be, bool echo); - -/** - * @qemu_chr_fe_set_open: - * - * Set character frontend open status. This is an indication that the - * front end is ready (or not) to begin doing I/O. - * Without associated Chardev, do nothing. - */ -void qemu_chr_fe_set_open(CharBackend *be, int fe_open); - -/** - * @qemu_chr_fe_printf: - * - * Write to a character backend using a printf style interface. This - * function is thread-safe. It does nothing without associated - * Chardev. - * - * @fmt see #printf - */ -void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); - -/** - * @qemu_chr_fe_add_watch: - * - * If the backend is connected, create and add a #GSource that fires - * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP) - * is active; return the #GSource's tag. If it is disconnected, - * or without associated Chardev, return 0. - * - * @cond the condition to poll for - * @func the function to call when the condition happens - * @user_data the opaque pointer to pass to @func - * - * Returns: the source tag - */ -guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, - GIOFunc func, void *user_data); - -/** - * @qemu_chr_fe_write: - * - * Write data to a character backend from the front end. This function - * will send data from the front end to the back end. This function - * is thread-safe. - * - * @buf the data - * @len the number of bytes to send - * - * Returns: the number of bytes consumed (0 if no assicated Chardev) - */ -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); - -/** - * @qemu_chr_fe_write_all: - * - * Write data to a character backend from the front end. This function will - * send data from the front end to the back end. Unlike @qemu_chr_fe_write, - * this function will block if the back end cannot consume all of the data - * attempted to be written. This function is thread-safe. - * - * @buf the data - * @len the number of bytes to send - * - * Returns: the number of bytes consumed (0 if no assicated Chardev) - */ -int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); - -/** - * @qemu_chr_fe_read_all: - * - * Read data to a buffer from the back end. - * - * @buf the data buffer - * @len the number of bytes to read - * - * Returns: the number of bytes read (0 if no assicated Chardev) - */ -int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); - -/** - * @qemu_chr_fe_ioctl: - * - * Issue a device specific ioctl to a backend. This function is thread-safe. - * - * @cmd see CHR_IOCTL_* - * @arg the data associated with @cmd - * - * Returns: if @cmd is not supported by the backend or there is no - * associated Chardev, -ENOTSUP, otherwise the return - * value depends on the semantics of @cmd - */ -int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); - -/** - * @qemu_chr_fe_get_msgfd: - * - * For backends capable of fd passing, return the latest file descriptor passed - * by a client. - * - * Returns: -1 if fd passing isn't supported or there is no pending file - * descriptor. If a file descriptor is returned, subsequent calls to - * this function will return -1 until a client sends a new file - * descriptor. - */ -int qemu_chr_fe_get_msgfd(CharBackend *be); - -/** - * @qemu_chr_fe_get_msgfds: - * - * For backends capable of fd passing, return the number of file received - * descriptors and fills the fds array up to num elements - * - * Returns: -1 if fd passing isn't supported or there are no pending file - * descriptors. If file descriptors are returned, subsequent calls to - * this function will return -1 until a client sends a new set of file - * descriptors. - */ -int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); - -/** - * @qemu_chr_fe_set_msgfds: - * - * For backends capable of fd passing, set an array of fds to be passed with - * the next send operation. - * A subsequent call to this function before calling a write function will - * result in overwriting the fd array with the new value without being send. - * Upon writing the message the fd array is freed. - * - * Returns: -1 if fd passing isn't supported or no associated Chardev. - */ -int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num); - -/** - * @qemu_chr_be_can_write: - * - * Determine how much data the front end can currently accept. This function - * returns the number of bytes the front end can accept. If it returns 0, the - * front end cannot receive data at the moment. The function must be polled - * to determine when data can be received. - * - * Returns: the number of bytes the front end can receive via @qemu_chr_be_write - */ -int qemu_chr_be_can_write(Chardev *s); - -/** - * @qemu_chr_be_write: - * - * Write data from the back end to the front end. Before issuing this call, - * the caller should call @qemu_chr_be_can_write to determine how much data - * the front end can currently accept. - * - * @buf a buffer to receive data from the front end - * @len the number of bytes to receive from the front end - */ -void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len); - -/** - * @qemu_chr_be_write_impl: - * - * Implementation of back end writing. Used by replay module. - * - * @buf a buffer to receive data from the front end - * @len the number of bytes to receive from the front end - */ -void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len); - -/** - * @qemu_chr_be_event: - * - * Send an event from the back end to the front end. - * - * @event the event to send - */ -void qemu_chr_be_event(Chardev *s, int event); - -/** - * @qemu_chr_fe_init: - * - * Initializes a front end for the given CharBackend and - * Chardev. Call qemu_chr_fe_deinit() to remove the association and - * release the driver. - * - * Returns: false on error. - */ -bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); - -/** - * @qemu_chr_fe_get_driver: - * - * Returns the driver associated with a CharBackend or NULL if no - * associated Chardev. - */ -Chardev *qemu_chr_fe_get_driver(CharBackend *be); - -/** - * @qemu_chr_fe_deinit: - * - * Dissociate the CharBackend from the Chardev. - * - * Safe to call without associated Chardev. - */ -void qemu_chr_fe_deinit(CharBackend *b); - -/** - * @qemu_chr_fe_set_handlers: - * @b: a CharBackend - * @fd_can_read: callback to get the amount of data the frontend may - * receive - * @fd_read: callback to receive data from char - * @fd_event: event callback - * @opaque: an opaque pointer for the callbacks - * @context: a main loop context or NULL for the default - * @set_open: whether to call qemu_chr_fe_set_open() implicitely when - * any of the handler is non-NULL - * - * Set the front end char handlers. The front end takes the focus if - * any of the handler is non-NULL. - * - * Without associated Chardev, nothing is changed. - */ -void qemu_chr_fe_set_handlers(CharBackend *b, - IOCanReadHandler *fd_can_read, - IOReadHandler *fd_read, - IOEventHandler *fd_event, - void *opaque, - GMainContext *context, - bool set_open); - -/** - * @qemu_chr_fe_take_focus: - * - * Take the focus (if the front end is muxed). - * - * Without associated Chardev, nothing is changed. - */ -void qemu_chr_fe_take_focus(CharBackend *b); - -void qemu_chr_fe_accept_input(CharBackend *be); -int qemu_chr_add_client(Chardev *s, int fd); -Chardev *qemu_chr_find(const char *name); - -bool qemu_chr_has_feature(Chardev *chr, - ChardevFeature feature); -void qemu_chr_set_feature(Chardev *chr, - ChardevFeature feature); -QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); -int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len); -int qemu_chr_wait_connected(Chardev *chr, Error **errp); - -#define TYPE_CHARDEV "chardev" -#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV) -#define CHARDEV_CLASS(klass) \ - OBJECT_CLASS_CHECK(ChardevClass, (klass), TYPE_CHARDEV) -#define CHARDEV_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ChardevClass, (obj), TYPE_CHARDEV) - -#define TYPE_CHARDEV_NULL "chardev-null" -#define TYPE_CHARDEV_MUX "chardev-mux" -#define TYPE_CHARDEV_RINGBUF "chardev-ringbuf" -#define TYPE_CHARDEV_PTY "chardev-pty" -#define TYPE_CHARDEV_CONSOLE "chardev-console" -#define TYPE_CHARDEV_STDIO "chardev-stdio" -#define TYPE_CHARDEV_PIPE "chardev-pipe" -#define TYPE_CHARDEV_MEMORY "chardev-memory" -#define TYPE_CHARDEV_PARALLEL "chardev-parallel" -#define TYPE_CHARDEV_FILE "chardev-file" -#define TYPE_CHARDEV_SERIAL "chardev-serial" -#define TYPE_CHARDEV_SOCKET "chardev-socket" -#define TYPE_CHARDEV_UDP "chardev-udp" - -#define CHARDEV_IS_RINGBUF(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_RINGBUF) -#define CHARDEV_IS_PTY(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_PTY) - -typedef struct ChardevClass { - ObjectClass parent_class; - - bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */ - void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); - - void (*open)(Chardev *chr, ChardevBackend *backend, - bool *be_opened, Error **errp); - - int (*chr_write)(Chardev *s, const uint8_t *buf, int len); - int (*chr_sync_read)(Chardev *s, const uint8_t *buf, int len); - GSource *(*chr_add_watch)(Chardev *s, GIOCondition cond); - void (*chr_update_read_handler)(Chardev *s, GMainContext *context); - int (*chr_ioctl)(Chardev *s, int cmd, void *arg); - int (*get_msgfds)(Chardev *s, int* fds, int num); - int (*set_msgfds)(Chardev *s, int *fds, int num); - int (*chr_add_client)(Chardev *chr, int fd); - int (*chr_wait_connected)(Chardev *chr, Error **errp); - void (*chr_disconnect)(Chardev *chr); - void (*chr_accept_input)(Chardev *chr); - void (*chr_set_echo)(Chardev *chr, bool echo); - void (*chr_set_fe_open)(Chardev *chr, int fe_open); -} ChardevClass; - -Chardev *qemu_chardev_new(const char *id, const char *typename, - ChardevBackend *backend, Error **errp); - -extern int term_escape_char; - -/* console.c */ -void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp); - -#endif diff --git a/monitor.c b/monitor.c index baa73c98b7..29b71ff2bc 100644 --- a/monitor.c +++ b/monitor.c @@ -35,7 +35,7 @@ #include "exec/gdbstub.h" #include "net/net.h" #include "net/slirp.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "ui/qemu-spice.h" #include "sysemu/numa.h" #include "monitor/monitor.h" diff --git a/net/colo-compare.c b/net/colo-compare.c index 2639c7f0a2..619335d5e8 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -25,7 +25,7 @@ #include "qom/object.h" #include "qemu/typedefs.h" #include "net/queue.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/sockets.h" #include "qapi-visit.h" #include "net/colo.h" diff --git a/net/filter-mirror.c b/net/filter-mirror.c index 8b1b06977d..7adc2c10d2 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -20,7 +20,7 @@ #include "qemu/main-loop.h" #include "qemu/error-report.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/iov.h" #include "qemu/sockets.h" diff --git a/net/slirp.c b/net/slirp.c index c705a60b62..af3e8b22ac 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -37,7 +37,7 @@ #include "qemu/sockets.h" #include "slirp/libslirp.h" #include "slirp/ip6.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "qemu/cutils.h" #include "qapi/error.h" diff --git a/net/vhost-user.c b/net/vhost-user.c index 00a0c1cbc5..77d2ce22a6 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -12,7 +12,7 @@ #include "clients.h" #include "net/vhost_net.h" #include "net/vhost-user.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/config-file.h" #include "qemu/error-report.h" #include "qmp-commands.h" diff --git a/qmp.c b/qmp.c index 84638e2b2b..7ee9bcfdcf 100644 --- a/qmp.c +++ b/qmp.c @@ -21,7 +21,7 @@ #include "qemu/config-file.h" #include "qemu/uuid.h" #include "qmp-commands.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "ui/qemu-spice.h" #include "ui/vnc.h" #include "sysemu/kvm.h" diff --git a/qtest.c b/qtest.c index 5aa6636ca8..dbf70a7018 100644 --- a/qtest.c +++ b/qtest.c @@ -17,7 +17,7 @@ #include "cpu.h" #include "sysemu/qtest.h" #include "hw/qdev.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "exec/ioport.h" #include "exec/memory.h" #include "hw/irq.h" diff --git a/replay/replay-char.c b/replay/replay-char.c index aa65955942..cbf7c04a9f 100755 --- a/replay/replay-char.c +++ b/replay/replay-char.c @@ -14,7 +14,7 @@ #include "sysemu/replay.h" #include "replay-internal.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" /* Char drivers that generate qemu_chr_be_write events that should be saved into the log. */ diff --git a/slirp/slirp.c b/slirp/slirp.c index 2f2ec2c1b3..3b92cb54ce 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -25,7 +25,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "qemu/error-report.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "slirp.h" #include "hw/hw.h" #include "qemu/cutils.h" diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 4d1c76e8a4..1c6c2e3969 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" #include "trace-root.h" #include "ui/qemu-spice.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" #include #include diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c index e86f87656a..8142f2ab90 100644 --- a/tests/postcopy-test.c +++ b/tests/postcopy-test.c @@ -16,7 +16,7 @@ #include "qemu/option.h" #include "qemu/range.h" #include "qemu/sockets.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "hw/nvram/chrp_nvram.h" diff --git a/tests/test-char.c b/tests/test-char.c index 124d0c5439..9340c55058 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "qemu/config-file.h" #include "qemu/sockets.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "qapi/error.h" #include "qom/qom-qobject.h" diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index 9095af267e..acc392d046 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -16,7 +16,7 @@ #include "qemu/option.h" #include "qemu/range.h" #include "qemu/sockets.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/sysemu.h" #include "libqos/libqos.h" #include "libqos/pci-pc.h" diff --git a/ui/console.c b/ui/console.c index ac66b3c910..6cf795a23d 100644 --- a/ui/console.c +++ b/ui/console.c @@ -27,7 +27,7 @@ #include "hw/qdev-core.h" #include "qemu/timer.h" #include "qmp-commands.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "trace.h" #include "exec/memory.h" diff --git a/ui/gtk.c b/ui/gtk.c index 0213ad0efc..5bd87c265a 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -54,7 +54,7 @@ #include "qmp-commands.h" #include "x_keymap.h" #include "keymaps.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qom/object.h" #define MAX_VCS 10 diff --git a/vl.c b/vl.c index 993690d450..8456a94438 100644 --- a/vl.c +++ b/vl.c @@ -81,7 +81,7 @@ int main(int argc, char **argv) #include "sysemu/numa.h" #include "exec/gdbstub.h" #include "qemu/timer.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/bitmap.h" #include "qemu/log.h" #include "sysemu/blockdev.h" -- cgit v1.2.3 From 7566c6efe75572c63a8841fc09d0a8935b188c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 26 Jan 2017 17:33:39 +0400 Subject: chardev: serial & parallel declaration to own headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- backends/wctablet.c | 2 +- hw/arm/strongarm.c | 2 +- hw/bt/hci-csr.c | 2 +- hw/char/cadence_uart.c | 2 +- hw/char/escc.c | 2 +- hw/char/exynos4210_uart.c | 2 +- hw/char/parallel.c | 2 +- hw/char/serial.c | 2 +- hw/usb/dev-serial.c | 2 +- include/chardev/char-parallel.h | 20 +++++++++++++++++++- include/chardev/char-serial.h | 22 ++++++++++++++++++++++ include/chardev/char.h | 36 ------------------------------------ 12 files changed, 50 insertions(+), 46 deletions(-) diff --git a/backends/wctablet.c b/backends/wctablet.c index 07a4cde956..6c13c2c58a 100644 --- a/backends/wctablet.c +++ b/backends/wctablet.c @@ -32,7 +32,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "ui/console.h" #include "ui/input.h" #include "trace.h" diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 66cad198d4..967caea749 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -34,7 +34,7 @@ #include "strongarm.h" #include "qemu/error-report.h" #include "hw/arm/arm.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "sysemu/sysemu.h" #include "hw/ssi/ssi.h" #include "qemu/cutils.h" diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c index cc2087392e..0f2021086d 100644 --- a/hw/bt/hci-csr.c +++ b/hw/bt/hci-csr.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "qemu/timer.h" #include "qemu/bswap.h" #include "hw/irq.h" diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index cf4c1d56ff..4bfc185376 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -23,7 +23,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "qemu/timer.h" #include "qemu/log.h" #include "hw/char/cadence_uart.h" diff --git a/hw/char/escc.c b/hw/char/escc.c index df89d58eed..81d792cb47 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/char/escc.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "ui/console.h" #include "ui/input.h" #include "trace.h" diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 94952fb90f..d93125645a 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -23,7 +23,7 @@ #include "hw/sysbus.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "hw/arm/exynos4210.h" diff --git a/hw/char/parallel.c b/hw/char/parallel.c index c926df0bee..1d6c6e9f33 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "chardev/char.h" +#include "chardev/char-parallel.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" #include "sysemu/sysemu.h" diff --git a/hw/char/serial.c b/hw/char/serial.c index aa336333be..23e5fe9d18 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "hw/char/serial.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" #include "qapi/error.h" #include "qemu/timer.h" #include "exec/address-spaces.h" diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 4df995109b..8baf040b5f 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -15,7 +15,7 @@ #include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "chardev/char.h" +#include "chardev/char-serial.h" //#define DEBUG_Serial diff --git a/include/chardev/char-parallel.h b/include/chardev/char-parallel.h index 26742f9d5c..3284a1b96b 100644 --- a/include/chardev/char-parallel.h +++ b/include/chardev/char-parallel.h @@ -24,9 +24,27 @@ #ifndef CHAR_PARALLEL_H #define CHAR_PARALLEL_H -#if defined(__linux__) || defined(__FreeBSD__) || \ +#include "chardev/char.h" + +#if defined(__linux__) || defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || defined(__DragonFly__) #define HAVE_CHARDEV_PARPORT 1 #endif +#define CHR_IOCTL_PP_READ_DATA 3 +#define CHR_IOCTL_PP_WRITE_DATA 4 +#define CHR_IOCTL_PP_READ_CONTROL 5 +#define CHR_IOCTL_PP_WRITE_CONTROL 6 +#define CHR_IOCTL_PP_READ_STATUS 7 +#define CHR_IOCTL_PP_EPP_READ_ADDR 8 +#define CHR_IOCTL_PP_EPP_READ 9 +#define CHR_IOCTL_PP_EPP_WRITE_ADDR 10 +#define CHR_IOCTL_PP_EPP_WRITE 11 +#define CHR_IOCTL_PP_DATA_DIR 12 + +struct ParallelIOArg { + void *buffer; + int count; +}; + #endif /* CHAR_PARALLEL_H */ diff --git a/include/chardev/char-serial.h b/include/chardev/char-serial.h index 64a27f63b1..cb2e59e82a 100644 --- a/include/chardev/char-serial.h +++ b/include/chardev/char-serial.h @@ -24,6 +24,8 @@ #ifndef CHAR_SERIAL_H #define CHAR_SERIAL_H +#include "chardev/char.h" + #ifdef _WIN32 #define HAVE_CHARDEV_SERIAL 1 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ @@ -32,4 +34,24 @@ #define HAVE_CHARDEV_SERIAL 1 #endif +#define CHR_IOCTL_SERIAL_SET_PARAMS 1 +typedef struct { + int speed; + int parity; + int data_bits; + int stop_bits; +} QEMUSerialSetParams; + +#define CHR_IOCTL_SERIAL_SET_BREAK 2 + +#define CHR_IOCTL_SERIAL_SET_TIOCM 13 +#define CHR_IOCTL_SERIAL_GET_TIOCM 14 + +#define CHR_TIOCM_CTS 0x020 +#define CHR_TIOCM_CAR 0x040 +#define CHR_TIOCM_DSR 0x100 +#define CHR_TIOCM_RI 0x080 +#define CHR_TIOCM_DTR 0x002 +#define CHR_TIOCM_RTS 0x004 + #endif diff --git a/include/chardev/char.h b/include/chardev/char.h index fffc0f40d4..95273e10ae 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -27,42 +27,6 @@ typedef enum { #define CHR_READ_BUF_LEN 4096 -#define CHR_IOCTL_SERIAL_SET_PARAMS 1 -typedef struct { - int speed; - int parity; - int data_bits; - int stop_bits; -} QEMUSerialSetParams; - -#define CHR_IOCTL_SERIAL_SET_BREAK 2 - -#define CHR_IOCTL_PP_READ_DATA 3 -#define CHR_IOCTL_PP_WRITE_DATA 4 -#define CHR_IOCTL_PP_READ_CONTROL 5 -#define CHR_IOCTL_PP_WRITE_CONTROL 6 -#define CHR_IOCTL_PP_READ_STATUS 7 -#define CHR_IOCTL_PP_EPP_READ_ADDR 8 -#define CHR_IOCTL_PP_EPP_READ 9 -#define CHR_IOCTL_PP_EPP_WRITE_ADDR 10 -#define CHR_IOCTL_PP_EPP_WRITE 11 -#define CHR_IOCTL_PP_DATA_DIR 12 - -struct ParallelIOArg { - void *buffer; - int count; -}; - -#define CHR_IOCTL_SERIAL_SET_TIOCM 13 -#define CHR_IOCTL_SERIAL_GET_TIOCM 14 - -#define CHR_TIOCM_CTS 0x020 -#define CHR_TIOCM_CAR 0x040 -#define CHR_TIOCM_DSR 0x100 -#define CHR_TIOCM_RI 0x080 -#define CHR_TIOCM_DTR 0x002 -#define CHR_TIOCM_RTS 0x004 - typedef void IOEventHandler(void *opaque, int event); typedef enum { -- cgit v1.2.3 From 93a78e41242ba164ae6af1690ea68fe22165ad4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 26 Jan 2017 17:55:04 +0400 Subject: be-hci: use backend functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid accessing CharBackend directly, use qemu_chr_be_* methods instead. be->chr_read should exists if qemu_chr_be_can_write() is true. (use qemu_chr_be_write(), _impl() bypasses replay) Signed-off-by: Marc-André Lureau Reviewed-by: Andrzej Zaborowski --- hw/bt/hci-csr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c index 0f2021086d..d13192b9b5 100644 --- a/hw/bt/hci-csr.c +++ b/hw/bt/hci-csr.c @@ -82,17 +82,14 @@ enum { static inline void csrhci_fifo_wake(struct csrhci_s *s) { - Chardev *chr = (Chardev *)s; - CharBackend *be = chr->be; + Chardev *chr = CHARDEV(s); if (!s->enable || !s->out_len) return; /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */ - if (be && be->chr_can_read && be->chr_can_read(be->opaque) && - be->chr_read) { - be->chr_read(be->opaque, - s->outfifo + s->out_start++, 1); + if (qemu_chr_be_can_write(chr)) { + qemu_chr_be_write(chr, s->outfifo + s->out_start++, 1); s->out_len--; if (s->out_start >= s->out_size) { s->out_start = 0; -- cgit v1.2.3 From c90e9392efa6579e714fe9aa2993e7d89e3792dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 26 Jan 2017 22:48:37 +0400 Subject: char: generalize qemu_chr_write_all() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_chr_fe_write() is similar to qemu_chr_write_all(): the later write all with a chardev backend. Make qemu_chr_write() and qemu_chr_fe_write_buffer() take an 'all' argument. If false, handle 'partial' write the way qemu_chr_fe_write() use to, and call qemu_chr_write() from qemu_chr_fe_write(). Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char.c | 70 +++++++++++++++++++++++----------------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/chardev/char.c b/chardev/char.c index 02142b480e..c9e46f00f0 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -96,7 +96,8 @@ static void qemu_chr_fe_write_log(Chardev *s, } static int qemu_chr_fe_write_buffer(Chardev *s, - const uint8_t *buf, int len, int *offset) + const uint8_t *buf, int len, + int *offset, bool write_all) { ChardevClass *cc = CHARDEV_GET_CLASS(s); int res = 0; @@ -106,7 +107,7 @@ static int qemu_chr_fe_write_buffer(Chardev *s, while (*offset < len) { retry: res = cc->chr_write(s, buf + *offset, len - *offset); - if (res < 0 && errno == EAGAIN) { + if (res < 0 && errno == EAGAIN && write_all) { g_usleep(100); goto retry; } @@ -116,6 +117,9 @@ static int qemu_chr_fe_write_buffer(Chardev *s, } *offset += res; + if (!write_all) { + break; + } } if (*offset > 0) { qemu_chr_fe_write_log(s, buf, *offset); @@ -130,54 +134,20 @@ static bool qemu_chr_replay(Chardev *chr) return qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_REPLAY); } -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) +static int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, + bool write_all) { - Chardev *s = be->chr; - ChardevClass *cc; - int ret; - - if (!s) { - return 0; - } - - if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) { - int offset; - replay_char_write_event_load(&ret, &offset); - assert(offset <= len); - qemu_chr_fe_write_buffer(s, buf, offset, &offset); - return ret; - } - - cc = CHARDEV_GET_CLASS(s); - qemu_mutex_lock(&s->chr_write_lock); - ret = cc->chr_write(s, buf, len); - - if (ret > 0) { - qemu_chr_fe_write_log(s, buf, ret); - } - - qemu_mutex_unlock(&s->chr_write_lock); - - if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { - replay_char_write_event_save(ret, ret < 0 ? 0 : ret); - } - - return ret; -} - -int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len) -{ - int offset; + int offset = 0; int res; if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) { replay_char_write_event_load(&res, &offset); assert(offset <= len); - qemu_chr_fe_write_buffer(s, buf, offset, &offset); + qemu_chr_fe_write_buffer(s, buf, offset, &offset, true); return res; } - res = qemu_chr_fe_write_buffer(s, buf, len, &offset); + res = qemu_chr_fe_write_buffer(s, buf, len, &offset, write_all); if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { replay_char_write_event_save(res, offset); @@ -189,6 +159,22 @@ int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len) return offset; } +int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len) +{ + return qemu_chr_write(s, buf, len, true); +} + +int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) +{ + Chardev *s = be->chr; + + if (!s) { + return 0; + } + + return qemu_chr_write(s, buf, len, false); +} + int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) { Chardev *s = be->chr; @@ -197,7 +183,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) return 0; } - return qemu_chr_write_all(s, buf, len); + return qemu_chr_write(s, buf, len, true); } int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) -- cgit v1.2.3 From 4d43a603c71d0eb92534bc82b72933f329d8a64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 26 Jan 2017 18:26:44 +0400 Subject: char: move CharBackend handling in char-fe unit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move all the frontend struct and methods to a seperate unit. This avoids accidentally mixing backend and frontend calls, and helps with readabilty. Make qemu_chr_replay() a macro shared by both char and char-fe. Export qemu_chr_write(), and use a macro for qemu_chr_write_all() (nb: yes, CharBackend is for char frontend :) Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- backends/rng-egd.c | 2 +- chardev/Makefile.objs | 1 + chardev/char-fe.c | 358 ++++++++++++++++++++++++++++++++++++++ chardev/char.c | 343 +----------------------------------- gdbstub.c | 1 + hw/arm/omap2.c | 2 +- hw/arm/pxa2xx.c | 2 +- hw/arm/strongarm.c | 1 + hw/char/cadence_uart.c | 1 + hw/char/debugcon.c | 2 +- hw/char/digic-uart.c | 2 +- hw/char/escc.c | 1 + hw/char/etraxfs_ser.c | 2 +- hw/char/exynos4210_uart.c | 1 + hw/char/grlib_apbuart.c | 2 +- hw/char/ipoctal232.c | 2 +- hw/char/lm32_juart.c | 2 +- hw/char/lm32_uart.c | 2 +- hw/char/mcf_uart.c | 2 +- hw/char/milkymist-uart.c | 2 +- hw/char/parallel.c | 1 + hw/char/pl011.c | 2 +- hw/char/sclpconsole-lm.c | 2 +- hw/char/sclpconsole.c | 2 +- hw/char/sh_serial.c | 2 +- hw/char/spapr_vty.c | 2 +- hw/char/terminal3270.c | 2 +- hw/char/virtio-console.c | 2 +- hw/char/xen_console.c | 2 +- hw/char/xilinx_uartlite.c | 2 +- hw/core/qdev-properties-system.c | 2 +- hw/ipmi/ipmi_bmc_extern.c | 2 +- hw/misc/ivshmem.c | 2 +- hw/usb/ccid-card-passthru.c | 2 +- hw/usb/dev-serial.c | 1 + hw/usb/redirect.c | 2 +- hw/virtio/vhost-user.c | 2 +- include/chardev/char-fe.h | 249 ++++++++++++++++++++++++++ include/chardev/char-mux.h | 1 + include/chardev/char.h | 242 +------------------------- include/hw/char/bcm2835_aux.h | 2 +- include/hw/char/cadence_uart.h | 2 +- include/hw/char/digic-uart.h | 2 +- include/hw/char/imx_serial.h | 2 +- include/hw/char/serial.h | 2 +- include/hw/char/stm32f2xx_usart.h | 2 +- monitor.c | 2 +- net/colo-compare.c | 2 +- net/filter-mirror.c | 2 +- net/slirp.c | 2 +- net/vhost-user.c | 2 +- qtest.c | 2 +- slirp/slirp.c | 2 +- tests/test-char.c | 2 +- tests/vhost-user-test.c | 2 +- ui/console.c | 2 +- 56 files changed, 664 insertions(+), 623 deletions(-) create mode 100644 chardev/char-fe.c create mode 100644 include/chardev/char-fe.h diff --git a/backends/rng-egd.c b/backends/rng-egd.c index 5448f6e5f5..ad3e1e5edf 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -12,7 +12,7 @@ #include "qemu/osdep.h" #include "sysemu/rng.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs index 1feda0f0ed..e0b37dbfd8 100644 --- a/chardev/Makefile.objs +++ b/chardev/Makefile.objs @@ -1,6 +1,7 @@ chardev-obj-y += char.o chardev-obj-$(CONFIG_WIN32) += char-console.o chardev-obj-$(CONFIG_POSIX) += char-fd.o +chardev-obj-y += char-fe.o chardev-obj-y += char-file.o chardev-obj-y += char-io.o chardev-obj-y += char-mux.o diff --git a/chardev/char-fe.c b/chardev/char-fe.c new file mode 100644 index 0000000000..341221d029 --- /dev/null +++ b/chardev/char-fe.c @@ -0,0 +1,358 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi-visit.h" +#include "sysemu/replay.h" + +#include "chardev/char-fe.h" +#include "chardev/char-io.h" +#include "chardev/char-mux.h" + +int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) +{ + Chardev *s = be->chr; + + if (!s) { + return 0; + } + + return qemu_chr_write(s, buf, len, false); +} + +int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) +{ + Chardev *s = be->chr; + + if (!s) { + return 0; + } + + return qemu_chr_write(s, buf, len, true); +} + +int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) +{ + Chardev *s = be->chr; + int offset = 0, counter = 10; + int res; + + if (!s || !CHARDEV_GET_CLASS(s)->chr_sync_read) { + return 0; + } + + if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) { + return replay_char_read_all_load(buf); + } + + while (offset < len) { + retry: + res = CHARDEV_GET_CLASS(s)->chr_sync_read(s, buf + offset, + len - offset); + if (res == -1 && errno == EAGAIN) { + g_usleep(100); + goto retry; + } + + if (res == 0) { + break; + } + + if (res < 0) { + if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { + replay_char_read_all_save_error(res); + } + return res; + } + + offset += res; + + if (!counter--) { + break; + } + } + + if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { + replay_char_read_all_save_buf(buf, offset); + } + return offset; +} + +int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg) +{ + Chardev *s = be->chr; + int res; + + if (!s || !CHARDEV_GET_CLASS(s)->chr_ioctl || qemu_chr_replay(s)) { + res = -ENOTSUP; + } else { + res = CHARDEV_GET_CLASS(s)->chr_ioctl(s, cmd, arg); + } + + return res; +} + +int qemu_chr_fe_get_msgfd(CharBackend *be) +{ + Chardev *s = be->chr; + int fd; + int res = (qemu_chr_fe_get_msgfds(be, &fd, 1) == 1) ? fd : -1; + if (s && qemu_chr_replay(s)) { + error_report("Replay: get msgfd is not supported " + "for serial devices yet"); + exit(1); + } + return res; +} + +int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int len) +{ + Chardev *s = be->chr; + + if (!s) { + return -1; + } + + return CHARDEV_GET_CLASS(s)->get_msgfds ? + CHARDEV_GET_CLASS(s)->get_msgfds(s, fds, len) : -1; +} + +int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num) +{ + Chardev *s = be->chr; + + if (!s) { + return -1; + } + + return CHARDEV_GET_CLASS(s)->set_msgfds ? + CHARDEV_GET_CLASS(s)->set_msgfds(s, fds, num) : -1; +} + +void qemu_chr_fe_accept_input(CharBackend *be) +{ + Chardev *s = be->chr; + + if (!s) { + return; + } + + if (CHARDEV_GET_CLASS(s)->chr_accept_input) { + CHARDEV_GET_CLASS(s)->chr_accept_input(s); + } + qemu_notify_event(); +} + +void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) +{ + char buf[CHR_READ_BUF_LEN]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(be, (uint8_t *)buf, strlen(buf)); + va_end(ap); +} + +Chardev *qemu_chr_fe_get_driver(CharBackend *be) +{ + return be->chr; +} + +bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) +{ + int tag = 0; + + if (CHARDEV_IS_MUX(s)) { + MuxChardev *d = MUX_CHARDEV(s); + + if (d->mux_cnt >= MAX_MUX) { + goto unavailable; + } + + d->backends[d->mux_cnt] = b; + tag = d->mux_cnt++; + } else if (s->be) { + goto unavailable; + } else { + s->be = b; + } + + b->fe_open = false; + b->tag = tag; + b->chr = s; + return true; + +unavailable: + error_setg(errp, QERR_DEVICE_IN_USE, s->label); + return false; +} + +void qemu_chr_fe_deinit(CharBackend *b) +{ + assert(b); + + if (b->chr) { + qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true); + if (b->chr->be == b) { + b->chr->be = NULL; + } + if (CHARDEV_IS_MUX(b->chr)) { + MuxChardev *d = MUX_CHARDEV(b->chr); + d->backends[b->tag] = NULL; + } + b->chr = NULL; + } +} + +void qemu_chr_fe_set_handlers(CharBackend *b, + IOCanReadHandler *fd_can_read, + IOReadHandler *fd_read, + IOEventHandler *fd_event, + void *opaque, + GMainContext *context, + bool set_open) +{ + Chardev *s; + ChardevClass *cc; + int fe_open; + + s = b->chr; + if (!s) { + return; + } + + cc = CHARDEV_GET_CLASS(s); + if (!opaque && !fd_can_read && !fd_read && !fd_event) { + fe_open = 0; + remove_fd_in_watch(s); + } else { + fe_open = 1; + } + b->chr_can_read = fd_can_read; + b->chr_read = fd_read; + b->chr_event = fd_event; + b->opaque = opaque; + if (cc->chr_update_read_handler) { + cc->chr_update_read_handler(s, context); + } + + if (set_open) { + qemu_chr_fe_set_open(b, fe_open); + } + + if (fe_open) { + qemu_chr_fe_take_focus(b); + /* We're connecting to an already opened device, so let's make sure we + also get the open event */ + if (s->be_open) { + qemu_chr_be_event(s, CHR_EVENT_OPENED); + } + } + + if (CHARDEV_IS_MUX(s)) { + mux_chr_set_handlers(s, context); + } +} + +void qemu_chr_fe_take_focus(CharBackend *b) +{ + if (!b->chr) { + return; + } + + if (CHARDEV_IS_MUX(b->chr)) { + mux_set_focus(b->chr, b->tag); + } +} + +int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp) +{ + if (!be->chr) { + error_setg(errp, "missing associated backend"); + return -1; + } + + return qemu_chr_wait_connected(be->chr, errp); +} + +void qemu_chr_fe_set_echo(CharBackend *be, bool echo) +{ + Chardev *chr = be->chr; + + if (chr && CHARDEV_GET_CLASS(chr)->chr_set_echo) { + CHARDEV_GET_CLASS(chr)->chr_set_echo(chr, echo); + } +} + +void qemu_chr_fe_set_open(CharBackend *be, int fe_open) +{ + Chardev *chr = be->chr; + + if (!chr) { + return; + } + + if (be->fe_open == fe_open) { + return; + } + be->fe_open = fe_open; + if (CHARDEV_GET_CLASS(chr)->chr_set_fe_open) { + CHARDEV_GET_CLASS(chr)->chr_set_fe_open(chr, fe_open); + } +} + +guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, + GIOFunc func, void *user_data) +{ + Chardev *s = be->chr; + GSource *src; + guint tag; + + if (!s || CHARDEV_GET_CLASS(s)->chr_add_watch == NULL) { + return 0; + } + + src = CHARDEV_GET_CLASS(s)->chr_add_watch(s, cond); + if (!src) { + return 0; + } + + g_source_set_callback(src, (GSourceFunc)func, user_data, NULL); + tag = g_source_attach(src, NULL); + g_source_unref(src); + + return tag; +} + +void qemu_chr_fe_disconnect(CharBackend *be) +{ + Chardev *chr = be->chr; + + if (chr && CHARDEV_GET_CLASS(chr)->chr_disconnect) { + CHARDEV_GET_CLASS(chr)->chr_disconnect(chr); + } +} diff --git a/chardev/char.c b/chardev/char.c index c9e46f00f0..8ea7b5777a 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "qemu-common.h" #include "qemu/cutils.h" #include "monitor/monitor.h" #include "sysemu/sysemu.h" @@ -35,9 +34,6 @@ #include "qemu/help_option.h" #include "chardev/char-mux.h" -#include "chardev/char-io.h" -#include "chardev/char-parallel.h" -#include "chardev/char-serial.h" /***********************************************************/ /* character device */ @@ -129,13 +125,7 @@ static int qemu_chr_fe_write_buffer(Chardev *s, return res; } -static bool qemu_chr_replay(Chardev *chr) -{ - return qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_REPLAY); -} - -static int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, - bool write_all) +int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all) { int offset = 0; int res; @@ -159,94 +149,6 @@ static int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, return offset; } -int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len) -{ - return qemu_chr_write(s, buf, len, true); -} - -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) -{ - Chardev *s = be->chr; - - if (!s) { - return 0; - } - - return qemu_chr_write(s, buf, len, false); -} - -int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) -{ - Chardev *s = be->chr; - - if (!s) { - return 0; - } - - return qemu_chr_write(s, buf, len, true); -} - -int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) -{ - Chardev *s = be->chr; - int offset = 0, counter = 10; - int res; - - if (!s || !CHARDEV_GET_CLASS(s)->chr_sync_read) { - return 0; - } - - if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) { - return replay_char_read_all_load(buf); - } - - while (offset < len) { - retry: - res = CHARDEV_GET_CLASS(s)->chr_sync_read(s, buf + offset, - len - offset); - if (res == -1 && errno == EAGAIN) { - g_usleep(100); - goto retry; - } - - if (res == 0) { - break; - } - - if (res < 0) { - if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { - replay_char_read_all_save_error(res); - } - return res; - } - - offset += res; - - if (!counter--) { - break; - } - } - - if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { - replay_char_read_all_save_buf(buf, offset); - } - return offset; -} - -int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg) -{ - Chardev *s = be->chr; - int res; - - if (!s || !CHARDEV_GET_CLASS(s)->chr_ioctl || qemu_chr_replay(s)) { - res = -ENOTSUP; - } else { - res = CHARDEV_GET_CLASS(s)->chr_ioctl(s, cmd, arg); - } - - return res; -} - int qemu_chr_be_can_write(Chardev *s) { CharBackend *be = s->be; @@ -279,75 +181,12 @@ void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len) } } -int qemu_chr_fe_get_msgfd(CharBackend *be) -{ - Chardev *s = be->chr; - int fd; - int res = (qemu_chr_fe_get_msgfds(be, &fd, 1) == 1) ? fd : -1; - if (s && qemu_chr_replay(s)) { - error_report("Replay: get msgfd is not supported " - "for serial devices yet"); - exit(1); - } - return res; -} - -int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int len) -{ - Chardev *s = be->chr; - - if (!s) { - return -1; - } - - return CHARDEV_GET_CLASS(s)->get_msgfds ? - CHARDEV_GET_CLASS(s)->get_msgfds(s, fds, len) : -1; -} - -int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num) -{ - Chardev *s = be->chr; - - if (!s) { - return -1; - } - - return CHARDEV_GET_CLASS(s)->set_msgfds ? - CHARDEV_GET_CLASS(s)->set_msgfds(s, fds, num) : -1; -} - int qemu_chr_add_client(Chardev *s, int fd) { return CHARDEV_GET_CLASS(s)->chr_add_client ? CHARDEV_GET_CLASS(s)->chr_add_client(s, fd) : -1; } -void qemu_chr_fe_accept_input(CharBackend *be) -{ - Chardev *s = be->chr; - - if (!s) { - return; - } - - if (CHARDEV_GET_CLASS(s)->chr_accept_input) { - CHARDEV_GET_CLASS(s)->chr_accept_input(s); - } - qemu_notify_event(); -} - -void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) -{ - char buf[CHR_READ_BUF_LEN]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - /* XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks */ - qemu_chr_fe_write_all(be, (uint8_t *)buf, strlen(buf)); - va_end(ap); -} - static void qemu_char_open(Chardev *chr, ChardevBackend *backend, bool *be_opened, Error **errp) { @@ -459,40 +298,6 @@ static Notifier muxes_realize_notify = { .notify = muxes_realize_done, }; -Chardev *qemu_chr_fe_get_driver(CharBackend *be) -{ - return be->chr; -} - -bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) -{ - int tag = 0; - - if (CHARDEV_IS_MUX(s)) { - MuxChardev *d = MUX_CHARDEV(s); - - if (d->mux_cnt >= MAX_MUX) { - goto unavailable; - } - - d->backends[d->mux_cnt] = b; - tag = d->mux_cnt++; - } else if (s->be) { - goto unavailable; - } else { - s->be = b; - } - - b->fe_open = false; - b->tag = tag; - b->chr = s; - return true; - -unavailable: - error_setg(errp, QERR_DEVICE_IN_USE, s->label); - return false; -} - static bool qemu_chr_is_busy(Chardev *s) { if (CHARDEV_IS_MUX(s)) { @@ -503,84 +308,6 @@ static bool qemu_chr_is_busy(Chardev *s) } } -void qemu_chr_fe_deinit(CharBackend *b) -{ - assert(b); - - if (b->chr) { - qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true); - if (b->chr->be == b) { - b->chr->be = NULL; - } - if (CHARDEV_IS_MUX(b->chr)) { - MuxChardev *d = MUX_CHARDEV(b->chr); - d->backends[b->tag] = NULL; - } - b->chr = NULL; - } -} - -void qemu_chr_fe_set_handlers(CharBackend *b, - IOCanReadHandler *fd_can_read, - IOReadHandler *fd_read, - IOEventHandler *fd_event, - void *opaque, - GMainContext *context, - bool set_open) -{ - Chardev *s; - ChardevClass *cc; - int fe_open; - - s = b->chr; - if (!s) { - return; - } - - cc = CHARDEV_GET_CLASS(s); - if (!opaque && !fd_can_read && !fd_read && !fd_event) { - fe_open = 0; - remove_fd_in_watch(s); - } else { - fe_open = 1; - } - b->chr_can_read = fd_can_read; - b->chr_read = fd_read; - b->chr_event = fd_event; - b->opaque = opaque; - if (cc->chr_update_read_handler) { - cc->chr_update_read_handler(s, context); - } - - if (set_open) { - qemu_chr_fe_set_open(b, fe_open); - } - - if (fe_open) { - qemu_chr_fe_take_focus(b); - /* We're connecting to an already opened device, so let's make sure we - also get the open event */ - if (s->be_open) { - qemu_chr_be_event(s, CHR_EVENT_OPENED); - } - } - - if (CHARDEV_IS_MUX(s)) { - mux_chr_set_handlers(s, context); - } -} - -void qemu_chr_fe_take_focus(CharBackend *b) -{ - if (!b->chr) { - return; - } - - if (CHARDEV_IS_MUX(b->chr)) { - mux_set_focus(b->chr, b->tag); - } -} - int qemu_chr_wait_connected(Chardev *chr, Error **errp) { ChardevClass *cc = CHARDEV_GET_CLASS(chr); @@ -592,16 +319,6 @@ int qemu_chr_wait_connected(Chardev *chr, Error **errp) return 0; } -int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp) -{ - if (!be->chr) { - error_setg(errp, "missing associated backend"); - return -1; - } - - return qemu_chr_wait_connected(be->chr, errp); -} - QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) { char host[65], port[33], width[8], height[8]; @@ -978,64 +695,6 @@ Chardev *qemu_chr_new(const char *label, const char *filename) return chr; } -void qemu_chr_fe_set_echo(CharBackend *be, bool echo) -{ - Chardev *chr = be->chr; - - if (chr && CHARDEV_GET_CLASS(chr)->chr_set_echo) { - CHARDEV_GET_CLASS(chr)->chr_set_echo(chr, echo); - } -} - -void qemu_chr_fe_set_open(CharBackend *be, int fe_open) -{ - Chardev *chr = be->chr; - - if (!chr) { - return; - } - - if (be->fe_open == fe_open) { - return; - } - be->fe_open = fe_open; - if (CHARDEV_GET_CLASS(chr)->chr_set_fe_open) { - CHARDEV_GET_CLASS(chr)->chr_set_fe_open(chr, fe_open); - } -} - -guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, - GIOFunc func, void *user_data) -{ - Chardev *s = be->chr; - GSource *src; - guint tag; - - if (!s || CHARDEV_GET_CLASS(s)->chr_add_watch == NULL) { - return 0; - } - - src = CHARDEV_GET_CLASS(s)->chr_add_watch(s, cond); - if (!src) { - return 0; - } - - g_source_set_callback(src, (GSourceFunc)func, user_data, NULL); - tag = g_source_attach(src, NULL); - g_source_unref(src); - - return tag; -} - -void qemu_chr_fe_disconnect(CharBackend *be) -{ - Chardev *chr = be->chr; - - if (chr && CHARDEV_GET_CLASS(chr)->chr_disconnect) { - CHARDEV_GET_CLASS(chr)->chr_disconnect(chr); - } -} - static int qmp_query_chardev_foreach(Object *obj, void *data) { Chardev *chr = CHARDEV(obj); diff --git a/gdbstub.c b/gdbstub.c index 6515c635dc..4251d23898 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -26,6 +26,7 @@ #else #include "monitor/monitor.h" #include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "exec/gdbstub.h" #endif diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 9eabbaeea5..91f573338c 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -30,7 +30,7 @@ #include "hw/arm/omap.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/block/flash.h" #include "hw/arm/soc_dma.h" #include "hw/sysbus.h" diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 0d43cc707c..629e6c64e6 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -17,7 +17,7 @@ #include "hw/char/serial.h" #include "hw/i2c/i2c.h" #include "hw/ssi/ssi.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qemu/cutils.h" diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 967caea749..7683edc9e5 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -34,6 +34,7 @@ #include "strongarm.h" #include "qemu/error-report.h" #include "hw/arm/arm.h" +#include "chardev/char-fe.h" #include "chardev/char-serial.h" #include "sysemu/sysemu.h" #include "hw/ssi/ssi.h" diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 4bfc185376..4a2c124104 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -23,6 +23,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "chardev/char-fe.h" #include "chardev/char-serial.h" #include "qemu/timer.h" #include "qemu/log.h" diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index 77d91c8558..762e3d8ada 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c index 4f1dec7f1d..34306e11ff 100644 --- a/hw/char/digic-uart.c +++ b/hw/char/digic-uart.c @@ -29,7 +29,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/log.h" #include "hw/char/digic-uart.h" diff --git a/hw/char/escc.c b/hw/char/escc.c index 81d792cb47..3f787632c7 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -26,6 +26,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/char/escc.h" +#include "chardev/char-fe.h" #include "chardev/char-serial.h" #include "ui/console.h" #include "ui/input.h" diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 33e3e16397..c1fba9f50f 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/log.h" #define D(x) diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index d93125645a..b51d44a321 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -23,6 +23,7 @@ #include "hw/sysbus.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" +#include "chardev/char-fe.h" #include "chardev/char-serial.h" #include "hw/arm/exynos4210.h" diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index 39d1133c61..32d98edf49 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "trace.h" diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index b8a3c92c9e..337a3e566a 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "hw/ipack/ipack.h" #include "qemu/bitops.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" /* #define DEBUG_IPOCTAL */ diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c index 6b0633e518..3948dcd332 100644 --- a/hw/char/lm32_juart.c +++ b/hw/char/lm32_juart.c @@ -21,7 +21,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/char/lm32_juart.h" diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index a7610c28ce..cff8c38f90 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" enum { diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index b639b53c83..fe12ad5ccb 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -9,7 +9,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/m68k/mcf.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "exec/address-spaces.h" #include "qapi/error.h" diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index 5ef847c5eb..e19d0f6520 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -25,7 +25,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" enum { diff --git a/hw/char/parallel.c b/hw/char/parallel.c index 1d6c6e9f33..75a1a2f55e 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -26,6 +26,7 @@ #include "qapi/error.h" #include "hw/hw.h" #include "chardev/char-parallel.h" +#include "chardev/char-fe.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" #include "sysemu/sysemu.h" diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 1757035bb3..33802f00c8 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -9,7 +9,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/log.h" #include "trace.h" diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 755d514188..1b15046690 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -17,7 +17,7 @@ #include "hw/qdev.h" #include "qemu/thread.h" #include "qemu/error-report.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 0fd3cb4887..4a107a268d 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -19,7 +19,7 @@ #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" typedef struct ASCIIConsoleData { EventBufferHeader ebh; diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 80c7696d8d..ca9816d045 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sh4/sh.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "exec/address-spaces.h" #include "qapi/error.h" diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index 2317e45404..8f02f3a612 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/qdev.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c index c043104185..7b10a04f18 100644 --- a/hw/char/terminal3270.c +++ b/hw/char/terminal3270.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/s390x/3270-ccw.h" /* Enough spaces for different window sizes. */ diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 8418db6a07..0cb1668c8a 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" #include "trace.h" #include "hw/virtio/virtio-serial.h" diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index 1cdbe59f8a..cb849c2e3e 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -25,7 +25,7 @@ #include "qapi/error.h" #include "hw/hw.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/xen/xen_backend.h" #include "qapi/error.h" diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index bcebdae3da..71ed2fc1be 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #define DUART(x) diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 4da0c6a24e..a549d39030 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -20,7 +20,7 @@ #include "hw/block/block.h" #include "net/hub.h" #include "qapi/visitor.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/iothread.h" static void get_pointer(Object *obj, Visitor *v, Property *prop, diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index 35285383fd..329b03e17f 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -30,7 +30,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/timer.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "hw/ipmi/ipmi.h" diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index cd064dcf8c..6367d041f0 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -29,7 +29,7 @@ #include "qemu/error-report.h" #include "qemu/event_notifier.h" #include "qom/object_interfaces.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/hostmem.h" #include "sysemu/qtest.h" #include "qapi/visitor.h" diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index c2096b25ab..fed3683a50 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -9,7 +9,7 @@ */ #include "qemu/osdep.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" #include "qemu/sockets.h" #include "ccid.h" diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 8baf040b5f..bfbf7cdce7 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -16,6 +16,7 @@ #include "hw/usb.h" #include "hw/usb/desc.h" #include "chardev/char-serial.h" +#include "chardev/char-fe.h" //#define DEBUG_Serial diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index c862c1adea..d2b3a84a03 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -33,7 +33,7 @@ #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "qemu/iov.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include #include diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 44c9d8c954..0aa446eb91 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -13,7 +13,7 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-backend.h" #include "hw/virtio/virtio-net.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/kvm.h" #include "qemu/error-report.h" #include "qemu/sockets.h" diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h new file mode 100644 index 0000000000..bd82093218 --- /dev/null +++ b/include/chardev/char-fe.h @@ -0,0 +1,249 @@ +#ifndef QEMU_CHAR_FE_H +#define QEMU_CHAR_FE_H + +#include "chardev/char.h" + +typedef void IOEventHandler(void *opaque, int event); + +/* This is the backend as seen by frontend, the actual backend is + * Chardev */ +struct CharBackend { + Chardev *chr; + IOEventHandler *chr_event; + IOCanReadHandler *chr_can_read; + IOReadHandler *chr_read; + void *opaque; + int tag; + int fe_open; +}; + +/** + * @qemu_chr_fe_init: + * + * Initializes a front end for the given CharBackend and + * Chardev. Call qemu_chr_fe_deinit() to remove the association and + * release the driver. + * + * Returns: false on error. + */ +bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); + +/** + * @qemu_chr_fe_deinit: + * + * Dissociate the CharBackend from the Chardev. + * + * Safe to call without associated Chardev. + */ +void qemu_chr_fe_deinit(CharBackend *b); + +/** + * @qemu_chr_fe_get_driver: + * + * Returns the driver associated with a CharBackend or NULL if no + * associated Chardev. + */ +Chardev *qemu_chr_fe_get_driver(CharBackend *be); + +/** + * @qemu_chr_fe_set_handlers: + * @b: a CharBackend + * @fd_can_read: callback to get the amount of data the frontend may + * receive + * @fd_read: callback to receive data from char + * @fd_event: event callback + * @opaque: an opaque pointer for the callbacks + * @context: a main loop context or NULL for the default + * @set_open: whether to call qemu_chr_fe_set_open() implicitely when + * any of the handler is non-NULL + * + * Set the front end char handlers. The front end takes the focus if + * any of the handler is non-NULL. + * + * Without associated Chardev, nothing is changed. + */ +void qemu_chr_fe_set_handlers(CharBackend *b, + IOCanReadHandler *fd_can_read, + IOReadHandler *fd_read, + IOEventHandler *fd_event, + void *opaque, + GMainContext *context, + bool set_open); + +/** + * @qemu_chr_fe_take_focus: + * + * Take the focus (if the front end is muxed). + * + * Without associated Chardev, nothing is changed. + */ +void qemu_chr_fe_take_focus(CharBackend *b); + +/** + * @qemu_chr_fe_accept_input: + * + * Notify that the frontend is ready to receive data + */ +void qemu_chr_fe_accept_input(CharBackend *be); + +/** + * @qemu_chr_fe_disconnect: + * + * Close a fd accpeted by character backend. + * Without associated Chardev, do nothing. + */ +void qemu_chr_fe_disconnect(CharBackend *be); + +/** + * @qemu_chr_fe_wait_connected: + * + * Wait for characted backend to be connected, return < 0 on error or + * if no assicated Chardev. + */ +int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); + +/** + * @qemu_chr_fe_set_echo: + * + * Ask the backend to override its normal echo setting. This only really + * applies to the stdio backend and is used by the QMP server such that you + * can see what you type if you try to type QMP commands. + * Without associated Chardev, do nothing. + * + * @echo true to enable echo, false to disable echo + */ +void qemu_chr_fe_set_echo(CharBackend *be, bool echo); + +/** + * @qemu_chr_fe_set_open: + * + * Set character frontend open status. This is an indication that the + * front end is ready (or not) to begin doing I/O. + * Without associated Chardev, do nothing. + */ +void qemu_chr_fe_set_open(CharBackend *be, int fe_open); + +/** + * @qemu_chr_fe_printf: + * + * Write to a character backend using a printf style interface. This + * function is thread-safe. It does nothing without associated + * Chardev. + * + * @fmt see #printf + */ +void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); + +/** + * @qemu_chr_fe_add_watch: + * + * If the backend is connected, create and add a #GSource that fires + * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP) + * is active; return the #GSource's tag. If it is disconnected, + * or without associated Chardev, return 0. + * + * @cond the condition to poll for + * @func the function to call when the condition happens + * @user_data the opaque pointer to pass to @func + * + * Returns: the source tag + */ +guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, + GIOFunc func, void *user_data); + +/** + * @qemu_chr_fe_write: + * + * Write data to a character backend from the front end. This function + * will send data from the front end to the back end. This function + * is thread-safe. + * + * @buf the data + * @len the number of bytes to send + * + * Returns: the number of bytes consumed (0 if no assicated Chardev) + */ +int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); + +/** + * @qemu_chr_fe_write_all: + * + * Write data to a character backend from the front end. This function will + * send data from the front end to the back end. Unlike @qemu_chr_fe_write, + * this function will block if the back end cannot consume all of the data + * attempted to be written. This function is thread-safe. + * + * @buf the data + * @len the number of bytes to send + * + * Returns: the number of bytes consumed (0 if no assicated Chardev) + */ +int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); + +/** + * @qemu_chr_fe_read_all: + * + * Read data to a buffer from the back end. + * + * @buf the data buffer + * @len the number of bytes to read + * + * Returns: the number of bytes read (0 if no assicated Chardev) + */ +int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); + +/** + * @qemu_chr_fe_ioctl: + * + * Issue a device specific ioctl to a backend. This function is thread-safe. + * + * @cmd see CHR_IOCTL_* + * @arg the data associated with @cmd + * + * Returns: if @cmd is not supported by the backend or there is no + * associated Chardev, -ENOTSUP, otherwise the return + * value depends on the semantics of @cmd + */ +int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); + +/** + * @qemu_chr_fe_get_msgfd: + * + * For backends capable of fd passing, return the latest file descriptor passed + * by a client. + * + * Returns: -1 if fd passing isn't supported or there is no pending file + * descriptor. If a file descriptor is returned, subsequent calls to + * this function will return -1 until a client sends a new file + * descriptor. + */ +int qemu_chr_fe_get_msgfd(CharBackend *be); + +/** + * @qemu_chr_fe_get_msgfds: + * + * For backends capable of fd passing, return the number of file received + * descriptors and fills the fds array up to num elements + * + * Returns: -1 if fd passing isn't supported or there are no pending file + * descriptors. If file descriptors are returned, subsequent calls to + * this function will return -1 until a client sends a new set of file + * descriptors. + */ +int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); + +/** + * @qemu_chr_fe_set_msgfds: + * + * For backends capable of fd passing, set an array of fds to be passed with + * the next send operation. + * A subsequent call to this function before calling a write function will + * result in overwriting the fd array with the new value without being send. + * Upon writing the message the fd array is freed. + * + * Returns: -1 if fd passing isn't supported or no associated Chardev. + */ +int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num); + +#endif /* QEMU_CHAR_FE_H */ diff --git a/include/chardev/char-mux.h b/include/chardev/char-mux.h index 45cdfc7e67..8928977897 100644 --- a/include/chardev/char-mux.h +++ b/include/chardev/char-mux.h @@ -25,6 +25,7 @@ #define CHAR_MUX_H #include "chardev/char.h" +#include "chardev/char-fe.h" extern bool muxes_realized; diff --git a/include/chardev/char.h b/include/chardev/char.h index 95273e10ae..8a9ade4931 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -16,6 +16,7 @@ #define IAC 255 /* character device */ +typedef struct CharBackend CharBackend; typedef enum { CHR_EVENT_BREAK, /* serial break char */ @@ -27,8 +28,6 @@ typedef enum { #define CHR_READ_BUF_LEN 4096 -typedef void IOEventHandler(void *opaque, int event); - typedef enum { /* Whether the chardev peer is able to close and * reopen the data channel, thus requiring support @@ -44,17 +43,7 @@ typedef enum { QEMU_CHAR_FEATURE_LAST, } ChardevFeature; -/* This is the backend as seen by frontend, the actual backend is - * Chardev */ -typedef struct CharBackend { - Chardev *chr; - IOEventHandler *chr_event; - IOCanReadHandler *chr_can_read; - IOReadHandler *chr_read; - void *opaque; - int tag; - int fe_open; -} CharBackend; +#define qemu_chr_replay(chr) qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_REPLAY) struct Chardev { Object parent_obj; @@ -103,15 +92,6 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend); */ Chardev *qemu_chr_new(const char *label, const char *filename); - -/** - * @qemu_chr_fe_disconnect: - * - * Close a fd accpeted by character backend. - * Without associated Chardev, do nothing. - */ -void qemu_chr_fe_disconnect(CharBackend *be); - /** * @qemu_chr_cleanup: * @@ -119,14 +99,6 @@ void qemu_chr_fe_disconnect(CharBackend *be); */ void qemu_chr_cleanup(void); -/** - * @qemu_chr_fe_wait_connected: - * - * Wait for characted backend to be connected, return < 0 on error or - * if no assicated Chardev. - */ -int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); - /** * @qemu_chr_new_noreplay: * @@ -141,150 +113,6 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); */ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename); -/** - * @qemu_chr_fe_set_echo: - * - * Ask the backend to override its normal echo setting. This only really - * applies to the stdio backend and is used by the QMP server such that you - * can see what you type if you try to type QMP commands. - * Without associated Chardev, do nothing. - * - * @echo true to enable echo, false to disable echo - */ -void qemu_chr_fe_set_echo(CharBackend *be, bool echo); - -/** - * @qemu_chr_fe_set_open: - * - * Set character frontend open status. This is an indication that the - * front end is ready (or not) to begin doing I/O. - * Without associated Chardev, do nothing. - */ -void qemu_chr_fe_set_open(CharBackend *be, int fe_open); - -/** - * @qemu_chr_fe_printf: - * - * Write to a character backend using a printf style interface. This - * function is thread-safe. It does nothing without associated - * Chardev. - * - * @fmt see #printf - */ -void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) - GCC_FMT_ATTR(2, 3); - -/** - * @qemu_chr_fe_add_watch: - * - * If the backend is connected, create and add a #GSource that fires - * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP) - * is active; return the #GSource's tag. If it is disconnected, - * or without associated Chardev, return 0. - * - * @cond the condition to poll for - * @func the function to call when the condition happens - * @user_data the opaque pointer to pass to @func - * - * Returns: the source tag - */ -guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, - GIOFunc func, void *user_data); - -/** - * @qemu_chr_fe_write: - * - * Write data to a character backend from the front end. This function - * will send data from the front end to the back end. This function - * is thread-safe. - * - * @buf the data - * @len the number of bytes to send - * - * Returns: the number of bytes consumed (0 if no assicated Chardev) - */ -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); - -/** - * @qemu_chr_fe_write_all: - * - * Write data to a character backend from the front end. This function will - * send data from the front end to the back end. Unlike @qemu_chr_fe_write, - * this function will block if the back end cannot consume all of the data - * attempted to be written. This function is thread-safe. - * - * @buf the data - * @len the number of bytes to send - * - * Returns: the number of bytes consumed (0 if no assicated Chardev) - */ -int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); - -/** - * @qemu_chr_fe_read_all: - * - * Read data to a buffer from the back end. - * - * @buf the data buffer - * @len the number of bytes to read - * - * Returns: the number of bytes read (0 if no assicated Chardev) - */ -int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); - -/** - * @qemu_chr_fe_ioctl: - * - * Issue a device specific ioctl to a backend. This function is thread-safe. - * - * @cmd see CHR_IOCTL_* - * @arg the data associated with @cmd - * - * Returns: if @cmd is not supported by the backend or there is no - * associated Chardev, -ENOTSUP, otherwise the return - * value depends on the semantics of @cmd - */ -int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); - -/** - * @qemu_chr_fe_get_msgfd: - * - * For backends capable of fd passing, return the latest file descriptor passed - * by a client. - * - * Returns: -1 if fd passing isn't supported or there is no pending file - * descriptor. If a file descriptor is returned, subsequent calls to - * this function will return -1 until a client sends a new file - * descriptor. - */ -int qemu_chr_fe_get_msgfd(CharBackend *be); - -/** - * @qemu_chr_fe_get_msgfds: - * - * For backends capable of fd passing, return the number of file received - * descriptors and fills the fds array up to num elements - * - * Returns: -1 if fd passing isn't supported or there are no pending file - * descriptors. If file descriptors are returned, subsequent calls to - * this function will return -1 until a client sends a new set of file - * descriptors. - */ -int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); - -/** - * @qemu_chr_fe_set_msgfds: - * - * For backends capable of fd passing, set an array of fds to be passed with - * the next send operation. - * A subsequent call to this function before calling a write function will - * result in overwriting the fd array with the new value without being send. - * Upon writing the message the fd array is freed. - * - * Returns: -1 if fd passing isn't supported or no associated Chardev. - */ -int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num); - /** * @qemu_chr_be_can_write: * @@ -328,69 +156,6 @@ void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len); */ void qemu_chr_be_event(Chardev *s, int event); -/** - * @qemu_chr_fe_init: - * - * Initializes a front end for the given CharBackend and - * Chardev. Call qemu_chr_fe_deinit() to remove the association and - * release the driver. - * - * Returns: false on error. - */ -bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); - -/** - * @qemu_chr_fe_get_driver: - * - * Returns the driver associated with a CharBackend or NULL if no - * associated Chardev. - */ -Chardev *qemu_chr_fe_get_driver(CharBackend *be); - -/** - * @qemu_chr_fe_deinit: - * - * Dissociate the CharBackend from the Chardev. - * - * Safe to call without associated Chardev. - */ -void qemu_chr_fe_deinit(CharBackend *b); - -/** - * @qemu_chr_fe_set_handlers: - * @b: a CharBackend - * @fd_can_read: callback to get the amount of data the frontend may - * receive - * @fd_read: callback to receive data from char - * @fd_event: event callback - * @opaque: an opaque pointer for the callbacks - * @context: a main loop context or NULL for the default - * @set_open: whether to call qemu_chr_fe_set_open() implicitely when - * any of the handler is non-NULL - * - * Set the front end char handlers. The front end takes the focus if - * any of the handler is non-NULL. - * - * Without associated Chardev, nothing is changed. - */ -void qemu_chr_fe_set_handlers(CharBackend *b, - IOCanReadHandler *fd_can_read, - IOReadHandler *fd_read, - IOEventHandler *fd_event, - void *opaque, - GMainContext *context, - bool set_open); - -/** - * @qemu_chr_fe_take_focus: - * - * Take the focus (if the front end is muxed). - * - * Without associated Chardev, nothing is changed. - */ -void qemu_chr_fe_take_focus(CharBackend *b); - -void qemu_chr_fe_accept_input(CharBackend *be); int qemu_chr_add_client(Chardev *s, int fd); Chardev *qemu_chr_find(const char *name); @@ -399,7 +164,8 @@ bool qemu_chr_has_feature(Chardev *chr, void qemu_chr_set_feature(Chardev *chr, ChardevFeature feature); QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); -int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len); +int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all); +#define qemu_chr_write_all(s, buf, len) qemu_chr_write(s, buf, len, true) int qemu_chr_wait_connected(Chardev *chr, Error **errp); #define TYPE_CHARDEV "chardev" diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h index 2a051c5646..cdbf7e3e37 100644 --- a/include/hw/char/bcm2835_aux.h +++ b/include/hw/char/bcm2835_aux.h @@ -9,7 +9,7 @@ #define BCM2835_AUX_H #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #define TYPE_BCM2835_AUX "bcm2835-aux" #define BCM2835_AUX(obj) OBJECT_CHECK(BCM2835AuxState, (obj), TYPE_BCM2835_AUX) diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h index eed7d8d358..118e3f10de 100644 --- a/include/hw/char/cadence_uart.h +++ b/include/hw/char/cadence_uart.h @@ -19,7 +19,7 @@ #ifndef CADENCE_UART_H #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/timer.h" #define CADENCE_UART_RX_FIFO_SIZE 16 diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h index 370b48a6c5..de9a3e3551 100644 --- a/include/hw/char/digic-uart.h +++ b/include/hw/char/digic-uart.h @@ -19,7 +19,7 @@ #define HW_CHAR_DIGIC_UART_H #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #define TYPE_DIGIC_UART "digic-uart" #define DIGIC_UART(obj) \ diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index 05500f5346..baeec3183f 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -19,7 +19,7 @@ #define IMX_SERIAL_H #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #define TYPE_IMX_SERIAL "imx.serial" #define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL) diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index 01dcd2a8d2..c4daf11a14 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -28,7 +28,7 @@ #include "hw/hw.h" #include "sysemu/sysemu.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "exec/memory.h" #include "qemu/fifo8.h" #include "chardev/char.h" diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h index 4259dbeb1e..9d03a7527c 100644 --- a/include/hw/char/stm32f2xx_usart.h +++ b/include/hw/char/stm32f2xx_usart.h @@ -26,7 +26,7 @@ #define HW_STM32F2XX_USART_H #include "hw/sysbus.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "hw/hw.h" #define USART_SR 0x00 diff --git a/monitor.c b/monitor.c index 29b71ff2bc..37f8d5645f 100644 --- a/monitor.c +++ b/monitor.c @@ -35,7 +35,7 @@ #include "exec/gdbstub.h" #include "net/net.h" #include "net/slirp.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "ui/qemu-spice.h" #include "sysemu/numa.h" #include "monitor/monitor.h" diff --git a/net/colo-compare.c b/net/colo-compare.c index 619335d5e8..2fb75bcca4 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -25,7 +25,7 @@ #include "qom/object.h" #include "qemu/typedefs.h" #include "net/queue.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/sockets.h" #include "qapi-visit.h" #include "net/colo.h" diff --git a/net/filter-mirror.c b/net/filter-mirror.c index 7adc2c10d2..a20330475c 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -20,7 +20,7 @@ #include "qemu/main-loop.h" #include "qemu/error-report.h" #include "trace.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/iov.h" #include "qemu/sockets.h" diff --git a/net/slirp.c b/net/slirp.c index af3e8b22ac..6a6d727999 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -37,7 +37,7 @@ #include "qemu/sockets.h" #include "slirp/libslirp.h" #include "slirp/ip6.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "qemu/cutils.h" #include "qapi/error.h" diff --git a/net/vhost-user.c b/net/vhost-user.c index 77d2ce22a6..526290d8c1 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -12,7 +12,7 @@ #include "clients.h" #include "net/vhost_net.h" #include "net/vhost-user.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "qemu/config-file.h" #include "qemu/error-report.h" #include "qmp-commands.h" diff --git a/qtest.c b/qtest.c index dbf70a7018..9a5d1dc50d 100644 --- a/qtest.c +++ b/qtest.c @@ -17,7 +17,7 @@ #include "cpu.h" #include "sysemu/qtest.h" #include "hw/qdev.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "exec/ioport.h" #include "exec/memory.h" #include "hw/irq.h" diff --git a/slirp/slirp.c b/slirp/slirp.c index 3b92cb54ce..e79345bdfc 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -25,7 +25,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "qemu/error-report.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "slirp.h" #include "hw/hw.h" #include "qemu/cutils.h" diff --git a/tests/test-char.c b/tests/test-char.c index 9340c55058..d7ecf1056a 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "qemu/config-file.h" #include "qemu/sockets.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "qapi/error.h" #include "qom/qom-qobject.h" diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index acc392d046..4ca11ae28d 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -16,7 +16,7 @@ #include "qemu/option.h" #include "qemu/range.h" #include "qemu/sockets.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "libqos/libqos.h" #include "libqos/pci-pc.h" diff --git a/ui/console.c b/ui/console.c index 6cf795a23d..d914cced53 100644 --- a/ui/console.c +++ b/ui/console.c @@ -27,7 +27,7 @@ #include "hw/qdev-core.h" #include "qemu/timer.h" #include "qmp-commands.h" -#include "chardev/char.h" +#include "chardev/char-fe.h" #include "trace.h" #include "exec/memory.h" -- cgit v1.2.3 From a9b1ca38c2b1f062f22d4847e3b4c848d0fb84c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 26 Jan 2017 23:38:22 +0400 Subject: char: rename functions that are not part of fe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no clear reason to have those functions associated with frontend. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- chardev/char.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/chardev/char.c b/chardev/char.c index 8ea7b5777a..7aa0210765 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -66,8 +66,7 @@ void qemu_chr_be_event(Chardev *s, int event) /* Not reporting errors from writing to logfile, as logs are * defined to be "best effort" only */ -static void qemu_chr_fe_write_log(Chardev *s, - const uint8_t *buf, size_t len) +static void qemu_chr_write_log(Chardev *s, const uint8_t *buf, size_t len) { size_t done = 0; ssize_t ret; @@ -91,9 +90,9 @@ static void qemu_chr_fe_write_log(Chardev *s, } } -static int qemu_chr_fe_write_buffer(Chardev *s, - const uint8_t *buf, int len, - int *offset, bool write_all) +static int qemu_chr_write_buffer(Chardev *s, + const uint8_t *buf, int len, + int *offset, bool write_all) { ChardevClass *cc = CHARDEV_GET_CLASS(s); int res = 0; @@ -118,7 +117,7 @@ static int qemu_chr_fe_write_buffer(Chardev *s, } } if (*offset > 0) { - qemu_chr_fe_write_log(s, buf, *offset); + qemu_chr_write_log(s, buf, *offset); } qemu_mutex_unlock(&s->chr_write_lock); @@ -133,11 +132,11 @@ int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all) if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) { replay_char_write_event_load(&res, &offset); assert(offset <= len); - qemu_chr_fe_write_buffer(s, buf, offset, &offset, true); + qemu_chr_write_buffer(s, buf, offset, &offset, true); return res; } - res = qemu_chr_fe_write_buffer(s, buf, len, &offset, write_all); + res = qemu_chr_write_buffer(s, buf, len, &offset, write_all); if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { replay_char_write_event_save(res, offset); -- cgit v1.2.3 From 1ce2610c106d925387669b3133fc18ea986f0476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 27 Jan 2017 00:49:13 +0400 Subject: char: make chr_fe_deinit() optionaly delete backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies removing a backend for a frontend user (no need to retrieve the associated driver and separate delete call etc). NB: many frontends have questionable handling of ending a chardev. They should probably delete the backend to prevent broken reusage. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- backends/rng-egd.c | 2 +- chardev/char-fe.c | 5 ++++- chardev/char-mux.c | 2 +- gdbstub.c | 15 ++------------- hw/char/serial.c | 2 +- hw/char/xen_console.c | 2 +- hw/core/qdev-properties-system.c | 2 +- hw/usb/ccid-card-passthru.c | 5 +---- hw/usb/redirect.c | 4 +--- include/chardev/char-fe.h | 6 ++++-- monitor.c | 2 +- net/colo-compare.c | 8 +++----- net/filter-mirror.c | 6 +++--- net/vhost-user.c | 5 +---- tests/test-char.c | 22 ++++++++-------------- tests/vhost-user-test.c | 4 +--- 16 files changed, 34 insertions(+), 58 deletions(-) diff --git a/backends/rng-egd.c b/backends/rng-egd.c index ad3e1e5edf..e7ce2cac80 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -145,7 +145,7 @@ static void rng_egd_finalize(Object *obj) { RngEgd *s = RNG_EGD(obj); - qemu_chr_fe_deinit(&s->chr); + qemu_chr_fe_deinit(&s->chr, false); g_free(s->chr_name); } diff --git a/chardev/char-fe.c b/chardev/char-fe.c index 341221d029..3f90f0567c 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -211,7 +211,7 @@ unavailable: return false; } -void qemu_chr_fe_deinit(CharBackend *b) +void qemu_chr_fe_deinit(CharBackend *b, bool del) { assert(b); @@ -224,6 +224,9 @@ void qemu_chr_fe_deinit(CharBackend *b) MuxChardev *d = MUX_CHARDEV(b->chr); d->backends[b->tag] = NULL; } + if (del) { + object_unparent(OBJECT(b->chr)); + } b->chr = NULL; } } diff --git a/chardev/char-mux.c b/chardev/char-mux.c index 106c682e7f..08570b915e 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -266,7 +266,7 @@ static void char_mux_finalize(Object *obj) be->chr = NULL; } } - qemu_chr_fe_deinit(&d->chr); + qemu_chr_fe_deinit(&d->chr, false); } void mux_chr_set_handlers(Chardev *chr, GMainContext *context) diff --git a/gdbstub.c b/gdbstub.c index 4251d23898..ec4e4b25be 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1678,9 +1678,6 @@ void gdb_exit(CPUArchState *env, int code) { GDBState *s; char buf[4]; -#ifndef CONFIG_USER_ONLY - Chardev *chr; -#endif s = gdbserver_state; if (!s) { @@ -1690,19 +1687,13 @@ void gdb_exit(CPUArchState *env, int code) if (gdbserver_fd < 0 || s->fd < 0) { return; } -#else - chr = qemu_chr_fe_get_driver(&s->chr); - if (!chr) { - return; - } #endif snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code); put_packet(s, buf); #ifndef CONFIG_USER_ONLY - qemu_chr_fe_deinit(&s->chr); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&s->chr, true); #endif } @@ -2002,9 +1993,7 @@ int gdbserver_start(const char *device) NULL, &error_abort); monitor_init(mon_chr, 0); } else { - if (qemu_chr_fe_get_driver(&s->chr)) { - object_unparent(OBJECT(qemu_chr_fe_get_driver(&s->chr))); - } + qemu_chr_fe_deinit(&s->chr, true); mon_chr = s->mon_chr; memset(s, 0, sizeof(GDBState)); s->mon_chr = mon_chr; diff --git a/hw/char/serial.c b/hw/char/serial.c index 23e5fe9d18..e1f12507bf 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -905,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp) void serial_exit_core(SerialState *s) { - qemu_chr_fe_deinit(&s->chr); + qemu_chr_fe_deinit(&s->chr, false); timer_del(s->modem_status_poll); timer_free(s->modem_status_poll); diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index cb849c2e3e..f9af8cadf4 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -261,7 +261,7 @@ static void con_disconnect(struct XenDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - qemu_chr_fe_deinit(&con->chr); + qemu_chr_fe_deinit(&con->chr, false); xen_pv_unbind_evtchn(&con->xendev); if (con->sring) { diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index a549d39030..3bef41914d 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -225,7 +225,7 @@ static void release_chr(Object *obj, const char *name, void *opaque) Property *prop = opaque; CharBackend *be = qdev_get_prop_ptr(dev, prop); - qemu_chr_fe_deinit(be); + qemu_chr_fe_deinit(be, false); } PropertyInfo qdev_prop_chr = { diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index fed3683a50..ac1725eeae 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -264,10 +264,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card, static void ccid_card_vscard_drop_connection(PassthruState *card) { - Chardev *chr = qemu_chr_fe_get_driver(&card->cs); - - qemu_chr_fe_deinit(&card->cs); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&card->cs, true); card->vscard_in_pos = card->vscard_in_hdr = 0; } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index d2b3a84a03..aa22d69216 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1419,10 +1419,8 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) static void usbredir_unrealize(USBDevice *udev, Error **errp) { USBRedirDevice *dev = USB_REDIRECT(udev); - Chardev *chr = qemu_chr_fe_get_driver(&dev->cs); - qemu_chr_fe_deinit(&dev->cs); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&dev->cs, true); /* Note must be done after qemu_chr_close, as that causes a close event */ qemu_bh_delete(dev->chardev_close_bh); diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h index bd82093218..2cbb262f66 100644 --- a/include/chardev/char-fe.h +++ b/include/chardev/char-fe.h @@ -30,12 +30,14 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); /** * @qemu_chr_fe_deinit: - * + * @b: a CharBackend + * @del: if true, delete the chardev backend +* * Dissociate the CharBackend from the Chardev. * * Safe to call without associated Chardev. */ -void qemu_chr_fe_deinit(CharBackend *b); +void qemu_chr_fe_deinit(CharBackend *b, bool del); /** * @qemu_chr_fe_get_driver: diff --git a/monitor.c b/monitor.c index 37f8d5645f..75e7cd26d0 100644 --- a/monitor.c +++ b/monitor.c @@ -578,7 +578,7 @@ static void monitor_data_init(Monitor *mon) static void monitor_data_destroy(Monitor *mon) { - qemu_chr_fe_deinit(&mon->chr); + qemu_chr_fe_deinit(&mon->chr, false); if (monitor_is_qmp(mon)) { json_message_parser_destroy(&mon->qmp.parser); } diff --git a/net/colo-compare.c b/net/colo-compare.c index 2fb75bcca4..6d500e1dc4 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -801,11 +801,9 @@ static void colo_compare_finalize(Object *obj) { CompareState *s = COLO_COMPARE(obj); - qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL, - s->worker_context, true); - qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL, - s->worker_context, true); - qemu_chr_fe_deinit(&s->chr_out); + qemu_chr_fe_deinit(&s->chr_pri_in, false); + qemu_chr_fe_deinit(&s->chr_sec_in, false); + qemu_chr_fe_deinit(&s->chr_out, false); g_main_loop_quit(s->compare_loop); qemu_thread_join(&s->thread); diff --git a/net/filter-mirror.c b/net/filter-mirror.c index a20330475c..52d978fce2 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -178,15 +178,15 @@ static void filter_mirror_cleanup(NetFilterState *nf) { MirrorState *s = FILTER_MIRROR(nf); - qemu_chr_fe_deinit(&s->chr_out); + qemu_chr_fe_deinit(&s->chr_out, false); } static void filter_redirector_cleanup(NetFilterState *nf) { MirrorState *s = FILTER_REDIRECTOR(nf); - qemu_chr_fe_deinit(&s->chr_in); - qemu_chr_fe_deinit(&s->chr_out); + qemu_chr_fe_deinit(&s->chr_in, false); + qemu_chr_fe_deinit(&s->chr_out, false); } static void filter_mirror_setup(NetFilterState *nf, Error **errp) diff --git a/net/vhost-user.c b/net/vhost-user.c index 526290d8c1..a042ec6a34 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -151,10 +151,7 @@ static void vhost_user_cleanup(NetClientState *nc) s->vhost_net = NULL; } if (nc->queue_index == 0) { - Chardev *chr = qemu_chr_fe_get_driver(&s->chr); - - qemu_chr_fe_deinit(&s->chr); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&s->chr, true); } qemu_purge_queued_packets(nc); diff --git a/tests/test-char.c b/tests/test-char.c index d7ecf1056a..dfe856cb85 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -97,8 +97,7 @@ static void char_stdio_test_subprocess(void) ret = qemu_chr_fe_write(&be, (void *)"buf", 4); g_assert_cmpint(ret, ==, 4); - qemu_chr_fe_deinit(&be); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&be, true); } static void char_stdio_test(void) @@ -146,8 +145,7 @@ static void char_ringbuf_test(void) g_assert_cmpstr(data, ==, ""); g_free(data); - qemu_chr_fe_deinit(&be); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&be, true); /* check alias */ opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label", @@ -231,9 +229,8 @@ static void char_mux_test(void) g_assert_cmpint(strlen(data), !=, 0); g_free(data); - qemu_chr_fe_deinit(&chr_be1); - qemu_chr_fe_deinit(&chr_be2); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&chr_be1, false); + qemu_chr_fe_deinit(&chr_be2, true); } typedef struct SocketIdleData { @@ -396,8 +393,7 @@ static void char_pipe_test(void) g_assert_cmpint(fe.read_count, ==, 8); g_assert_cmpstr(fe.read_buf, ==, "pipe-in"); - qemu_chr_fe_deinit(&be); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&be, true); g_assert(g_unlink(in) == 0); g_assert(g_unlink(out) == 0); @@ -511,8 +507,7 @@ static void char_file_test(void) g_assert_cmpint(fe.read_count, ==, 8); g_assert_cmpstr(fe.read_buf, ==, "fifo-in"); - qemu_chr_fe_deinit(&be); - object_unref(OBJECT(chr)); + qemu_chr_fe_deinit(&be, true); g_unlink(fifo); g_free(fifo); } @@ -549,7 +544,7 @@ static void char_null_test(void) error_free_or_abort(&err); /* deinit & reinit */ - qemu_chr_fe_deinit(&be); + qemu_chr_fe_deinit(&be, false); qemu_chr_fe_init(&be, chr, &error_abort); qemu_chr_fe_set_open(&be, true); @@ -563,8 +558,7 @@ static void char_null_test(void) ret = qemu_chr_fe_write(&be, (void *)"buf", 4); g_assert_cmpint(ret, ==, 4); - qemu_chr_fe_deinit(&be); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&be, true); } static void char_invalid_test(void) diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index 4ca11ae28d..b3cc045765 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -488,10 +488,8 @@ static inline void test_server_connect(TestServer *server) static gboolean _test_server_free(TestServer *server) { int i; - Chardev *chr = qemu_chr_fe_get_driver(&server->chr); - qemu_chr_fe_deinit(&server->chr); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&server->chr, true); for (i = 0; i < server->fds_num; i++) { close(server->fds[i]); -- cgit v1.2.3 From 6b10e573d15ef82dbc5c5b3726028e6642e134f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 29 May 2017 12:39:42 +0400 Subject: char: move char devices to chardev/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested by Paolo Bonzini during series review. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- MAINTAINERS | 4 +- Makefile.objs | 4 +- backends/Makefile.objs | 4 - backends/baum.c | 677 ------------------------------------------------- backends/msmouse.c | 190 -------------- backends/testdev.c | 129 ---------- backends/trace-events | 10 - backends/wctablet.c | 369 --------------------------- chardev/Makefile.objs | 6 + chardev/baum.c | 677 +++++++++++++++++++++++++++++++++++++++++++++++++ chardev/msmouse.c | 190 ++++++++++++++ chardev/spice.c | 421 ++++++++++++++++++++++++++++++ chardev/testdev.c | 129 ++++++++++ chardev/trace-events | 18 ++ chardev/wctablet.c | 369 +++++++++++++++++++++++++++ spice-qemu-char.c | 421 ------------------------------ trace-events | 7 - 17 files changed, 1813 insertions(+), 1812 deletions(-) delete mode 100644 backends/baum.c delete mode 100644 backends/msmouse.c delete mode 100644 backends/testdev.c delete mode 100644 backends/wctablet.c create mode 100644 chardev/baum.c create mode 100644 chardev/msmouse.c create mode 100644 chardev/spice.c create mode 100644 chardev/testdev.c create mode 100644 chardev/trace-events create mode 100644 chardev/wctablet.c delete mode 100644 spice-qemu-char.c diff --git a/MAINTAINERS b/MAINTAINERS index 48e2964ed8..120788d8fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1239,13 +1239,11 @@ M: Marc-André Lureau S: Maintained F: chardev/ F: include/chardev/ -F: backends/msmouse.c -F: backends/testdev.c Character Devices (Braille) M: Samuel Thibault S: Maintained -F: backends/baum.c +F: chardev/baum.c Command line option argument parsing M: Markus Armbruster diff --git a/Makefile.objs b/Makefile.objs index 2100845ce2..0575802440 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -50,8 +50,6 @@ common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += migration/ -common-obj-$(CONFIG_SPICE) += spice-qemu-char.o - common-obj-y += audio/ common-obj-y += hw/ common-obj-y += accel.o @@ -70,6 +68,7 @@ common-obj-y += tpm.o common-obj-$(CONFIG_SLIRP) += slirp/ common-obj-y += backends/ +common-obj-y += chardev/ common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o @@ -121,6 +120,7 @@ trace-events-subdirs += io trace-events-subdirs += migration trace-events-subdirs += block trace-events-subdirs += backends +trace-events-subdirs += chardev trace-events-subdirs += hw/block trace-events-subdirs += hw/block/dataplane trace-events-subdirs += hw/char diff --git a/backends/Makefile.objs b/backends/Makefile.objs index 0e0f1567b2..0400799efd 100644 --- a/backends/Makefile.objs +++ b/backends/Makefile.objs @@ -1,10 +1,6 @@ common-obj-y += rng.o rng-egd.o common-obj-$(CONFIG_POSIX) += rng-random.o -common-obj-y += msmouse.o wctablet.o testdev.o -common-obj-$(CONFIG_BRLAPI) += baum.o -baum.o-cflags := $(SDL_CFLAGS) - common-obj-$(CONFIG_TPM) += tpm.o common-obj-y += hostmem.o hostmem-ram.o diff --git a/backends/baum.c b/backends/baum.c deleted file mode 100644 index 302dd9666c..0000000000 --- a/backends/baum.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * QEMU Baum Braille Device - * - * Copyright (c) 2008, 2010-2011, 2016 Samuel Thibault - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu-common.h" -#include "chardev/char.h" -#include "qemu/timer.h" -#include "hw/usb.h" -#include "ui/console.h" -#include -#include -#include - -#if 0 -#define DPRINTF(fmt, ...) \ - printf(fmt, ## __VA_ARGS__) -#else -#define DPRINTF(fmt, ...) -#endif - -#define ESC 0x1B - -#define BAUM_REQ_DisplayData 0x01 -#define BAUM_REQ_GetVersionNumber 0x05 -#define BAUM_REQ_GetKeys 0x08 -#define BAUM_REQ_SetMode 0x12 -#define BAUM_REQ_SetProtocol 0x15 -#define BAUM_REQ_GetDeviceIdentity 0x84 -#define BAUM_REQ_GetSerialNumber 0x8A - -#define BAUM_RSP_CellCount 0x01 -#define BAUM_RSP_VersionNumber 0x05 -#define BAUM_RSP_ModeSetting 0x11 -#define BAUM_RSP_CommunicationChannel 0x16 -#define BAUM_RSP_PowerdownSignal 0x17 -#define BAUM_RSP_HorizontalSensors 0x20 -#define BAUM_RSP_VerticalSensors 0x21 -#define BAUM_RSP_RoutingKeys 0x22 -#define BAUM_RSP_Switches 0x23 -#define BAUM_RSP_TopKeys 0x24 -#define BAUM_RSP_HorizontalSensor 0x25 -#define BAUM_RSP_VerticalSensor 0x26 -#define BAUM_RSP_RoutingKey 0x27 -#define BAUM_RSP_FrontKeys6 0x28 -#define BAUM_RSP_BackKeys6 0x29 -#define BAUM_RSP_CommandKeys 0x2B -#define BAUM_RSP_FrontKeys10 0x2C -#define BAUM_RSP_BackKeys10 0x2D -#define BAUM_RSP_EntryKeys 0x33 -#define BAUM_RSP_JoyStick 0x34 -#define BAUM_RSP_ErrorCode 0x40 -#define BAUM_RSP_InfoBlock 0x42 -#define BAUM_RSP_DeviceIdentity 0x84 -#define BAUM_RSP_SerialNumber 0x8A -#define BAUM_RSP_BluetoothName 0x8C - -#define BAUM_TL1 0x01 -#define BAUM_TL2 0x02 -#define BAUM_TL3 0x04 -#define BAUM_TR1 0x08 -#define BAUM_TR2 0x10 -#define BAUM_TR3 0x20 - -#define BUF_SIZE 256 - -typedef struct { - Chardev parent; - - brlapi_handle_t *brlapi; - int brlapi_fd; - unsigned int x, y; - bool deferred_init; - - uint8_t in_buf[BUF_SIZE]; - uint8_t in_buf_used; - uint8_t out_buf[BUF_SIZE]; - uint8_t out_buf_used, out_buf_ptr; - - QEMUTimer *cellCount_timer; -} BaumChardev; - -#define TYPE_CHARDEV_BRAILLE "chardev-braille" -#define BAUM_CHARDEV(obj) OBJECT_CHECK(BaumChardev, (obj), TYPE_CHARDEV_BRAILLE) - -/* Let's assume NABCC by default */ -enum way { - DOTS2ASCII, - ASCII2DOTS -}; -static const uint8_t nabcc_translation[2][256] = { -#ifndef BRLAPI_DOTS -#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \ - ((d1?BRLAPI_DOT1:0)|\ - (d2?BRLAPI_DOT2:0)|\ - (d3?BRLAPI_DOT3:0)|\ - (d4?BRLAPI_DOT4:0)|\ - (d5?BRLAPI_DOT5:0)|\ - (d6?BRLAPI_DOT6:0)|\ - (d7?BRLAPI_DOT7:0)|\ - (d8?BRLAPI_DOT8:0)) -#endif -#define DO(dots, ascii) \ - [DOTS2ASCII][dots] = ascii, \ - [ASCII2DOTS][ascii] = dots - DO(0, ' '), - DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 0, 0, 0), 'a'), - DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 0, 0, 0), 'b'), - DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 0, 0, 0), 'c'), - DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 0, 0, 0), 'd'), - DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 0, 0, 0), 'e'), - DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 0, 0, 0), 'f'), - DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 0, 0, 0), 'g'), - DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 0, 0, 0), 'h'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 0, 0, 0), 'i'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 0, 0, 0), 'j'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 0, 0, 0), 'k'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 0, 0, 0), 'l'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 0, 0, 0), 'm'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 0, 0, 0), 'n'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 0, 0, 0), 'o'), - DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 0, 0, 0), 'p'), - DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 0, 0, 0), 'q'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 0, 0, 0), 'r'), - DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 0, 0, 0), 's'), - DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 0, 0, 0), 't'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 1, 0, 0), 'u'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 1, 0, 0), 'v'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 1, 0, 0), 'w'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 1, 0, 0), 'x'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 1, 0, 0), 'y'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 1, 0, 0), 'z'), - - DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 0, 1, 0), 'A'), - DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 0, 1, 0), 'B'), - DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 0, 1, 0), 'C'), - DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 0, 1, 0), 'D'), - DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 0, 1, 0), 'E'), - DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 0, 1, 0), 'F'), - DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 0, 1, 0), 'G'), - DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 0, 1, 0), 'H'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 0, 1, 0), 'I'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 0, 1, 0), 'J'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 0, 1, 0), 'K'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 0, 1, 0), 'L'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 0, 1, 0), 'M'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 0, 1, 0), 'N'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 0, 1, 0), 'O'), - DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 0, 1, 0), 'P'), - DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 0, 1, 0), 'Q'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 0, 1, 0), 'R'), - DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 0, 1, 0), 'S'), - DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 0, 1, 0), 'T'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 1, 1, 0), 'U'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 1, 1, 0), 'V'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 1, 1, 0), 'W'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 1, 1, 0), 'X'), - DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 1, 1, 0), 'Y'), - DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 1, 1, 0), 'Z'), - - DO(BRLAPI_DOTS(0, 0, 1, 0, 1, 1, 0, 0), '0'), - DO(BRLAPI_DOTS(0, 1, 0, 0, 0, 0, 0, 0), '1'), - DO(BRLAPI_DOTS(0, 1, 1, 0, 0, 0, 0, 0), '2'), - DO(BRLAPI_DOTS(0, 1, 0, 0, 1, 0, 0, 0), '3'), - DO(BRLAPI_DOTS(0, 1, 0, 0, 1, 1, 0, 0), '4'), - DO(BRLAPI_DOTS(0, 1, 0, 0, 0, 1, 0, 0), '5'), - DO(BRLAPI_DOTS(0, 1, 1, 0, 1, 0, 0, 0), '6'), - DO(BRLAPI_DOTS(0, 1, 1, 0, 1, 1, 0, 0), '7'), - DO(BRLAPI_DOTS(0, 1, 1, 0, 0, 1, 0, 0), '8'), - DO(BRLAPI_DOTS(0, 0, 1, 0, 1, 0, 0, 0), '9'), - - DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 1, 0, 0), '.'), - DO(BRLAPI_DOTS(0, 0, 1, 1, 0, 1, 0, 0), '+'), - DO(BRLAPI_DOTS(0, 0, 1, 0, 0, 1, 0, 0), '-'), - DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 1, 0, 0), '*'), - DO(BRLAPI_DOTS(0, 0, 1, 1, 0, 0, 0, 0), '/'), - DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 1, 0, 0), '('), - DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 1, 0, 0), ')'), - - DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 1, 0, 0), '&'), - DO(BRLAPI_DOTS(0, 0, 1, 1, 1, 1, 0, 0), '#'), - - DO(BRLAPI_DOTS(0, 0, 0, 0, 0, 1, 0, 0), ','), - DO(BRLAPI_DOTS(0, 0, 0, 0, 1, 1, 0, 0), ';'), - DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 1, 0, 0), ':'), - DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 1, 0, 0), '!'), - DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 1, 0, 0), '?'), - DO(BRLAPI_DOTS(0, 0, 0, 0, 1, 0, 0, 0), '"'), - DO(BRLAPI_DOTS(0, 0, 1, 0, 0, 0, 0, 0), '\''), - DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 0, 0, 0), '`'), - DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 0, 1, 0), '^'), - DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 0, 0, 0), '~'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 1, 1, 0), '['), - DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 1, 1, 0), ']'), - DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 1, 0, 0), '{'), - DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 1, 0, 0), '}'), - DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 1, 0, 0), '='), - DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 1, 0, 0), '<'), - DO(BRLAPI_DOTS(0, 0, 1, 1, 1, 0, 0, 0), '>'), - DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 1, 0, 0), '$'), - DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 1, 0, 0), '%'), - DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 0, 1, 0), '@'), - DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 1, 0, 0), '|'), - DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 1, 1, 0), '\\'), - DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 1, 0, 0), '_'), -}; - -/* The guest OS has started discussing with us, finish initializing BrlAPI */ -static int baum_deferred_init(BaumChardev *baum) -{ - int tty = BRLAPI_TTY_DEFAULT; - QemuConsole *con; - - if (baum->deferred_init) { - return 1; - } - - if (brlapi__getDisplaySize(baum->brlapi, &baum->x, &baum->y) == -1) { - brlapi_perror("baum: brlapi__getDisplaySize"); - return 0; - } - - con = qemu_console_lookup_by_index(0); - if (con && qemu_console_is_graphic(con)) { - tty = qemu_console_get_window_id(con); - if (tty == -1) - tty = BRLAPI_TTY_DEFAULT; - } - - if (brlapi__enterTtyMode(baum->brlapi, tty, NULL) == -1) { - brlapi_perror("baum: brlapi__enterTtyMode"); - return 0; - } - baum->deferred_init = 1; - return 1; -} - -/* The serial port can receive more of our data */ -static void baum_chr_accept_input(struct Chardev *chr) -{ - BaumChardev *baum = BAUM_CHARDEV(chr); - int room, first; - - if (!baum->out_buf_used) - return; - room = qemu_chr_be_can_write(chr); - if (!room) - return; - if (room > baum->out_buf_used) - room = baum->out_buf_used; - - first = BUF_SIZE - baum->out_buf_ptr; - if (room > first) { - qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first); - baum->out_buf_ptr = 0; - baum->out_buf_used -= first; - room -= first; - } - qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room); - baum->out_buf_ptr += room; - baum->out_buf_used -= room; -} - -/* We want to send a packet */ -static void baum_write_packet(BaumChardev *baum, const uint8_t *buf, int len) -{ - Chardev *chr = CHARDEV(baum); - uint8_t io_buf[1 + 2 * len], *cur = io_buf; - int room; - *cur++ = ESC; - while (len--) - if ((*cur++ = *buf++) == ESC) - *cur++ = ESC; - room = qemu_chr_be_can_write(chr); - len = cur - io_buf; - if (len <= room) { - /* Fits */ - qemu_chr_be_write(chr, io_buf, len); - } else { - int first; - uint8_t out; - /* Can't fit all, send what can be, and store the rest. */ - qemu_chr_be_write(chr, io_buf, room); - len -= room; - cur = io_buf + room; - if (len > BUF_SIZE - baum->out_buf_used) { - /* Can't even store it, drop the previous data... */ - assert(len <= BUF_SIZE); - baum->out_buf_used = 0; - baum->out_buf_ptr = 0; - } - out = baum->out_buf_ptr; - baum->out_buf_used += len; - first = BUF_SIZE - baum->out_buf_ptr; - if (len > first) { - memcpy(baum->out_buf + out, cur, first); - out = 0; - len -= first; - cur += first; - } - memcpy(baum->out_buf + out, cur, len); - } -} - -/* Called when the other end seems to have a wrong idea of our display size */ -static void baum_cellCount_timer_cb(void *opaque) -{ - BaumChardev *baum = BAUM_CHARDEV(opaque); - uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y }; - DPRINTF("Timeout waiting for DisplayData, sending cell count\n"); - baum_write_packet(baum, cell_count, sizeof(cell_count)); -} - -/* Try to interpret a whole incoming packet */ -static int baum_eat_packet(BaumChardev *baum, const uint8_t *buf, int len) -{ - const uint8_t *cur = buf; - uint8_t req = 0; - - if (!len--) - return 0; - if (*cur++ != ESC) { - while (*cur != ESC) { - if (!len--) - return 0; - cur++; - } - DPRINTF("Dropped %td bytes!\n", cur - buf); - } - -#define EAT(c) do {\ - if (!len--) \ - return 0; \ - if ((c = *cur++) == ESC) { \ - if (!len--) \ - return 0; \ - if (*cur++ != ESC) { \ - DPRINTF("Broken packet %#2x, tossing\n", req); \ - if (timer_pending(baum->cellCount_timer)) { \ - timer_del(baum->cellCount_timer); \ - baum_cellCount_timer_cb(baum); \ - } \ - return (cur - 2 - buf); \ - } \ - } \ -} while (0) - - EAT(req); - switch (req) { - case BAUM_REQ_DisplayData: - { - uint8_t cells[baum->x * baum->y], c; - uint8_t text[baum->x * baum->y]; - uint8_t zero[baum->x * baum->y]; - int cursor = BRLAPI_CURSOR_OFF; - int i; - - /* Allow 100ms to complete the DisplayData packet */ - timer_mod(baum->cellCount_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - NANOSECONDS_PER_SECOND / 10); - for (i = 0; i < baum->x * baum->y ; i++) { - EAT(c); - cells[i] = c; - if ((c & (BRLAPI_DOT7|BRLAPI_DOT8)) - == (BRLAPI_DOT7|BRLAPI_DOT8)) { - cursor = i + 1; - c &= ~(BRLAPI_DOT7|BRLAPI_DOT8); - } - c = nabcc_translation[DOTS2ASCII][c]; - if (!c) { - c = '?'; - } - text[i] = c; - } - timer_del(baum->cellCount_timer); - - memset(zero, 0, sizeof(zero)); - - brlapi_writeArguments_t wa = { - .displayNumber = BRLAPI_DISPLAY_DEFAULT, - .regionBegin = 1, - .regionSize = baum->x * baum->y, - .text = (char *)text, - .textSize = baum->x * baum->y, - .andMask = zero, - .orMask = cells, - .cursor = cursor, - .charset = (char *)"ISO-8859-1", - }; - - if (brlapi__write(baum->brlapi, &wa) == -1) - brlapi_perror("baum brlapi_write"); - break; - } - case BAUM_REQ_SetMode: - { - uint8_t mode, setting; - DPRINTF("SetMode\n"); - EAT(mode); - EAT(setting); - /* ignore */ - break; - } - case BAUM_REQ_SetProtocol: - { - uint8_t protocol; - DPRINTF("SetProtocol\n"); - EAT(protocol); - /* ignore */ - break; - } - case BAUM_REQ_GetDeviceIdentity: - { - uint8_t identity[17] = { BAUM_RSP_DeviceIdentity, - 'B','a','u','m',' ','V','a','r','i','o' }; - DPRINTF("GetDeviceIdentity\n"); - identity[11] = '0' + baum->x / 10; - identity[12] = '0' + baum->x % 10; - baum_write_packet(baum, identity, sizeof(identity)); - break; - } - case BAUM_REQ_GetVersionNumber: - { - uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */ - DPRINTF("GetVersionNumber\n"); - baum_write_packet(baum, version, sizeof(version)); - break; - } - case BAUM_REQ_GetSerialNumber: - { - uint8_t serial[] = { BAUM_RSP_SerialNumber, - '0','0','0','0','0','0','0','0' }; - DPRINTF("GetSerialNumber\n"); - baum_write_packet(baum, serial, sizeof(serial)); - break; - } - case BAUM_REQ_GetKeys: - { - DPRINTF("Get%0#2x\n", req); - /* ignore */ - break; - } - default: - DPRINTF("unrecognized request %0#2x\n", req); - do - if (!len--) - return 0; - while (*cur++ != ESC); - cur--; - break; - } - return cur - buf; -} - -/* The other end is writing some data. Store it and try to interpret */ -static int baum_chr_write(Chardev *chr, const uint8_t *buf, int len) -{ - BaumChardev *baum = BAUM_CHARDEV(chr); - int tocopy, cur, eaten, orig_len = len; - - if (!len) - return 0; - if (!baum->brlapi) - return len; - if (!baum_deferred_init(baum)) - return len; - - while (len) { - /* Complete our buffer as much as possible */ - tocopy = len; - if (tocopy > BUF_SIZE - baum->in_buf_used) - tocopy = BUF_SIZE - baum->in_buf_used; - - memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy); - baum->in_buf_used += tocopy; - buf += tocopy; - len -= tocopy; - - /* Interpret it as much as possible */ - cur = 0; - while (cur < baum->in_buf_used && - (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur))) - cur += eaten; - - /* Shift the remainder */ - if (cur) { - memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur); - baum->in_buf_used -= cur; - } - - /* And continue if any data left */ - } - return orig_len; -} - -/* Send the key code to the other end */ -static void baum_send_key(BaumChardev *baum, uint8_t type, uint8_t value) -{ - uint8_t packet[] = { type, value }; - DPRINTF("writing key %x %x\n", type, value); - baum_write_packet(baum, packet, sizeof(packet)); -} - -static void baum_send_key2(BaumChardev *baum, uint8_t type, uint8_t value, - uint8_t value2) -{ - uint8_t packet[] = { type, value, value2 }; - DPRINTF("writing key %x %x\n", type, value); - baum_write_packet(baum, packet, sizeof(packet)); -} - -/* We got some data on the BrlAPI socket */ -static void baum_chr_read(void *opaque) -{ - BaumChardev *baum = BAUM_CHARDEV(opaque); - brlapi_keyCode_t code; - int ret; - if (!baum->brlapi) - return; - if (!baum_deferred_init(baum)) - return; - while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) { - DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code); - /* Emulate */ - switch (code & BRLAPI_KEY_TYPE_MASK) { - case BRLAPI_KEY_TYPE_CMD: - switch (code & BRLAPI_KEY_CMD_BLK_MASK) { - case BRLAPI_KEY_CMD_ROUTE: - baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1); - baum_send_key(baum, BAUM_RSP_RoutingKey, 0); - break; - case 0: - switch (code & BRLAPI_KEY_CMD_ARG_MASK) { - case BRLAPI_KEY_CMD_FWINLT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_FWINRT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_LNUP: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_LNDN: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_TOP: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_BOT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_TOP_LEFT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_BOT_LEFT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_HOME: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_PREFMENU: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - } - } - break; - case BRLAPI_KEY_TYPE_SYM: - { - brlapi_keyCode_t keysym = code & BRLAPI_KEY_CODE_MASK; - if (keysym < 0x100) { - uint8_t dots = nabcc_translation[ASCII2DOTS][keysym]; - if (dots) { - baum_send_key2(baum, BAUM_RSP_EntryKeys, 0, dots); - baum_send_key2(baum, BAUM_RSP_EntryKeys, 0, 0); - } - } - break; - } - } - } - if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) { - brlapi_perror("baum: brlapi_readKey"); - brlapi__closeConnection(baum->brlapi); - g_free(baum->brlapi); - baum->brlapi = NULL; - } -} - -static void char_braille_finalize(Object *obj) -{ - BaumChardev *baum = BAUM_CHARDEV(obj); - - timer_free(baum->cellCount_timer); - if (baum->brlapi) { - brlapi__closeConnection(baum->brlapi); - g_free(baum->brlapi); - } -} - -static void baum_chr_open(Chardev *chr, - ChardevBackend *backend, - bool *be_opened, - Error **errp) -{ - BaumChardev *baum = BAUM_CHARDEV(chr); - brlapi_handle_t *handle; - - handle = g_malloc0(brlapi_getHandleSize()); - baum->brlapi = handle; - - baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL); - if (baum->brlapi_fd == -1) { - error_setg(errp, "brlapi__openConnection: %s", - brlapi_strerror(brlapi_error_location())); - g_free(handle); - return; - } - baum->deferred_init = 0; - - baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum); - - qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum); -} - -static void char_braille_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->open = baum_chr_open; - cc->chr_write = baum_chr_write; - cc->chr_accept_input = baum_chr_accept_input; -} - -static const TypeInfo char_braille_type_info = { - .name = TYPE_CHARDEV_BRAILLE, - .parent = TYPE_CHARDEV, - .instance_size = sizeof(BaumChardev), - .instance_finalize = char_braille_finalize, - .class_init = char_braille_class_init, -}; - -static void register_types(void) -{ - type_register_static(&char_braille_type_info); -} - -type_init(register_types); diff --git a/backends/msmouse.c b/backends/msmouse.c deleted file mode 100644 index 0ffd137ce8..0000000000 --- a/backends/msmouse.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * QEMU Microsoft serial mouse emulation - * - * Copyright (c) 2008 Lubomir Rintel - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "chardev/char.h" -#include "ui/console.h" -#include "ui/input.h" - -#define MSMOUSE_LO6(n) ((n) & 0x3f) -#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) - -typedef struct { - Chardev parent; - - QemuInputHandlerState *hs; - int axis[INPUT_AXIS__MAX]; - bool btns[INPUT_BUTTON__MAX]; - bool btnc[INPUT_BUTTON__MAX]; - uint8_t outbuf[32]; - int outlen; -} MouseChardev; - -#define TYPE_CHARDEV_MSMOUSE "chardev-msmouse" -#define MOUSE_CHARDEV(obj) \ - OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE) - -static void msmouse_chr_accept_input(Chardev *chr) -{ - MouseChardev *mouse = MOUSE_CHARDEV(chr); - int len; - - len = qemu_chr_be_can_write(chr); - if (len > mouse->outlen) { - len = mouse->outlen; - } - if (!len) { - return; - } - - qemu_chr_be_write(chr, mouse->outbuf, len); - mouse->outlen -= len; - if (mouse->outlen) { - memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen); - } -} - -static void msmouse_queue_event(MouseChardev *mouse) -{ - unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 }; - int dx, dy, count = 3; - - dx = mouse->axis[INPUT_AXIS_X]; - mouse->axis[INPUT_AXIS_X] = 0; - - dy = mouse->axis[INPUT_AXIS_Y]; - mouse->axis[INPUT_AXIS_Y] = 0; - - /* Movement deltas */ - bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx); - bytes[1] |= MSMOUSE_LO6(dx); - bytes[2] |= MSMOUSE_LO6(dy); - - /* Buttons */ - bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT] ? 0x20 : 0x00); - bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT] ? 0x10 : 0x00); - if (mouse->btns[INPUT_BUTTON_MIDDLE] || - mouse->btnc[INPUT_BUTTON_MIDDLE]) { - bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00); - mouse->btnc[INPUT_BUTTON_MIDDLE] = false; - count = 4; - } - - if (mouse->outlen <= sizeof(mouse->outbuf) - count) { - memcpy(mouse->outbuf + mouse->outlen, bytes, count); - mouse->outlen += count; - } else { - /* queue full -> drop event */ - } -} - -static void msmouse_input_event(DeviceState *dev, QemuConsole *src, - InputEvent *evt) -{ - MouseChardev *mouse = MOUSE_CHARDEV(dev); - InputMoveEvent *move; - InputBtnEvent *btn; - - switch (evt->type) { - case INPUT_EVENT_KIND_REL: - move = evt->u.rel.data; - mouse->axis[move->axis] += move->value; - break; - - case INPUT_EVENT_KIND_BTN: - btn = evt->u.btn.data; - mouse->btns[btn->button] = btn->down; - mouse->btnc[btn->button] = true; - break; - - default: - /* keep gcc happy */ - break; - } -} - -static void msmouse_input_sync(DeviceState *dev) -{ - MouseChardev *mouse = MOUSE_CHARDEV(dev); - Chardev *chr = CHARDEV(dev); - - msmouse_queue_event(mouse); - msmouse_chr_accept_input(chr); -} - -static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len) -{ - /* Ignore writes to mouse port */ - return len; -} - -static void char_msmouse_finalize(Object *obj) -{ - MouseChardev *mouse = MOUSE_CHARDEV(obj); - - qemu_input_handler_unregister(mouse->hs); -} - -static QemuInputHandler msmouse_handler = { - .name = "QEMU Microsoft Mouse", - .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, - .event = msmouse_input_event, - .sync = msmouse_input_sync, -}; - -static void msmouse_chr_open(Chardev *chr, - ChardevBackend *backend, - bool *be_opened, - Error **errp) -{ - MouseChardev *mouse = MOUSE_CHARDEV(chr); - - *be_opened = false; - mouse->hs = qemu_input_handler_register((DeviceState *)mouse, - &msmouse_handler); -} - -static void char_msmouse_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->open = msmouse_chr_open; - cc->chr_write = msmouse_chr_write; - cc->chr_accept_input = msmouse_chr_accept_input; -} - -static const TypeInfo char_msmouse_type_info = { - .name = TYPE_CHARDEV_MSMOUSE, - .parent = TYPE_CHARDEV, - .instance_size = sizeof(MouseChardev), - .instance_finalize = char_msmouse_finalize, - .class_init = char_msmouse_class_init, -}; - -static void register_types(void) -{ - type_register_static(&char_msmouse_type_info); -} - -type_init(register_types); diff --git a/backends/testdev.c b/backends/testdev.c deleted file mode 100644 index 031e9a23e8..0000000000 --- a/backends/testdev.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * QEMU Char Device for testsuite control - * - * Copyright (c) 2014 Red Hat, Inc. - * - * Author: Paolo Bonzini - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "chardev/char.h" - -#define BUF_SIZE 32 - -typedef struct { - Chardev parent; - - uint8_t in_buf[32]; - int in_buf_used; -} TestdevChardev; - -#define TYPE_CHARDEV_TESTDEV "chardev-testdev" -#define TESTDEV_CHARDEV(obj) \ - OBJECT_CHECK(TestdevChardev, (obj), TYPE_CHARDEV_TESTDEV) - -/* Try to interpret a whole incoming packet */ -static int testdev_eat_packet(TestdevChardev *testdev) -{ - const uint8_t *cur = testdev->in_buf; - int len = testdev->in_buf_used; - uint8_t c; - int arg; - -#define EAT(c) do { \ - if (!len--) { \ - return 0; \ - } \ - c = *cur++; \ -} while (0) - - EAT(c); - - while (isspace(c)) { - EAT(c); - } - - arg = 0; - while (isdigit(c)) { - arg = arg * 10 + c - '0'; - EAT(c); - } - - while (isspace(c)) { - EAT(c); - } - - switch (c) { - case 'q': - exit((arg << 1) | 1); - break; - default: - break; - } - return cur - testdev->in_buf; -} - -/* The other end is writing some data. Store it and try to interpret */ -static int testdev_chr_write(Chardev *chr, const uint8_t *buf, int len) -{ - TestdevChardev *testdev = TESTDEV_CHARDEV(chr); - int tocopy, eaten, orig_len = len; - - while (len) { - /* Complete our buffer as much as possible */ - tocopy = MIN(len, BUF_SIZE - testdev->in_buf_used); - - memcpy(testdev->in_buf + testdev->in_buf_used, buf, tocopy); - testdev->in_buf_used += tocopy; - buf += tocopy; - len -= tocopy; - - /* Interpret it as much as possible */ - while (testdev->in_buf_used > 0 && - (eaten = testdev_eat_packet(testdev)) > 0) { - memmove(testdev->in_buf, testdev->in_buf + eaten, - testdev->in_buf_used - eaten); - testdev->in_buf_used -= eaten; - } - } - return orig_len; -} - -static void char_testdev_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->chr_write = testdev_chr_write; -} - -static const TypeInfo char_testdev_type_info = { - .name = TYPE_CHARDEV_TESTDEV, - .parent = TYPE_CHARDEV, - .instance_size = sizeof(TestdevChardev), - .class_init = char_testdev_class_init, -}; - -static void register_types(void) -{ - type_register_static(&char_testdev_type_info); -} - -type_init(register_types); diff --git a/backends/trace-events b/backends/trace-events index 8c3289a3f9..e69de29bb2 100644 --- a/backends/trace-events +++ b/backends/trace-events @@ -1,10 +0,0 @@ -# See docs/tracing.txt for syntax documentation. - -# backends/wctablet.c -wct_init(void) "" -wct_cmd_re(void) "" -wct_cmd_st(void) "" -wct_cmd_sp(void) "" -wct_cmd_ts(int input) "0x%02x" -wct_cmd_other(const char *cmd) "%s" -wct_speed(int speed) "%d" diff --git a/backends/wctablet.c b/backends/wctablet.c deleted file mode 100644 index 6c13c2c58a..0000000000 --- a/backends/wctablet.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * QEMU Wacom Penpartner serial tablet emulation - * - * some protocol details: - * http://linuxwacom.sourceforge.net/wiki/index.php/Serial_Protocol_IV - * - * Copyright (c) 2016 Anatoli Huseu1 - * Copyright (c) 2016,17 Gerd Hoffmann - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "chardev/char-serial.h" -#include "ui/console.h" -#include "ui/input.h" -#include "trace.h" - - -#define WC_OUTPUT_BUF_MAX_LEN 512 -#define WC_COMMAND_MAX_LEN 60 - -#define WC_L7(n) ((n) & 127) -#define WC_M7(n) (((n) >> 7) & 127) -#define WC_H2(n) ((n) >> 14) - -#define WC_L4(n) ((n) & 15) -#define WC_H4(n) (((n) >> 4) & 15) - -/* Model string and config string */ -#define WC_MODEL_STRING_LENGTH 18 -uint8_t WC_MODEL_STRING[WC_MODEL_STRING_LENGTH + 1] = "~#CT-0045R,V1.3-5,"; - -#define WC_CONFIG_STRING_LENGTH 8 -uint8_t WC_CONFIG_STRING[WC_CONFIG_STRING_LENGTH + 1] = "96,N,8,0"; - -#define WC_FULL_CONFIG_STRING_LENGTH 61 -uint8_t WC_FULL_CONFIG_STRING[WC_FULL_CONFIG_STRING_LENGTH + 1] = { - 0x5c, 0x39, 0x36, 0x2c, 0x4e, 0x2c, 0x38, 0x2c, - 0x31, 0x28, 0x01, 0x24, 0x57, 0x41, 0x43, 0x30, - 0x30, 0x34, 0x35, 0x5c, 0x5c, 0x50, 0x45, 0x4e, 0x5c, - 0x57, 0x41, 0x43, 0x30, 0x30, 0x30, 0x30, 0x5c, - 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x0d, 0x0a, - 0x43, 0x54, 0x2d, 0x30, 0x30, 0x34, 0x35, 0x52, - 0x2c, 0x56, 0x31, 0x2e, 0x33, 0x2d, 0x35, 0x0d, - 0x0a, 0x45, 0x37, 0x29 -}; - -/* This structure is used to save private info for Wacom Tablet. */ -typedef struct { - Chardev parent; - QemuInputHandlerState *hs; - - /* Query string from serial */ - uint8_t query[100]; - int query_index; - - /* Command to be sent to serial port */ - uint8_t outbuf[WC_OUTPUT_BUF_MAX_LEN]; - int outlen; - - int line_speed; - bool send_events; - int axis[INPUT_AXIS__MAX]; - bool btns[INPUT_BUTTON__MAX]; - -} TabletChardev; - -#define TYPE_CHARDEV_WCTABLET "chardev-wctablet" -#define WCTABLET_CHARDEV(obj) \ - OBJECT_CHECK(TabletChardev, (obj), TYPE_CHARDEV_WCTABLET) - - -static void wctablet_chr_accept_input(Chardev *chr); - -static void wctablet_shift_input(TabletChardev *tablet, int count) -{ - tablet->query_index -= count; - memmove(tablet->query, tablet->query + count, tablet->query_index); - tablet->query[tablet->query_index] = 0; -} - -static void wctablet_queue_output(TabletChardev *tablet, uint8_t *buf, int count) -{ - if (tablet->outlen + count > sizeof(tablet->outbuf)) { - return; - } - - memcpy(tablet->outbuf + tablet->outlen, buf, count); - tablet->outlen += count; - wctablet_chr_accept_input(CHARDEV(tablet)); -} - -static void wctablet_reset(TabletChardev *tablet) -{ - /* clear buffers */ - tablet->query_index = 0; - tablet->outlen = 0; - /* reset state */ - tablet->send_events = false; -} - -static void wctablet_queue_event(TabletChardev *tablet) -{ - uint8_t codes[8] = { 0xe0, 0, 0, 0, 0, 0, 0 }; - - if (tablet->line_speed != 9600) { - return; - } - - int newX = tablet->axis[INPUT_AXIS_X] * 0.1537; - int nexY = tablet->axis[INPUT_AXIS_Y] * 0.1152; - - codes[0] = codes[0] | WC_H2(newX); - codes[1] = codes[1] | WC_M7(newX); - codes[2] = codes[2] | WC_L7(newX); - - codes[3] = codes[3] | WC_H2(nexY); - codes[4] = codes[4] | WC_M7(nexY); - codes[5] = codes[5] | WC_L7(nexY); - - if (tablet->btns[INPUT_BUTTON_LEFT]) { - codes[0] = 0xa0; - } - - wctablet_queue_output(tablet, codes, 7); -} - -static void wctablet_input_event(DeviceState *dev, QemuConsole *src, - InputEvent *evt) -{ - TabletChardev *tablet = (TabletChardev *)dev; - InputMoveEvent *move; - InputBtnEvent *btn; - - switch (evt->type) { - case INPUT_EVENT_KIND_ABS: - move = evt->u.abs.data; - tablet->axis[move->axis] = move->value; - break; - - case INPUT_EVENT_KIND_BTN: - btn = evt->u.btn.data; - tablet->btns[btn->button] = btn->down; - break; - - default: - /* keep gcc happy */ - break; - } -} - -static void wctablet_input_sync(DeviceState *dev) -{ - TabletChardev *tablet = (TabletChardev *)dev; - - if (tablet->send_events) { - wctablet_queue_event(tablet); - } -} - -static QemuInputHandler wctablet_handler = { - .name = "QEMU Wacome Pen Tablet", - .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, - .event = wctablet_input_event, - .sync = wctablet_input_sync, -}; - -static void wctablet_chr_accept_input(Chardev *chr) -{ - TabletChardev *tablet = WCTABLET_CHARDEV(chr); - int len, canWrite; - - canWrite = qemu_chr_be_can_write(chr); - len = canWrite; - if (len > tablet->outlen) { - len = tablet->outlen; - } - - if (len) { - qemu_chr_be_write(chr, tablet->outbuf, len); - tablet->outlen -= len; - if (tablet->outlen) { - memmove(tablet->outbuf, tablet->outbuf + len, tablet->outlen); - } - } -} - -static int wctablet_chr_write(struct Chardev *chr, - const uint8_t *buf, int len) -{ - TabletChardev *tablet = WCTABLET_CHARDEV(chr); - unsigned int i, clen; - char *pos; - - if (tablet->line_speed != 9600) { - return len; - } - for (i = 0; i < len && tablet->query_index < sizeof(tablet->query) - 1; i++) { - tablet->query[tablet->query_index++] = buf[i]; - } - tablet->query[tablet->query_index] = 0; - - while (tablet->query_index > 0 && (tablet->query[0] == '@' || - tablet->query[0] == '\r' || - tablet->query[0] == '\n')) { - wctablet_shift_input(tablet, 1); - } - if (!tablet->query_index) { - return len; - } - - if (strncmp((char *)tablet->query, "~#", 2) == 0) { - /* init / detect sequence */ - trace_wct_init(); - wctablet_shift_input(tablet, 2); - wctablet_queue_output(tablet, WC_MODEL_STRING, - WC_MODEL_STRING_LENGTH); - return len; - } - - /* detect line */ - pos = strchr((char *)tablet->query, '\r'); - if (!pos) { - pos = strchr((char *)tablet->query, '\n'); - } - if (!pos) { - return len; - } - clen = pos - (char *)tablet->query; - - /* process commands */ - if (strncmp((char *)tablet->query, "RE", 2) == 0 && - clen == 2) { - trace_wct_cmd_re(); - wctablet_shift_input(tablet, 3); - wctablet_queue_output(tablet, WC_CONFIG_STRING, - WC_CONFIG_STRING_LENGTH); - - } else if (strncmp((char *)tablet->query, "ST", 2) == 0 && - clen == 2) { - trace_wct_cmd_st(); - wctablet_shift_input(tablet, 3); - tablet->send_events = true; - wctablet_queue_event(tablet); - - } else if (strncmp((char *)tablet->query, "SP", 2) == 0 && - clen == 2) { - trace_wct_cmd_sp(); - wctablet_shift_input(tablet, 3); - tablet->send_events = false; - - } else if (strncmp((char *)tablet->query, "TS", 2) == 0 && - clen == 3) { - unsigned int input = tablet->query[2]; - uint8_t codes[7] = { - 0xa3, - ((input & 0x80) == 0) ? 0x7e : 0x7f, - (((WC_H4(input) & 0x7) ^ 0x5) << 4) | (WC_L4(input) ^ 0x7), - 0x03, - 0x7f, - 0x7f, - 0x00, - }; - trace_wct_cmd_ts(input); - wctablet_shift_input(tablet, 4); - wctablet_queue_output(tablet, codes, 7); - - } else { - tablet->query[clen] = 0; /* terminate line for printing */ - trace_wct_cmd_other((char *)tablet->query); - wctablet_shift_input(tablet, clen + 1); - - } - - return len; -} - -static int wctablet_chr_ioctl(Chardev *chr, int cmd, void *arg) -{ - TabletChardev *tablet = WCTABLET_CHARDEV(chr); - QEMUSerialSetParams *ssp; - - switch (cmd) { - case CHR_IOCTL_SERIAL_SET_PARAMS: - ssp = arg; - if (tablet->line_speed != ssp->speed) { - trace_wct_speed(ssp->speed); - wctablet_reset(tablet); - tablet->line_speed = ssp->speed; - } - break; - default: - return -ENOTSUP; - } - return 0; -} - -static void wctablet_chr_finalize(Object *obj) -{ - TabletChardev *tablet = WCTABLET_CHARDEV(obj); - - qemu_input_handler_unregister(tablet->hs); - g_free(tablet); -} - -static void wctablet_chr_open(Chardev *chr, - ChardevBackend *backend, - bool *be_opened, - Error **errp) -{ - TabletChardev *tablet = WCTABLET_CHARDEV(chr); - - *be_opened = true; - - /* init state machine */ - memcpy(tablet->outbuf, WC_FULL_CONFIG_STRING, WC_FULL_CONFIG_STRING_LENGTH); - tablet->outlen = WC_FULL_CONFIG_STRING_LENGTH; - tablet->query_index = 0; - - tablet->hs = qemu_input_handler_register((DeviceState *)tablet, - &wctablet_handler); -} - -static void wctablet_chr_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->open = wctablet_chr_open; - cc->chr_write = wctablet_chr_write; - cc->chr_ioctl = wctablet_chr_ioctl; - cc->chr_accept_input = wctablet_chr_accept_input; -} - -static const TypeInfo wctablet_type_info = { - .name = TYPE_CHARDEV_WCTABLET, - .parent = TYPE_CHARDEV, - .instance_size = sizeof(TabletChardev), - .instance_finalize = wctablet_chr_finalize, - .class_init = wctablet_chr_class_init, -}; - -static void register_types(void) -{ - type_register_static(&wctablet_type_info); -} - -type_init(register_types); diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs index e0b37dbfd8..52a8127606 100644 --- a/chardev/Makefile.objs +++ b/chardev/Makefile.objs @@ -16,3 +16,9 @@ chardev-obj-y += char-stdio.o chardev-obj-y += char-udp.o chardev-obj-$(CONFIG_WIN32) += char-win.o chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o + +common-obj-y += msmouse.o wctablet.o testdev.o +common-obj-$(CONFIG_BRLAPI) += baum.o +baum.o-cflags := $(SDL_CFLAGS) + +common-obj-$(CONFIG_SPICE) += spice.o diff --git a/chardev/baum.c b/chardev/baum.c new file mode 100644 index 0000000000..302dd9666c --- /dev/null +++ b/chardev/baum.c @@ -0,0 +1,677 @@ +/* + * QEMU Baum Braille Device + * + * Copyright (c) 2008, 2010-2011, 2016 Samuel Thibault + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "chardev/char.h" +#include "qemu/timer.h" +#include "hw/usb.h" +#include "ui/console.h" +#include +#include +#include + +#if 0 +#define DPRINTF(fmt, ...) \ + printf(fmt, ## __VA_ARGS__) +#else +#define DPRINTF(fmt, ...) +#endif + +#define ESC 0x1B + +#define BAUM_REQ_DisplayData 0x01 +#define BAUM_REQ_GetVersionNumber 0x05 +#define BAUM_REQ_GetKeys 0x08 +#define BAUM_REQ_SetMode 0x12 +#define BAUM_REQ_SetProtocol 0x15 +#define BAUM_REQ_GetDeviceIdentity 0x84 +#define BAUM_REQ_GetSerialNumber 0x8A + +#define BAUM_RSP_CellCount 0x01 +#define BAUM_RSP_VersionNumber 0x05 +#define BAUM_RSP_ModeSetting 0x11 +#define BAUM_RSP_CommunicationChannel 0x16 +#define BAUM_RSP_PowerdownSignal 0x17 +#define BAUM_RSP_HorizontalSensors 0x20 +#define BAUM_RSP_VerticalSensors 0x21 +#define BAUM_RSP_RoutingKeys 0x22 +#define BAUM_RSP_Switches 0x23 +#define BAUM_RSP_TopKeys 0x24 +#define BAUM_RSP_HorizontalSensor 0x25 +#define BAUM_RSP_VerticalSensor 0x26 +#define BAUM_RSP_RoutingKey 0x27 +#define BAUM_RSP_FrontKeys6 0x28 +#define BAUM_RSP_BackKeys6 0x29 +#define BAUM_RSP_CommandKeys 0x2B +#define BAUM_RSP_FrontKeys10 0x2C +#define BAUM_RSP_BackKeys10 0x2D +#define BAUM_RSP_EntryKeys 0x33 +#define BAUM_RSP_JoyStick 0x34 +#define BAUM_RSP_ErrorCode 0x40 +#define BAUM_RSP_InfoBlock 0x42 +#define BAUM_RSP_DeviceIdentity 0x84 +#define BAUM_RSP_SerialNumber 0x8A +#define BAUM_RSP_BluetoothName 0x8C + +#define BAUM_TL1 0x01 +#define BAUM_TL2 0x02 +#define BAUM_TL3 0x04 +#define BAUM_TR1 0x08 +#define BAUM_TR2 0x10 +#define BAUM_TR3 0x20 + +#define BUF_SIZE 256 + +typedef struct { + Chardev parent; + + brlapi_handle_t *brlapi; + int brlapi_fd; + unsigned int x, y; + bool deferred_init; + + uint8_t in_buf[BUF_SIZE]; + uint8_t in_buf_used; + uint8_t out_buf[BUF_SIZE]; + uint8_t out_buf_used, out_buf_ptr; + + QEMUTimer *cellCount_timer; +} BaumChardev; + +#define TYPE_CHARDEV_BRAILLE "chardev-braille" +#define BAUM_CHARDEV(obj) OBJECT_CHECK(BaumChardev, (obj), TYPE_CHARDEV_BRAILLE) + +/* Let's assume NABCC by default */ +enum way { + DOTS2ASCII, + ASCII2DOTS +}; +static const uint8_t nabcc_translation[2][256] = { +#ifndef BRLAPI_DOTS +#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \ + ((d1?BRLAPI_DOT1:0)|\ + (d2?BRLAPI_DOT2:0)|\ + (d3?BRLAPI_DOT3:0)|\ + (d4?BRLAPI_DOT4:0)|\ + (d5?BRLAPI_DOT5:0)|\ + (d6?BRLAPI_DOT6:0)|\ + (d7?BRLAPI_DOT7:0)|\ + (d8?BRLAPI_DOT8:0)) +#endif +#define DO(dots, ascii) \ + [DOTS2ASCII][dots] = ascii, \ + [ASCII2DOTS][ascii] = dots + DO(0, ' '), + DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 0, 0, 0), 'a'), + DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 0, 0, 0), 'b'), + DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 0, 0, 0), 'c'), + DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 0, 0, 0), 'd'), + DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 0, 0, 0), 'e'), + DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 0, 0, 0), 'f'), + DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 0, 0, 0), 'g'), + DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 0, 0, 0), 'h'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 0, 0, 0), 'i'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 0, 0, 0), 'j'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 0, 0, 0), 'k'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 0, 0, 0), 'l'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 0, 0, 0), 'm'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 0, 0, 0), 'n'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 0, 0, 0), 'o'), + DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 0, 0, 0), 'p'), + DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 0, 0, 0), 'q'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 0, 0, 0), 'r'), + DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 0, 0, 0), 's'), + DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 0, 0, 0), 't'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 1, 0, 0), 'u'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 1, 0, 0), 'v'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 1, 0, 0), 'w'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 1, 0, 0), 'x'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 1, 0, 0), 'y'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 1, 0, 0), 'z'), + + DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 0, 1, 0), 'A'), + DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 0, 1, 0), 'B'), + DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 0, 1, 0), 'C'), + DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 0, 1, 0), 'D'), + DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 0, 1, 0), 'E'), + DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 0, 1, 0), 'F'), + DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 0, 1, 0), 'G'), + DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 0, 1, 0), 'H'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 0, 1, 0), 'I'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 0, 1, 0), 'J'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 0, 1, 0), 'K'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 0, 1, 0), 'L'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 0, 1, 0), 'M'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 0, 1, 0), 'N'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 0, 1, 0), 'O'), + DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 0, 1, 0), 'P'), + DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 0, 1, 0), 'Q'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 0, 1, 0), 'R'), + DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 0, 1, 0), 'S'), + DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 0, 1, 0), 'T'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 1, 1, 0), 'U'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 1, 1, 0), 'V'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 1, 1, 0), 'W'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 1, 1, 0), 'X'), + DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 1, 1, 0), 'Y'), + DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 1, 1, 0), 'Z'), + + DO(BRLAPI_DOTS(0, 0, 1, 0, 1, 1, 0, 0), '0'), + DO(BRLAPI_DOTS(0, 1, 0, 0, 0, 0, 0, 0), '1'), + DO(BRLAPI_DOTS(0, 1, 1, 0, 0, 0, 0, 0), '2'), + DO(BRLAPI_DOTS(0, 1, 0, 0, 1, 0, 0, 0), '3'), + DO(BRLAPI_DOTS(0, 1, 0, 0, 1, 1, 0, 0), '4'), + DO(BRLAPI_DOTS(0, 1, 0, 0, 0, 1, 0, 0), '5'), + DO(BRLAPI_DOTS(0, 1, 1, 0, 1, 0, 0, 0), '6'), + DO(BRLAPI_DOTS(0, 1, 1, 0, 1, 1, 0, 0), '7'), + DO(BRLAPI_DOTS(0, 1, 1, 0, 0, 1, 0, 0), '8'), + DO(BRLAPI_DOTS(0, 0, 1, 0, 1, 0, 0, 0), '9'), + + DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 1, 0, 0), '.'), + DO(BRLAPI_DOTS(0, 0, 1, 1, 0, 1, 0, 0), '+'), + DO(BRLAPI_DOTS(0, 0, 1, 0, 0, 1, 0, 0), '-'), + DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 1, 0, 0), '*'), + DO(BRLAPI_DOTS(0, 0, 1, 1, 0, 0, 0, 0), '/'), + DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 1, 0, 0), '('), + DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 1, 0, 0), ')'), + + DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 1, 0, 0), '&'), + DO(BRLAPI_DOTS(0, 0, 1, 1, 1, 1, 0, 0), '#'), + + DO(BRLAPI_DOTS(0, 0, 0, 0, 0, 1, 0, 0), ','), + DO(BRLAPI_DOTS(0, 0, 0, 0, 1, 1, 0, 0), ';'), + DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 1, 0, 0), ':'), + DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 1, 0, 0), '!'), + DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 1, 0, 0), '?'), + DO(BRLAPI_DOTS(0, 0, 0, 0, 1, 0, 0, 0), '"'), + DO(BRLAPI_DOTS(0, 0, 1, 0, 0, 0, 0, 0), '\''), + DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 0, 0, 0), '`'), + DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 0, 1, 0), '^'), + DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 0, 0, 0), '~'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 1, 1, 0), '['), + DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 1, 1, 0), ']'), + DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 1, 0, 0), '{'), + DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 1, 0, 0), '}'), + DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 1, 0, 0), '='), + DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 1, 0, 0), '<'), + DO(BRLAPI_DOTS(0, 0, 1, 1, 1, 0, 0, 0), '>'), + DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 1, 0, 0), '$'), + DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 1, 0, 0), '%'), + DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 0, 1, 0), '@'), + DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 1, 0, 0), '|'), + DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 1, 1, 0), '\\'), + DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 1, 0, 0), '_'), +}; + +/* The guest OS has started discussing with us, finish initializing BrlAPI */ +static int baum_deferred_init(BaumChardev *baum) +{ + int tty = BRLAPI_TTY_DEFAULT; + QemuConsole *con; + + if (baum->deferred_init) { + return 1; + } + + if (brlapi__getDisplaySize(baum->brlapi, &baum->x, &baum->y) == -1) { + brlapi_perror("baum: brlapi__getDisplaySize"); + return 0; + } + + con = qemu_console_lookup_by_index(0); + if (con && qemu_console_is_graphic(con)) { + tty = qemu_console_get_window_id(con); + if (tty == -1) + tty = BRLAPI_TTY_DEFAULT; + } + + if (brlapi__enterTtyMode(baum->brlapi, tty, NULL) == -1) { + brlapi_perror("baum: brlapi__enterTtyMode"); + return 0; + } + baum->deferred_init = 1; + return 1; +} + +/* The serial port can receive more of our data */ +static void baum_chr_accept_input(struct Chardev *chr) +{ + BaumChardev *baum = BAUM_CHARDEV(chr); + int room, first; + + if (!baum->out_buf_used) + return; + room = qemu_chr_be_can_write(chr); + if (!room) + return; + if (room > baum->out_buf_used) + room = baum->out_buf_used; + + first = BUF_SIZE - baum->out_buf_ptr; + if (room > first) { + qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first); + baum->out_buf_ptr = 0; + baum->out_buf_used -= first; + room -= first; + } + qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room); + baum->out_buf_ptr += room; + baum->out_buf_used -= room; +} + +/* We want to send a packet */ +static void baum_write_packet(BaumChardev *baum, const uint8_t *buf, int len) +{ + Chardev *chr = CHARDEV(baum); + uint8_t io_buf[1 + 2 * len], *cur = io_buf; + int room; + *cur++ = ESC; + while (len--) + if ((*cur++ = *buf++) == ESC) + *cur++ = ESC; + room = qemu_chr_be_can_write(chr); + len = cur - io_buf; + if (len <= room) { + /* Fits */ + qemu_chr_be_write(chr, io_buf, len); + } else { + int first; + uint8_t out; + /* Can't fit all, send what can be, and store the rest. */ + qemu_chr_be_write(chr, io_buf, room); + len -= room; + cur = io_buf + room; + if (len > BUF_SIZE - baum->out_buf_used) { + /* Can't even store it, drop the previous data... */ + assert(len <= BUF_SIZE); + baum->out_buf_used = 0; + baum->out_buf_ptr = 0; + } + out = baum->out_buf_ptr; + baum->out_buf_used += len; + first = BUF_SIZE - baum->out_buf_ptr; + if (len > first) { + memcpy(baum->out_buf + out, cur, first); + out = 0; + len -= first; + cur += first; + } + memcpy(baum->out_buf + out, cur, len); + } +} + +/* Called when the other end seems to have a wrong idea of our display size */ +static void baum_cellCount_timer_cb(void *opaque) +{ + BaumChardev *baum = BAUM_CHARDEV(opaque); + uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y }; + DPRINTF("Timeout waiting for DisplayData, sending cell count\n"); + baum_write_packet(baum, cell_count, sizeof(cell_count)); +} + +/* Try to interpret a whole incoming packet */ +static int baum_eat_packet(BaumChardev *baum, const uint8_t *buf, int len) +{ + const uint8_t *cur = buf; + uint8_t req = 0; + + if (!len--) + return 0; + if (*cur++ != ESC) { + while (*cur != ESC) { + if (!len--) + return 0; + cur++; + } + DPRINTF("Dropped %td bytes!\n", cur - buf); + } + +#define EAT(c) do {\ + if (!len--) \ + return 0; \ + if ((c = *cur++) == ESC) { \ + if (!len--) \ + return 0; \ + if (*cur++ != ESC) { \ + DPRINTF("Broken packet %#2x, tossing\n", req); \ + if (timer_pending(baum->cellCount_timer)) { \ + timer_del(baum->cellCount_timer); \ + baum_cellCount_timer_cb(baum); \ + } \ + return (cur - 2 - buf); \ + } \ + } \ +} while (0) + + EAT(req); + switch (req) { + case BAUM_REQ_DisplayData: + { + uint8_t cells[baum->x * baum->y], c; + uint8_t text[baum->x * baum->y]; + uint8_t zero[baum->x * baum->y]; + int cursor = BRLAPI_CURSOR_OFF; + int i; + + /* Allow 100ms to complete the DisplayData packet */ + timer_mod(baum->cellCount_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + NANOSECONDS_PER_SECOND / 10); + for (i = 0; i < baum->x * baum->y ; i++) { + EAT(c); + cells[i] = c; + if ((c & (BRLAPI_DOT7|BRLAPI_DOT8)) + == (BRLAPI_DOT7|BRLAPI_DOT8)) { + cursor = i + 1; + c &= ~(BRLAPI_DOT7|BRLAPI_DOT8); + } + c = nabcc_translation[DOTS2ASCII][c]; + if (!c) { + c = '?'; + } + text[i] = c; + } + timer_del(baum->cellCount_timer); + + memset(zero, 0, sizeof(zero)); + + brlapi_writeArguments_t wa = { + .displayNumber = BRLAPI_DISPLAY_DEFAULT, + .regionBegin = 1, + .regionSize = baum->x * baum->y, + .text = (char *)text, + .textSize = baum->x * baum->y, + .andMask = zero, + .orMask = cells, + .cursor = cursor, + .charset = (char *)"ISO-8859-1", + }; + + if (brlapi__write(baum->brlapi, &wa) == -1) + brlapi_perror("baum brlapi_write"); + break; + } + case BAUM_REQ_SetMode: + { + uint8_t mode, setting; + DPRINTF("SetMode\n"); + EAT(mode); + EAT(setting); + /* ignore */ + break; + } + case BAUM_REQ_SetProtocol: + { + uint8_t protocol; + DPRINTF("SetProtocol\n"); + EAT(protocol); + /* ignore */ + break; + } + case BAUM_REQ_GetDeviceIdentity: + { + uint8_t identity[17] = { BAUM_RSP_DeviceIdentity, + 'B','a','u','m',' ','V','a','r','i','o' }; + DPRINTF("GetDeviceIdentity\n"); + identity[11] = '0' + baum->x / 10; + identity[12] = '0' + baum->x % 10; + baum_write_packet(baum, identity, sizeof(identity)); + break; + } + case BAUM_REQ_GetVersionNumber: + { + uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */ + DPRINTF("GetVersionNumber\n"); + baum_write_packet(baum, version, sizeof(version)); + break; + } + case BAUM_REQ_GetSerialNumber: + { + uint8_t serial[] = { BAUM_RSP_SerialNumber, + '0','0','0','0','0','0','0','0' }; + DPRINTF("GetSerialNumber\n"); + baum_write_packet(baum, serial, sizeof(serial)); + break; + } + case BAUM_REQ_GetKeys: + { + DPRINTF("Get%0#2x\n", req); + /* ignore */ + break; + } + default: + DPRINTF("unrecognized request %0#2x\n", req); + do + if (!len--) + return 0; + while (*cur++ != ESC); + cur--; + break; + } + return cur - buf; +} + +/* The other end is writing some data. Store it and try to interpret */ +static int baum_chr_write(Chardev *chr, const uint8_t *buf, int len) +{ + BaumChardev *baum = BAUM_CHARDEV(chr); + int tocopy, cur, eaten, orig_len = len; + + if (!len) + return 0; + if (!baum->brlapi) + return len; + if (!baum_deferred_init(baum)) + return len; + + while (len) { + /* Complete our buffer as much as possible */ + tocopy = len; + if (tocopy > BUF_SIZE - baum->in_buf_used) + tocopy = BUF_SIZE - baum->in_buf_used; + + memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy); + baum->in_buf_used += tocopy; + buf += tocopy; + len -= tocopy; + + /* Interpret it as much as possible */ + cur = 0; + while (cur < baum->in_buf_used && + (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur))) + cur += eaten; + + /* Shift the remainder */ + if (cur) { + memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur); + baum->in_buf_used -= cur; + } + + /* And continue if any data left */ + } + return orig_len; +} + +/* Send the key code to the other end */ +static void baum_send_key(BaumChardev *baum, uint8_t type, uint8_t value) +{ + uint8_t packet[] = { type, value }; + DPRINTF("writing key %x %x\n", type, value); + baum_write_packet(baum, packet, sizeof(packet)); +} + +static void baum_send_key2(BaumChardev *baum, uint8_t type, uint8_t value, + uint8_t value2) +{ + uint8_t packet[] = { type, value, value2 }; + DPRINTF("writing key %x %x\n", type, value); + baum_write_packet(baum, packet, sizeof(packet)); +} + +/* We got some data on the BrlAPI socket */ +static void baum_chr_read(void *opaque) +{ + BaumChardev *baum = BAUM_CHARDEV(opaque); + brlapi_keyCode_t code; + int ret; + if (!baum->brlapi) + return; + if (!baum_deferred_init(baum)) + return; + while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) { + DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code); + /* Emulate */ + switch (code & BRLAPI_KEY_TYPE_MASK) { + case BRLAPI_KEY_TYPE_CMD: + switch (code & BRLAPI_KEY_CMD_BLK_MASK) { + case BRLAPI_KEY_CMD_ROUTE: + baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1); + baum_send_key(baum, BAUM_RSP_RoutingKey, 0); + break; + case 0: + switch (code & BRLAPI_KEY_CMD_ARG_MASK) { + case BRLAPI_KEY_CMD_FWINLT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_FWINRT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_LNUP: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_LNDN: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_TOP: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_BOT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_TOP_LEFT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_BOT_LEFT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_HOME: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_PREFMENU: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + } + } + break; + case BRLAPI_KEY_TYPE_SYM: + { + brlapi_keyCode_t keysym = code & BRLAPI_KEY_CODE_MASK; + if (keysym < 0x100) { + uint8_t dots = nabcc_translation[ASCII2DOTS][keysym]; + if (dots) { + baum_send_key2(baum, BAUM_RSP_EntryKeys, 0, dots); + baum_send_key2(baum, BAUM_RSP_EntryKeys, 0, 0); + } + } + break; + } + } + } + if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) { + brlapi_perror("baum: brlapi_readKey"); + brlapi__closeConnection(baum->brlapi); + g_free(baum->brlapi); + baum->brlapi = NULL; + } +} + +static void char_braille_finalize(Object *obj) +{ + BaumChardev *baum = BAUM_CHARDEV(obj); + + timer_free(baum->cellCount_timer); + if (baum->brlapi) { + brlapi__closeConnection(baum->brlapi); + g_free(baum->brlapi); + } +} + +static void baum_chr_open(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + BaumChardev *baum = BAUM_CHARDEV(chr); + brlapi_handle_t *handle; + + handle = g_malloc0(brlapi_getHandleSize()); + baum->brlapi = handle; + + baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL); + if (baum->brlapi_fd == -1) { + error_setg(errp, "brlapi__openConnection: %s", + brlapi_strerror(brlapi_error_location())); + g_free(handle); + return; + } + baum->deferred_init = 0; + + baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum); + + qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum); +} + +static void char_braille_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->open = baum_chr_open; + cc->chr_write = baum_chr_write; + cc->chr_accept_input = baum_chr_accept_input; +} + +static const TypeInfo char_braille_type_info = { + .name = TYPE_CHARDEV_BRAILLE, + .parent = TYPE_CHARDEV, + .instance_size = sizeof(BaumChardev), + .instance_finalize = char_braille_finalize, + .class_init = char_braille_class_init, +}; + +static void register_types(void) +{ + type_register_static(&char_braille_type_info); +} + +type_init(register_types); diff --git a/chardev/msmouse.c b/chardev/msmouse.c new file mode 100644 index 0000000000..0ffd137ce8 --- /dev/null +++ b/chardev/msmouse.c @@ -0,0 +1,190 @@ +/* + * QEMU Microsoft serial mouse emulation + * + * Copyright (c) 2008 Lubomir Rintel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "chardev/char.h" +#include "ui/console.h" +#include "ui/input.h" + +#define MSMOUSE_LO6(n) ((n) & 0x3f) +#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) + +typedef struct { + Chardev parent; + + QemuInputHandlerState *hs; + int axis[INPUT_AXIS__MAX]; + bool btns[INPUT_BUTTON__MAX]; + bool btnc[INPUT_BUTTON__MAX]; + uint8_t outbuf[32]; + int outlen; +} MouseChardev; + +#define TYPE_CHARDEV_MSMOUSE "chardev-msmouse" +#define MOUSE_CHARDEV(obj) \ + OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE) + +static void msmouse_chr_accept_input(Chardev *chr) +{ + MouseChardev *mouse = MOUSE_CHARDEV(chr); + int len; + + len = qemu_chr_be_can_write(chr); + if (len > mouse->outlen) { + len = mouse->outlen; + } + if (!len) { + return; + } + + qemu_chr_be_write(chr, mouse->outbuf, len); + mouse->outlen -= len; + if (mouse->outlen) { + memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen); + } +} + +static void msmouse_queue_event(MouseChardev *mouse) +{ + unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 }; + int dx, dy, count = 3; + + dx = mouse->axis[INPUT_AXIS_X]; + mouse->axis[INPUT_AXIS_X] = 0; + + dy = mouse->axis[INPUT_AXIS_Y]; + mouse->axis[INPUT_AXIS_Y] = 0; + + /* Movement deltas */ + bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx); + bytes[1] |= MSMOUSE_LO6(dx); + bytes[2] |= MSMOUSE_LO6(dy); + + /* Buttons */ + bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT] ? 0x20 : 0x00); + bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT] ? 0x10 : 0x00); + if (mouse->btns[INPUT_BUTTON_MIDDLE] || + mouse->btnc[INPUT_BUTTON_MIDDLE]) { + bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00); + mouse->btnc[INPUT_BUTTON_MIDDLE] = false; + count = 4; + } + + if (mouse->outlen <= sizeof(mouse->outbuf) - count) { + memcpy(mouse->outbuf + mouse->outlen, bytes, count); + mouse->outlen += count; + } else { + /* queue full -> drop event */ + } +} + +static void msmouse_input_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) +{ + MouseChardev *mouse = MOUSE_CHARDEV(dev); + InputMoveEvent *move; + InputBtnEvent *btn; + + switch (evt->type) { + case INPUT_EVENT_KIND_REL: + move = evt->u.rel.data; + mouse->axis[move->axis] += move->value; + break; + + case INPUT_EVENT_KIND_BTN: + btn = evt->u.btn.data; + mouse->btns[btn->button] = btn->down; + mouse->btnc[btn->button] = true; + break; + + default: + /* keep gcc happy */ + break; + } +} + +static void msmouse_input_sync(DeviceState *dev) +{ + MouseChardev *mouse = MOUSE_CHARDEV(dev); + Chardev *chr = CHARDEV(dev); + + msmouse_queue_event(mouse); + msmouse_chr_accept_input(chr); +} + +static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len) +{ + /* Ignore writes to mouse port */ + return len; +} + +static void char_msmouse_finalize(Object *obj) +{ + MouseChardev *mouse = MOUSE_CHARDEV(obj); + + qemu_input_handler_unregister(mouse->hs); +} + +static QemuInputHandler msmouse_handler = { + .name = "QEMU Microsoft Mouse", + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, + .event = msmouse_input_event, + .sync = msmouse_input_sync, +}; + +static void msmouse_chr_open(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + MouseChardev *mouse = MOUSE_CHARDEV(chr); + + *be_opened = false; + mouse->hs = qemu_input_handler_register((DeviceState *)mouse, + &msmouse_handler); +} + +static void char_msmouse_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->open = msmouse_chr_open; + cc->chr_write = msmouse_chr_write; + cc->chr_accept_input = msmouse_chr_accept_input; +} + +static const TypeInfo char_msmouse_type_info = { + .name = TYPE_CHARDEV_MSMOUSE, + .parent = TYPE_CHARDEV, + .instance_size = sizeof(MouseChardev), + .instance_finalize = char_msmouse_finalize, + .class_init = char_msmouse_class_init, +}; + +static void register_types(void) +{ + type_register_static(&char_msmouse_type_info); +} + +type_init(register_types); diff --git a/chardev/spice.c b/chardev/spice.c new file mode 100644 index 0000000000..a312078812 --- /dev/null +++ b/chardev/spice.c @@ -0,0 +1,421 @@ +#include "qemu/osdep.h" +#include "trace.h" +#include "ui/qemu-spice.h" +#include "chardev/char.h" +#include "qemu/error-report.h" +#include +#include + + +typedef struct SpiceChardev { + Chardev parent; + + SpiceCharDeviceInstance sin; + bool active; + bool blocked; + const uint8_t *datapos; + int datalen; + QLIST_ENTRY(SpiceChardev) next; +} SpiceChardev; + +#define TYPE_CHARDEV_SPICE "chardev-spice" +#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc" +#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport" + +#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE) + +typedef struct SpiceCharSource { + GSource source; + SpiceChardev *scd; +} SpiceCharSource; + +static QLIST_HEAD(, SpiceChardev) spice_chars = + QLIST_HEAD_INITIALIZER(spice_chars); + +static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) +{ + SpiceChardev *scd = container_of(sin, SpiceChardev, sin); + Chardev *chr = CHARDEV(scd); + ssize_t out = 0; + ssize_t last_out; + uint8_t* p = (uint8_t*)buf; + + while (len > 0) { + int can_write = qemu_chr_be_can_write(chr); + last_out = MIN(len, can_write); + if (last_out <= 0) { + break; + } + qemu_chr_be_write(chr, p, last_out); + out += last_out; + len -= last_out; + p += last_out; + } + + trace_spice_vmc_write(out, len + out); + return out; +} + +static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) +{ + SpiceChardev *scd = container_of(sin, SpiceChardev, sin); + int bytes = MIN(len, scd->datalen); + + if (bytes > 0) { + memcpy(buf, scd->datapos, bytes); + scd->datapos += bytes; + scd->datalen -= bytes; + assert(scd->datalen >= 0); + } + if (scd->datalen == 0) { + scd->datapos = 0; + scd->blocked = false; + } + trace_spice_vmc_read(bytes, len); + return bytes; +} + +#if SPICE_SERVER_VERSION >= 0x000c02 +static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event) +{ + SpiceChardev *scd = container_of(sin, SpiceChardev, sin); + Chardev *chr = CHARDEV(scd); + int chr_event; + + switch (event) { + case SPICE_PORT_EVENT_BREAK: + chr_event = CHR_EVENT_BREAK; + break; + default: + return; + } + + trace_spice_vmc_event(chr_event); + qemu_chr_be_event(chr, chr_event); +} +#endif + +static void vmc_state(SpiceCharDeviceInstance *sin, int connected) +{ + SpiceChardev *scd = container_of(sin, SpiceChardev, sin); + Chardev *chr = CHARDEV(scd); + + if ((chr->be_open && connected) || + (!chr->be_open && !connected)) { + return; + } + + qemu_chr_be_event(chr, + connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED); +} + +static SpiceCharDeviceInterface vmc_interface = { + .base.type = SPICE_INTERFACE_CHAR_DEVICE, + .base.description = "spice virtual channel char device", + .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, + .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, + .state = vmc_state, + .write = vmc_write, + .read = vmc_read, +#if SPICE_SERVER_VERSION >= 0x000c02 + .event = vmc_event, +#endif +#if SPICE_SERVER_VERSION >= 0x000c06 + .flags = SPICE_CHAR_DEVICE_NOTIFY_WRITABLE, +#endif +}; + + +static void vmc_register_interface(SpiceChardev *scd) +{ + if (scd->active) { + return; + } + scd->sin.base.sif = &vmc_interface.base; + qemu_spice_add_interface(&scd->sin.base); + scd->active = true; + trace_spice_vmc_register_interface(scd); +} + +static void vmc_unregister_interface(SpiceChardev *scd) +{ + if (!scd->active) { + return; + } + spice_server_remove_interface(&scd->sin.base); + scd->active = false; + trace_spice_vmc_unregister_interface(scd); +} + +static gboolean spice_char_source_prepare(GSource *source, gint *timeout) +{ + SpiceCharSource *src = (SpiceCharSource *)source; + + *timeout = -1; + + return !src->scd->blocked; +} + +static gboolean spice_char_source_check(GSource *source) +{ + SpiceCharSource *src = (SpiceCharSource *)source; + + return !src->scd->blocked; +} + +static gboolean spice_char_source_dispatch(GSource *source, + GSourceFunc callback, gpointer user_data) +{ + GIOFunc func = (GIOFunc)callback; + + return func(NULL, G_IO_OUT, user_data); +} + +static GSourceFuncs SpiceCharSourceFuncs = { + .prepare = spice_char_source_prepare, + .check = spice_char_source_check, + .dispatch = spice_char_source_dispatch, +}; + +static GSource *spice_chr_add_watch(Chardev *chr, GIOCondition cond) +{ + SpiceChardev *scd = SPICE_CHARDEV(chr); + SpiceCharSource *src; + + assert(cond & G_IO_OUT); + + src = (SpiceCharSource *)g_source_new(&SpiceCharSourceFuncs, + sizeof(SpiceCharSource)); + src->scd = scd; + + return (GSource *)src; +} + +static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len) +{ + SpiceChardev *s = SPICE_CHARDEV(chr); + int read_bytes; + + assert(s->datalen == 0); + s->datapos = buf; + s->datalen = len; + spice_server_char_device_wakeup(&s->sin); + read_bytes = len - s->datalen; + if (read_bytes != len) { + /* We'll get passed in the unconsumed data with the next call */ + s->datalen = 0; + s->datapos = NULL; + s->blocked = true; + } + return read_bytes; +} + +static void char_spice_finalize(Object *obj) +{ + SpiceChardev *s = SPICE_CHARDEV(obj); + + vmc_unregister_interface(s); + + if (s->next.le_prev) { + QLIST_REMOVE(s, next); + } + + g_free((char *)s->sin.subtype); +#if SPICE_SERVER_VERSION >= 0x000c02 + g_free((char *)s->sin.portname); +#endif +} + +static void spice_vmc_set_fe_open(struct Chardev *chr, int fe_open) +{ + SpiceChardev *s = SPICE_CHARDEV(chr); + if (fe_open) { + vmc_register_interface(s); + } else { + vmc_unregister_interface(s); + } +} + +static void spice_port_set_fe_open(struct Chardev *chr, int fe_open) +{ +#if SPICE_SERVER_VERSION >= 0x000c02 + SpiceChardev *s = SPICE_CHARDEV(chr); + + if (fe_open) { + spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED); + } else { + spice_server_port_event(&s->sin, SPICE_PORT_EVENT_CLOSED); + } +#endif +} + +static void spice_chr_accept_input(struct Chardev *chr) +{ + SpiceChardev *s = SPICE_CHARDEV(chr); + + spice_server_char_device_wakeup(&s->sin); +} + +static void chr_open(Chardev *chr, const char *subtype) +{ + SpiceChardev *s = SPICE_CHARDEV(chr); + + s->active = false; + s->sin.subtype = g_strdup(subtype); + + QLIST_INSERT_HEAD(&spice_chars, s, next); +} + +static void qemu_chr_open_spice_vmc(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data; + const char *type = spicevmc->type; + const char **psubtype = spice_server_char_device_recognized_subtypes(); + + for (; *psubtype != NULL; ++psubtype) { + if (strcmp(type, *psubtype) == 0) { + break; + } + } + if (*psubtype == NULL) { + char *subtypes = g_strjoinv(", ", + (gchar **)spice_server_char_device_recognized_subtypes()); + + error_setg(errp, "unsupported type name: %s", type); + error_append_hint(errp, "allowed spice char type names: %s\n", + subtypes); + + g_free(subtypes); + return; + } + + *be_opened = false; + chr_open(chr, type); +} + +#if SPICE_SERVER_VERSION >= 0x000c02 +static void qemu_chr_open_spice_port(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + ChardevSpicePort *spiceport = backend->u.spiceport.data; + const char *name = spiceport->fqdn; + SpiceChardev *s; + + if (name == NULL) { + error_setg(errp, "missing name parameter"); + return; + } + + chr_open(chr, "port"); + + *be_opened = false; + s = SPICE_CHARDEV(chr); + s->sin.portname = g_strdup(name); +} + +void qemu_spice_register_ports(void) +{ + SpiceChardev *s; + + QLIST_FOREACH(s, &spice_chars, next) { + if (s->sin.portname == NULL) { + continue; + } + vmc_register_interface(s); + } +} +#endif + +static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + const char *name = qemu_opt_get(opts, "name"); + ChardevSpiceChannel *spicevmc; + + if (name == NULL) { + error_setg(errp, "chardev: spice channel: no name given"); + return; + } + backend->type = CHARDEV_BACKEND_KIND_SPICEVMC; + spicevmc = backend->u.spicevmc.data = g_new0(ChardevSpiceChannel, 1); + qemu_chr_parse_common(opts, qapi_ChardevSpiceChannel_base(spicevmc)); + spicevmc->type = g_strdup(name); +} + +static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + const char *name = qemu_opt_get(opts, "name"); + ChardevSpicePort *spiceport; + + if (name == NULL) { + error_setg(errp, "chardev: spice port: no name given"); + return; + } + backend->type = CHARDEV_BACKEND_KIND_SPICEPORT; + spiceport = backend->u.spiceport.data = g_new0(ChardevSpicePort, 1); + qemu_chr_parse_common(opts, qapi_ChardevSpicePort_base(spiceport)); + spiceport->fqdn = g_strdup(name); +} + +static void char_spice_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->chr_write = spice_chr_write; + cc->chr_add_watch = spice_chr_add_watch; + cc->chr_accept_input = spice_chr_accept_input; +} + +static const TypeInfo char_spice_type_info = { + .name = TYPE_CHARDEV_SPICE, + .parent = TYPE_CHARDEV, + .instance_size = sizeof(SpiceChardev), + .instance_finalize = char_spice_finalize, + .class_init = char_spice_class_init, + .abstract = true, +}; + +static void char_spicevmc_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->parse = qemu_chr_parse_spice_vmc; + cc->open = qemu_chr_open_spice_vmc; + cc->chr_set_fe_open = spice_vmc_set_fe_open; +} + +static const TypeInfo char_spicevmc_type_info = { + .name = TYPE_CHARDEV_SPICEVMC, + .parent = TYPE_CHARDEV_SPICE, + .class_init = char_spicevmc_class_init, +}; + +static void char_spiceport_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->parse = qemu_chr_parse_spice_port; + cc->open = qemu_chr_open_spice_port; + cc->chr_set_fe_open = spice_port_set_fe_open; +} + +static const TypeInfo char_spiceport_type_info = { + .name = TYPE_CHARDEV_SPICEPORT, + .parent = TYPE_CHARDEV_SPICE, + .class_init = char_spiceport_class_init, +}; + +static void register_types(void) +{ + type_register_static(&char_spice_type_info); + type_register_static(&char_spicevmc_type_info); + type_register_static(&char_spiceport_type_info); +} + +type_init(register_types); diff --git a/chardev/testdev.c b/chardev/testdev.c new file mode 100644 index 0000000000..031e9a23e8 --- /dev/null +++ b/chardev/testdev.c @@ -0,0 +1,129 @@ +/* + * QEMU Char Device for testsuite control + * + * Copyright (c) 2014 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "chardev/char.h" + +#define BUF_SIZE 32 + +typedef struct { + Chardev parent; + + uint8_t in_buf[32]; + int in_buf_used; +} TestdevChardev; + +#define TYPE_CHARDEV_TESTDEV "chardev-testdev" +#define TESTDEV_CHARDEV(obj) \ + OBJECT_CHECK(TestdevChardev, (obj), TYPE_CHARDEV_TESTDEV) + +/* Try to interpret a whole incoming packet */ +static int testdev_eat_packet(TestdevChardev *testdev) +{ + const uint8_t *cur = testdev->in_buf; + int len = testdev->in_buf_used; + uint8_t c; + int arg; + +#define EAT(c) do { \ + if (!len--) { \ + return 0; \ + } \ + c = *cur++; \ +} while (0) + + EAT(c); + + while (isspace(c)) { + EAT(c); + } + + arg = 0; + while (isdigit(c)) { + arg = arg * 10 + c - '0'; + EAT(c); + } + + while (isspace(c)) { + EAT(c); + } + + switch (c) { + case 'q': + exit((arg << 1) | 1); + break; + default: + break; + } + return cur - testdev->in_buf; +} + +/* The other end is writing some data. Store it and try to interpret */ +static int testdev_chr_write(Chardev *chr, const uint8_t *buf, int len) +{ + TestdevChardev *testdev = TESTDEV_CHARDEV(chr); + int tocopy, eaten, orig_len = len; + + while (len) { + /* Complete our buffer as much as possible */ + tocopy = MIN(len, BUF_SIZE - testdev->in_buf_used); + + memcpy(testdev->in_buf + testdev->in_buf_used, buf, tocopy); + testdev->in_buf_used += tocopy; + buf += tocopy; + len -= tocopy; + + /* Interpret it as much as possible */ + while (testdev->in_buf_used > 0 && + (eaten = testdev_eat_packet(testdev)) > 0) { + memmove(testdev->in_buf, testdev->in_buf + eaten, + testdev->in_buf_used - eaten); + testdev->in_buf_used -= eaten; + } + } + return orig_len; +} + +static void char_testdev_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->chr_write = testdev_chr_write; +} + +static const TypeInfo char_testdev_type_info = { + .name = TYPE_CHARDEV_TESTDEV, + .parent = TYPE_CHARDEV, + .instance_size = sizeof(TestdevChardev), + .class_init = char_testdev_class_init, +}; + +static void register_types(void) +{ + type_register_static(&char_testdev_type_info); +} + +type_init(register_types); diff --git a/chardev/trace-events b/chardev/trace-events new file mode 100644 index 0000000000..822dde668b --- /dev/null +++ b/chardev/trace-events @@ -0,0 +1,18 @@ +# See docs/tracing.txt for syntax documentation. + +# chardev/wctablet.c +wct_init(void) "" +wct_cmd_re(void) "" +wct_cmd_st(void) "" +wct_cmd_sp(void) "" +wct_cmd_ts(int input) "0x%02x" +wct_cmd_other(const char *cmd) "%s" +wct_speed(int speed) "%d" + +# chardev/spice.c +spice_vmc_write(ssize_t out, int len) "spice wrote %zd of requested %d" +spice_vmc_read(int bytes, int len) "spice read %d of requested %d" +spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" +spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" +spice_vmc_event(int event) "spice vmc event %d" + diff --git a/chardev/wctablet.c b/chardev/wctablet.c new file mode 100644 index 0000000000..6c13c2c58a --- /dev/null +++ b/chardev/wctablet.c @@ -0,0 +1,369 @@ +/* + * QEMU Wacom Penpartner serial tablet emulation + * + * some protocol details: + * http://linuxwacom.sourceforge.net/wiki/index.php/Serial_Protocol_IV + * + * Copyright (c) 2016 Anatoli Huseu1 + * Copyright (c) 2016,17 Gerd Hoffmann + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "chardev/char-serial.h" +#include "ui/console.h" +#include "ui/input.h" +#include "trace.h" + + +#define WC_OUTPUT_BUF_MAX_LEN 512 +#define WC_COMMAND_MAX_LEN 60 + +#define WC_L7(n) ((n) & 127) +#define WC_M7(n) (((n) >> 7) & 127) +#define WC_H2(n) ((n) >> 14) + +#define WC_L4(n) ((n) & 15) +#define WC_H4(n) (((n) >> 4) & 15) + +/* Model string and config string */ +#define WC_MODEL_STRING_LENGTH 18 +uint8_t WC_MODEL_STRING[WC_MODEL_STRING_LENGTH + 1] = "~#CT-0045R,V1.3-5,"; + +#define WC_CONFIG_STRING_LENGTH 8 +uint8_t WC_CONFIG_STRING[WC_CONFIG_STRING_LENGTH + 1] = "96,N,8,0"; + +#define WC_FULL_CONFIG_STRING_LENGTH 61 +uint8_t WC_FULL_CONFIG_STRING[WC_FULL_CONFIG_STRING_LENGTH + 1] = { + 0x5c, 0x39, 0x36, 0x2c, 0x4e, 0x2c, 0x38, 0x2c, + 0x31, 0x28, 0x01, 0x24, 0x57, 0x41, 0x43, 0x30, + 0x30, 0x34, 0x35, 0x5c, 0x5c, 0x50, 0x45, 0x4e, 0x5c, + 0x57, 0x41, 0x43, 0x30, 0x30, 0x30, 0x30, 0x5c, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x0d, 0x0a, + 0x43, 0x54, 0x2d, 0x30, 0x30, 0x34, 0x35, 0x52, + 0x2c, 0x56, 0x31, 0x2e, 0x33, 0x2d, 0x35, 0x0d, + 0x0a, 0x45, 0x37, 0x29 +}; + +/* This structure is used to save private info for Wacom Tablet. */ +typedef struct { + Chardev parent; + QemuInputHandlerState *hs; + + /* Query string from serial */ + uint8_t query[100]; + int query_index; + + /* Command to be sent to serial port */ + uint8_t outbuf[WC_OUTPUT_BUF_MAX_LEN]; + int outlen; + + int line_speed; + bool send_events; + int axis[INPUT_AXIS__MAX]; + bool btns[INPUT_BUTTON__MAX]; + +} TabletChardev; + +#define TYPE_CHARDEV_WCTABLET "chardev-wctablet" +#define WCTABLET_CHARDEV(obj) \ + OBJECT_CHECK(TabletChardev, (obj), TYPE_CHARDEV_WCTABLET) + + +static void wctablet_chr_accept_input(Chardev *chr); + +static void wctablet_shift_input(TabletChardev *tablet, int count) +{ + tablet->query_index -= count; + memmove(tablet->query, tablet->query + count, tablet->query_index); + tablet->query[tablet->query_index] = 0; +} + +static void wctablet_queue_output(TabletChardev *tablet, uint8_t *buf, int count) +{ + if (tablet->outlen + count > sizeof(tablet->outbuf)) { + return; + } + + memcpy(tablet->outbuf + tablet->outlen, buf, count); + tablet->outlen += count; + wctablet_chr_accept_input(CHARDEV(tablet)); +} + +static void wctablet_reset(TabletChardev *tablet) +{ + /* clear buffers */ + tablet->query_index = 0; + tablet->outlen = 0; + /* reset state */ + tablet->send_events = false; +} + +static void wctablet_queue_event(TabletChardev *tablet) +{ + uint8_t codes[8] = { 0xe0, 0, 0, 0, 0, 0, 0 }; + + if (tablet->line_speed != 9600) { + return; + } + + int newX = tablet->axis[INPUT_AXIS_X] * 0.1537; + int nexY = tablet->axis[INPUT_AXIS_Y] * 0.1152; + + codes[0] = codes[0] | WC_H2(newX); + codes[1] = codes[1] | WC_M7(newX); + codes[2] = codes[2] | WC_L7(newX); + + codes[3] = codes[3] | WC_H2(nexY); + codes[4] = codes[4] | WC_M7(nexY); + codes[5] = codes[5] | WC_L7(nexY); + + if (tablet->btns[INPUT_BUTTON_LEFT]) { + codes[0] = 0xa0; + } + + wctablet_queue_output(tablet, codes, 7); +} + +static void wctablet_input_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) +{ + TabletChardev *tablet = (TabletChardev *)dev; + InputMoveEvent *move; + InputBtnEvent *btn; + + switch (evt->type) { + case INPUT_EVENT_KIND_ABS: + move = evt->u.abs.data; + tablet->axis[move->axis] = move->value; + break; + + case INPUT_EVENT_KIND_BTN: + btn = evt->u.btn.data; + tablet->btns[btn->button] = btn->down; + break; + + default: + /* keep gcc happy */ + break; + } +} + +static void wctablet_input_sync(DeviceState *dev) +{ + TabletChardev *tablet = (TabletChardev *)dev; + + if (tablet->send_events) { + wctablet_queue_event(tablet); + } +} + +static QemuInputHandler wctablet_handler = { + .name = "QEMU Wacome Pen Tablet", + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, + .event = wctablet_input_event, + .sync = wctablet_input_sync, +}; + +static void wctablet_chr_accept_input(Chardev *chr) +{ + TabletChardev *tablet = WCTABLET_CHARDEV(chr); + int len, canWrite; + + canWrite = qemu_chr_be_can_write(chr); + len = canWrite; + if (len > tablet->outlen) { + len = tablet->outlen; + } + + if (len) { + qemu_chr_be_write(chr, tablet->outbuf, len); + tablet->outlen -= len; + if (tablet->outlen) { + memmove(tablet->outbuf, tablet->outbuf + len, tablet->outlen); + } + } +} + +static int wctablet_chr_write(struct Chardev *chr, + const uint8_t *buf, int len) +{ + TabletChardev *tablet = WCTABLET_CHARDEV(chr); + unsigned int i, clen; + char *pos; + + if (tablet->line_speed != 9600) { + return len; + } + for (i = 0; i < len && tablet->query_index < sizeof(tablet->query) - 1; i++) { + tablet->query[tablet->query_index++] = buf[i]; + } + tablet->query[tablet->query_index] = 0; + + while (tablet->query_index > 0 && (tablet->query[0] == '@' || + tablet->query[0] == '\r' || + tablet->query[0] == '\n')) { + wctablet_shift_input(tablet, 1); + } + if (!tablet->query_index) { + return len; + } + + if (strncmp((char *)tablet->query, "~#", 2) == 0) { + /* init / detect sequence */ + trace_wct_init(); + wctablet_shift_input(tablet, 2); + wctablet_queue_output(tablet, WC_MODEL_STRING, + WC_MODEL_STRING_LENGTH); + return len; + } + + /* detect line */ + pos = strchr((char *)tablet->query, '\r'); + if (!pos) { + pos = strchr((char *)tablet->query, '\n'); + } + if (!pos) { + return len; + } + clen = pos - (char *)tablet->query; + + /* process commands */ + if (strncmp((char *)tablet->query, "RE", 2) == 0 && + clen == 2) { + trace_wct_cmd_re(); + wctablet_shift_input(tablet, 3); + wctablet_queue_output(tablet, WC_CONFIG_STRING, + WC_CONFIG_STRING_LENGTH); + + } else if (strncmp((char *)tablet->query, "ST", 2) == 0 && + clen == 2) { + trace_wct_cmd_st(); + wctablet_shift_input(tablet, 3); + tablet->send_events = true; + wctablet_queue_event(tablet); + + } else if (strncmp((char *)tablet->query, "SP", 2) == 0 && + clen == 2) { + trace_wct_cmd_sp(); + wctablet_shift_input(tablet, 3); + tablet->send_events = false; + + } else if (strncmp((char *)tablet->query, "TS", 2) == 0 && + clen == 3) { + unsigned int input = tablet->query[2]; + uint8_t codes[7] = { + 0xa3, + ((input & 0x80) == 0) ? 0x7e : 0x7f, + (((WC_H4(input) & 0x7) ^ 0x5) << 4) | (WC_L4(input) ^ 0x7), + 0x03, + 0x7f, + 0x7f, + 0x00, + }; + trace_wct_cmd_ts(input); + wctablet_shift_input(tablet, 4); + wctablet_queue_output(tablet, codes, 7); + + } else { + tablet->query[clen] = 0; /* terminate line for printing */ + trace_wct_cmd_other((char *)tablet->query); + wctablet_shift_input(tablet, clen + 1); + + } + + return len; +} + +static int wctablet_chr_ioctl(Chardev *chr, int cmd, void *arg) +{ + TabletChardev *tablet = WCTABLET_CHARDEV(chr); + QEMUSerialSetParams *ssp; + + switch (cmd) { + case CHR_IOCTL_SERIAL_SET_PARAMS: + ssp = arg; + if (tablet->line_speed != ssp->speed) { + trace_wct_speed(ssp->speed); + wctablet_reset(tablet); + tablet->line_speed = ssp->speed; + } + break; + default: + return -ENOTSUP; + } + return 0; +} + +static void wctablet_chr_finalize(Object *obj) +{ + TabletChardev *tablet = WCTABLET_CHARDEV(obj); + + qemu_input_handler_unregister(tablet->hs); + g_free(tablet); +} + +static void wctablet_chr_open(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + TabletChardev *tablet = WCTABLET_CHARDEV(chr); + + *be_opened = true; + + /* init state machine */ + memcpy(tablet->outbuf, WC_FULL_CONFIG_STRING, WC_FULL_CONFIG_STRING_LENGTH); + tablet->outlen = WC_FULL_CONFIG_STRING_LENGTH; + tablet->query_index = 0; + + tablet->hs = qemu_input_handler_register((DeviceState *)tablet, + &wctablet_handler); +} + +static void wctablet_chr_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->open = wctablet_chr_open; + cc->chr_write = wctablet_chr_write; + cc->chr_ioctl = wctablet_chr_ioctl; + cc->chr_accept_input = wctablet_chr_accept_input; +} + +static const TypeInfo wctablet_type_info = { + .name = TYPE_CHARDEV_WCTABLET, + .parent = TYPE_CHARDEV, + .instance_size = sizeof(TabletChardev), + .instance_finalize = wctablet_chr_finalize, + .class_init = wctablet_chr_class_init, +}; + +static void register_types(void) +{ + type_register_static(&wctablet_type_info); +} + +type_init(register_types); diff --git a/spice-qemu-char.c b/spice-qemu-char.c deleted file mode 100644 index 1c6c2e3969..0000000000 --- a/spice-qemu-char.c +++ /dev/null @@ -1,421 +0,0 @@ -#include "qemu/osdep.h" -#include "trace-root.h" -#include "ui/qemu-spice.h" -#include "chardev/char.h" -#include "qemu/error-report.h" -#include -#include - - -typedef struct SpiceChardev { - Chardev parent; - - SpiceCharDeviceInstance sin; - bool active; - bool blocked; - const uint8_t *datapos; - int datalen; - QLIST_ENTRY(SpiceChardev) next; -} SpiceChardev; - -#define TYPE_CHARDEV_SPICE "chardev-spice" -#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc" -#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport" - -#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE) - -typedef struct SpiceCharSource { - GSource source; - SpiceChardev *scd; -} SpiceCharSource; - -static QLIST_HEAD(, SpiceChardev) spice_chars = - QLIST_HEAD_INITIALIZER(spice_chars); - -static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) -{ - SpiceChardev *scd = container_of(sin, SpiceChardev, sin); - Chardev *chr = CHARDEV(scd); - ssize_t out = 0; - ssize_t last_out; - uint8_t* p = (uint8_t*)buf; - - while (len > 0) { - int can_write = qemu_chr_be_can_write(chr); - last_out = MIN(len, can_write); - if (last_out <= 0) { - break; - } - qemu_chr_be_write(chr, p, last_out); - out += last_out; - len -= last_out; - p += last_out; - } - - trace_spice_vmc_write(out, len + out); - return out; -} - -static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) -{ - SpiceChardev *scd = container_of(sin, SpiceChardev, sin); - int bytes = MIN(len, scd->datalen); - - if (bytes > 0) { - memcpy(buf, scd->datapos, bytes); - scd->datapos += bytes; - scd->datalen -= bytes; - assert(scd->datalen >= 0); - } - if (scd->datalen == 0) { - scd->datapos = 0; - scd->blocked = false; - } - trace_spice_vmc_read(bytes, len); - return bytes; -} - -#if SPICE_SERVER_VERSION >= 0x000c02 -static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event) -{ - SpiceChardev *scd = container_of(sin, SpiceChardev, sin); - Chardev *chr = CHARDEV(scd); - int chr_event; - - switch (event) { - case SPICE_PORT_EVENT_BREAK: - chr_event = CHR_EVENT_BREAK; - break; - default: - return; - } - - trace_spice_vmc_event(chr_event); - qemu_chr_be_event(chr, chr_event); -} -#endif - -static void vmc_state(SpiceCharDeviceInstance *sin, int connected) -{ - SpiceChardev *scd = container_of(sin, SpiceChardev, sin); - Chardev *chr = CHARDEV(scd); - - if ((chr->be_open && connected) || - (!chr->be_open && !connected)) { - return; - } - - qemu_chr_be_event(chr, - connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED); -} - -static SpiceCharDeviceInterface vmc_interface = { - .base.type = SPICE_INTERFACE_CHAR_DEVICE, - .base.description = "spice virtual channel char device", - .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, - .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, - .state = vmc_state, - .write = vmc_write, - .read = vmc_read, -#if SPICE_SERVER_VERSION >= 0x000c02 - .event = vmc_event, -#endif -#if SPICE_SERVER_VERSION >= 0x000c06 - .flags = SPICE_CHAR_DEVICE_NOTIFY_WRITABLE, -#endif -}; - - -static void vmc_register_interface(SpiceChardev *scd) -{ - if (scd->active) { - return; - } - scd->sin.base.sif = &vmc_interface.base; - qemu_spice_add_interface(&scd->sin.base); - scd->active = true; - trace_spice_vmc_register_interface(scd); -} - -static void vmc_unregister_interface(SpiceChardev *scd) -{ - if (!scd->active) { - return; - } - spice_server_remove_interface(&scd->sin.base); - scd->active = false; - trace_spice_vmc_unregister_interface(scd); -} - -static gboolean spice_char_source_prepare(GSource *source, gint *timeout) -{ - SpiceCharSource *src = (SpiceCharSource *)source; - - *timeout = -1; - - return !src->scd->blocked; -} - -static gboolean spice_char_source_check(GSource *source) -{ - SpiceCharSource *src = (SpiceCharSource *)source; - - return !src->scd->blocked; -} - -static gboolean spice_char_source_dispatch(GSource *source, - GSourceFunc callback, gpointer user_data) -{ - GIOFunc func = (GIOFunc)callback; - - return func(NULL, G_IO_OUT, user_data); -} - -static GSourceFuncs SpiceCharSourceFuncs = { - .prepare = spice_char_source_prepare, - .check = spice_char_source_check, - .dispatch = spice_char_source_dispatch, -}; - -static GSource *spice_chr_add_watch(Chardev *chr, GIOCondition cond) -{ - SpiceChardev *scd = SPICE_CHARDEV(chr); - SpiceCharSource *src; - - assert(cond & G_IO_OUT); - - src = (SpiceCharSource *)g_source_new(&SpiceCharSourceFuncs, - sizeof(SpiceCharSource)); - src->scd = scd; - - return (GSource *)src; -} - -static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len) -{ - SpiceChardev *s = SPICE_CHARDEV(chr); - int read_bytes; - - assert(s->datalen == 0); - s->datapos = buf; - s->datalen = len; - spice_server_char_device_wakeup(&s->sin); - read_bytes = len - s->datalen; - if (read_bytes != len) { - /* We'll get passed in the unconsumed data with the next call */ - s->datalen = 0; - s->datapos = NULL; - s->blocked = true; - } - return read_bytes; -} - -static void char_spice_finalize(Object *obj) -{ - SpiceChardev *s = SPICE_CHARDEV(obj); - - vmc_unregister_interface(s); - - if (s->next.le_prev) { - QLIST_REMOVE(s, next); - } - - g_free((char *)s->sin.subtype); -#if SPICE_SERVER_VERSION >= 0x000c02 - g_free((char *)s->sin.portname); -#endif -} - -static void spice_vmc_set_fe_open(struct Chardev *chr, int fe_open) -{ - SpiceChardev *s = SPICE_CHARDEV(chr); - if (fe_open) { - vmc_register_interface(s); - } else { - vmc_unregister_interface(s); - } -} - -static void spice_port_set_fe_open(struct Chardev *chr, int fe_open) -{ -#if SPICE_SERVER_VERSION >= 0x000c02 - SpiceChardev *s = SPICE_CHARDEV(chr); - - if (fe_open) { - spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED); - } else { - spice_server_port_event(&s->sin, SPICE_PORT_EVENT_CLOSED); - } -#endif -} - -static void spice_chr_accept_input(struct Chardev *chr) -{ - SpiceChardev *s = SPICE_CHARDEV(chr); - - spice_server_char_device_wakeup(&s->sin); -} - -static void chr_open(Chardev *chr, const char *subtype) -{ - SpiceChardev *s = SPICE_CHARDEV(chr); - - s->active = false; - s->sin.subtype = g_strdup(subtype); - - QLIST_INSERT_HEAD(&spice_chars, s, next); -} - -static void qemu_chr_open_spice_vmc(Chardev *chr, - ChardevBackend *backend, - bool *be_opened, - Error **errp) -{ - ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data; - const char *type = spicevmc->type; - const char **psubtype = spice_server_char_device_recognized_subtypes(); - - for (; *psubtype != NULL; ++psubtype) { - if (strcmp(type, *psubtype) == 0) { - break; - } - } - if (*psubtype == NULL) { - char *subtypes = g_strjoinv(", ", - (gchar **)spice_server_char_device_recognized_subtypes()); - - error_setg(errp, "unsupported type name: %s", type); - error_append_hint(errp, "allowed spice char type names: %s\n", - subtypes); - - g_free(subtypes); - return; - } - - *be_opened = false; - chr_open(chr, type); -} - -#if SPICE_SERVER_VERSION >= 0x000c02 -static void qemu_chr_open_spice_port(Chardev *chr, - ChardevBackend *backend, - bool *be_opened, - Error **errp) -{ - ChardevSpicePort *spiceport = backend->u.spiceport.data; - const char *name = spiceport->fqdn; - SpiceChardev *s; - - if (name == NULL) { - error_setg(errp, "missing name parameter"); - return; - } - - chr_open(chr, "port"); - - *be_opened = false; - s = SPICE_CHARDEV(chr); - s->sin.portname = g_strdup(name); -} - -void qemu_spice_register_ports(void) -{ - SpiceChardev *s; - - QLIST_FOREACH(s, &spice_chars, next) { - if (s->sin.portname == NULL) { - continue; - } - vmc_register_interface(s); - } -} -#endif - -static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend, - Error **errp) -{ - const char *name = qemu_opt_get(opts, "name"); - ChardevSpiceChannel *spicevmc; - - if (name == NULL) { - error_setg(errp, "chardev: spice channel: no name given"); - return; - } - backend->type = CHARDEV_BACKEND_KIND_SPICEVMC; - spicevmc = backend->u.spicevmc.data = g_new0(ChardevSpiceChannel, 1); - qemu_chr_parse_common(opts, qapi_ChardevSpiceChannel_base(spicevmc)); - spicevmc->type = g_strdup(name); -} - -static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend, - Error **errp) -{ - const char *name = qemu_opt_get(opts, "name"); - ChardevSpicePort *spiceport; - - if (name == NULL) { - error_setg(errp, "chardev: spice port: no name given"); - return; - } - backend->type = CHARDEV_BACKEND_KIND_SPICEPORT; - spiceport = backend->u.spiceport.data = g_new0(ChardevSpicePort, 1); - qemu_chr_parse_common(opts, qapi_ChardevSpicePort_base(spiceport)); - spiceport->fqdn = g_strdup(name); -} - -static void char_spice_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->chr_write = spice_chr_write; - cc->chr_add_watch = spice_chr_add_watch; - cc->chr_accept_input = spice_chr_accept_input; -} - -static const TypeInfo char_spice_type_info = { - .name = TYPE_CHARDEV_SPICE, - .parent = TYPE_CHARDEV, - .instance_size = sizeof(SpiceChardev), - .instance_finalize = char_spice_finalize, - .class_init = char_spice_class_init, - .abstract = true, -}; - -static void char_spicevmc_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->parse = qemu_chr_parse_spice_vmc; - cc->open = qemu_chr_open_spice_vmc; - cc->chr_set_fe_open = spice_vmc_set_fe_open; -} - -static const TypeInfo char_spicevmc_type_info = { - .name = TYPE_CHARDEV_SPICEVMC, - .parent = TYPE_CHARDEV_SPICE, - .class_init = char_spicevmc_class_init, -}; - -static void char_spiceport_class_init(ObjectClass *oc, void *data) -{ - ChardevClass *cc = CHARDEV_CLASS(oc); - - cc->parse = qemu_chr_parse_spice_port; - cc->open = qemu_chr_open_spice_port; - cc->chr_set_fe_open = spice_port_set_fe_open; -} - -static const TypeInfo char_spiceport_type_info = { - .name = TYPE_CHARDEV_SPICEPORT, - .parent = TYPE_CHARDEV_SPICE, - .class_init = char_spiceport_class_init, -}; - -static void register_types(void) -{ - type_register_static(&char_spice_type_info); - type_register_static(&char_spicevmc_type_info); - type_register_static(&char_spiceport_type_info); -} - -type_init(register_types); diff --git a/trace-events b/trace-events index 433865fa97..d7a4d94168 100644 --- a/trace-events +++ b/trace-events @@ -41,13 +41,6 @@ system_wakeup_request(int reason) "reason=%d" qemu_system_shutdown_request(int reason) "reason=%d" qemu_system_powerdown_request(void) "" -# spice-qemu-char.c -spice_vmc_write(ssize_t out, int len) "spice wrote %zd of requested %d" -spice_vmc_read(int bytes, int len) "spice read %d of requested %d" -spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" -spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" -spice_vmc_event(int event) "spice vmc event %d" - # monitor.c monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p" monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p" -- cgit v1.2.3