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
25 #include "qemu/osdep.h"
26 #include "qemu/module.h"
27 #include "chardev/char.h"
28 #include "ui/console.h"
31 #define MSMOUSE_LO6(n) ((n) & 0x3f)
32 #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
37 QemuInputHandlerState
*hs
;
38 int axis
[INPUT_AXIS__MAX
];
39 bool btns
[INPUT_BUTTON__MAX
];
40 bool btnc
[INPUT_BUTTON__MAX
];
45 #define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
46 #define MOUSE_CHARDEV(obj) \
47 OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE)
49 static void msmouse_chr_accept_input(Chardev
*chr
)
51 MouseChardev
*mouse
= MOUSE_CHARDEV(chr
);
54 len
= qemu_chr_be_can_write(chr
);
55 if (len
> mouse
->outlen
) {
62 qemu_chr_be_write(chr
, mouse
->outbuf
, len
);
65 memmove(mouse
->outbuf
, mouse
->outbuf
+ len
, mouse
->outlen
);
69 static void msmouse_queue_event(MouseChardev
*mouse
)
71 unsigned char bytes
[4] = { 0x40, 0x00, 0x00, 0x00 };
72 int dx
, dy
, count
= 3;
74 dx
= mouse
->axis
[INPUT_AXIS_X
];
75 mouse
->axis
[INPUT_AXIS_X
] = 0;
77 dy
= mouse
->axis
[INPUT_AXIS_Y
];
78 mouse
->axis
[INPUT_AXIS_Y
] = 0;
81 bytes
[0] |= (MSMOUSE_HI2(dy
) << 2) | MSMOUSE_HI2(dx
);
82 bytes
[1] |= MSMOUSE_LO6(dx
);
83 bytes
[2] |= MSMOUSE_LO6(dy
);
86 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_LEFT
] ? 0x20 : 0x00);
87 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_RIGHT
] ? 0x10 : 0x00);
88 if (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ||
89 mouse
->btnc
[INPUT_BUTTON_MIDDLE
]) {
90 bytes
[3] |= (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ? 0x20 : 0x00);
91 mouse
->btnc
[INPUT_BUTTON_MIDDLE
] = false;
95 if (mouse
->outlen
<= sizeof(mouse
->outbuf
) - count
) {
96 memcpy(mouse
->outbuf
+ mouse
->outlen
, bytes
, count
);
97 mouse
->outlen
+= count
;
99 /* queue full -> drop event */
103 static void msmouse_input_event(DeviceState
*dev
, QemuConsole
*src
,
106 MouseChardev
*mouse
= MOUSE_CHARDEV(dev
);
107 InputMoveEvent
*move
;
111 case INPUT_EVENT_KIND_REL
:
112 move
= evt
->u
.rel
.data
;
113 mouse
->axis
[move
->axis
] += move
->value
;
116 case INPUT_EVENT_KIND_BTN
:
117 btn
= evt
->u
.btn
.data
;
118 mouse
->btns
[btn
->button
] = btn
->down
;
119 mouse
->btnc
[btn
->button
] = true;
128 static void msmouse_input_sync(DeviceState
*dev
)
130 MouseChardev
*mouse
= MOUSE_CHARDEV(dev
);
131 Chardev
*chr
= CHARDEV(dev
);
133 msmouse_queue_event(mouse
);
134 msmouse_chr_accept_input(chr
);
137 static int msmouse_chr_write(struct Chardev
*s
, const uint8_t *buf
, int len
)
139 /* Ignore writes to mouse port */
143 static void char_msmouse_finalize(Object
*obj
)
145 MouseChardev
*mouse
= MOUSE_CHARDEV(obj
);
147 qemu_input_handler_unregister(mouse
->hs
);
150 static QemuInputHandler msmouse_handler
= {
151 .name
= "QEMU Microsoft Mouse",
152 .mask
= INPUT_EVENT_MASK_BTN
| INPUT_EVENT_MASK_REL
,
153 .event
= msmouse_input_event
,
154 .sync
= msmouse_input_sync
,
157 static void msmouse_chr_open(Chardev
*chr
,
158 ChardevBackend
*backend
,
162 MouseChardev
*mouse
= MOUSE_CHARDEV(chr
);
165 mouse
->hs
= qemu_input_handler_register((DeviceState
*)mouse
,
169 static void char_msmouse_class_init(ObjectClass
*oc
, void *data
)
171 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
173 cc
->open
= msmouse_chr_open
;
174 cc
->chr_write
= msmouse_chr_write
;
175 cc
->chr_accept_input
= msmouse_chr_accept_input
;
178 static const TypeInfo char_msmouse_type_info
= {
179 .name
= TYPE_CHARDEV_MSMOUSE
,
180 .parent
= TYPE_CHARDEV
,
181 .instance_size
= sizeof(MouseChardev
),
182 .instance_finalize
= char_msmouse_finalize
,
183 .class_init
= char_msmouse_class_init
,
186 static void register_types(void)
188 type_register_static(&char_msmouse_type_info
);
191 type_init(register_types
);