diff mbox series

[v2,1/5] msmouse: Handle mouse reset

Message ID 20220908173120.16779-2-arwed.meyer@gmx.de
State New
Headers show
Series Make serial msmouse work | expand

Commit Message

Arwed Meyer Sept. 8, 2022, 5:31 p.m. UTC
Detect mouse reset via RTS or DTR line:
Don't send or process anything while in reset.
When coming out of reset, send ID sequence first thing.
This allows msmouse to be detected by common mouse drivers.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77
Signed-off-by: Arwed Meyer <arwed.meyer@gmx.de>
---
 chardev/msmouse.c | 63 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 61 insertions(+), 2 deletions(-)

--
2.34.1

Comments

Peter Maydell Sept. 8, 2022, 9:11 p.m. UTC | #1
On Thu, 8 Sept 2022 at 18:43, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>
> Detect mouse reset via RTS or DTR line:
> Don't send or process anything while in reset.
> When coming out of reset, send ID sequence first thing.
> This allows msmouse to be detected by common mouse drivers.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77
> Signed-off-by: Arwed Meyer <arwed.meyer@gmx.de>

How does this work across migration? There doesn't seem
to be anything that handles migration of the existing
state inside the MouseChardev either, though...

-- PMM
Arwed Meyer Sept. 11, 2022, 5:14 p.m. UTC | #2
Am 08.09.22 um 23:11 schrieb Peter Maydell:
> On Thu, 8 Sept 2022 at 18:43, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>>
>> Detect mouse reset via RTS or DTR line:
>> Don't send or process anything while in reset.
>> When coming out of reset, send ID sequence first thing.
>> This allows msmouse to be detected by common mouse drivers.
>>
>> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77
>> Signed-off-by: Arwed Meyer <arwed.meyer@gmx.de>
>
> How does this work across migration? There doesn't seem
> to be anything that handles migration of the existing
> state inside the MouseChardev either, though...
>
> -- PMM
Hi,

can you please explain in more detail what you don't understand and what
you mean by "migration"?
Peter Maydell Sept. 11, 2022, 6:27 p.m. UTC | #3
On Sun, 11 Sept 2022 at 18:14, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>
> Am 08.09.22 um 23:11 schrieb Peter Maydell:
> > On Thu, 8 Sept 2022 at 18:43, Arwed Meyer <arwed.meyer@gmx.de> wrote:
> >>
> >> Detect mouse reset via RTS or DTR line:
> >> Don't send or process anything while in reset.
> >> When coming out of reset, send ID sequence first thing.
> >> This allows msmouse to be detected by common mouse drivers.
> >>
> >> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77
> >> Signed-off-by: Arwed Meyer <arwed.meyer@gmx.de>
> >
> > How does this work across migration? There doesn't seem
> > to be anything that handles migration of the existing
> > state inside the MouseChardev either, though...

> can you please explain in more detail what you don't understand and what
> you mean by "migration"?

Migration is when the state of the whole VM is copied from
one host to another, or, equivalently, when it is saved to
the disk image with 'savevm' to be restarted later. For this
to work all the guest-changeable state in the whole VM (all
device registers, internal state, etc) has to be saved so
it can be reloaded on the destination. My question is basically
how this new state in mouse->tiocm, and more generally how
the existing other state fields in that struct, are saved
and loaded during the migration process. I know how this
works for device models, but I'm not sure how chardevs
figure into it. (Perhaps the answer is "this shouldn't be
a chardev at all" ???)

thanks
-- PMM
Arwed Meyer Sept. 12, 2022, 5:45 p.m. UTC | #4
Am 11.09.22 um 20:27 schrieb Peter Maydell:
> On Sun, 11 Sept 2022 at 18:14, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>>
>> Am 08.09.22 um 23:11 schrieb Peter Maydell:
>>> On Thu, 8 Sept 2022 at 18:43, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>>>>
>>>> Detect mouse reset via RTS or DTR line:
>>>> Don't send or process anything while in reset.
>>>> When coming out of reset, send ID sequence first thing.
>>>> This allows msmouse to be detected by common mouse drivers.
>>>>
>>>> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77
>>>> Signed-off-by: Arwed Meyer <arwed.meyer@gmx.de>
>>>
>>> How does this work across migration? There doesn't seem
>>> to be anything that handles migration of the existing
>>> state inside the MouseChardev either, though...
>
>> can you please explain in more detail what you don't understand and what
>> you mean by "migration"?
>
> Migration is when the state of the whole VM is copied from
> one host to another, or, equivalently, when it is saved to
> the disk image with 'savevm' to be restarted later. For this
> to work all the guest-changeable state in the whole VM (all
> device registers, internal state, etc) has to be saved so
> it can be reloaded on the destination. My question is basically
> how this new state in mouse->tiocm, and more generally how
> the existing other state fields in that struct, are saved
> and loaded during the migration process. I know how this
> works for device models, but I'm not sure how chardevs
> figure into it. (Perhaps the answer is "this shouldn't be
> a chardev at all" ???)
>
> thanks
> -- PMM

Hi,

thanks for adding some context. Good question.
Unfortunately I don't know the device and migration code much, so I
can't really say anything about this. I guess(!) it should be enough to
save/load contents of struct MouseChardev. No idea if and how this can
be done though.
Also since saving/loading device state wasn't supported in the msmouse
code to begin with, for me this is a new feature and out of scope for
this patch set.
The result of this missing feature might be that mouse buttons are
detected as not pressed and mouse movement data is lost after migration.


Regards
Arwed Meyer Sept. 12, 2022, 5:54 p.m. UTC | #5
Am 12.09.22 um 19:45 schrieb Arwed Meyer:
> Am 11.09.22 um 20:27 schrieb Peter Maydell:
>> On Sun, 11 Sept 2022 at 18:14, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>>>
>>> Am 08.09.22 um 23:11 schrieb Peter Maydell:
>>>> On Thu, 8 Sept 2022 at 18:43, Arwed Meyer <arwed.meyer@gmx.de> wrote:
>>>>>
>>>>> Detect mouse reset via RTS or DTR line:
>>>>> Don't send or process anything while in reset.
>>>>> When coming out of reset, send ID sequence first thing.
>>>>> This allows msmouse to be detected by common mouse drivers.
>>>>>
>>>>> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77
>>>>> Signed-off-by: Arwed Meyer <arwed.meyer@gmx.de>
>>>>
>>>> How does this work across migration? There doesn't seem
>>>> to be anything that handles migration of the existing
>>>> state inside the MouseChardev either, though...
>>
>>> can you please explain in more detail what you don't understand and what
>>> you mean by "migration"?
>>
>> Migration is when the state of the whole VM is copied from
>> one host to another, or, equivalently, when it is saved to
>> the disk image with 'savevm' to be restarted later. For this
>> to work all the guest-changeable state in the whole VM (all
>> device registers, internal state, etc) has to be saved so
>> it can be reloaded on the destination. My question is basically
>> how this new state in mouse->tiocm, and more generally how
>> the existing other state fields in that struct, are saved
>> and loaded during the migration process. I know how this
>> works for device models, but I'm not sure how chardevs
>> figure into it. (Perhaps the answer is "this shouldn't be
>> a chardev at all" ???)
>>
>> thanks
>> -- PMM
>
> Hi,
>
> thanks for adding some context. Good question.
> Unfortunately I don't know the device and migration code much, so I
> can't really say anything about this. I guess(!) it should be enough to
> save/load contents of struct MouseChardev. No idea if and how this can
> be done though.
> Also since saving/loading device state wasn't supported in the msmouse
> code to begin with, for me this is a new feature and out of scope for
> this patch set.
> The result of this missing feature might be that mouse buttons are
> detected as not pressed and mouse movement data is lost after migration.
>
>
> Regards

... more specific regarding to mouse->tiocm:
Since it is initialized to 0, the device is put to reset after restoring
state/migrating and won't react. You'd probably have to reload the
client's mouse driver to get the mouse up and running again.


Regards
Peter Maydell Sept. 13, 2022, 12:30 p.m. UTC | #6
On Mon, 12 Sept 2022 at 18:45, Arwed Meyer <arwed.meyer@gmx.de> wrote:
> thanks for adding some context. Good question.
> Unfortunately I don't know the device and migration code much, so I
> can't really say anything about this. I guess(!) it should be enough to
> save/load contents of struct MouseChardev. No idea if and how this can
> be done though.
> Also since saving/loading device state wasn't supported in the msmouse
> code to begin with, for me this is a new feature and out of scope for
> this patch set.

Yes, agreed. I was really hoping to catch the attention of one
of the reviewers who's more familiar with chardev...

-- PMM
diff mbox series

Patch

diff --git a/chardev/msmouse.c b/chardev/msmouse.c
index eb9231dcdb..95fa488339 100644
--- a/chardev/msmouse.c
+++ b/chardev/msmouse.c
@@ -25,17 +25,20 @@ 
 #include "qemu/osdep.h"
 #include "qemu/module.h"
 #include "chardev/char.h"
+#include "chardev/char-serial.h"
 #include "ui/console.h"
 #include "ui/input.h"
 #include "qom/object.h"

-#define MSMOUSE_LO6(n) ((n) & 0x3f)
-#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
+#define MSMOUSE_LO6(n)  ((n) & 0x3f)
+#define MSMOUSE_HI2(n)  (((n) & 0xc0) >> 6)
+#define MSMOUSE_PWR(cm) (cm & (CHR_TIOCM_RTS | CHR_TIOCM_DTR))

 struct MouseChardev {
     Chardev parent;

     QemuInputHandlerState *hs;
+    int tiocm;
     int axis[INPUT_AXIS__MAX];
     bool btns[INPUT_BUTTON__MAX];
     bool btnc[INPUT_BUTTON__MAX];
@@ -109,6 +112,11 @@  static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
     InputMoveEvent *move;
     InputBtnEvent *btn;

+    /* Ignore events if serial mouse powered down. */
+    if (!MSMOUSE_PWR(mouse->tiocm)) {
+        return;
+    }
+
     switch (evt->type) {
     case INPUT_EVENT_KIND_REL:
         move = evt->u.rel.data;
@@ -132,6 +140,11 @@  static void msmouse_input_sync(DeviceState *dev)
     MouseChardev *mouse = MOUSE_CHARDEV(dev);
     Chardev *chr = CHARDEV(dev);

+    /* Ignore events if serial mouse powered down. */
+    if (!MSMOUSE_PWR(mouse->tiocm)) {
+        return;
+    }
+
     msmouse_queue_event(mouse);
     msmouse_chr_accept_input(chr);
 }
@@ -142,6 +155,50 @@  static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len)
     return len;
 }

+static int msmouse_ioctl(Chardev *chr, int cmd, void *arg)
+{
+    MouseChardev *mouse = MOUSE_CHARDEV(chr);
+    int c;
+    int *targ = (int *)arg;
+
+    switch (cmd) {
+    case CHR_IOCTL_SERIAL_SET_TIOCM:
+        c = mouse->tiocm;
+        mouse->tiocm = *(int *)arg;
+        if (MSMOUSE_PWR(mouse->tiocm)) {
+            if (!MSMOUSE_PWR(c)) {
+                /*
+                 * Power on after reset: send "M3"
+                 * cause we behave like a 3 button logitech
+                 * mouse.
+                 */
+                mouse->outbuf[0] = 'M';
+                mouse->outbuf[1] = '3';
+                mouse->outlen = 2;
+                /* Start sending data to serial. */
+                msmouse_chr_accept_input(chr);
+            }
+            break;
+        }
+        /*
+         * Reset mouse buffers on power down.
+         * Mouse won't send anything without power.
+         */
+        mouse->outlen = 0;
+        memset(mouse->axis, 0, sizeof(mouse->axis));
+        memset(mouse->btns, false, sizeof(mouse->btns));
+        memset(mouse->btnc, false, sizeof(mouse->btns));
+        break;
+    case CHR_IOCTL_SERIAL_GET_TIOCM:
+        /* Remember line control status. */
+        *targ = mouse->tiocm;
+        break;
+    default:
+        return -ENOTSUP;
+    }
+    return 0;
+}
+
 static void char_msmouse_finalize(Object *obj)
 {
     MouseChardev *mouse = MOUSE_CHARDEV(obj);
@@ -166,6 +223,7 @@  static void msmouse_chr_open(Chardev *chr,
     *be_opened = false;
     mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
                                             &msmouse_handler);
+    mouse->tiocm = 0;
 }

 static void char_msmouse_class_init(ObjectClass *oc, void *data)
@@ -175,6 +233,7 @@  static void char_msmouse_class_init(ObjectClass *oc, void *data)
     cc->open = msmouse_chr_open;
     cc->chr_write = msmouse_chr_write;
     cc->chr_accept_input = msmouse_chr_accept_input;
+    cc->chr_ioctl = msmouse_ioctl;
 }

 static const TypeInfo char_msmouse_type_info = {