/*
 * QEMU System Emulator
 *
 * Copyright (c) 2003-2008 Fabrice Bellard
 *
 * 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 "qapi/error.h"
#include "qemu/module.h"
#include "qemu/option.h"
#include "chardev/char.h"
#include "sysemu/block-backend.h"
#include "qapi/qapi-commands-control.h"
#include "chardev-internal.h"

/* MUX driver for serial I/O splitting */

/*
 * Set to false by suspend_mux_open.  Open events are delayed until
 * resume_mux_open.  Usually suspend_mux_open is called before
 * command line processing and resume_mux_open afterwards.
 */
static bool muxes_opened = true;

/* Called with chr_write_lock held.  */
static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
    MuxChardev *d = MUX_CHARDEV(chr);
    int ret;
    if (!d->timestamps) {
        ret = qemu_chr_fe_write(&d->chr, buf, len);
    } else {
        int i;

        ret = 0;
        for (i = 0; i < len; i++) {
            if (d->linestart) {
                char buf1[64];
                int64_t ti;
                int secs;

                ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
                if (d->timestamps_start == -1) {
                    d->timestamps_start = ti;
                }
                ti -= d->timestamps_start;
                secs = ti / 1000;
                snprintf(buf1, sizeof(buf1),
                         "[%02d:%02d:%02d.%03d] ",
                         secs / 3600,
                         (secs / 60) % 60,
                         secs % 60,
                         (int)(ti % 1000));
                /* XXX this blocks entire thread. Rewrite to use
                 * qemu_chr_fe_write and background I/O callbacks */
                qemu_chr_fe_write_all(&d->chr,
                                      (uint8_t *)buf1, strlen(buf1));
                d->linestart = 0;
            }
            ret += qemu_chr_fe_write(&d->chr, buf + i, 1);
            if (buf[i] == '\n') {
                d->linestart = 1;
            }
        }
    }
    return ret;
}

static const char * const mux_help[] = {
    "% h    print this help\n\r",
    "% x    exit emulator\n\r",
    "% s    save disk data back to file (if -snapshot)\n\r",
    "% t    toggle console timestamps\n\r",
    "% b    send break (magic sysrq)\n\r",
    "% c    switch between console and monitor\n\r",
    "% %  sends %\n\r",
    NULL
};

int term_escape_char = 0x01; /* ctrl-a is used for escape */
static void mux_print_help(Chardev *chr)
{
    int i, j;
    char ebuf[15] = "Escape-Char";
    char cbuf[50] = "\n\r";

    if (term_escape_char > 0 && term_escape_char < 26) {
        snprintf(cbuf, sizeof(cbuf), "\n\r");
        snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a');
    } else {
        snprintf(cbuf, sizeof(cbuf),
                 "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
                 term_escape_char);
    }
    /* XXX this blocks entire thread. Rewrite to use
     * qemu_chr_fe_write and background I/O callbacks */
    qemu_chr_write_all(chr, (uint8_t *)cbuf, strlen(cbuf));
    for (i = 0; mux_help[i] != NULL; i++) {
        for (j = 0; mux_help[i][j] != '\0'; j++) {
            if (mux_help[i][j] == '%') {
                qemu_chr_write_all(chr, (uint8_t *)ebuf, strlen(ebuf));
            } else {
                qemu_chr_write_all(chr, (uint8_t *)&mux_help[i][j], 1);
            }
        }
    }
}

static void mux_chr_send_event(MuxChardev *d, int mux_nr, QEMUChrEvent event)
{
    CharBackend *be = d->backends[mux_nr];

    if (be && be->chr_event) {
        be->chr_event(be->opaque, event);
    }
}

static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event)
{
    MuxChardev *d = MUX_CHARDEV(chr);

    if (d->focus != -1) {
        mux_chr_send_event(d, d->focus, event);
    }
}

static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
{
    if (d->term_got_escape) {
        d->term_got_escape = 0;
        if (ch == term_escape_char) {
            goto send_char;
        }
        switch (ch) {
        case '?':
        case 'h':
            mux_print_help(chr);
            break;
        case 'x':
            {
                 const char *term =  "QEMU: Terminated\n\r";
                 qemu_chr_write_all(chr, (uint8_t *)term, strlen(term));
                 qmp_quit(NULL);
                 break;
            }
        case 's':
            blk_commit_all();
            break;
        case 'b':
            qemu_chr_be_event(chr, CHR_EVENT_BREAK);
            break;
        case 'c':
            assert(d->mux_cnt > 0); /* handler registered with first fe */
            /* Switch to the next registered device */
            mux_set_focus(chr, (d->focus + 1) % d->mux_cnt);
            break;
        case 't':
            d->timestamps = !d->timestamps;
            d->timestamps_start = -1;
            d->linestart = 0;
            break;
        }
    } else if (ch == term_escape_char) {
        d->term_got_escape = 1;
    } else {
    send_char:
        return 1;
    }
    return 0;
}

static void mux_chr_accept_input(Chardev *chr)
{
    MuxChardev *d = MUX_CHARDEV(chr);
    int m = d->focus;
    CharBackend *be = d->backends[m];

    while (be && d->prod[m] != d->cons[m] &&
           be->chr_can_read && be->chr_can_read(be->opaque)) {
        be->chr_read(be->opaque,
                     &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
    }
}

static int mux_chr_can_read(void *opaque)
{
    MuxChardev *d = MUX_CHARDEV(opaque);
    int m = d->focus;
    CharBackend *be = d->backends[m];

    if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) {
        return 1;
    }

    if (be && be->chr_can_read) {
        return be->chr_can_read(be->opaque);
    }

    return 0;
}

static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
{
    Chardev *chr = CHARDEV(opaque);
    MuxChardev *d = MUX_CHARDEV(opaque);
    int m = d->focus;
    CharBackend *be = d->backends[m];
    int i;

    mux_chr_accept_input(opaque);

    for (i = 0; i < size; i++)
        if (mux_proc_byte(chr, d, buf[i])) {
            if (d->prod[m] == d->cons[m] &&
                be && be->chr_can_read &&
                be->chr_can_read(be->opaque)) {
                be->chr_read(be->opaque, &buf[i], 1);
            } else {
                d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
            }
        }
}

void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
{
    MuxChardev *d = MUX_CHARDEV(chr);
    int i;

    if (!muxes_opened) {
        return;
    }

    /* Send the event to all registered listeners */
    for (i = 0; i < d->mux_cnt; i++) {
        mux_chr_send_event(d, i, event);
    }
}

static void mux_chr_event(void *opaque, QEMUChrEvent event)
{
    mux_chr_send_all_event(CHARDEV(opaque), event);
}

static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
{
    MuxChardev *d = MUX_CHARDEV(s);
    Chardev *chr = qemu_chr_fe_get_driver(&d->chr);
    ChardevClass *cc = CHARDEV_GET_CLASS(chr);

    if (!cc->chr_add_watch) {
        return NULL;
    }

    return cc->chr_add_watch(chr, cond);
}

static void char_mux_finalize(Object *obj)
{
    MuxChardev *d = MUX_CHARDEV(obj);
    int i;

    for (i = 0; i < d->mux_cnt; i++) {
        CharBackend *be = d->backends[i];
        if (be) {
            be->chr = NULL;
        }
    }
    qemu_chr_fe_deinit(&d->chr, false);
}

static void mux_chr_update_read_handlers(Chardev *chr)
{
    MuxChardev *d = MUX_CHARDEV(chr);

    /* Fix up the real driver with mux routines */
    qemu_chr_fe_set_handlers_full(&d->chr,
                                  mux_chr_can_read,
                                  mux_chr_read,
                                  mux_chr_event,
                                  NULL,
                                  chr,
                                  chr->gcontext, true, false);
}

void mux_set_focus(Chardev *chr, int focus)
{
    MuxChardev *d = MUX_CHARDEV(chr);

    assert(focus >= 0);
    assert(focus < d->mux_cnt);

    if (d->focus != -1) {
        mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
    }

    d->focus = focus;
    chr->be = d->backends[focus];
    mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
}

static void qemu_chr_open_mux(Chardev *chr,
                              ChardevBackend *backend,
                              bool *be_opened,
                              Error **errp)
{
    ChardevMux *mux = backend->u.mux.data;
    Chardev *drv;
    MuxChardev *d = MUX_CHARDEV(chr);

    drv = qemu_chr_find(mux->chardev);
    if (drv == NULL) {
        error_setg(errp, "mux: base chardev %s not found", mux->chardev);
        return;
    }

    d->focus = -1;
    /* only default to opened state if we've realized the initial
     * set of muxes
     */
    *be_opened = muxes_opened;
    qemu_chr_fe_init(&d->chr, drv, errp);
}

static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
                               Error **errp)
{
    const char *chardev = qemu_opt_get(opts, "chardev");
    ChardevMux *mux;

    if (chardev == NULL) {
        error_setg(errp, "chardev: mux: no chardev given");
        return;
    }
    backend->type = CHARDEV_BACKEND_KIND_MUX;
    mux = backend->u.mux.data = g_new0(ChardevMux, 1);
    qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));
    mux->chardev = g_strdup(chardev);
}

/**
 * Called after processing of default and command-line-specified
 * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
 * to a mux chardev. This is done here to ensure that
 * output/prompts/banners are only displayed for the FE that has
 * focus when initial command-line processing/machine init is
 * completed.
 *
 * After this point, any new FE attached to any new or existing
 * mux will receive CHR_EVENT_OPENED notifications for the BE
 * immediately.
 */
static void open_muxes(Chardev *chr)
{
    /* send OPENED to all already-attached FEs */
    mux_chr_send_all_event(chr, CHR_EVENT_OPENED);

    /*
     * mark mux as OPENED so any new FEs will immediately receive
     * OPENED event
     */
    chr->be_open = 1;
}

void suspend_mux_open(void)
{
    muxes_opened = false;
}

static int chardev_options_parsed_cb(Object *child, void *opaque)
{
    Chardev *chr = (Chardev *)child;

    if (!chr->be_open && CHARDEV_IS_MUX(chr)) {
        open_muxes(chr);
    }

    return 0;
}

void resume_mux_open(void)
{
    muxes_opened = true;
    object_child_foreach(get_chardevs_root(),
                         chardev_options_parsed_cb, NULL);
}

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

    cc->parse = qemu_chr_parse_mux;
    cc->open = qemu_chr_open_mux;
    cc->chr_write = mux_chr_write;
    cc->chr_accept_input = mux_chr_accept_input;
    cc->chr_add_watch = mux_chr_add_watch;
    cc->chr_be_event = mux_chr_be_event;
    cc->chr_update_read_handler = mux_chr_update_read_handlers;
}

static const TypeInfo char_mux_type_info = {
    .name = TYPE_CHARDEV_MUX,
    .parent = TYPE_CHARDEV,
    .class_init = char_mux_class_init,
    .instance_size = sizeof(MuxChardev),
    .instance_finalize = char_mux_finalize,
};

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

type_init(register_types);
