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

msmouse.c (5546B)


      1/*
      2 * QEMU Microsoft serial mouse emulation
      3 *
      4 * Copyright (c) 2008 Lubomir Rintel
      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 "qemu/module.h"
     27#include "chardev/char.h"
     28#include "ui/console.h"
     29#include "ui/input.h"
     30#include "qom/object.h"
     31
     32#define MSMOUSE_LO6(n) ((n) & 0x3f)
     33#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
     34
     35struct MouseChardev {
     36    Chardev parent;
     37
     38    QemuInputHandlerState *hs;
     39    int axis[INPUT_AXIS__MAX];
     40    bool btns[INPUT_BUTTON__MAX];
     41    bool btnc[INPUT_BUTTON__MAX];
     42    uint8_t outbuf[32];
     43    int outlen;
     44};
     45typedef struct MouseChardev MouseChardev;
     46
     47#define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
     48DECLARE_INSTANCE_CHECKER(MouseChardev, MOUSE_CHARDEV,
     49                         TYPE_CHARDEV_MSMOUSE)
     50
     51static void msmouse_chr_accept_input(Chardev *chr)
     52{
     53    MouseChardev *mouse = MOUSE_CHARDEV(chr);
     54    int len;
     55
     56    len = qemu_chr_be_can_write(chr);
     57    if (len > mouse->outlen) {
     58        len = mouse->outlen;
     59    }
     60    if (!len) {
     61        return;
     62    }
     63
     64    qemu_chr_be_write(chr, mouse->outbuf, len);
     65    mouse->outlen -= len;
     66    if (mouse->outlen) {
     67        memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen);
     68    }
     69}
     70
     71static void msmouse_queue_event(MouseChardev *mouse)
     72{
     73    unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
     74    int dx, dy, count = 3;
     75
     76    dx = mouse->axis[INPUT_AXIS_X];
     77    mouse->axis[INPUT_AXIS_X] = 0;
     78
     79    dy = mouse->axis[INPUT_AXIS_Y];
     80    mouse->axis[INPUT_AXIS_Y] = 0;
     81
     82    /* Movement deltas */
     83    bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
     84    bytes[1] |= MSMOUSE_LO6(dx);
     85    bytes[2] |= MSMOUSE_LO6(dy);
     86
     87    /* Buttons */
     88    bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT]   ? 0x20 : 0x00);
     89    bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT]  ? 0x10 : 0x00);
     90    if (mouse->btns[INPUT_BUTTON_MIDDLE] ||
     91        mouse->btnc[INPUT_BUTTON_MIDDLE]) {
     92        bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00);
     93        mouse->btnc[INPUT_BUTTON_MIDDLE] = false;
     94        count = 4;
     95    }
     96
     97    if (mouse->outlen <= sizeof(mouse->outbuf) - count) {
     98        memcpy(mouse->outbuf + mouse->outlen, bytes, count);
     99        mouse->outlen += count;
    100    } else {
    101        /* queue full -> drop event */
    102    }
    103}
    104
    105static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
    106                                InputEvent *evt)
    107{
    108    MouseChardev *mouse = MOUSE_CHARDEV(dev);
    109    InputMoveEvent *move;
    110    InputBtnEvent *btn;
    111
    112    switch (evt->type) {
    113    case INPUT_EVENT_KIND_REL:
    114        move = evt->u.rel.data;
    115        mouse->axis[move->axis] += move->value;
    116        break;
    117
    118    case INPUT_EVENT_KIND_BTN:
    119        btn = evt->u.btn.data;
    120        mouse->btns[btn->button] = btn->down;
    121        mouse->btnc[btn->button] = true;
    122        break;
    123
    124    default:
    125        /* keep gcc happy */
    126        break;
    127    }
    128}
    129
    130static void msmouse_input_sync(DeviceState *dev)
    131{
    132    MouseChardev *mouse = MOUSE_CHARDEV(dev);
    133    Chardev *chr = CHARDEV(dev);
    134
    135    msmouse_queue_event(mouse);
    136    msmouse_chr_accept_input(chr);
    137}
    138
    139static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len)
    140{
    141    /* Ignore writes to mouse port */
    142    return len;
    143}
    144
    145static void char_msmouse_finalize(Object *obj)
    146{
    147    MouseChardev *mouse = MOUSE_CHARDEV(obj);
    148
    149    qemu_input_handler_unregister(mouse->hs);
    150}
    151
    152static QemuInputHandler msmouse_handler = {
    153    .name  = "QEMU Microsoft Mouse",
    154    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
    155    .event = msmouse_input_event,
    156    .sync  = msmouse_input_sync,
    157};
    158
    159static void msmouse_chr_open(Chardev *chr,
    160                             ChardevBackend *backend,
    161                             bool *be_opened,
    162                             Error **errp)
    163{
    164    MouseChardev *mouse = MOUSE_CHARDEV(chr);
    165
    166    *be_opened = false;
    167    mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
    168                                            &msmouse_handler);
    169}
    170
    171static void char_msmouse_class_init(ObjectClass *oc, void *data)
    172{
    173    ChardevClass *cc = CHARDEV_CLASS(oc);
    174
    175    cc->open = msmouse_chr_open;
    176    cc->chr_write = msmouse_chr_write;
    177    cc->chr_accept_input = msmouse_chr_accept_input;
    178}
    179
    180static const TypeInfo char_msmouse_type_info = {
    181    .name = TYPE_CHARDEV_MSMOUSE,
    182    .parent = TYPE_CHARDEV,
    183    .instance_size = sizeof(MouseChardev),
    184    .instance_finalize = char_msmouse_finalize,
    185    .class_init = char_msmouse_class_init,
    186};
    187
    188static void register_types(void)
    189{
    190    type_register_static(&char_msmouse_type_info);
    191}
    192
    193type_init(register_types);