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)
35 QemuInputHandlerState
*hs
;
36 int axis
[INPUT_AXIS__MAX
];
37 bool btns
[INPUT_BUTTON__MAX
];
38 bool btnc
[INPUT_BUTTON__MAX
];
43 static void msmouse_chr_accept_input(CharDriverState
*chr
)
45 MouseState
*mouse
= chr
->opaque
;
48 len
= qemu_chr_be_can_write(chr
);
49 if (len
> mouse
->outlen
) {
56 qemu_chr_be_write(chr
, mouse
->outbuf
, len
);
59 memmove(mouse
->outbuf
, mouse
->outbuf
+ len
, mouse
->outlen
);
63 static void msmouse_queue_event(MouseState
*mouse
)
65 unsigned char bytes
[4] = { 0x40, 0x00, 0x00, 0x00 };
66 int dx
, dy
, count
= 3;
68 dx
= mouse
->axis
[INPUT_AXIS_X
];
69 mouse
->axis
[INPUT_AXIS_X
] = 0;
71 dy
= mouse
->axis
[INPUT_AXIS_Y
];
72 mouse
->axis
[INPUT_AXIS_Y
] = 0;
75 bytes
[0] |= (MSMOUSE_HI2(dy
) << 2) | MSMOUSE_HI2(dx
);
76 bytes
[1] |= MSMOUSE_LO6(dx
);
77 bytes
[2] |= MSMOUSE_LO6(dy
);
80 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_LEFT
] ? 0x20 : 0x00);
81 bytes
[0] |= (mouse
->btns
[INPUT_BUTTON_RIGHT
] ? 0x10 : 0x00);
82 if (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ||
83 mouse
->btnc
[INPUT_BUTTON_MIDDLE
]) {
84 bytes
[3] |= (mouse
->btns
[INPUT_BUTTON_MIDDLE
] ? 0x20 : 0x00);
85 mouse
->btnc
[INPUT_BUTTON_MIDDLE
] = false;
89 if (mouse
->outlen
<= sizeof(mouse
->outbuf
) - count
) {
90 memcpy(mouse
->outbuf
+ mouse
->outlen
, bytes
, count
);
91 mouse
->outlen
+= count
;
93 /* queue full -> drop event */
97 static void msmouse_input_event(DeviceState
*dev
, QemuConsole
*src
,
100 MouseState
*mouse
= (MouseState
*)dev
;
101 InputMoveEvent
*move
;
105 case INPUT_EVENT_KIND_REL
:
106 move
= evt
->u
.rel
.data
;
107 mouse
->axis
[move
->axis
] += move
->value
;
110 case INPUT_EVENT_KIND_BTN
:
111 btn
= evt
->u
.btn
.data
;
112 mouse
->btns
[btn
->button
] = btn
->down
;
113 mouse
->btnc
[btn
->button
] = true;
122 static void msmouse_input_sync(DeviceState
*dev
)
124 MouseState
*mouse
= (MouseState
*)dev
;
126 msmouse_queue_event(mouse
);
127 msmouse_chr_accept_input(mouse
->chr
);
130 static int msmouse_chr_write (struct CharDriverState
*s
, const uint8_t *buf
, int len
)
132 /* Ignore writes to mouse port */
136 static void msmouse_chr_close (struct CharDriverState
*chr
)
138 MouseState
*mouse
= chr
->opaque
;
140 qemu_input_handler_unregister(mouse
->hs
);
144 static QemuInputHandler msmouse_handler
= {
145 .name
= "QEMU Microsoft Mouse",
146 .mask
= INPUT_EVENT_MASK_BTN
| INPUT_EVENT_MASK_REL
,
147 .event
= msmouse_input_event
,
148 .sync
= msmouse_input_sync
,
151 static CharDriverState
*qemu_chr_open_msmouse(const char *id
,
152 ChardevBackend
*backend
,
156 ChardevCommon
*common
= backend
->u
.msmouse
.data
;
158 CharDriverState
*chr
;
160 chr
= qemu_chr_alloc(common
, errp
);
164 chr
->chr_write
= msmouse_chr_write
;
165 chr
->chr_close
= msmouse_chr_close
;
166 chr
->chr_accept_input
= msmouse_chr_accept_input
;
167 chr
->explicit_be_open
= true;
169 mouse
= g_new0(MouseState
, 1);
170 mouse
->hs
= qemu_input_handler_register((DeviceState
*)mouse
,
179 static void register_types(void)
181 register_char_driver("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE
, NULL
,
182 qemu_chr_open_msmouse
);
185 type_init(register_types
);