Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220130' into staging
[qemu.git] / hw / input / adb-mouse.c
blobe6b341f0280809caab87dc6d61316dd979df442a
1 /*
2 * QEMU ADB mouse support
4 * Copyright (c) 2004 Fabrice Bellard
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
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "ui/console.h"
27 #include "hw/input/adb.h"
28 #include "migration/vmstate.h"
29 #include "qemu/module.h"
30 #include "adb-internal.h"
31 #include "trace.h"
32 #include "qom/object.h"
34 OBJECT_DECLARE_TYPE(MouseState, ADBMouseClass, ADB_MOUSE)
36 struct MouseState {
37 /*< public >*/
38 ADBDevice parent_obj;
39 /*< private >*/
41 int buttons_state, last_buttons_state;
42 int dx, dy, dz;
46 struct ADBMouseClass {
47 /*< public >*/
48 ADBDeviceClass parent_class;
49 /*< private >*/
51 DeviceRealize parent_realize;
54 static void adb_mouse_event(void *opaque,
55 int dx1, int dy1, int dz1, int buttons_state)
57 MouseState *s = opaque;
59 s->dx += dx1;
60 s->dy += dy1;
61 s->dz += dz1;
62 s->buttons_state = buttons_state;
66 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
68 MouseState *s = ADB_MOUSE(d);
69 int dx, dy;
71 if (s->last_buttons_state == s->buttons_state &&
72 s->dx == 0 && s->dy == 0) {
73 return 0;
76 dx = s->dx;
77 if (dx < -63) {
78 dx = -63;
79 } else if (dx > 63) {
80 dx = 63;
83 dy = s->dy;
84 if (dy < -63) {
85 dy = -63;
86 } else if (dy > 63) {
87 dy = 63;
90 s->dx -= dx;
91 s->dy -= dy;
92 s->last_buttons_state = s->buttons_state;
94 dx &= 0x7f;
95 dy &= 0x7f;
97 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON)) {
98 dy |= 0x80;
100 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON)) {
101 dx |= 0x80;
104 obuf[0] = dy;
105 obuf[1] = dx;
106 return 2;
109 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
110 const uint8_t *buf, int len)
112 MouseState *s = ADB_MOUSE(d);
113 int cmd, reg, olen;
115 if ((buf[0] & 0x0f) == ADB_FLUSH) {
116 /* flush mouse fifo */
117 s->buttons_state = s->last_buttons_state;
118 s->dx = 0;
119 s->dy = 0;
120 s->dz = 0;
121 trace_adb_device_mouse_flush();
122 return 0;
125 cmd = buf[0] & 0xc;
126 reg = buf[0] & 0x3;
127 olen = 0;
128 switch (cmd) {
129 case ADB_WRITEREG:
130 trace_adb_device_mouse_writereg(reg, buf[1]);
131 switch (reg) {
132 case 2:
133 break;
134 case 3:
136 * MacOS 9 has a bug in its ADB driver whereby after configuring
137 * the ADB bus devices it sends another write of invalid length
138 * to reg 3. Make sure we ignore it to prevent an address clash
139 * with the previous device.
141 if (len != 3) {
142 return 0;
145 switch (buf[2]) {
146 case ADB_CMD_SELF_TEST:
147 break;
148 case ADB_CMD_CHANGE_ID:
149 case ADB_CMD_CHANGE_ID_AND_ACT:
150 case ADB_CMD_CHANGE_ID_AND_ENABLE:
151 d->devaddr = buf[1] & 0xf;
152 trace_adb_device_mouse_request_change_addr(d->devaddr);
153 break;
154 default:
155 d->devaddr = buf[1] & 0xf;
157 * we support handlers:
158 * 0x01: Classic Apple Mouse Protocol / 100 cpi operations
159 * 0x02: Classic Apple Mouse Protocol / 200 cpi operations
160 * we don't support handlers (at least):
161 * 0x03: Mouse systems A3 trackball
162 * 0x04: Extended Apple Mouse Protocol
163 * 0x2f: Microspeed mouse
164 * 0x42: Macally
165 * 0x5f: Microspeed mouse
166 * 0x66: Microspeed mouse
168 if (buf[2] == 1 || buf[2] == 2) {
169 d->handler = buf[2];
172 trace_adb_device_mouse_request_change_addr_and_handler(
173 d->devaddr, d->handler);
174 break;
177 break;
178 case ADB_READREG:
179 switch (reg) {
180 case 0:
181 olen = adb_mouse_poll(d, obuf);
182 break;
183 case 1:
184 break;
185 case 3:
186 obuf[0] = d->devaddr;
187 obuf[1] = d->handler;
188 olen = 2;
189 break;
191 trace_adb_device_mouse_readreg(reg, obuf[0], obuf[1]);
192 break;
194 return olen;
197 static bool adb_mouse_has_data(ADBDevice *d)
199 MouseState *s = ADB_MOUSE(d);
201 return !(s->last_buttons_state == s->buttons_state &&
202 s->dx == 0 && s->dy == 0);
205 static void adb_mouse_reset(DeviceState *dev)
207 ADBDevice *d = ADB_DEVICE(dev);
208 MouseState *s = ADB_MOUSE(dev);
210 d->handler = 2;
211 d->devaddr = ADB_DEVID_MOUSE;
212 s->last_buttons_state = s->buttons_state = 0;
213 s->dx = s->dy = s->dz = 0;
216 static const VMStateDescription vmstate_adb_mouse = {
217 .name = "adb_mouse",
218 .version_id = 2,
219 .minimum_version_id = 2,
220 .fields = (VMStateField[]) {
221 VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device,
222 ADBDevice),
223 VMSTATE_INT32(buttons_state, MouseState),
224 VMSTATE_INT32(last_buttons_state, MouseState),
225 VMSTATE_INT32(dx, MouseState),
226 VMSTATE_INT32(dy, MouseState),
227 VMSTATE_INT32(dz, MouseState),
228 VMSTATE_END_OF_LIST()
232 static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
234 MouseState *s = ADB_MOUSE(dev);
235 ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
237 amc->parent_realize(dev, errp);
239 qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
242 static void adb_mouse_initfn(Object *obj)
244 ADBDevice *d = ADB_DEVICE(obj);
246 d->devaddr = ADB_DEVID_MOUSE;
249 static void adb_mouse_class_init(ObjectClass *oc, void *data)
251 DeviceClass *dc = DEVICE_CLASS(oc);
252 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
253 ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
255 device_class_set_parent_realize(dc, adb_mouse_realizefn,
256 &amc->parent_realize);
257 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
259 adc->devreq = adb_mouse_request;
260 adc->devhasdata = adb_mouse_has_data;
261 dc->reset = adb_mouse_reset;
262 dc->vmsd = &vmstate_adb_mouse;
265 static const TypeInfo adb_mouse_type_info = {
266 .name = TYPE_ADB_MOUSE,
267 .parent = TYPE_ADB_DEVICE,
268 .instance_size = sizeof(MouseState),
269 .instance_init = adb_mouse_initfn,
270 .class_init = adb_mouse_class_init,
271 .class_size = sizeof(ADBMouseClass),
274 static void adb_mouse_register_types(void)
276 type_register_static(&adb_mouse_type_info);
279 type_init(adb_mouse_register_types)