qemu/hw/input/adb-mouse.c
<<
>>
Prefs
   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
  33#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
  34
  35typedef struct MouseState {
  36    /*< public >*/
  37    ADBDevice parent_obj;
  38    /*< private >*/
  39
  40    int buttons_state, last_buttons_state;
  41    int dx, dy, dz;
  42} MouseState;
  43
  44#define ADB_MOUSE_CLASS(class) \
  45    OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
  46#define ADB_MOUSE_GET_CLASS(obj) \
  47    OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
  48
  49typedef struct ADBMouseClass {
  50    /*< public >*/
  51    ADBDeviceClass parent_class;
  52    /*< private >*/
  53
  54    DeviceRealize parent_realize;
  55} ADBMouseClass;
  56
  57static 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
  69static 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
 112static 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_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_mouse_writereg(reg, buf[1]);
 134        switch (reg) {
 135        case 2:
 136            break;
 137        case 3:
 138            switch (buf[2]) {
 139            case ADB_CMD_SELF_TEST:
 140                break;
 141            case ADB_CMD_CHANGE_ID:
 142            case ADB_CMD_CHANGE_ID_AND_ACT:
 143            case ADB_CMD_CHANGE_ID_AND_ENABLE:
 144                d->devaddr = buf[1] & 0xf;
 145                trace_adb_mouse_request_change_addr(d->devaddr);
 146                break;
 147            default:
 148                if (!d->disable_direct_reg3_writes) {
 149                    d->devaddr = buf[1] & 0xf;
 150
 151                    /* we support handlers:
 152                     * 0x01: Classic Apple Mouse Protocol / 100 cpi operations
 153                     * 0x02: Classic Apple Mouse Protocol / 200 cpi operations
 154                     * we don't support handlers (at least):
 155                     * 0x03: Mouse systems A3 trackball
 156                     * 0x04: Extended Apple Mouse Protocol
 157                     * 0x2f: Microspeed mouse
 158                     * 0x42: Macally
 159                     * 0x5f: Microspeed mouse
 160                     * 0x66: Microspeed mouse
 161                     */
 162                    if (buf[2] == 1 || buf[2] == 2) {
 163                        d->handler = buf[2];
 164                    }
 165
 166                    trace_adb_mouse_request_change_addr_and_handler(
 167                        d->devaddr, d->handler);
 168                }
 169                break;
 170            }
 171        }
 172        break;
 173    case ADB_READREG:
 174        switch (reg) {
 175        case 0:
 176            olen = adb_mouse_poll(d, obuf);
 177            break;
 178        case 1:
 179            break;
 180        case 3:
 181            obuf[0] = d->devaddr;
 182            obuf[1] = d->handler;
 183            olen = 2;
 184            break;
 185        }
 186        trace_adb_mouse_readreg(reg, obuf[0], obuf[1]);
 187        break;
 188    }
 189    return olen;
 190}
 191
 192static void adb_mouse_reset(DeviceState *dev)
 193{
 194    ADBDevice *d = ADB_DEVICE(dev);
 195    MouseState *s = ADB_MOUSE(dev);
 196
 197    d->handler = 2;
 198    d->devaddr = ADB_DEVID_MOUSE;
 199    s->last_buttons_state = s->buttons_state = 0;
 200    s->dx = s->dy = s->dz = 0;
 201}
 202
 203static const VMStateDescription vmstate_adb_mouse = {
 204    .name = "adb_mouse",
 205    .version_id = 2,
 206    .minimum_version_id = 2,
 207    .fields = (VMStateField[]) {
 208        VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device,
 209                       ADBDevice),
 210        VMSTATE_INT32(buttons_state, MouseState),
 211        VMSTATE_INT32(last_buttons_state, MouseState),
 212        VMSTATE_INT32(dx, MouseState),
 213        VMSTATE_INT32(dy, MouseState),
 214        VMSTATE_INT32(dz, MouseState),
 215        VMSTATE_END_OF_LIST()
 216    }
 217};
 218
 219static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
 220{
 221    MouseState *s = ADB_MOUSE(dev);
 222    ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
 223
 224    amc->parent_realize(dev, errp);
 225
 226    qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
 227}
 228
 229static void adb_mouse_initfn(Object *obj)
 230{
 231    ADBDevice *d = ADB_DEVICE(obj);
 232
 233    d->devaddr = ADB_DEVID_MOUSE;
 234}
 235
 236static void adb_mouse_class_init(ObjectClass *oc, void *data)
 237{
 238    DeviceClass *dc = DEVICE_CLASS(oc);
 239    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
 240    ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
 241
 242    device_class_set_parent_realize(dc, adb_mouse_realizefn,
 243                                    &amc->parent_realize);
 244    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 245
 246    adc->devreq = adb_mouse_request;
 247    dc->reset = adb_mouse_reset;
 248    dc->vmsd = &vmstate_adb_mouse;
 249}
 250
 251static const TypeInfo adb_mouse_type_info = {
 252    .name = TYPE_ADB_MOUSE,
 253    .parent = TYPE_ADB_DEVICE,
 254    .instance_size = sizeof(MouseState),
 255    .instance_init = adb_mouse_initfn,
 256    .class_init = adb_mouse_class_init,
 257    .class_size = sizeof(ADBMouseClass),
 258};
 259
 260static void adb_mouse_register_types(void)
 261{
 262    type_register_static(&adb_mouse_type_info);
 263}
 264
 265type_init(adb_mouse_register_types)
 266