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"
30 #include "qom/object.h"
32 #define MSMOUSE_LO6(n) ((n) & 0x3f)
33 #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
38 QemuInputHandlerState
*hs
;
39 int axis
[INPUT_AXIS__MAX
];
40 bool btns
[INPUT_BUTTON__MAX
];
41 bool btnc
[INPUT_BUTTON__MAX
];
45 typedef struct MouseChardev MouseChardev
;
47 #define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
48 DECLARE_INSTANCE_CHECKER(MouseChardev
, MOUSE_CHARDEV
,
51 static void msmouse_chr_accept_input(Chardev
*chr
)
53 MouseChardev
*mouse
= MOUSE_CHARDEV(chr
);
56 len
= qemu_chr_be_can_write(chr
);
57 if (len
> mouse
->outlen
) {
64 qemu_chr_be_write(chr
, mouse
->outbuf
, len
);
67 memmove(mouse
->outbuf
, mouse
->outbuf
+ len
, mouse
->outlen
);
71 static void msmouse_queue_event(MouseChardev
*mouse
)
73 unsigned char bytes
[4] = { 0x40, 0x00, 0x00, 0x00 };
74 int dx
, dy
, count
= 3;
76 dx
= mouse
->axis
[INPUT_AXIS_X
];
77 mouse
->axis
[INPUT_AXIS_X
] = 0;
79 dy
= mouse
->axis
[INPUT_AXIS_Y
];
80 mouse
->axis
[INPUT_AXIS_Y
] = 0;
83 bytes
[0] |= (MSMOUSE_HI2(dy
) << 2) | MSMOUSE_HI2(dx
);
84 bytes
[1] |= MSMOUSE_LO6(dx
);
85 bytes
[2] |= MSMOUSE_LO6(dy
);
88 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_LEFT
] ? 0x20 : 0x00);
89 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_RIGHT
] ? 0x10 : 0x00);
90 if (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ||
91 mouse
->btnc
[INPUT_BUTTON_MIDDLE
]) {
92 bytes
[3] |= (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ? 0x20 : 0x00);
93 mouse
->btnc
[INPUT_BUTTON_MIDDLE
] = false;
97 if (mouse
->outlen
<= sizeof(mouse
->outbuf
) - count
) {
98 memcpy(mouse
->outbuf
+ mouse
->outlen
, bytes
, count
);
99 mouse
->outlen
+= count
;
101 /* queue full -> drop event */
105 static void msmouse_input_event(DeviceState
*dev
, QemuConsole
*src
,
108 MouseChardev
*mouse
= MOUSE_CHARDEV(dev
);
109 InputMoveEvent
*move
;
113 case INPUT_EVENT_KIND_REL
:
114 move
= evt
->u
.rel
.data
;
115 mouse
->axis
[move
->axis
] += move
->value
;
118 case INPUT_EVENT_KIND_BTN
:
119 btn
= evt
->u
.btn
.data
;
120 mouse
->btns
[btn
->button
] = btn
->down
;
121 mouse
->btnc
[btn
->button
] = true;
130 static void msmouse_input_sync(DeviceState
*dev
)
132 MouseChardev
*mouse
= MOUSE_CHARDEV(dev
);
133 Chardev
*chr
= CHARDEV(dev
);
135 msmouse_queue_event(mouse
);
136 msmouse_chr_accept_input(chr
);
139 static int msmouse_chr_write(struct Chardev
*s
, const uint8_t *buf
, int len
)
141 /* Ignore writes to mouse port */
145 static void char_msmouse_finalize(Object
*obj
)
147 MouseChardev
*mouse
= MOUSE_CHARDEV(obj
);
149 qemu_input_handler_unregister(mouse
->hs
);
152 static QemuInputHandler msmouse_handler
= {
153 .name
= "QEMU Microsoft Mouse",
154 .mask
= INPUT_EVENT_MASK_BTN
| INPUT_EVENT_MASK_REL
,
155 .event
= msmouse_input_event
,
156 .sync
= msmouse_input_sync
,
159 static void msmouse_chr_open(Chardev
*chr
,
160 ChardevBackend
*backend
,
164 MouseChardev
*mouse
= MOUSE_CHARDEV(chr
);
167 mouse
->hs
= qemu_input_handler_register((DeviceState
*)mouse
,
171 static void char_msmouse_class_init(ObjectClass
*oc
, void *data
)
173 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
175 cc
->open
= msmouse_chr_open
;
176 cc
->chr_write
= msmouse_chr_write
;
177 cc
->chr_accept_input
= msmouse_chr_accept_input
;
180 static const TypeInfo char_msmouse_type_info
= {
181 .name
= TYPE_CHARDEV_MSMOUSE
,
182 .parent
= TYPE_CHARDEV
,
183 .instance_size
= sizeof(MouseChardev
),
184 .instance_finalize
= char_msmouse_finalize
,
185 .class_init
= char_msmouse_class_init
,
188 static void register_types(void)
190 type_register_static(&char_msmouse_type_info
);
193 type_init(register_types
);