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
| @@ -1852,7 +1852,7 @@ int gdbserver_start(const char *port) | @@ -1852,7 +1852,7 @@ int gdbserver_start(const char *port) | ||
| 1852 | port = gdbstub_port_name; | 1852 | port = gdbstub_port_name; |
| 1853 | } | 1853 | } |
| 1854 | 1854 | ||
| 1855 | - chr = qemu_chr_open(port); | 1855 | + chr = qemu_chr_open("gdb", port); |
| 1856 | if (!chr) | 1856 | if (!chr) |
| 1857 | return -1; | 1857 | return -1; |
| 1858 | 1858 |
hw/usb-serial.c
| @@ -521,6 +521,8 @@ USBDevice *usb_serial_init(const char *filename) | @@ -521,6 +521,8 @@ USBDevice *usb_serial_init(const char *filename) | ||
| 521 | USBSerialState *s; | 521 | USBSerialState *s; |
| 522 | CharDriverState *cdrv; | 522 | CharDriverState *cdrv; |
| 523 | unsigned short vendorid = 0x0403, productid = 0x6001; | 523 | unsigned short vendorid = 0x0403, productid = 0x6001; |
| 524 | + char label[32]; | ||
| 525 | + static int index; | ||
| 524 | 526 | ||
| 525 | while (*filename && *filename != ':') { | 527 | while (*filename && *filename != ':') { |
| 526 | const char *p; | 528 | const char *p; |
| @@ -555,7 +557,8 @@ USBDevice *usb_serial_init(const char *filename) | @@ -555,7 +557,8 @@ USBDevice *usb_serial_init(const char *filename) | ||
| 555 | if (!s) | 557 | if (!s) |
| 556 | return NULL; | 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 | if (!cdrv) | 562 | if (!cdrv) |
| 560 | goto fail; | 563 | goto fail; |
| 561 | s->cs = cdrv; | 564 | s->cs = cdrv; |
monitor.c
| @@ -1469,6 +1469,8 @@ static const term_cmd_t info_cmds[] = { | @@ -1469,6 +1469,8 @@ static const term_cmd_t info_cmds[] = { | ||
| 1469 | "", "show the version of qemu" }, | 1469 | "", "show the version of qemu" }, |
| 1470 | { "network", "", do_info_network, | 1470 | { "network", "", do_info_network, |
| 1471 | "", "show the network state" }, | 1471 | "", "show the network state" }, |
| 1472 | + { "chardev", "", qemu_chr_info, | ||
| 1473 | + "", "show the character devices" }, | ||
| 1472 | { "block", "", do_info_block, | 1474 | { "block", "", do_info_block, |
| 1473 | "", "show the block devices" }, | 1475 | "", "show the block devices" }, |
| 1474 | { "blockstats", "", do_info_blockstats, | 1476 | { "blockstats", "", do_info_blockstats, |
qemu-char.h
| 1 | #ifndef QEMU_CHAR_H | 1 | #ifndef QEMU_CHAR_H |
| 2 | #define QEMU_CHAR_H | 2 | #define QEMU_CHAR_H |
| 3 | 3 | ||
| 4 | +#include "sys-queue.h" | ||
| 4 | /* character device */ | 5 | /* character device */ |
| 5 | 6 | ||
| 6 | #define CHR_EVENT_BREAK 0 /* serial break char */ | 7 | #define CHR_EVENT_BREAK 0 /* serial break char */ |
| @@ -55,9 +56,12 @@ struct CharDriverState { | @@ -55,9 +56,12 @@ struct CharDriverState { | ||
| 55 | void *opaque; | 56 | void *opaque; |
| 56 | int focus; | 57 | int focus; |
| 57 | QEMUBH *bh; | 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 | void qemu_chr_close(CharDriverState *chr); | 65 | void qemu_chr_close(CharDriverState *chr); |
| 62 | void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); | 66 | void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); |
| 63 | int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); | 67 | int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); |
| @@ -72,6 +76,7 @@ void qemu_chr_reset(CharDriverState *s); | @@ -72,6 +76,7 @@ void qemu_chr_reset(CharDriverState *s); | ||
| 72 | int qemu_chr_can_read(CharDriverState *s); | 76 | int qemu_chr_can_read(CharDriverState *s); |
| 73 | void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); | 77 | void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); |
| 74 | void qemu_chr_accept_input(CharDriverState *s); | 78 | void qemu_chr_accept_input(CharDriverState *s); |
| 79 | +void qemu_chr_info(void); | ||
| 75 | 80 | ||
| 76 | /* async I/O support */ | 81 | /* async I/O support */ |
| 77 | 82 |
vl.c
| @@ -2581,7 +2581,7 @@ static CharDriverState *qemu_chr_open_pty(void) | @@ -2581,7 +2581,7 @@ static CharDriverState *qemu_chr_open_pty(void) | ||
| 2581 | CharDriverState *chr; | 2581 | CharDriverState *chr; |
| 2582 | PtyCharDriver *s; | 2582 | PtyCharDriver *s; |
| 2583 | struct termios tty; | 2583 | struct termios tty; |
| 2584 | - int slave_fd; | 2584 | + int slave_fd, len; |
| 2585 | #if defined(__OpenBSD__) | 2585 | #if defined(__OpenBSD__) |
| 2586 | char pty_name[PATH_MAX]; | 2586 | char pty_name[PATH_MAX]; |
| 2587 | #define q_ptsname(x) pty_name | 2587 | #define q_ptsname(x) pty_name |
| @@ -2608,6 +2608,9 @@ static CharDriverState *qemu_chr_open_pty(void) | @@ -2608,6 +2608,9 @@ static CharDriverState *qemu_chr_open_pty(void) | ||
| 2608 | tcsetattr(slave_fd, TCSAFLUSH, &tty); | 2608 | tcsetattr(slave_fd, TCSAFLUSH, &tty); |
| 2609 | close(slave_fd); | 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 | fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd)); | 2614 | fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd)); |
| 2612 | 2615 | ||
| 2613 | chr->opaque = s; | 2616 | chr->opaque = s; |
| @@ -3767,90 +3770,115 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | @@ -3767,90 +3770,115 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, | ||
| 3767 | return NULL; | 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 | const char *p; | 3778 | const char *p; |
| 3779 | + CharDriverState *chr; | ||
| 3773 | 3780 | ||
| 3774 | if (!strcmp(filename, "vc")) { | 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 | } else | 3789 | } else |
| 3781 | if (strstart(filename, "tcp:", &p)) { | 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 | } else | 3792 | } else |
| 3784 | if (strstart(filename, "telnet:", &p)) { | 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 | } else | 3795 | } else |
| 3787 | if (strstart(filename, "udp:", &p)) { | 3796 | if (strstart(filename, "udp:", &p)) { |
| 3788 | - return qemu_chr_open_udp(p); | 3797 | + chr = qemu_chr_open_udp(p); |
| 3789 | } else | 3798 | } else |
| 3790 | if (strstart(filename, "mon:", &p)) { | 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 | } else | 3807 | } else |
| 3800 | #ifndef _WIN32 | 3808 | #ifndef _WIN32 |
| 3801 | if (strstart(filename, "unix:", &p)) { | 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 | } else if (strstart(filename, "file:", &p)) { | 3811 | } else if (strstart(filename, "file:", &p)) { |
| 3804 | - return qemu_chr_open_file_out(p); | 3812 | + chr = qemu_chr_open_file_out(p); |
| 3805 | } else if (strstart(filename, "pipe:", &p)) { | 3813 | } else if (strstart(filename, "pipe:", &p)) { |
| 3806 | - return qemu_chr_open_pipe(p); | 3814 | + chr = qemu_chr_open_pipe(p); |
| 3807 | } else if (!strcmp(filename, "pty")) { | 3815 | } else if (!strcmp(filename, "pty")) { |
| 3808 | - return qemu_chr_open_pty(); | 3816 | + chr = qemu_chr_open_pty(); |
| 3809 | } else if (!strcmp(filename, "stdio")) { | 3817 | } else if (!strcmp(filename, "stdio")) { |
| 3810 | - return qemu_chr_open_stdio(); | 3818 | + chr = qemu_chr_open_stdio(); |
| 3811 | } else | 3819 | } else |
| 3812 | #if defined(__linux__) | 3820 | #if defined(__linux__) |
| 3813 | if (strstart(filename, "/dev/parport", NULL)) { | 3821 | if (strstart(filename, "/dev/parport", NULL)) { |
| 3814 | - return qemu_chr_open_pp(filename); | 3822 | + chr = qemu_chr_open_pp(filename); |
| 3815 | } else | 3823 | } else |
| 3816 | #endif | 3824 | #endif |
| 3817 | #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ | 3825 | #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ |
| 3818 | || defined(__NetBSD__) || defined(__OpenBSD__) | 3826 | || defined(__NetBSD__) || defined(__OpenBSD__) |
| 3819 | if (strstart(filename, "/dev/", NULL)) { | 3827 | if (strstart(filename, "/dev/", NULL)) { |
| 3820 | - return qemu_chr_open_tty(filename); | 3828 | + chr = qemu_chr_open_tty(filename); |
| 3821 | } else | 3829 | } else |
| 3822 | #endif | 3830 | #endif |
| 3823 | #else /* !_WIN32 */ | 3831 | #else /* !_WIN32 */ |
| 3824 | if (strstart(filename, "COM", NULL)) { | 3832 | if (strstart(filename, "COM", NULL)) { |
| 3825 | - return qemu_chr_open_win(filename); | 3833 | + chr = qemu_chr_open_win(filename); |
| 3826 | } else | 3834 | } else |
| 3827 | if (strstart(filename, "pipe:", &p)) { | 3835 | if (strstart(filename, "pipe:", &p)) { |
| 3828 | - return qemu_chr_open_win_pipe(p); | 3836 | + chr = qemu_chr_open_win_pipe(p); |
| 3829 | } else | 3837 | } else |
| 3830 | if (strstart(filename, "con:", NULL)) { | 3838 | if (strstart(filename, "con:", NULL)) { |
| 3831 | - return qemu_chr_open_win_con(filename); | 3839 | + chr = qemu_chr_open_win_con(filename); |
| 3832 | } else | 3840 | } else |
| 3833 | if (strstart(filename, "file:", &p)) { | 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 | } else | 3843 | } else |
| 3836 | #endif | 3844 | #endif |
| 3837 | #ifdef CONFIG_BRLAPI | 3845 | #ifdef CONFIG_BRLAPI |
| 3838 | if (!strcmp(filename, "braille")) { | 3846 | if (!strcmp(filename, "braille")) { |
| 3839 | - return chr_baum_init(); | 3847 | + chr = chr_baum_init(); |
| 3840 | } else | 3848 | } else |
| 3841 | #endif | 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 | void qemu_chr_close(CharDriverState *chr) | 3863 | void qemu_chr_close(CharDriverState *chr) |
| 3848 | { | 3864 | { |
| 3865 | + TAILQ_REMOVE(&chardevs, chr, next); | ||
| 3849 | if (chr->chr_close) | 3866 | if (chr->chr_close) |
| 3850 | chr->chr_close(chr); | 3867 | chr->chr_close(chr); |
| 3868 | + qemu_free(chr->filename); | ||
| 3869 | + qemu_free(chr->label); | ||
| 3851 | qemu_free(chr); | 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 | /* network device redirectors */ | 3883 | /* network device redirectors */ |
| 3856 | 3884 | ||
| @@ -9689,7 +9717,7 @@ int main(int argc, char **argv) | @@ -9689,7 +9717,7 @@ int main(int argc, char **argv) | ||
| 9689 | } | 9717 | } |
| 9690 | } | 9718 | } |
| 9691 | if (monitor_device) { | 9719 | if (monitor_device) { |
| 9692 | - monitor_hd = qemu_chr_open(monitor_device); | 9720 | + monitor_hd = qemu_chr_open("monitor", monitor_device); |
| 9693 | if (!monitor_hd) { | 9721 | if (!monitor_hd) { |
| 9694 | fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); | 9722 | fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); |
| 9695 | exit(1); | 9723 | exit(1); |
| @@ -9700,7 +9728,9 @@ int main(int argc, char **argv) | @@ -9700,7 +9728,9 @@ int main(int argc, char **argv) | ||
| 9700 | for(i = 0; i < MAX_SERIAL_PORTS; i++) { | 9728 | for(i = 0; i < MAX_SERIAL_PORTS; i++) { |
| 9701 | const char *devname = serial_devices[i]; | 9729 | const char *devname = serial_devices[i]; |
| 9702 | if (devname && strcmp(devname, "none")) { | 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 | if (!serial_hds[i]) { | 9734 | if (!serial_hds[i]) { |
| 9705 | fprintf(stderr, "qemu: could not open serial device '%s'\n", | 9735 | fprintf(stderr, "qemu: could not open serial device '%s'\n", |
| 9706 | devname); | 9736 | devname); |
| @@ -9714,7 +9744,9 @@ int main(int argc, char **argv) | @@ -9714,7 +9744,9 @@ int main(int argc, char **argv) | ||
| 9714 | for(i = 0; i < MAX_PARALLEL_PORTS; i++) { | 9744 | for(i = 0; i < MAX_PARALLEL_PORTS; i++) { |
| 9715 | const char *devname = parallel_devices[i]; | 9745 | const char *devname = parallel_devices[i]; |
| 9716 | if (devname && strcmp(devname, "none")) { | 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 | if (!parallel_hds[i]) { | 9750 | if (!parallel_hds[i]) { |
| 9719 | fprintf(stderr, "qemu: could not open parallel device '%s'\n", | 9751 | fprintf(stderr, "qemu: could not open parallel device '%s'\n", |
| 9720 | devname); | 9752 | devname); |