1 /* 2 * QEMU ADB mouse support 3 * 4 * Copyright (c) 2004 Fabrice Bellard 5 * 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: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 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. 23 */ 24 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" 33 34 typedef struct ADBMouseClass ADBMouseClass; 35 typedef struct MouseState MouseState; 36 DECLARE_OBJ_CHECKERS(MouseState, ADBMouseClass, 37 ADB_MOUSE, TYPE_ADB_MOUSE) 38 39 struct MouseState { 40 /*< public >*/ 41 ADBDevice parent_obj; 42 /*< private >*/ 43 44 int buttons_state, last_buttons_state; 45 int dx, dy, dz; 46 }; 47 48 49 struct ADBMouseClass { 50 /*< public >*/ 51 ADBDeviceClass parent_class; 52 /*< private >*/ 53 54 DeviceRealize parent_realize; 55 }; 56 57 static void adb_mouse_event(void *opaque, 58 int dx1, int dy1, int dz1, int buttons_state) 59 { 60 MouseState *s = opaque; 61 62 s->dx += dx1; 63 s->dy += dy1; 64 s->dz += dz1; 65 s->buttons_state = buttons_state; 66 } 67 68 69 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf) 70 { 71 MouseState *s = ADB_MOUSE(d); 72 int dx, dy; 73 74 if (s->last_buttons_state == s->buttons_state && 75 s->dx == 0 && s->dy == 0) { 76 return 0; 77 } 78 79 dx = s->dx; 80 if (dx < -63) { 81 dx = -63; 82 } else if (dx > 63) { 83 dx = 63; 84 } 85 86 dy = s->dy; 87 if (dy < -63) { 88 dy = -63; 89 } else if (dy > 63) { 90 dy = 63; 91 } 92 93 s->dx -= dx; 94 s->dy -= dy; 95 s->last_buttons_state = s->buttons_state; 96 97 dx &= 0x7f; 98 dy &= 0x7f; 99 100 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON)) { 101 dy |= 0x80; 102 } 103 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON)) { 104 dx |= 0x80; 105 } 106 107 obuf[0] = dy; 108 obuf[1] = dx; 109 return 2; 110 } 111 112 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, 113 const uint8_t *buf, int len) 114 { 115 MouseState *s = ADB_MOUSE(d); 116 int cmd, reg, olen; 117 118 if ((buf[0] & 0x0f) == ADB_FLUSH) { 119 /* flush mouse fifo */ 120 s->buttons_state = s->last_buttons_state; 121 s->dx = 0; 122 s->dy = 0; 123 s->dz = 0; 124 trace_adb_device_mouse_flush(); 125 return 0; 126 } 127 128 cmd = buf[0] & 0xc; 129 reg = buf[0] & 0x3; 130 olen = 0; 131 switch (cmd) { 132 case ADB_WRITEREG: 133 trace_adb_device_mouse_writereg(reg, buf[1]); 134 switch (reg) { 135 case 2: 136 break; 137 case 3: 138 /* 139 * MacOS 9 has a bug in its ADB driver whereby after configuring 140 * the ADB bus devices it sends another write of invalid length 141 * to reg 3. Make sure we ignore it to prevent an address clash 142 * with the previous device. 143 */ 144 if (len != 3) { 145 return 0; 146 } 147 148 switch (buf[2]) { 149 case ADB_CMD_SELF_TEST: 150 break; 151 case ADB_CMD_CHANGE_ID: 152 case ADB_CMD_CHANGE_ID_AND_ACT: 153 case ADB_CMD_CHANGE_ID_AND_ENABLE: 154 d->devaddr = buf[1] & 0xf; 155 trace_adb_device_mouse_request_change_addr(d->devaddr); 156 break; 157 default: 158 d->devaddr = buf[1] & 0xf; 159 /* 160 * we support handlers: 161 * 0x01: Classic Apple Mouse Protocol / 100 cpi operations 162 * 0x02: Classic Apple Mouse Protocol / 200 cpi operations 163 * we don't support handlers (at least): 164 * 0x03: Mouse systems A3 trackball 165 * 0x04: Extended Apple Mouse Protocol 166 * 0x2f: Microspeed mouse 167 * 0x42: Macally 168 * 0x5f: Microspeed mouse 169 * 0x66: Microspeed mouse 170 */ 171 if (buf[2] == 1 || buf[2] == 2) { 172 d->handler = buf[2]; 173 } 174 175 trace_adb_device_mouse_request_change_addr_and_handler( 176 d->devaddr, d->handler); 177 break; 178 } 179 } 180 break; 181 case ADB_READREG: 182 switch (reg) { 183 case 0: 184 olen = adb_mouse_poll(d, obuf); 185 break; 186 case 1: 187 break; 188 case 3: 189 obuf[0] = d->devaddr; 190 obuf[1] = d->handler; 191 olen = 2; 192 break; 193 } 194 trace_adb_device_mouse_readreg(reg, obuf[0], obuf[1]); 195 break; 196 } 197 return olen; 198 } 199 200 static bool adb_mouse_has_data(ADBDevice *d) 201 { 202 MouseState *s = ADB_MOUSE(d); 203 204 return !(s->last_buttons_state == s->buttons_state && 205 s->dx == 0 && s->dy == 0); 206 } 207 208 static void adb_mouse_reset(DeviceState *dev) 209 { 210 ADBDevice *d = ADB_DEVICE(dev); 211 MouseState *s = ADB_MOUSE(dev); 212 213 d->handler = 2; 214 d->devaddr = ADB_DEVID_MOUSE; 215 s->last_buttons_state = s->buttons_state = 0; 216 s->dx = s->dy = s->dz = 0; 217 } 218 219 static const VMStateDescription vmstate_adb_mouse = { 220 .name = "adb_mouse", 221 .version_id = 2, 222 .minimum_version_id = 2, 223 .fields = (VMStateField[]) { 224 VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device, 225 ADBDevice), 226 VMSTATE_INT32(buttons_state, MouseState), 227 VMSTATE_INT32(last_buttons_state, MouseState), 228 VMSTATE_INT32(dx, MouseState), 229 VMSTATE_INT32(dy, MouseState), 230 VMSTATE_INT32(dz, MouseState), 231 VMSTATE_END_OF_LIST() 232 } 233 }; 234 235 static void adb_mouse_realizefn(DeviceState *dev, Error **errp) 236 { 237 MouseState *s = ADB_MOUSE(dev); 238 ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev); 239 240 amc->parent_realize(dev, errp); 241 242 qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse"); 243 } 244 245 static void adb_mouse_initfn(Object *obj) 246 { 247 ADBDevice *d = ADB_DEVICE(obj); 248 249 d->devaddr = ADB_DEVID_MOUSE; 250 } 251 252 static void adb_mouse_class_init(ObjectClass *oc, void *data) 253 { 254 DeviceClass *dc = DEVICE_CLASS(oc); 255 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc); 256 ADBMouseClass *amc = ADB_MOUSE_CLASS(oc); 257 258 device_class_set_parent_realize(dc, adb_mouse_realizefn, 259 &amc->parent_realize); 260 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 261 262 adc->devreq = adb_mouse_request; 263 adc->devhasdata = adb_mouse_has_data; 264 dc->reset = adb_mouse_reset; 265 dc->vmsd = &vmstate_adb_mouse; 266 } 267 268 static const TypeInfo adb_mouse_type_info = { 269 .name = TYPE_ADB_MOUSE, 270 .parent = TYPE_ADB_DEVICE, 271 .instance_size = sizeof(MouseState), 272 .instance_init = adb_mouse_initfn, 273 .class_init = adb_mouse_class_init, 274 .class_size = sizeof(ADBMouseClass), 275 }; 276 277 static void adb_mouse_register_types(void) 278 { 279 type_register_static(&adb_mouse_type_info); 280 } 281 282 type_init(adb_mouse_register_types) 283