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 "chardev/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 #define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
45 #define MOUSE_CHARDEV(obj) \
46 OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE)
48 static void msmouse_chr_accept_input(Chardev
*chr
)
50 MouseChardev
*mouse
= MOUSE_CHARDEV(chr
);
53 len
= qemu_chr_be_can_write(chr
);
54 if (len
> mouse
->outlen
) {
61 qemu_chr_be_write(chr
, mouse
->outbuf
, len
);
64 memmove(mouse
->outbuf
, mouse
->outbuf
+ len
, mouse
->outlen
);
68 static void msmouse_queue_event(MouseChardev
*mouse
)
70 unsigned char bytes
[4] = { 0x40, 0x00, 0x00, 0x00 };
71 int dx
, dy
, count
= 3;
73 dx
= mouse
->axis
[INPUT_AXIS_X
];
74 mouse
->axis
[INPUT_AXIS_X
] = 0;
76 dy
= mouse
->axis
[INPUT_AXIS_Y
];
77 mouse
->axis
[INPUT_AXIS_Y
] = 0;
80 bytes
[0] |= (MSMOUSE_HI2(dy
) << 2) | MSMOUSE_HI2(dx
);
81 bytes
[1] |= MSMOUSE_LO6(dx
);
82 bytes
[2] |= MSMOUSE_LO6(dy
);
85 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_LEFT
] ? 0x20 : 0x00);
86 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_RIGHT
] ? 0x10 : 0x00);
87 if (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ||
88 mouse
->btnc
[INPUT_BUTTON_MIDDLE
]) {
89 bytes
[3] |= (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ? 0x20 : 0x00);
90 mouse
->btnc
[INPUT_BUTTON_MIDDLE
] = false;
94 if (mouse
->outlen
<= sizeof(mouse
->outbuf
) - count
) {
95 memcpy(mouse
->outbuf
+ mouse
->outlen
, bytes
, count
);
96 mouse
->outlen
+= count
;
98 /* queue full -> drop event */
102 static void msmouse_input_event(DeviceState
*dev
, QemuConsole
*src
,
105 MouseChardev
*mouse
= MOUSE_CHARDEV(dev
);
106 InputMoveEvent
*move
;
110 case INPUT_EVENT_KIND_REL
:
111 move
= evt
->u
.rel
.data
;
112 mouse
->axis
[move
->axis
] += move
->value
;
115 case INPUT_EVENT_KIND_BTN
:
116 btn
= evt
->u
.btn
.data
;
117 mouse
->btns
[btn
->button
] = btn
->down
;
118 mouse
->btnc
[btn
->button
] = true;
127 static void msmouse_input_sync(DeviceState
*dev
)
129 MouseChardev
*mouse
= MOUSE_CHARDEV(dev
);
130 Chardev
*chr
= CHARDEV(dev
);
132 msmouse_queue_event(mouse
);
133 msmouse_chr_accept_input(chr
);
136 static int msmouse_chr_write(struct Chardev
*s
, const uint8_t *buf
, int len
)
138 /* Ignore writes to mouse port */
142 static void char_msmouse_finalize(Object
*obj
)
144 MouseChardev
*mouse
= MOUSE_CHARDEV(obj
);
146 qemu_input_handler_unregister(mouse
->hs
);
149 static QemuInputHandler msmouse_handler
= {
150 .name
= "QEMU Microsoft Mouse",
151 .mask
= INPUT_EVENT_MASK_BTN
| INPUT_EVENT_MASK_REL
,
152 .event
= msmouse_input_event
,
153 .sync
= msmouse_input_sync
,
156 static void msmouse_chr_open(Chardev
*chr
,
157 ChardevBackend
*backend
,
161 MouseChardev
*mouse
= MOUSE_CHARDEV(chr
);
164 mouse
->hs
= qemu_input_handler_register((DeviceState
*)mouse
,
168 static void char_msmouse_class_init(ObjectClass
*oc
, void *data
)
170 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
172 cc
->open
= msmouse_chr_open
;
173 cc
->chr_write
= msmouse_chr_write
;
174 cc
->chr_accept_input
= msmouse_chr_accept_input
;
177 static const TypeInfo char_msmouse_type_info
= {
178 .name
= TYPE_CHARDEV_MSMOUSE
,
179 .parent
= TYPE_CHARDEV
,
180 .instance_size
= sizeof(MouseChardev
),
181 .instance_finalize
= char_msmouse_finalize
,
182 .class_init
= char_msmouse_class_init
,
185 static void register_types(void)
187 type_register_static(&char_msmouse_type_info
);
190 type_init(register_types
);