2 * QEMU Microsoft serial mouse emulation
4 * Copyright (c) 2008 Lubomir Rintel
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include "qemu/osdep.h"
25 #include "qemu-common.h"
26 #include "sysemu/char.h"
27 #include "ui/console.h"
30 #define MSMOUSE_LO6(n) ((n) & 0x3f)
31 #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
36 QemuInputHandlerState
*hs
;
37 int axis
[INPUT_AXIS__MAX
];
38 bool btns
[INPUT_BUTTON__MAX
];
39 bool btnc
[INPUT_BUTTON__MAX
];
44 static void msmouse_chr_accept_input(Chardev
*chr
)
46 MouseChardev
*mouse
= (MouseChardev
*)chr
;
49 len
= qemu_chr_be_can_write(chr
);
50 if (len
> mouse
->outlen
) {
57 qemu_chr_be_write(chr
, mouse
->outbuf
, len
);
60 memmove(mouse
->outbuf
, mouse
->outbuf
+ len
, mouse
->outlen
);
64 static void msmouse_queue_event(MouseChardev
*mouse
)
66 unsigned char bytes
[4] = { 0x40, 0x00, 0x00, 0x00 };
67 int dx
, dy
, count
= 3;
69 dx
= mouse
->axis
[INPUT_AXIS_X
];
70 mouse
->axis
[INPUT_AXIS_X
] = 0;
72 dy
= mouse
->axis
[INPUT_AXIS_Y
];
73 mouse
->axis
[INPUT_AXIS_Y
] = 0;
76 bytes
[0] |= (MSMOUSE_HI2(dy
) << 2) | MSMOUSE_HI2(dx
);
77 bytes
[1] |= MSMOUSE_LO6(dx
);
78 bytes
[2] |= MSMOUSE_LO6(dy
);
81 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_LEFT
] ? 0x20 : 0x00);
82 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_RIGHT
] ? 0x10 : 0x00);
83 if (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ||
84 mouse
->btnc
[INPUT_BUTTON_MIDDLE
]) {
85 bytes
[3] |= (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ? 0x20 : 0x00);
86 mouse
->btnc
[INPUT_BUTTON_MIDDLE
] = false;
90 if (mouse
->outlen
<= sizeof(mouse
->outbuf
) - count
) {
91 memcpy(mouse
->outbuf
+ mouse
->outlen
, bytes
, count
);
92 mouse
->outlen
+= count
;
94 /* queue full -> drop event */
98 static void msmouse_input_event(DeviceState
*dev
, QemuConsole
*src
,
101 MouseChardev
*mouse
= (MouseChardev
*)dev
;
102 InputMoveEvent
*move
;
106 case INPUT_EVENT_KIND_REL
:
107 move
= evt
->u
.rel
.data
;
108 mouse
->axis
[move
->axis
] += move
->value
;
111 case INPUT_EVENT_KIND_BTN
:
112 btn
= evt
->u
.btn
.data
;
113 mouse
->btns
[btn
->button
] = btn
->down
;
114 mouse
->btnc
[btn
->button
] = true;
123 static void msmouse_input_sync(DeviceState
*dev
)
125 MouseChardev
*mouse
= (MouseChardev
*)dev
;
126 Chardev
*chr
= (Chardev
*)dev
;
128 msmouse_queue_event(mouse
);
129 msmouse_chr_accept_input(chr
);
132 static int msmouse_chr_write(struct Chardev
*s
, const uint8_t *buf
, int len
)
134 /* Ignore writes to mouse port */
138 static void msmouse_chr_free(struct Chardev
*chr
)
140 MouseChardev
*mouse
= (MouseChardev
*)chr
;
142 qemu_input_handler_unregister(mouse
->hs
);
145 static QemuInputHandler msmouse_handler
= {
146 .name
= "QEMU Microsoft Mouse",
147 .mask
= INPUT_EVENT_MASK_BTN
| INPUT_EVENT_MASK_REL
,
148 .event
= msmouse_input_event
,
149 .sync
= msmouse_input_sync
,
152 static Chardev
*qemu_chr_open_msmouse(const CharDriver
*driver
,
154 ChardevBackend
*backend
,
159 ChardevCommon
*common
= backend
->u
.msmouse
.data
;
163 chr
= qemu_chr_alloc(driver
, common
, errp
);
169 mouse
= (MouseChardev
*)chr
;
170 mouse
->hs
= qemu_input_handler_register((DeviceState
*)mouse
,
177 static void register_types(void)
179 static const CharDriver driver
= {
180 .instance_size
= sizeof(MouseChardev
),
181 .kind
= CHARDEV_BACKEND_KIND_MSMOUSE
,
182 .create
= qemu_chr_open_msmouse
,
183 .chr_write
= msmouse_chr_write
,
184 .chr_accept_input
= msmouse_chr_accept_input
,
185 .chr_free
= msmouse_chr_free
,
187 register_char_driver(&driver
);
190 type_init(register_types
);