cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

adb-mouse.c (7657B)


      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
     34OBJECT_DECLARE_TYPE(MouseState, ADBMouseClass, ADB_MOUSE)
     35
     36struct MouseState {
     37    /*< public >*/
     38    ADBDevice parent_obj;
     39    /*< private >*/
     40
     41    int buttons_state, last_buttons_state;
     42    int dx, dy, dz;
     43};
     44
     45
     46struct ADBMouseClass {
     47    /*< public >*/
     48    ADBDeviceClass parent_class;
     49    /*< private >*/
     50
     51    DeviceRealize parent_realize;
     52};
     53
     54static void adb_mouse_event(void *opaque,
     55                            int dx1, int dy1, int dz1, int buttons_state)
     56{
     57    MouseState *s = opaque;
     58
     59    s->dx += dx1;
     60    s->dy += dy1;
     61    s->dz += dz1;
     62    s->buttons_state = buttons_state;
     63}
     64
     65
     66static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
     67{
     68    MouseState *s = ADB_MOUSE(d);
     69    int dx, dy;
     70
     71    if (s->last_buttons_state == s->buttons_state &&
     72        s->dx == 0 && s->dy == 0) {
     73        return 0;
     74    }
     75
     76    dx = s->dx;
     77    if (dx < -63) {
     78        dx = -63;
     79    } else if (dx > 63) {
     80        dx = 63;
     81    }
     82
     83    dy = s->dy;
     84    if (dy < -63) {
     85        dy = -63;
     86    } else if (dy > 63) {
     87        dy = 63;
     88    }
     89
     90    s->dx -= dx;
     91    s->dy -= dy;
     92    s->last_buttons_state = s->buttons_state;
     93
     94    dx &= 0x7f;
     95    dy &= 0x7f;
     96
     97    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON)) {
     98        dy |= 0x80;
     99    }
    100    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON)) {
    101        dx |= 0x80;
    102    }
    103
    104    obuf[0] = dy;
    105    obuf[1] = dx;
    106    return 2;
    107}
    108
    109static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
    110                             const uint8_t *buf, int len)
    111{
    112    MouseState *s = ADB_MOUSE(d);
    113    int cmd, reg, olen;
    114
    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;
    123    }
    124
    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:
    135            /*
    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.
    140             */
    141            if (len != 3) {
    142                return 0;
    143            }
    144
    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;
    156                /*
    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
    167                 */
    168                if (buf[2] == 1 || buf[2] == 2) {
    169                    d->handler = buf[2];
    170                }
    171
    172                trace_adb_device_mouse_request_change_addr_and_handler(
    173                    d->devaddr, d->handler);
    174                break;
    175            }
    176        }
    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;
    190        }
    191        trace_adb_device_mouse_readreg(reg, obuf[0], obuf[1]);
    192        break;
    193    }
    194    return olen;
    195}
    196
    197static bool adb_mouse_has_data(ADBDevice *d)
    198{
    199    MouseState *s = ADB_MOUSE(d);
    200
    201    return !(s->last_buttons_state == s->buttons_state &&
    202             s->dx == 0 && s->dy == 0);
    203}
    204
    205static void adb_mouse_reset(DeviceState *dev)
    206{
    207    ADBDevice *d = ADB_DEVICE(dev);
    208    MouseState *s = ADB_MOUSE(dev);
    209
    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;
    214}
    215
    216static 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()
    229    }
    230};
    231
    232static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
    233{
    234    MouseState *s = ADB_MOUSE(dev);
    235    ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
    236
    237    amc->parent_realize(dev, errp);
    238
    239    qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
    240}
    241
    242static void adb_mouse_initfn(Object *obj)
    243{
    244    ADBDevice *d = ADB_DEVICE(obj);
    245
    246    d->devaddr = ADB_DEVID_MOUSE;
    247}
    248
    249static void adb_mouse_class_init(ObjectClass *oc, void *data)
    250{
    251    DeviceClass *dc = DEVICE_CLASS(oc);
    252    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
    253    ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
    254
    255    device_class_set_parent_realize(dc, adb_mouse_realizefn,
    256                                    &amc->parent_realize);
    257    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
    258
    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;
    263}
    264
    265static 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),
    272};
    273
    274static void adb_mouse_register_types(void)
    275{
    276    type_register_static(&adb_mouse_type_info);
    277}
    278
    279type_init(adb_mouse_register_types)