From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MM2e9-0006A9-IW for qemu-devel@nongnu.org; Wed, 01 Jul 2009 12:26:57 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MM2e5-00068W-SL for qemu-devel@nongnu.org; Wed, 01 Jul 2009 12:26:57 -0400 Received: from [199.232.76.173] (port=44553 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MM2e5-00068Q-Jp for qemu-devel@nongnu.org; Wed, 01 Jul 2009 12:26:53 -0400 Received: from mx1.redhat.com ([66.187.233.31]:44901) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MM2e5-0002hB-12 for qemu-devel@nongnu.org; Wed, 01 Jul 2009 12:26:53 -0400 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n61GQqa0025301 for ; Wed, 1 Jul 2009 12:26:52 -0400 Received: from file.fab.redhat.com (file.fab.redhat.com [10.33.63.6]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n61GQpbv015836 for ; Wed, 1 Jul 2009 12:26:52 -0400 Received: from file.fab.redhat.com (localhost.localdomain [127.0.0.1]) by file.fab.redhat.com (8.13.1/8.13.1) with ESMTP id n61GQpa7020019 for ; Wed, 1 Jul 2009 17:26:51 +0100 Received: (from berrange@localhost) by file.fab.redhat.com (8.13.1/8.13.1/Submit) id n61GQpbc020015 for qemu-devel@nongnu.org; Wed, 1 Jul 2009 17:26:51 +0100 Date: Wed, 1 Jul 2009 17:26:51 +0100 From: "Daniel P. Berrange" Subject: Re: [Qemu-devel] [PATCH 1/2] APIs to capture character device data Message-ID: <20090701162651.GC24296@redhat.com> References: <20090701162114.GB24296@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090701162114.GB24296@redhat.com> Reply-To: "Daniel P. Berrange" List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org commit b6d541a02ffa3dbff3f0e6a27d7441ff24481185 Author: Daniel P. Berrange Date: Wed Jul 1 14:21:17 2009 +0100 Add APIs for capturing data written to character devices, and for receiving notification of creation & deletion of character devices diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..bee309c 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -106,6 +106,23 @@ /***********************************************************/ /* character device */ +struct CharCaptureState { + struct CharCaptureOps *ops; + void *opaque; + + TAILQ_ENTRY(CharCaptureState) next; +}; + +struct CharMonitorState { + struct CharMonitorOps *ops; + void *opaque; + + TAILQ_ENTRY(CharMonitorState) next; +}; + +static TAILQ_HEAD(CharMonitorStateHead, CharMonitorState) charmonitors = + TAILQ_HEAD_INITIALIZER(charmonitors); + static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = TAILQ_HEAD_INITIALIZER(chardevs); static int initial_reset_issued; @@ -146,6 +163,13 @@ void qemu_chr_initial_reset(void) int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) { + CharCaptureState *cap; + + TAILQ_FOREACH(cap, &s->capture, next) { + if (cap->ops->capture) + (*cap->ops->capture)(cap->opaque, buf, len); + } + return s->chr_write(s, buf, len); } @@ -2215,17 +2239,41 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i } if (chr) { + CharMonitorState *mon; + if (!chr->filename) chr->filename = qemu_strdup(filename); chr->init = init; chr->label = qemu_strdup(label); TAILQ_INSERT_TAIL(&chardevs, chr, next); + + TAILQ_INIT(&chr->capture); + + TAILQ_FOREACH(mon, &charmonitors, next) { + if (mon->ops->opened) + (*mon->ops->opened)(chr, mon->opaque); + } } return chr; } void qemu_chr_close(CharDriverState *chr) { + CharMonitorState *mon; + CharCaptureState *cap, *captmp; + + TAILQ_FOREACH_SAFE(cap, &chr->capture, next, captmp) { + if (cap->ops->destroy) + (*cap->ops->destroy)(cap->opaque); + + qemu_free(cap); + } + + TAILQ_FOREACH(mon, &charmonitors, next) { + if (mon->ops->closing) + (*mon->ops->closing)(chr, mon->opaque); + } + TAILQ_REMOVE(&chardevs, chr, next); if (chr->chr_close) chr->chr_close(chr); @@ -2242,3 +2290,77 @@ void qemu_chr_info(Monitor *mon) monitor_printf(mon, "%s: filename=%s\n", chr->label, chr->filename); } } + + + +CharCaptureState *qemu_chr_add_capture(CharDriverState *s, + struct CharCaptureOps *ops, + void *opaque) +{ + CharCaptureState *cap; + + cap = qemu_mallocz(sizeof(*cap)); + + cap->ops = ops; + cap->opaque = opaque; + + TAILQ_INSERT_TAIL(&s->capture, cap, next); + + return cap; +} + + +void qemu_chr_del_capture(CharDriverState *s, + CharCaptureState *cap) +{ + TAILQ_REMOVE(&s->capture, cap, next); + + qemu_free(cap); +} + +CharMonitorState *qemu_chr_add_monitor(struct CharMonitorOps *ops, + void *opaque) +{ + CharMonitorState *mon; + + mon = qemu_mallocz(sizeof(*mon)); + + mon->ops = ops; + mon->opaque = opaque; + + TAILQ_INSERT_TAIL(&charmonitors, mon, next); + + return mon; +} + + +void qemu_chr_remove_monitor(CharMonitorState *mon) +{ + TAILQ_REMOVE(&charmonitors, mon, next); + + qemu_free(mon); +} + + +int qemu_chr_iterate(qemu_chr_iterator iter, + void *opaque) +{ + CharDriverState *chr; + + TAILQ_FOREACH(chr, &chardevs, next) { + if ((*iter)(chr, opaque) < 0) + return -1; + } + return 0; +} + +CharDriverState *qemu_chr_fetch(const char *label) +{ + CharDriverState *chr; + + TAILQ_FOREACH(chr, &chardevs, next) { + if (strcmp(chr->label, label) == 0) + return chr; + } + return NULL; +} diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..94613e7 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -46,6 +46,19 @@ typedef struct { typedef void IOEventHandler(void *opaque, int event); +struct CharCaptureOps { + void (*capture) (void *opaque, const void *buf, int size); + void (*destroy) (void *opaque); +}; + +struct CharMonitorOps { + void (*opened) (CharDriverState *s, void *opaque); + void (*closing) (CharDriverState *s, void *opaque); +}; + +typedef struct CharMonitorState CharMonitorState; +typedef struct CharCaptureState CharCaptureState; + struct CharDriverState { void (*init)(struct CharDriverState *s); int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); @@ -64,6 +77,8 @@ struct CharDriverState { char *label; char *filename; TAILQ_ENTRY(CharDriverState) next; + + TAILQ_HEAD(CharCaptureStateHead, CharCaptureState) capture; }; CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s)); @@ -84,6 +99,48 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); +/* + * Register to capture all data written to the character + * device. + */ +CharCaptureState *qemu_chr_add_capture(CharDriverState *s, + struct CharCaptureOps *ops, + void *opaque); + +/* + * Unregister a capture register on the character device + */ +void qemu_chr_del_capture(CharDriverState *s, + CharCaptureState *c); + + +/* + * Register to get notifications of the creation and deletion + * of character devices + */ +CharMonitorState *qemu_chr_add_monitor(struct CharMonitorOps *ops, + void *opaque); +/* + * Unregister notification of creation and deletion of + * character devices + */ +void qemu_chr_del_monitor(CharMonitorState *m); + + +/* + * Iterate over all existing character devices + */ +typedef int (*qemu_chr_iterator)(CharDriverState *s, + void *opaque); +int qemu_chr_iterate(qemu_chr_iterator iter, + void *opaque); + +/* + * Fetch a character device based on its assigned label + */ +CharDriverState *qemu_chr_fetch(const char *label); + + extern int term_escape_char; /* async I/O support */ -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|