diff options
author | Peter Maydell | 2017-06-05 11:09:14 +0200 |
---|---|---|
committer | Peter Maydell | 2017-06-05 11:09:14 +0200 |
commit | cb8b8ef4578dc17c350fd4b27700a9f178e2dad0 (patch) | |
tree | 6bd382062ac77cc25bece492b78e15fec2a313e5 /chardev/testdev.c | |
parent | Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (diff) | |
parent | char: move char devices to chardev/ (diff) | |
download | qemu-cb8b8ef4578dc17c350fd4b27700a9f178e2dad0.tar.gz qemu-cb8b8ef4578dc17c350fd4b27700a9f178e2dad0.tar.xz qemu-cb8b8ef4578dc17c350fd4b27700a9f178e2dad0.zip |
Merge remote-tracking branch 'remotes/elmarco/tags/chrfe-pull-request' into staging
# gpg: Signature made Fri 02 Jun 2017 20:12:48 BST
# gpg: using RSA key 0xDAE8E10975969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>"
# gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5
* remotes/elmarco/tags/chrfe-pull-request:
char: move char devices to chardev/
char: make chr_fe_deinit() optionaly delete backend
char: rename functions that are not part of fe
char: move CharBackend handling in char-fe unit
char: generalize qemu_chr_write_all()
be-hci: use backend functions
chardev: serial & parallel declaration to own headers
chardev: move headers to include/chardev
Remove/replace sysemu/char.h inclusion
char-win: close file handle except with console
char-win: rename hcom->file
char-win: rename win_chr_init/poll win_chr_serial_init/poll
char-win: remove WinChardev.len
char-win: simplify win_chr_read()
char: cast ARRAY_SIZE() as signed to silent warning on empty array
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'chardev/testdev.c')
-rw-r--r-- | chardev/testdev.c | 129 |
1 files changed, 129 insertions, 0 deletions
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 <pbonzini@redhat.com> + * + * 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); |