Commit 5ccfae10a79e52654c9edc68da6d05f29466b4f9
1 parent
1490791f
Implement "info chardev" command. (Gerd Hoffmann)
This patch makes qemu keep track of the character devices in use and implements a "info chardev" monitor command to print a list. qemu_chr_open() sticks the devices into a linked list now. It got a new argument (label), so there is a name for each device. It also assigns a filename to each character device. By default it just copyes the filename passed in. Individual drivers can fill in something else though. qemu_chr_open_pty() sets the filename to name of the pseudo tty allocated. Output looks like this: (qemu) info chardev monitor: filename=unix:/tmp/run.sh-26827/monitor,server,nowait serial0: filename=unix:/tmp/run.sh-26827/console,server serial1: filename=pty:/dev/pts/5 parallel0: filename=vc:640x480 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5575 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
78 additions
and
36 deletions
gdbstub.c
hw/usb-serial.c
... | ... | @@ -521,6 +521,8 @@ USBDevice *usb_serial_init(const char *filename) |
521 | 521 | USBSerialState *s; |
522 | 522 | CharDriverState *cdrv; |
523 | 523 | unsigned short vendorid = 0x0403, productid = 0x6001; |
524 | + char label[32]; | |
525 | + static int index; | |
524 | 526 | |
525 | 527 | while (*filename && *filename != ':') { |
526 | 528 | const char *p; |
... | ... | @@ -555,7 +557,8 @@ USBDevice *usb_serial_init(const char *filename) |
555 | 557 | if (!s) |
556 | 558 | return NULL; |
557 | 559 | |
558 | - cdrv = qemu_chr_open(filename); | |
560 | + snprintf(label, sizeof(label), "usbserial%d", index++); | |
561 | + cdrv = qemu_chr_open(label, filename); | |
559 | 562 | if (!cdrv) |
560 | 563 | goto fail; |
561 | 564 | s->cs = cdrv; | ... | ... |
monitor.c
... | ... | @@ -1469,6 +1469,8 @@ static const term_cmd_t info_cmds[] = { |
1469 | 1469 | "", "show the version of qemu" }, |
1470 | 1470 | { "network", "", do_info_network, |
1471 | 1471 | "", "show the network state" }, |
1472 | + { "chardev", "", qemu_chr_info, | |
1473 | + "", "show the character devices" }, | |
1472 | 1474 | { "block", "", do_info_block, |
1473 | 1475 | "", "show the block devices" }, |
1474 | 1476 | { "blockstats", "", do_info_blockstats, | ... | ... |
qemu-char.h
1 | 1 | #ifndef QEMU_CHAR_H |
2 | 2 | #define QEMU_CHAR_H |
3 | 3 | |
4 | +#include "sys-queue.h" | |
4 | 5 | /* character device */ |
5 | 6 | |
6 | 7 | #define CHR_EVENT_BREAK 0 /* serial break char */ |
... | ... | @@ -55,9 +56,12 @@ struct CharDriverState { |
55 | 56 | void *opaque; |
56 | 57 | int focus; |
57 | 58 | QEMUBH *bh; |
59 | + char *label; | |
60 | + char *filename; | |
61 | + TAILQ_ENTRY(CharDriverState) next; | |
58 | 62 | }; |
59 | 63 | |
60 | -CharDriverState *qemu_chr_open(const char *filename); | |
64 | +CharDriverState *qemu_chr_open(const char *label, const char *filename); | |
61 | 65 | void qemu_chr_close(CharDriverState *chr); |
62 | 66 | void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); |
63 | 67 | int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); |
... | ... | @@ -72,6 +76,7 @@ void qemu_chr_reset(CharDriverState *s); |
72 | 76 | int qemu_chr_can_read(CharDriverState *s); |
73 | 77 | void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); |
74 | 78 | void qemu_chr_accept_input(CharDriverState *s); |
79 | +void qemu_chr_info(void); | |
75 | 80 | |
76 | 81 | /* async I/O support */ |
77 | 82 | ... | ... |
vl.c
... | ... | @@ -2581,7 +2581,7 @@ static CharDriverState *qemu_chr_open_pty(void) |
2581 | 2581 | CharDriverState *chr; |
2582 | 2582 | PtyCharDriver *s; |
2583 | 2583 | struct termios tty; |
2584 | - int slave_fd; | |
2584 | + int slave_fd, len; | |
2585 | 2585 | #if defined(__OpenBSD__) |
2586 | 2586 | char pty_name[PATH_MAX]; |
2587 | 2587 | #define q_ptsname(x) pty_name |
... | ... | @@ -2608,6 +2608,9 @@ static CharDriverState *qemu_chr_open_pty(void) |
2608 | 2608 | tcsetattr(slave_fd, TCSAFLUSH, &tty); |
2609 | 2609 | close(slave_fd); |
2610 | 2610 | |
2611 | + len = strlen(q_ptsname(s->fd)) + 5; | |
2612 | + chr->filename = qemu_malloc(len); | |
2613 | + snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd)); | |
2611 | 2614 | fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd)); |
2612 | 2615 | |
2613 | 2616 | chr->opaque = s; |
... | ... | @@ -3767,90 +3770,115 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
3767 | 3770 | return NULL; |
3768 | 3771 | } |
3769 | 3772 | |
3770 | -CharDriverState *qemu_chr_open(const char *filename) | |
3773 | +static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs | |
3774 | += TAILQ_HEAD_INITIALIZER(chardevs); | |
3775 | + | |
3776 | +CharDriverState *qemu_chr_open(const char *label, const char *filename) | |
3771 | 3777 | { |
3772 | 3778 | const char *p; |
3779 | + CharDriverState *chr; | |
3773 | 3780 | |
3774 | 3781 | if (!strcmp(filename, "vc")) { |
3775 | - return text_console_init(&display_state, 0); | |
3776 | - } else if (strstart(filename, "vc:", &p)) { | |
3777 | - return text_console_init(&display_state, p); | |
3778 | - } else if (!strcmp(filename, "null")) { | |
3779 | - return qemu_chr_open_null(); | |
3782 | + chr = text_console_init(&display_state, 0); | |
3783 | + } else | |
3784 | + if (strstart(filename, "vc:", &p)) { | |
3785 | + chr = text_console_init(&display_state, p); | |
3786 | + } else | |
3787 | + if (!strcmp(filename, "null")) { | |
3788 | + chr = qemu_chr_open_null(); | |
3780 | 3789 | } else |
3781 | 3790 | if (strstart(filename, "tcp:", &p)) { |
3782 | - return qemu_chr_open_tcp(p, 0, 0); | |
3791 | + chr = qemu_chr_open_tcp(p, 0, 0); | |
3783 | 3792 | } else |
3784 | 3793 | if (strstart(filename, "telnet:", &p)) { |
3785 | - return qemu_chr_open_tcp(p, 1, 0); | |
3794 | + chr = qemu_chr_open_tcp(p, 1, 0); | |
3786 | 3795 | } else |
3787 | 3796 | if (strstart(filename, "udp:", &p)) { |
3788 | - return qemu_chr_open_udp(p); | |
3797 | + chr = qemu_chr_open_udp(p); | |
3789 | 3798 | } else |
3790 | 3799 | if (strstart(filename, "mon:", &p)) { |
3791 | - CharDriverState *drv = qemu_chr_open(p); | |
3792 | - if (drv) { | |
3793 | - drv = qemu_chr_open_mux(drv); | |
3794 | - monitor_init(drv, !nographic); | |
3795 | - return drv; | |
3800 | + chr = qemu_chr_open(label, p); | |
3801 | + if (chr) { | |
3802 | + chr = qemu_chr_open_mux(chr); | |
3803 | + monitor_init(chr, !nographic); | |
3804 | + } else { | |
3805 | + printf("Unable to open driver: %s\n", p); | |
3796 | 3806 | } |
3797 | - printf("Unable to open driver: %s\n", p); | |
3798 | - return 0; | |
3799 | 3807 | } else |
3800 | 3808 | #ifndef _WIN32 |
3801 | 3809 | if (strstart(filename, "unix:", &p)) { |
3802 | - return qemu_chr_open_tcp(p, 0, 1); | |
3810 | + chr = qemu_chr_open_tcp(p, 0, 1); | |
3803 | 3811 | } else if (strstart(filename, "file:", &p)) { |
3804 | - return qemu_chr_open_file_out(p); | |
3812 | + chr = qemu_chr_open_file_out(p); | |
3805 | 3813 | } else if (strstart(filename, "pipe:", &p)) { |
3806 | - return qemu_chr_open_pipe(p); | |
3814 | + chr = qemu_chr_open_pipe(p); | |
3807 | 3815 | } else if (!strcmp(filename, "pty")) { |
3808 | - return qemu_chr_open_pty(); | |
3816 | + chr = qemu_chr_open_pty(); | |
3809 | 3817 | } else if (!strcmp(filename, "stdio")) { |
3810 | - return qemu_chr_open_stdio(); | |
3818 | + chr = qemu_chr_open_stdio(); | |
3811 | 3819 | } else |
3812 | 3820 | #if defined(__linux__) |
3813 | 3821 | if (strstart(filename, "/dev/parport", NULL)) { |
3814 | - return qemu_chr_open_pp(filename); | |
3822 | + chr = qemu_chr_open_pp(filename); | |
3815 | 3823 | } else |
3816 | 3824 | #endif |
3817 | 3825 | #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ |
3818 | 3826 | || defined(__NetBSD__) || defined(__OpenBSD__) |
3819 | 3827 | if (strstart(filename, "/dev/", NULL)) { |
3820 | - return qemu_chr_open_tty(filename); | |
3828 | + chr = qemu_chr_open_tty(filename); | |
3821 | 3829 | } else |
3822 | 3830 | #endif |
3823 | 3831 | #else /* !_WIN32 */ |
3824 | 3832 | if (strstart(filename, "COM", NULL)) { |
3825 | - return qemu_chr_open_win(filename); | |
3833 | + chr = qemu_chr_open_win(filename); | |
3826 | 3834 | } else |
3827 | 3835 | if (strstart(filename, "pipe:", &p)) { |
3828 | - return qemu_chr_open_win_pipe(p); | |
3836 | + chr = qemu_chr_open_win_pipe(p); | |
3829 | 3837 | } else |
3830 | 3838 | if (strstart(filename, "con:", NULL)) { |
3831 | - return qemu_chr_open_win_con(filename); | |
3839 | + chr = qemu_chr_open_win_con(filename); | |
3832 | 3840 | } else |
3833 | 3841 | if (strstart(filename, "file:", &p)) { |
3834 | - return qemu_chr_open_win_file_out(p); | |
3842 | + chr = qemu_chr_open_win_file_out(p); | |
3835 | 3843 | } else |
3836 | 3844 | #endif |
3837 | 3845 | #ifdef CONFIG_BRLAPI |
3838 | 3846 | if (!strcmp(filename, "braille")) { |
3839 | - return chr_baum_init(); | |
3847 | + chr = chr_baum_init(); | |
3840 | 3848 | } else |
3841 | 3849 | #endif |
3842 | 3850 | { |
3843 | - return NULL; | |
3851 | + chr = NULL; | |
3852 | + } | |
3853 | + | |
3854 | + if (chr) { | |
3855 | + if (!chr->filename) | |
3856 | + chr->filename = qemu_strdup(filename); | |
3857 | + chr->label = qemu_strdup(label); | |
3858 | + TAILQ_INSERT_TAIL(&chardevs, chr, next); | |
3844 | 3859 | } |
3860 | + return chr; | |
3845 | 3861 | } |
3846 | 3862 | |
3847 | 3863 | void qemu_chr_close(CharDriverState *chr) |
3848 | 3864 | { |
3865 | + TAILQ_REMOVE(&chardevs, chr, next); | |
3849 | 3866 | if (chr->chr_close) |
3850 | 3867 | chr->chr_close(chr); |
3868 | + qemu_free(chr->filename); | |
3869 | + qemu_free(chr->label); | |
3851 | 3870 | qemu_free(chr); |
3852 | 3871 | } |
3853 | 3872 | |
3873 | +void qemu_chr_info(void) | |
3874 | +{ | |
3875 | + CharDriverState *chr; | |
3876 | + | |
3877 | + TAILQ_FOREACH(chr, &chardevs, next) { | |
3878 | + term_printf("%s: filename=%s\n", chr->label, chr->filename); | |
3879 | + } | |
3880 | +} | |
3881 | + | |
3854 | 3882 | /***********************************************************/ |
3855 | 3883 | /* network device redirectors */ |
3856 | 3884 | |
... | ... | @@ -9689,7 +9717,7 @@ int main(int argc, char **argv) |
9689 | 9717 | } |
9690 | 9718 | } |
9691 | 9719 | if (monitor_device) { |
9692 | - monitor_hd = qemu_chr_open(monitor_device); | |
9720 | + monitor_hd = qemu_chr_open("monitor", monitor_device); | |
9693 | 9721 | if (!monitor_hd) { |
9694 | 9722 | fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); |
9695 | 9723 | exit(1); |
... | ... | @@ -9700,7 +9728,9 @@ int main(int argc, char **argv) |
9700 | 9728 | for(i = 0; i < MAX_SERIAL_PORTS; i++) { |
9701 | 9729 | const char *devname = serial_devices[i]; |
9702 | 9730 | if (devname && strcmp(devname, "none")) { |
9703 | - serial_hds[i] = qemu_chr_open(devname); | |
9731 | + char label[32]; | |
9732 | + snprintf(label, sizeof(label), "serial%d", i); | |
9733 | + serial_hds[i] = qemu_chr_open(label, devname); | |
9704 | 9734 | if (!serial_hds[i]) { |
9705 | 9735 | fprintf(stderr, "qemu: could not open serial device '%s'\n", |
9706 | 9736 | devname); |
... | ... | @@ -9714,7 +9744,9 @@ int main(int argc, char **argv) |
9714 | 9744 | for(i = 0; i < MAX_PARALLEL_PORTS; i++) { |
9715 | 9745 | const char *devname = parallel_devices[i]; |
9716 | 9746 | if (devname && strcmp(devname, "none")) { |
9717 | - parallel_hds[i] = qemu_chr_open(devname); | |
9747 | + char label[32]; | |
9748 | + snprintf(label, sizeof(label), "parallel%d", i); | |
9749 | + parallel_hds[i] = qemu_chr_open(label, devname); | |
9718 | 9750 | if (!parallel_hds[i]) { |
9719 | 9751 | fprintf(stderr, "qemu: could not open parallel device '%s'\n", |
9720 | 9752 | devname); | ... | ... |