From patchwork Thu Mar 11 21:57:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shahar Havivi X-Patchwork-Id: 47634 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 26BCCB7D01 for ; Fri, 12 Mar 2010 08:58:02 +1100 (EST) Received: from localhost ([127.0.0.1]:48330 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NpqOE-0004Mp-T9 for incoming@patchwork.ozlabs.org; Thu, 11 Mar 2010 16:57:58 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NpqNg-0004KT-CQ for qemu-devel@nongnu.org; Thu, 11 Mar 2010 16:57:24 -0500 Received: from [199.232.76.173] (port=51436 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NpqNf-0004Jo-W0 for qemu-devel@nongnu.org; Thu, 11 Mar 2010 16:57:24 -0500 Received: from Debian-exim by monty-python.gnu.org with spam-scanned (Exim 4.60) (envelope-from ) id 1NpqNe-0000yw-1B for qemu-devel@nongnu.org; Thu, 11 Mar 2010 16:57:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44002) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NpqNd-0000ys-JL for qemu-devel@nongnu.org; Thu, 11 Mar 2010 16:57:21 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o2BLvJrF032388 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 11 Mar 2010 16:57:20 -0500 Received: from localhost (dhcp-1-229.tlv.redhat.com [10.35.1.229]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o2BLvICK009807; Thu, 11 Mar 2010 16:57:19 -0500 Date: Thu, 11 Mar 2010 23:57:16 +0200 From: Shahar Havivi To: qemu-devel@nongnu.org Message-ID: <20100311215712.GA6606@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-08-17) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: Dor Laor Subject: [Qemu-devel] [PATCH] Support for multiple keyboard device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently qemu use the last keyboard device that added, When removing keyboard (via device_del kbd) you get segfault next time you try to write in the client. i.e. start qemu x86_64-softmmu/qemu-system-x86_64 -usb -device usb-kbd,id=kbd switch to monitor device_del kbd switch back to client, segfault This patch fix the segfault and add list of all the keyboard handle much like the mouse device does. Signed-off-by: Shahar Havivi --- console.h | 9 +++++- hw/usb-hid.c | 9 ++++-- input.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 88 insertions(+), 11 deletions(-) diff --git a/console.h b/console.h index 71e8ff2..e250008 100644 --- a/console.h +++ b/console.h @@ -38,7 +38,14 @@ typedef struct QEMUPutLEDEntry { QTAILQ_ENTRY(QEMUPutLEDEntry) next; } QEMUPutLEDEntry; -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); +typedef struct QEMUPutKbdEntry { + QEMUPutKBDEvent *qemu_put_kbd_event; + void *qemu_put_kbd_event_opaque; + struct QEMUPutKbdEntry *next; +} QEMUPutKbdEntry; + +QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); +void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry); QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute, const char *name); diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 2e4e647..1dd0cc9 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -55,6 +55,7 @@ typedef struct USBKeyboardState { uint8_t leds; uint8_t key[16]; int keys; + QEMUPutKbdEntry *eh_entry; } USBKeyboardState; typedef struct USBHIDState { @@ -635,7 +636,7 @@ static void usb_keyboard_handle_reset(USBDevice *dev) { USBHIDState *s = (USBHIDState *)dev; - qemu_add_kbd_event_handler(usb_keyboard_event, s); + s->kbd.eh_entry = qemu_add_kbd_event_handler(usb_keyboard_event, s); s->protocol = 1; } @@ -856,9 +857,11 @@ static void usb_hid_handle_destroy(USBDevice *dev) { USBHIDState *s = (USBHIDState *)dev; - if (s->kind != USB_KEYBOARD) + if (s->kind != USB_KEYBOARD) { qemu_remove_mouse_event_handler(s->ptr.eh_entry); - /* TODO: else */ + } else { + qemu_remove_kbd_event_handler(s->kbd.eh_entry); + } } static int usb_hid_initfn(USBDevice *dev, int kind) diff --git a/input.c b/input.c index baaa4c6..90b6cfb 100644 --- a/input.c +++ b/input.c @@ -29,16 +29,82 @@ #include "qjson.h" -static QEMUPutKBDEvent *qemu_put_kbd_event; -static void *qemu_put_kbd_event_opaque; +static QEMUPutKbdEntry *qemu_put_kbd_event_head; +static QEMUPutKbdEntry *qemu_put_kbd_event_current; static QEMUPutMouseEntry *qemu_put_mouse_event_head; static QEMUPutMouseEntry *qemu_put_mouse_event_current; static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers); -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) +QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) { - qemu_put_kbd_event_opaque = opaque; - qemu_put_kbd_event = func; + QEMUPutKbdEntry *s, *cursor; + + cursor = qemu_put_kbd_event_head; + while (cursor) { + if (cursor->qemu_put_kbd_event == func && + cursor->qemu_put_kbd_event_opaque == opaque) { + + qemu_put_kbd_event_current = cursor; + return cursor; + } + cursor = cursor->next; + } + + s = qemu_mallocz(sizeof(QEMUPutKbdEntry)); + + s->qemu_put_kbd_event_opaque = opaque; + s->qemu_put_kbd_event = func; + s->next = NULL; + + if (!qemu_put_kbd_event_head) { + qemu_put_kbd_event_head = s; + qemu_put_kbd_event_current = s; + return s; + } + + cursor = qemu_put_kbd_event_head; + while (cursor->next) { + cursor = cursor->next; + } + + cursor->next = s; + qemu_put_kbd_event_current = s; + + return s; +} + +void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry) +{ + QEMUPutKbdEntry *prev = NULL, *cursor; + + if (!qemu_put_kbd_event_head || !entry) { + return; + } + + cursor = qemu_put_kbd_event_head; + while (cursor && cursor != entry) { + prev = cursor; + cursor = cursor->next; + } + + if (cursor == NULL) { + return; + } else if (prev == NULL) { + qemu_put_kbd_event_head = cursor->next; + if (qemu_put_kbd_event_current == entry) { + qemu_put_kbd_event_current = cursor->next; + } + qemu_free(entry); + return; + } + + prev->next = entry->next; + + if (qemu_put_kbd_event_current == entry) { + qemu_put_kbd_event_current = prev; + } + + qemu_free(entry); } QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, @@ -126,8 +192,9 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) void kbd_put_keycode(int keycode) { - if (qemu_put_kbd_event) { - qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode); + if (qemu_put_kbd_event_current) { + qemu_put_kbd_event_current->qemu_put_kbd_event( + qemu_put_kbd_event_current->qemu_put_kbd_event_opaque, keycode); } }