/*
 * QEMU Microsoft serial mouse emulation
 *
 * Copyright (c) 2008 Lubomir Rintel
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "chardev/char.h"
#include "ui/console.h"
#include "ui/input.h"

#define MSMOUSE_LO6(n) ((n) & 0x3f)
#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)

typedef struct {
    Chardev parent;

    QemuInputHandlerState *hs;
    int axis[INPUT_AXIS__MAX];
    bool btns[INPUT_BUTTON__MAX];
    bool btnc[INPUT_BUTTON__MAX];
    uint8_t outbuf[32];
    int outlen;
} MouseChardev;

#define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
#define MOUSE_CHARDEV(obj)                                      \
    OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE)

static void msmouse_chr_accept_input(Chardev *chr)
{
    MouseChardev *mouse = MOUSE_CHARDEV(chr);
    int len;

    len = qemu_chr_be_can_write(chr);
    if (len > mouse->outlen) {
        len = mouse->outlen;
    }
    if (!len) {
        return;
    }

    qemu_chr_be_write(chr, mouse->outbuf, len);
    mouse->outlen -= len;
    if (mouse->outlen) {
        memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen);
    }
}

static void msmouse_queue_event(MouseChardev *mouse)
{
    unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
    int dx, dy, count = 3;

    dx = mouse->axis[INPUT_AXIS_X];
    mouse->axis[INPUT_AXIS_X] = 0;

    dy = mouse->axis[INPUT_AXIS_Y];
    mouse->axis[INPUT_AXIS_Y] = 0;

    /* Movement deltas */
    bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
    bytes[1] |= MSMOUSE_LO6(dx);
    bytes[2] |= MSMOUSE_LO6(dy);

    /* Buttons */
    bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT]   ? 0x20 : 0x00);
    bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT]  ? 0x10 : 0x00);
    if (mouse->btns[INPUT_BUTTON_MIDDLE] ||
        mouse->btnc[INPUT_BUTTON_MIDDLE]) {
        bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00);
        mouse->btnc[INPUT_BUTTON_MIDDLE] = false;
        count = 4;
    }

    if (mouse->outlen <= sizeof(mouse->outbuf) - count) {
        memcpy(mouse->outbuf + mouse->outlen, bytes, count);
        mouse->outlen += count;
    } else {
        /* queue full -> drop event */
    }
}

static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
                                InputEvent *evt)
{
    MouseChardev *mouse = MOUSE_CHARDEV(dev);
    InputMoveEvent *move;
    InputBtnEvent *btn;

    switch (evt->type) {
    case INPUT_EVENT_KIND_REL:
        move = evt->u.rel.data;
        mouse->axis[move->axis] += move->value;
        break;

    case INPUT_EVENT_KIND_BTN:
        btn = evt->u.btn.data;
        mouse->btns[btn->button] = btn->down;
        mouse->btnc[btn->button] = true;
        break;

    default:
        /* keep gcc happy */
        break;
    }
}

static void msmouse_input_sync(DeviceState *dev)
{
    MouseChardev *mouse = MOUSE_CHARDEV(dev);
    Chardev *chr = CHARDEV(dev);

    msmouse_queue_event(mouse);
    msmouse_chr_accept_input(chr);
}

static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len)
{
    /* Ignore writes to mouse port */
    return len;
}

static void char_msmouse_finalize(Object *obj)
{
    MouseChardev *mouse = MOUSE_CHARDEV(obj);

    qemu_input_handler_unregister(mouse->hs);
}

static QemuInputHandler msmouse_handler = {
    .name  = "QEMU Microsoft Mouse",
    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
    .event = msmouse_input_event,
    .sync  = msmouse_input_sync,
};

static void msmouse_chr_open(Chardev *chr,
                             ChardevBackend *backend,
                             bool *be_opened,
                             Error **errp)
{
    MouseChardev *mouse = MOUSE_CHARDEV(chr);

    *be_opened = false;
    mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
                                            &msmouse_handler);
}

static void char_msmouse_class_init(ObjectClass *oc, void *data)
{
    ChardevClass *cc = CHARDEV_CLASS(oc);

    cc->open = msmouse_chr_open;
    cc->chr_write = msmouse_chr_write;
    cc->chr_accept_input = msmouse_chr_accept_input;
}

static const TypeInfo char_msmouse_type_info = {
    .name = TYPE_CHARDEV_MSMOUSE,
    .parent = TYPE_CHARDEV,
    .instance_size = sizeof(MouseChardev),
    .instance_finalize = char_msmouse_finalize,
    .class_init = char_msmouse_class_init,
};

static void register_types(void)
{
    type_register_static(&char_msmouse_type_info);
}

type_init(register_types);
