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

virtio-input-hid.c (16860B)


      1/*
      2 * This work is licensed under the terms of the GNU GPL, version 2 or
      3 * (at your option) any later version.  See the COPYING file in the
      4 * top-level directory.
      5 */
      6
      7#include "qemu/osdep.h"
      8#include "qemu/iov.h"
      9#include "qemu/module.h"
     10
     11#include "hw/virtio/virtio.h"
     12#include "hw/qdev-properties.h"
     13#include "hw/virtio/virtio-input.h"
     14
     15#include "ui/console.h"
     16
     17#include "standard-headers/linux/input.h"
     18
     19#define VIRTIO_ID_NAME_KEYBOARD "QEMU Virtio Keyboard"
     20#define VIRTIO_ID_NAME_MOUSE    "QEMU Virtio Mouse"
     21#define VIRTIO_ID_NAME_TABLET   "QEMU Virtio Tablet"
     22
     23/* ----------------------------------------------------------------- */
     24
     25static const unsigned short keymap_button[INPUT_BUTTON__MAX] = {
     26    [INPUT_BUTTON_LEFT]              = BTN_LEFT,
     27    [INPUT_BUTTON_RIGHT]             = BTN_RIGHT,
     28    [INPUT_BUTTON_MIDDLE]            = BTN_MIDDLE,
     29    [INPUT_BUTTON_WHEEL_UP]          = BTN_GEAR_UP,
     30    [INPUT_BUTTON_WHEEL_DOWN]        = BTN_GEAR_DOWN,
     31    [INPUT_BUTTON_SIDE]              = BTN_SIDE,
     32    [INPUT_BUTTON_EXTRA]             = BTN_EXTRA,
     33};
     34
     35static const unsigned short axismap_rel[INPUT_AXIS__MAX] = {
     36    [INPUT_AXIS_X]                   = REL_X,
     37    [INPUT_AXIS_Y]                   = REL_Y,
     38};
     39
     40static const unsigned short axismap_abs[INPUT_AXIS__MAX] = {
     41    [INPUT_AXIS_X]                   = ABS_X,
     42    [INPUT_AXIS_Y]                   = ABS_Y,
     43};
     44
     45/* ----------------------------------------------------------------- */
     46
     47static void virtio_input_key_config(VirtIOInput *vinput,
     48                                    const unsigned short *keymap,
     49                                    size_t mapsize)
     50{
     51    virtio_input_config keys;
     52    int i, bit, byte, bmax = 0;
     53
     54    memset(&keys, 0, sizeof(keys));
     55    for (i = 0; i < mapsize; i++) {
     56        bit = keymap[i];
     57        if (!bit) {
     58            continue;
     59        }
     60        byte = bit / 8;
     61        bit  = bit % 8;
     62        keys.u.bitmap[byte] |= (1 << bit);
     63        if (bmax < byte+1) {
     64            bmax = byte+1;
     65        }
     66    }
     67    keys.select = VIRTIO_INPUT_CFG_EV_BITS;
     68    keys.subsel = EV_KEY;
     69    keys.size   = bmax;
     70    virtio_input_add_config(vinput, &keys);
     71}
     72
     73static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
     74                                      InputEvent *evt)
     75{
     76    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
     77    VirtIOInput *vinput = VIRTIO_INPUT(dev);
     78    virtio_input_event event;
     79    int qcode;
     80    InputKeyEvent *key;
     81    InputMoveEvent *move;
     82    InputBtnEvent *btn;
     83
     84    switch (evt->type) {
     85    case INPUT_EVENT_KIND_KEY:
     86        key = evt->u.key.data;
     87        qcode = qemu_input_key_value_to_qcode(key->key);
     88        if (qcode < qemu_input_map_qcode_to_linux_len &&
     89            qemu_input_map_qcode_to_linux[qcode]) {
     90            event.type  = cpu_to_le16(EV_KEY);
     91            event.code  = cpu_to_le16(qemu_input_map_qcode_to_linux[qcode]);
     92            event.value = cpu_to_le32(key->down ? 1 : 0);
     93            virtio_input_send(vinput, &event);
     94        } else {
     95            if (key->down) {
     96                fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
     97                        qcode, QKeyCode_str(qcode));
     98            }
     99        }
    100        break;
    101    case INPUT_EVENT_KIND_BTN:
    102        btn = evt->u.btn.data;
    103        if (vhid->wheel_axis &&
    104            (btn->button == INPUT_BUTTON_WHEEL_UP ||
    105             btn->button == INPUT_BUTTON_WHEEL_DOWN) &&
    106            btn->down) {
    107            event.type  = cpu_to_le16(EV_REL);
    108            event.code  = cpu_to_le16(REL_WHEEL);
    109            event.value = cpu_to_le32(btn->button == INPUT_BUTTON_WHEEL_UP
    110                                      ? 1 : -1);
    111            virtio_input_send(vinput, &event);
    112        } else if (keymap_button[btn->button]) {
    113            event.type  = cpu_to_le16(EV_KEY);
    114            event.code  = cpu_to_le16(keymap_button[btn->button]);
    115            event.value = cpu_to_le32(btn->down ? 1 : 0);
    116            virtio_input_send(vinput, &event);
    117        } else {
    118            if (btn->down) {
    119                fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
    120                        btn->button,
    121                        InputButton_str(btn->button));
    122            }
    123        }
    124        break;
    125    case INPUT_EVENT_KIND_REL:
    126        move = evt->u.rel.data;
    127        event.type  = cpu_to_le16(EV_REL);
    128        event.code  = cpu_to_le16(axismap_rel[move->axis]);
    129        event.value = cpu_to_le32(move->value);
    130        virtio_input_send(vinput, &event);
    131        break;
    132    case INPUT_EVENT_KIND_ABS:
    133        move = evt->u.abs.data;
    134        event.type  = cpu_to_le16(EV_ABS);
    135        event.code  = cpu_to_le16(axismap_abs[move->axis]);
    136        event.value = cpu_to_le32(move->value);
    137        virtio_input_send(vinput, &event);
    138        break;
    139    default:
    140        /* keep gcc happy */
    141        break;
    142    }
    143}
    144
    145static void virtio_input_handle_sync(DeviceState *dev)
    146{
    147    VirtIOInput *vinput = VIRTIO_INPUT(dev);
    148    virtio_input_event event = {
    149        .type  = cpu_to_le16(EV_SYN),
    150        .code  = cpu_to_le16(SYN_REPORT),
    151        .value = 0,
    152    };
    153
    154    virtio_input_send(vinput, &event);
    155}
    156
    157static void virtio_input_hid_realize(DeviceState *dev, Error **errp)
    158{
    159    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
    160
    161    vhid->hs = qemu_input_handler_register(dev, vhid->handler);
    162    if (vhid->display && vhid->hs) {
    163        qemu_input_handler_bind(vhid->hs, vhid->display, vhid->head, NULL);
    164    }
    165}
    166
    167static void virtio_input_hid_unrealize(DeviceState *dev)
    168{
    169    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
    170    qemu_input_handler_unregister(vhid->hs);
    171}
    172
    173static void virtio_input_hid_change_active(VirtIOInput *vinput)
    174{
    175    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
    176
    177    if (vinput->active) {
    178        qemu_input_handler_activate(vhid->hs);
    179    } else {
    180        qemu_input_handler_deactivate(vhid->hs);
    181    }
    182}
    183
    184static void virtio_input_hid_handle_status(VirtIOInput *vinput,
    185                                           virtio_input_event *event)
    186{
    187    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(vinput);
    188    int ledbit = 0;
    189
    190    switch (le16_to_cpu(event->type)) {
    191    case EV_LED:
    192        if (event->code == LED_NUML) {
    193            ledbit = QEMU_NUM_LOCK_LED;
    194        } else if (event->code == LED_CAPSL) {
    195            ledbit = QEMU_CAPS_LOCK_LED;
    196        } else if (event->code == LED_SCROLLL) {
    197            ledbit = QEMU_SCROLL_LOCK_LED;
    198        }
    199        if (event->value) {
    200            vhid->ledstate |= ledbit;
    201        } else {
    202            vhid->ledstate &= ~ledbit;
    203        }
    204        kbd_put_ledstate(vhid->ledstate);
    205        break;
    206    default:
    207        fprintf(stderr, "%s: unknown type %d\n", __func__,
    208                le16_to_cpu(event->type));
    209        break;
    210    }
    211}
    212
    213static Property virtio_input_hid_properties[] = {
    214    DEFINE_PROP_STRING("display", VirtIOInputHID, display),
    215    DEFINE_PROP_UINT32("head", VirtIOInputHID, head, 0),
    216    DEFINE_PROP_END_OF_LIST(),
    217};
    218
    219static void virtio_input_hid_class_init(ObjectClass *klass, void *data)
    220{
    221    DeviceClass *dc = DEVICE_CLASS(klass);
    222    VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
    223
    224    device_class_set_props(dc, virtio_input_hid_properties);
    225    vic->realize       = virtio_input_hid_realize;
    226    vic->unrealize     = virtio_input_hid_unrealize;
    227    vic->change_active = virtio_input_hid_change_active;
    228    vic->handle_status = virtio_input_hid_handle_status;
    229}
    230
    231static const TypeInfo virtio_input_hid_info = {
    232    .name          = TYPE_VIRTIO_INPUT_HID,
    233    .parent        = TYPE_VIRTIO_INPUT,
    234    .instance_size = sizeof(VirtIOInputHID),
    235    .class_init    = virtio_input_hid_class_init,
    236    .abstract      = true,
    237};
    238
    239/* ----------------------------------------------------------------- */
    240
    241static QemuInputHandler virtio_keyboard_handler = {
    242    .name  = VIRTIO_ID_NAME_KEYBOARD,
    243    .mask  = INPUT_EVENT_MASK_KEY,
    244    .event = virtio_input_handle_event,
    245    .sync  = virtio_input_handle_sync,
    246};
    247
    248static struct virtio_input_config virtio_keyboard_config[] = {
    249    {
    250        .select    = VIRTIO_INPUT_CFG_ID_NAME,
    251        .size      = sizeof(VIRTIO_ID_NAME_KEYBOARD),
    252        .u.string  = VIRTIO_ID_NAME_KEYBOARD,
    253    },{
    254        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
    255        .size      = sizeof(struct virtio_input_devids),
    256        .u.ids     = {
    257            .bustype = const_le16(BUS_VIRTUAL),
    258            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
    259            .product = const_le16(0x0001),
    260            .version = const_le16(0x0001),
    261        },
    262    },{
    263        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    264        .subsel    = EV_REP,
    265        .size      = 1,
    266    },{
    267        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    268        .subsel    = EV_LED,
    269        .size      = 1,
    270        .u.bitmap  = {
    271            (1 << LED_NUML) | (1 << LED_CAPSL) | (1 << LED_SCROLLL),
    272        },
    273    },
    274    { /* end of list */ },
    275};
    276
    277static void virtio_keyboard_init(Object *obj)
    278{
    279    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
    280    VirtIOInput *vinput = VIRTIO_INPUT(obj);
    281
    282    vhid->handler = &virtio_keyboard_handler;
    283    virtio_input_init_config(vinput, virtio_keyboard_config);
    284    virtio_input_key_config(vinput, qemu_input_map_qcode_to_linux,
    285                            qemu_input_map_qcode_to_linux_len);
    286}
    287
    288static const TypeInfo virtio_keyboard_info = {
    289    .name          = TYPE_VIRTIO_KEYBOARD,
    290    .parent        = TYPE_VIRTIO_INPUT_HID,
    291    .instance_size = sizeof(VirtIOInputHID),
    292    .instance_init = virtio_keyboard_init,
    293};
    294
    295/* ----------------------------------------------------------------- */
    296
    297static QemuInputHandler virtio_mouse_handler = {
    298    .name  = VIRTIO_ID_NAME_MOUSE,
    299    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
    300    .event = virtio_input_handle_event,
    301    .sync  = virtio_input_handle_sync,
    302};
    303
    304static struct virtio_input_config virtio_mouse_config_v1[] = {
    305    {
    306        .select    = VIRTIO_INPUT_CFG_ID_NAME,
    307        .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
    308        .u.string  = VIRTIO_ID_NAME_MOUSE,
    309    },{
    310        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
    311        .size      = sizeof(struct virtio_input_devids),
    312        .u.ids     = {
    313            .bustype = const_le16(BUS_VIRTUAL),
    314            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
    315            .product = const_le16(0x0002),
    316            .version = const_le16(0x0001),
    317        },
    318    },{
    319        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    320        .subsel    = EV_REL,
    321        .size      = 1,
    322        .u.bitmap  = {
    323            (1 << REL_X) | (1 << REL_Y),
    324        },
    325    },
    326    { /* end of list */ },
    327};
    328
    329static struct virtio_input_config virtio_mouse_config_v2[] = {
    330    {
    331        .select    = VIRTIO_INPUT_CFG_ID_NAME,
    332        .size      = sizeof(VIRTIO_ID_NAME_MOUSE),
    333        .u.string  = VIRTIO_ID_NAME_MOUSE,
    334    },{
    335        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
    336        .size      = sizeof(struct virtio_input_devids),
    337        .u.ids     = {
    338            .bustype = const_le16(BUS_VIRTUAL),
    339            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
    340            .product = const_le16(0x0002),
    341            .version = const_le16(0x0002),
    342        },
    343    },{
    344        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    345        .subsel    = EV_REL,
    346        .size      = 2,
    347        .u.bitmap  = {
    348            (1 << REL_X) | (1 << REL_Y),
    349            (1 << (REL_WHEEL - 8))
    350        },
    351    },
    352    { /* end of list */ },
    353};
    354
    355static Property virtio_mouse_properties[] = {
    356    DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
    357    DEFINE_PROP_END_OF_LIST(),
    358};
    359
    360static void virtio_mouse_class_init(ObjectClass *klass, void *data)
    361{
    362    DeviceClass *dc = DEVICE_CLASS(klass);
    363
    364    device_class_set_props(dc, virtio_mouse_properties);
    365}
    366
    367static void virtio_mouse_init(Object *obj)
    368{
    369    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
    370    VirtIOInput *vinput = VIRTIO_INPUT(obj);
    371
    372    vhid->handler = &virtio_mouse_handler;
    373    virtio_input_init_config(vinput, vhid->wheel_axis
    374                             ? virtio_mouse_config_v2
    375                             : virtio_mouse_config_v1);
    376    virtio_input_key_config(vinput, keymap_button,
    377                            ARRAY_SIZE(keymap_button));
    378}
    379
    380static const TypeInfo virtio_mouse_info = {
    381    .name          = TYPE_VIRTIO_MOUSE,
    382    .parent        = TYPE_VIRTIO_INPUT_HID,
    383    .instance_size = sizeof(VirtIOInputHID),
    384    .instance_init = virtio_mouse_init,
    385    .class_init    = virtio_mouse_class_init,
    386};
    387
    388/* ----------------------------------------------------------------- */
    389
    390static QemuInputHandler virtio_tablet_handler = {
    391    .name  = VIRTIO_ID_NAME_TABLET,
    392    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
    393    .event = virtio_input_handle_event,
    394    .sync  = virtio_input_handle_sync,
    395};
    396
    397static struct virtio_input_config virtio_tablet_config_v1[] = {
    398    {
    399        .select    = VIRTIO_INPUT_CFG_ID_NAME,
    400        .size      = sizeof(VIRTIO_ID_NAME_TABLET),
    401        .u.string  = VIRTIO_ID_NAME_TABLET,
    402    },{
    403        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
    404        .size      = sizeof(struct virtio_input_devids),
    405        .u.ids     = {
    406            .bustype = const_le16(BUS_VIRTUAL),
    407            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
    408            .product = const_le16(0x0003),
    409            .version = const_le16(0x0001),
    410        },
    411    },{
    412        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    413        .subsel    = EV_ABS,
    414        .size      = 1,
    415        .u.bitmap  = {
    416            (1 << ABS_X) | (1 << ABS_Y),
    417        },
    418    },{
    419        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
    420        .subsel    = ABS_X,
    421        .size      = sizeof(virtio_input_absinfo),
    422        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
    423        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
    424    },{
    425        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
    426        .subsel    = ABS_Y,
    427        .size      = sizeof(virtio_input_absinfo),
    428        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
    429        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
    430    },
    431    { /* end of list */ },
    432};
    433
    434static struct virtio_input_config virtio_tablet_config_v2[] = {
    435    {
    436        .select    = VIRTIO_INPUT_CFG_ID_NAME,
    437        .size      = sizeof(VIRTIO_ID_NAME_TABLET),
    438        .u.string  = VIRTIO_ID_NAME_TABLET,
    439    },{
    440        .select    = VIRTIO_INPUT_CFG_ID_DEVIDS,
    441        .size      = sizeof(struct virtio_input_devids),
    442        .u.ids     = {
    443            .bustype = const_le16(BUS_VIRTUAL),
    444            .vendor  = const_le16(0x0627), /* same we use for usb hid devices */
    445            .product = const_le16(0x0003),
    446            .version = const_le16(0x0002),
    447        },
    448    },{
    449        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    450        .subsel    = EV_ABS,
    451        .size      = 1,
    452        .u.bitmap  = {
    453            (1 << ABS_X) | (1 << ABS_Y),
    454        },
    455    },{
    456        .select    = VIRTIO_INPUT_CFG_EV_BITS,
    457        .subsel    = EV_REL,
    458        .size      = 2,
    459        .u.bitmap  = {
    460            0,
    461            (1 << (REL_WHEEL - 8))
    462        },
    463    },{
    464        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
    465        .subsel    = ABS_X,
    466        .size      = sizeof(virtio_input_absinfo),
    467        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
    468        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
    469    },{
    470        .select    = VIRTIO_INPUT_CFG_ABS_INFO,
    471        .subsel    = ABS_Y,
    472        .size      = sizeof(virtio_input_absinfo),
    473        .u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
    474        .u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
    475    },
    476    { /* end of list */ },
    477};
    478
    479static Property virtio_tablet_properties[] = {
    480    DEFINE_PROP_BOOL("wheel-axis", VirtIOInputHID, wheel_axis, true),
    481    DEFINE_PROP_END_OF_LIST(),
    482};
    483
    484static void virtio_tablet_class_init(ObjectClass *klass, void *data)
    485{
    486    DeviceClass *dc = DEVICE_CLASS(klass);
    487
    488    device_class_set_props(dc, virtio_tablet_properties);
    489}
    490
    491static void virtio_tablet_init(Object *obj)
    492{
    493    VirtIOInputHID *vhid = VIRTIO_INPUT_HID(obj);
    494    VirtIOInput *vinput = VIRTIO_INPUT(obj);
    495
    496    vhid->handler = &virtio_tablet_handler;
    497    virtio_input_init_config(vinput, vhid->wheel_axis
    498                             ? virtio_tablet_config_v2
    499                             : virtio_tablet_config_v1);
    500    virtio_input_key_config(vinput, keymap_button,
    501                            ARRAY_SIZE(keymap_button));
    502}
    503
    504static const TypeInfo virtio_tablet_info = {
    505    .name          = TYPE_VIRTIO_TABLET,
    506    .parent        = TYPE_VIRTIO_INPUT_HID,
    507    .instance_size = sizeof(VirtIOInputHID),
    508    .instance_init = virtio_tablet_init,
    509    .class_init    = virtio_tablet_class_init,
    510};
    511
    512/* ----------------------------------------------------------------- */
    513
    514static void virtio_register_types(void)
    515{
    516    type_register_static(&virtio_input_hid_info);
    517    type_register_static(&virtio_keyboard_info);
    518    type_register_static(&virtio_mouse_info);
    519    type_register_static(&virtio_tablet_info);
    520}
    521
    522type_init(virtio_register_types)