1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "qemu/osdep.h"
15#include "qapi/error.h"
16#include "cpu.h"
17#include "sysemu/qtest.h"
18#include "sysemu/runstate.h"
19#include "chardev/char-fe.h"
20#include "exec/ioport.h"
21#include "exec/memory.h"
22#include "hw/irq.h"
23#include "qemu/accel.h"
24#include "sysemu/cpu-timers.h"
25#include "qemu/config-file.h"
26#include "qemu/option.h"
27#include "qemu/error-report.h"
28#include "qemu/module.h"
29#include "qemu/cutils.h"
30#include CONFIG_DEVICES
31#ifdef CONFIG_PSERIES
32#include "hw/ppc/spapr_rtas.h"
33#endif
34
35#define MAX_IRQ 256
36
37bool qtest_allowed;
38
39static DeviceState *irq_intercept_dev;
40static FILE *qtest_log_fp;
41static CharBackend qtest_chr;
42static GString *inbuf;
43static int irq_levels[MAX_IRQ];
44static qemu_timeval start_time;
45static bool qtest_opened;
46static void (*qtest_server_send)(void*, const char*);
47static void *qtest_server_send_opaque;
48
49#define FMT_timeval "%ld.%06ld"
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237static int hex2nib(char ch)
238{
239 if (ch >= '0' && ch <= '9') {
240 return ch - '0';
241 } else if (ch >= 'a' && ch <= 'f') {
242 return 10 + (ch - 'a');
243 } else if (ch >= 'A' && ch <= 'F') {
244 return 10 + (ch - 'A');
245 } else {
246 return -1;
247 }
248}
249
250static void qtest_get_time(qemu_timeval *tv)
251{
252 qemu_gettimeofday(tv);
253 tv->tv_sec -= start_time.tv_sec;
254 tv->tv_usec -= start_time.tv_usec;
255 if (tv->tv_usec < 0) {
256 tv->tv_usec += 1000000;
257 tv->tv_sec -= 1;
258 }
259}
260
261static void qtest_send_prefix(CharBackend *chr)
262{
263 qemu_timeval tv;
264
265 if (!qtest_log_fp || !qtest_opened) {
266 return;
267 }
268
269 qtest_get_time(&tv);
270 fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
271 (long) tv.tv_sec, (long) tv.tv_usec);
272}
273
274static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
275{
276 va_list ap;
277
278 if (!qtest_log_fp || !qtest_opened) {
279 return;
280 }
281
282 qtest_send_prefix(NULL);
283
284 va_start(ap, fmt);
285 vfprintf(qtest_log_fp, fmt, ap);
286 va_end(ap);
287}
288
289static void qtest_server_char_be_send(void *opaque, const char *str)
290{
291 size_t len = strlen(str);
292 CharBackend* chr = (CharBackend *)opaque;
293 qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
294 if (qtest_log_fp && qtest_opened) {
295 fprintf(qtest_log_fp, "%s", str);
296 }
297}
298
299static void qtest_send(CharBackend *chr, const char *str)
300{
301 qtest_server_send(qtest_server_send_opaque, str);
302}
303
304static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharBackend *chr,
305 const char *fmt, ...)
306{
307 va_list ap;
308 gchar *buffer;
309
310 va_start(ap, fmt);
311 buffer = g_strdup_vprintf(fmt, ap);
312 qtest_send(chr, buffer);
313 g_free(buffer);
314 va_end(ap);
315}
316
317static void qtest_irq_handler(void *opaque, int n, int level)
318{
319 qemu_irq old_irq = *(qemu_irq *)opaque;
320 qemu_set_irq(old_irq, level);
321
322 if (irq_levels[n] != level) {
323 CharBackend *chr = &qtest_chr;
324 irq_levels[n] = level;
325 qtest_send_prefix(chr);
326 qtest_sendf(chr, "IRQ %s %d\n",
327 level ? "raise" : "lower", n);
328 }
329}
330
331static int64_t qtest_clock_counter;
332
333int64_t qtest_get_virtual_clock(void)
334{
335 return qatomic_read_i64(&qtest_clock_counter);
336}
337
338static void qtest_set_virtual_clock(int64_t count)
339{
340 qatomic_set_i64(&qtest_clock_counter, count);
341}
342
343static void qtest_clock_warp(int64_t dest)
344{
345 int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
346 AioContext *aio_context;
347 assert(qtest_enabled());
348 aio_context = qemu_get_aio_context();
349 while (clock < dest) {
350 int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
351 QEMU_TIMER_ATTR_ALL);
352 int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
353
354 qtest_set_virtual_clock(qtest_get_virtual_clock() + warp);
355
356 qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
357 timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
358 clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
359 }
360 qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
361}
362
363static void qtest_process_command(CharBackend *chr, gchar **words)
364{
365 const gchar *command;
366
367 g_assert(words);
368
369 command = words[0];
370
371 if (qtest_log_fp) {
372 qemu_timeval tv;
373 int i;
374
375 qtest_get_time(&tv);
376 fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
377 (long) tv.tv_sec, (long) tv.tv_usec);
378 for (i = 0; words[i]; i++) {
379 fprintf(qtest_log_fp, " %s", words[i]);
380 }
381 fprintf(qtest_log_fp, "\n");
382 }
383
384 g_assert(command);
385 if (strcmp(words[0], "irq_intercept_out") == 0
386 || strcmp(words[0], "irq_intercept_in") == 0) {
387 DeviceState *dev;
388 NamedGPIOList *ngl;
389
390 g_assert(words[1]);
391 dev = DEVICE(object_resolve_path(words[1], NULL));
392 if (!dev) {
393 qtest_send_prefix(chr);
394 qtest_send(chr, "FAIL Unknown device\n");
395 return;
396 }
397
398 if (irq_intercept_dev) {
399 qtest_send_prefix(chr);
400 if (irq_intercept_dev != dev) {
401 qtest_send(chr, "FAIL IRQ intercept already enabled\n");
402 } else {
403 qtest_send(chr, "OK\n");
404 }
405 return;
406 }
407
408 QLIST_FOREACH(ngl, &dev->gpios, node) {
409
410 if (ngl->name) {
411 continue;
412 }
413 if (words[0][14] == 'o') {
414 int i;
415 for (i = 0; i < ngl->num_out; ++i) {
416 qemu_irq *disconnected = g_new0(qemu_irq, 1);
417 qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
418 disconnected, i);
419
420 *disconnected = qdev_intercept_gpio_out(dev, icpt,
421 ngl->name, i);
422 }
423 } else {
424 qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
425 ngl->num_in);
426 }
427 }
428 irq_intercept_dev = dev;
429 qtest_send_prefix(chr);
430 qtest_send(chr, "OK\n");
431 } else if (strcmp(words[0], "set_irq_in") == 0) {
432 DeviceState *dev;
433 qemu_irq irq;
434 char *name;
435 int ret;
436 int num;
437 int level;
438
439 g_assert(words[1] && words[2] && words[3] && words[4]);
440
441 dev = DEVICE(object_resolve_path(words[1], NULL));
442 if (!dev) {
443 qtest_send_prefix(chr);
444 qtest_send(chr, "FAIL Unknown device\n");
445 return;
446 }
447
448 if (strcmp(words[2], "unnamed-gpio-in") == 0) {
449 name = NULL;
450 } else {
451 name = words[2];
452 }
453
454 ret = qemu_strtoi(words[3], NULL, 0, &num);
455 g_assert(!ret);
456 ret = qemu_strtoi(words[4], NULL, 0, &level);
457 g_assert(!ret);
458
459 irq = qdev_get_gpio_in_named(dev, name, num);
460
461 qemu_set_irq(irq, level);
462 qtest_send_prefix(chr);
463 qtest_send(chr, "OK\n");
464 } else if (strcmp(words[0], "outb") == 0 ||
465 strcmp(words[0], "outw") == 0 ||
466 strcmp(words[0], "outl") == 0) {
467 unsigned long addr;
468 unsigned long value;
469 int ret;
470
471 g_assert(words[1] && words[2]);
472 ret = qemu_strtoul(words[1], NULL, 0, &addr);
473 g_assert(ret == 0);
474 ret = qemu_strtoul(words[2], NULL, 0, &value);
475 g_assert(ret == 0);
476 g_assert(addr <= 0xffff);
477
478 if (words[0][3] == 'b') {
479 cpu_outb(addr, value);
480 } else if (words[0][3] == 'w') {
481 cpu_outw(addr, value);
482 } else if (words[0][3] == 'l') {
483 cpu_outl(addr, value);
484 }
485 qtest_send_prefix(chr);
486 qtest_send(chr, "OK\n");
487 } else if (strcmp(words[0], "inb") == 0 ||
488 strcmp(words[0], "inw") == 0 ||
489 strcmp(words[0], "inl") == 0) {
490 unsigned long addr;
491 uint32_t value = -1U;
492 int ret;
493
494 g_assert(words[1]);
495 ret = qemu_strtoul(words[1], NULL, 0, &addr);
496 g_assert(ret == 0);
497 g_assert(addr <= 0xffff);
498
499 if (words[0][2] == 'b') {
500 value = cpu_inb(addr);
501 } else if (words[0][2] == 'w') {
502 value = cpu_inw(addr);
503 } else if (words[0][2] == 'l') {
504 value = cpu_inl(addr);
505 }
506 qtest_send_prefix(chr);
507 qtest_sendf(chr, "OK 0x%04x\n", value);
508 } else if (strcmp(words[0], "writeb") == 0 ||
509 strcmp(words[0], "writew") == 0 ||
510 strcmp(words[0], "writel") == 0 ||
511 strcmp(words[0], "writeq") == 0) {
512 uint64_t addr;
513 uint64_t value;
514 int ret;
515
516 g_assert(words[1] && words[2]);
517 ret = qemu_strtou64(words[1], NULL, 0, &addr);
518 g_assert(ret == 0);
519 ret = qemu_strtou64(words[2], NULL, 0, &value);
520 g_assert(ret == 0);
521
522 if (words[0][5] == 'b') {
523 uint8_t data = value;
524 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
525 &data, 1);
526 } else if (words[0][5] == 'w') {
527 uint16_t data = value;
528 tswap16s(&data);
529 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
530 &data, 2);
531 } else if (words[0][5] == 'l') {
532 uint32_t data = value;
533 tswap32s(&data);
534 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
535 &data, 4);
536 } else if (words[0][5] == 'q') {
537 uint64_t data = value;
538 tswap64s(&data);
539 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
540 &data, 8);
541 }
542 qtest_send_prefix(chr);
543 qtest_send(chr, "OK\n");
544 } else if (strcmp(words[0], "readb") == 0 ||
545 strcmp(words[0], "readw") == 0 ||
546 strcmp(words[0], "readl") == 0 ||
547 strcmp(words[0], "readq") == 0) {
548 uint64_t addr;
549 uint64_t value = UINT64_C(-1);
550 int ret;
551
552 g_assert(words[1]);
553 ret = qemu_strtou64(words[1], NULL, 0, &addr);
554 g_assert(ret == 0);
555
556 if (words[0][4] == 'b') {
557 uint8_t data;
558 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
559 &data, 1);
560 value = data;
561 } else if (words[0][4] == 'w') {
562 uint16_t data;
563 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
564 &data, 2);
565 value = tswap16(data);
566 } else if (words[0][4] == 'l') {
567 uint32_t data;
568 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
569 &data, 4);
570 value = tswap32(data);
571 } else if (words[0][4] == 'q') {
572 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
573 &value, 8);
574 tswap64s(&value);
575 }
576 qtest_send_prefix(chr);
577 qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
578 } else if (strcmp(words[0], "read") == 0) {
579 uint64_t addr, len, i;
580 uint8_t *data;
581 char *enc;
582 int ret;
583
584 g_assert(words[1] && words[2]);
585 ret = qemu_strtou64(words[1], NULL, 0, &addr);
586 g_assert(ret == 0);
587 ret = qemu_strtou64(words[2], NULL, 0, &len);
588 g_assert(ret == 0);
589
590 g_assert(len);
591
592 data = g_malloc(len);
593 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
594 len);
595
596 enc = g_malloc(2 * len + 1);
597 for (i = 0; i < len; i++) {
598 sprintf(&enc[i * 2], "%02x", data[i]);
599 }
600
601 qtest_send_prefix(chr);
602 qtest_sendf(chr, "OK 0x%s\n", enc);
603
604 g_free(data);
605 g_free(enc);
606 } else if (strcmp(words[0], "b64read") == 0) {
607 uint64_t addr, len;
608 uint8_t *data;
609 gchar *b64_data;
610 int ret;
611
612 g_assert(words[1] && words[2]);
613 ret = qemu_strtou64(words[1], NULL, 0, &addr);
614 g_assert(ret == 0);
615 ret = qemu_strtou64(words[2], NULL, 0, &len);
616 g_assert(ret == 0);
617
618 data = g_malloc(len);
619 address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
620 len);
621 b64_data = g_base64_encode(data, len);
622 qtest_send_prefix(chr);
623 qtest_sendf(chr, "OK %s\n", b64_data);
624
625 g_free(data);
626 g_free(b64_data);
627 } else if (strcmp(words[0], "write") == 0) {
628 uint64_t addr, len, i;
629 uint8_t *data;
630 size_t data_len;
631 int ret;
632
633 g_assert(words[1] && words[2] && words[3]);
634 ret = qemu_strtou64(words[1], NULL, 0, &addr);
635 g_assert(ret == 0);
636 ret = qemu_strtou64(words[2], NULL, 0, &len);
637 g_assert(ret == 0);
638
639 data_len = strlen(words[3]);
640 if (data_len < 3) {
641 qtest_send(chr, "ERR invalid argument size\n");
642 return;
643 }
644
645 data = g_malloc(len);
646 for (i = 0; i < len; i++) {
647 if ((i * 2 + 4) <= data_len) {
648 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
649 data[i] |= hex2nib(words[3][i * 2 + 3]);
650 } else {
651 data[i] = 0;
652 }
653 }
654 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
655 len);
656 g_free(data);
657
658 qtest_send_prefix(chr);
659 qtest_send(chr, "OK\n");
660 } else if (strcmp(words[0], "memset") == 0) {
661 uint64_t addr, len;
662 uint8_t *data;
663 unsigned long pattern;
664 int ret;
665
666 g_assert(words[1] && words[2] && words[3]);
667 ret = qemu_strtou64(words[1], NULL, 0, &addr);
668 g_assert(ret == 0);
669 ret = qemu_strtou64(words[2], NULL, 0, &len);
670 g_assert(ret == 0);
671 ret = qemu_strtoul(words[3], NULL, 0, &pattern);
672 g_assert(ret == 0);
673
674 if (len) {
675 data = g_malloc(len);
676 memset(data, pattern, len);
677 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,
678 data, len);
679 g_free(data);
680 }
681
682 qtest_send_prefix(chr);
683 qtest_send(chr, "OK\n");
684 } else if (strcmp(words[0], "b64write") == 0) {
685 uint64_t addr, len;
686 uint8_t *data;
687 size_t data_len;
688 gsize out_len;
689 int ret;
690
691 g_assert(words[1] && words[2] && words[3]);
692 ret = qemu_strtou64(words[1], NULL, 0, &addr);
693 g_assert(ret == 0);
694 ret = qemu_strtou64(words[2], NULL, 0, &len);
695 g_assert(ret == 0);
696
697 data_len = strlen(words[3]);
698 if (data_len < 3) {
699 qtest_send(chr, "ERR invalid argument size\n");
700 return;
701 }
702
703 data = g_base64_decode_inplace(words[3], &out_len);
704 if (out_len != len) {
705 qtest_log_send("b64write: data length mismatch (told %"PRIu64", "
706 "found %zu)\n",
707 len, out_len);
708 out_len = MIN(out_len, len);
709 }
710
711 address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
712 len);
713
714 qtest_send_prefix(chr);
715 qtest_send(chr, "OK\n");
716 } else if (strcmp(words[0], "endianness") == 0) {
717 qtest_send_prefix(chr);
718#if defined(TARGET_WORDS_BIGENDIAN)
719 qtest_sendf(chr, "OK big\n");
720#else
721 qtest_sendf(chr, "OK little\n");
722#endif
723#ifdef CONFIG_PSERIES
724 } else if (strcmp(words[0], "rtas") == 0) {
725 uint64_t res, args, ret;
726 unsigned long nargs, nret;
727 int rc;
728
729 rc = qemu_strtoul(words[2], NULL, 0, &nargs);
730 g_assert(rc == 0);
731 rc = qemu_strtou64(words[3], NULL, 0, &args);
732 g_assert(rc == 0);
733 rc = qemu_strtoul(words[4], NULL, 0, &nret);
734 g_assert(rc == 0);
735 rc = qemu_strtou64(words[5], NULL, 0, &ret);
736 g_assert(rc == 0);
737 res = qtest_rtas_call(words[1], nargs, args, nret, ret);
738
739 qtest_send_prefix(chr);
740 qtest_sendf(chr, "OK %"PRIu64"\n", res);
741#endif
742 } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
743 int64_t ns;
744
745 if (words[1]) {
746 int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
747 g_assert(ret == 0);
748 } else {
749 ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
750 QEMU_TIMER_ATTR_ALL);
751 }
752 qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
753 qtest_send_prefix(chr);
754 qtest_sendf(chr, "OK %"PRIi64"\n",
755 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
756 } else if (strcmp(words[0], "module_load") == 0) {
757 g_assert(words[1] && words[2]);
758
759 qtest_send_prefix(chr);
760 if (module_load_one(words[1], words[2], false)) {
761 qtest_sendf(chr, "OK\n");
762 } else {
763 qtest_sendf(chr, "FAIL\n");
764 }
765 } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
766 int64_t ns;
767 int ret;
768
769 g_assert(words[1]);
770 ret = qemu_strtoi64(words[1], NULL, 0, &ns);
771 g_assert(ret == 0);
772 qtest_clock_warp(ns);
773 qtest_send_prefix(chr);
774 qtest_sendf(chr, "OK %"PRIi64"\n",
775 (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
776 } else {
777 qtest_send_prefix(chr);
778 qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
779 }
780}
781
782static void qtest_process_inbuf(CharBackend *chr, GString *inbuf)
783{
784 char *end;
785
786 while ((end = strchr(inbuf->str, '\n')) != NULL) {
787 size_t offset;
788 GString *cmd;
789 gchar **words;
790
791 offset = end - inbuf->str;
792
793 cmd = g_string_new_len(inbuf->str, offset);
794 g_string_erase(inbuf, 0, offset + 1);
795
796 words = g_strsplit(cmd->str, " ", 0);
797 qtest_process_command(chr, words);
798 g_strfreev(words);
799
800 g_string_free(cmd, TRUE);
801 }
802}
803
804static void qtest_read(void *opaque, const uint8_t *buf, int size)
805{
806 CharBackend *chr = opaque;
807
808 g_string_append_len(inbuf, (const gchar *)buf, size);
809 qtest_process_inbuf(chr, inbuf);
810}
811
812static int qtest_can_read(void *opaque)
813{
814 return 1024;
815}
816
817static void qtest_event(void *opaque, QEMUChrEvent event)
818{
819 int i;
820
821 switch (event) {
822 case CHR_EVENT_OPENED:
823
824
825
826
827
828
829 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
830 irq_levels[i] = 0;
831 }
832 qemu_gettimeofday(&start_time);
833 qtest_opened = true;
834 if (qtest_log_fp) {
835 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
836 (long) start_time.tv_sec, (long) start_time.tv_usec);
837 }
838 break;
839 case CHR_EVENT_CLOSED:
840 qtest_opened = false;
841 if (qtest_log_fp) {
842 qemu_timeval tv;
843 qtest_get_time(&tv);
844 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
845 (long) tv.tv_sec, (long) tv.tv_usec);
846 }
847 break;
848 default:
849 break;
850 }
851}
852void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
853{
854 Chardev *chr;
855
856 chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
857
858 if (chr == NULL) {
859 error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
860 qtest_chrdev);
861 return;
862 }
863
864 if (qtest_log) {
865 if (strcmp(qtest_log, "none") != 0) {
866 qtest_log_fp = fopen(qtest_log, "w+");
867 }
868 } else {
869 qtest_log_fp = stderr;
870 }
871
872 qemu_chr_fe_init(&qtest_chr, chr, errp);
873 qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read,
874 qtest_event, NULL, &qtest_chr, NULL, true);
875 qemu_chr_fe_set_echo(&qtest_chr, true);
876
877 inbuf = g_string_new("");
878
879 if (!qtest_server_send) {
880 qtest_server_set_send_handler(qtest_server_char_be_send, &qtest_chr);
881 }
882}
883
884void qtest_server_set_send_handler(void (*send)(void*, const char*),
885 void *opaque)
886{
887 qtest_server_send = send;
888 qtest_server_send_opaque = opaque;
889}
890
891bool qtest_driver(void)
892{
893 return qtest_chr.chr != NULL;
894}
895
896void qtest_server_inproc_recv(void *dummy, const char *buf)
897{
898 static GString *gstr;
899 if (!gstr) {
900 gstr = g_string_new(NULL);
901 }
902 g_string_append(gstr, buf);
903 if (gstr->str[gstr->len - 1] == '\n') {
904 qtest_process_inbuf(NULL, gstr);
905 g_string_truncate(gstr, 0);
906 }
907}
908