/*
 * Copyright (c) 2001-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Ali Saidi
 */

/* @file
 * Implements the user interface to a serial terminal
 */

#include <sys/ioctl.h>
#include <sys/termios.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>

#include <cctype>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include "base/atomicio.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/socket.hh"
#include "base/trace.hh"
#include "dev/platform.hh"
#include "dev/terminal.hh"
#include "dev/uart.hh"

using namespace std;


/*
 * Poll event for the listen socket
 */
Terminal::ListenEvent::ListenEvent(Terminal *t, int fd, int e)
    : PollEvent(fd, e), term(t)
{
}

void
Terminal::ListenEvent::process(int revent)
{
    term->accept();
}

/*
 * Poll event for the data socket
 */
Terminal::DataEvent::DataEvent(Terminal *t, int fd, int e)
    : PollEvent(fd, e), term(t)
{
}

void
Terminal::DataEvent::process(int revent)
{
    if (revent & POLLIN)
        term->data();
    else if (revent & POLLNVAL)
        term->detach();
}

/*
 * Terminal code
 */
Terminal::Terminal(const Params *p)
    : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number),
      data_fd(-1), txbuf(16384), rxbuf(16384), outfile(NULL)
#if TRACING_ON == 1
      , linebuf(16384)
#endif
{
    if (p->output) {
        outfile = simout.find(p->name);
        outfile->setf(ios::unitbuf);
    }

    if (p->port)
        listen(p->port);
}

Terminal::~Terminal()
{
    if (data_fd != -1)
        ::close(data_fd);

    if (listenEvent)
        delete listenEvent;

    if (dataEvent)
        delete dataEvent;
}

///////////////////////////////////////////////////////////////////////
// socket creation and terminal attach
//

void
Terminal::listen(int port)
{
    if (ListenSocket::allDisabled()) {
        warn_once("Sockets disabled, not accepting terminal connections");
        return;
    }

    while (!listener.listen(port, true)) {
        DPRINTF(Terminal,
                ": can't bind address terminal port %d inuse PID %d\n",
                port, getpid());
        port++;
    }

    int p1, p2;
    p2 = name().rfind('.') - 1;
    p1 = name().rfind('.', p2);
    ccprintf(cerr, "Listening for %s connection on port %d\n",
            name().substr(p1+1,p2-p1), port);

    listenEvent = new ListenEvent(this, listener.getfd(), POLLIN);
    pollQueue.schedule(listenEvent);
}

void
Terminal::accept()
{
    if (!listener.islistening())
        panic("%s: cannot accept a connection if not listening!", name());

    int fd = listener.accept(true);
    if (data_fd != -1) {
        char message[] = "terminal already attached!\n";
        atomic_write(fd, message, sizeof(message));
        ::close(fd);
        return;
    }

    data_fd = fd;
    dataEvent = new DataEvent(this, data_fd, POLLIN);
    pollQueue.schedule(dataEvent);

    stringstream stream;
    ccprintf(stream, "==== m5 slave terminal: Terminal %d ====", number);

    // we need an actual carriage return followed by a newline for the
    // terminal
    stream << "\r\n";

    write((const uint8_t *)stream.str().c_str(), stream.str().size());

    DPRINTFN("attach terminal %d\n", number);

    txbuf.readall(data_fd);
}

void
Terminal::detach()
{
    if (data_fd != -1) {
        ::close(data_fd);
        data_fd = -1;
    }

    pollQueue.remove(dataEvent);
    delete dataEvent;
    dataEvent = NULL;

    DPRINTFN("detach terminal %d\n", number);
}

void
Terminal::data()
{
    uint8_t buf[1024];
    int len;

    len = read(buf, sizeof(buf));
    if (len) {
        rxbuf.write((char *)buf, len);
        // Inform the UART there is data available
        uart->dataAvailable();
    }
}

size_t
Terminal::read(uint8_t *buf, size_t len)
{
    if (data_fd < 0)
        panic("Terminal not properly attached.\n");

    size_t ret;
    do {
      ret = ::read(data_fd, buf, len);
    } while (ret == -1 && errno == EINTR);


    if (ret < 0)
        DPRINTFN("Read failed.\n");

    if (ret <= 0) {
        detach();
        return 0;
    }

    return ret;
}

// Terminal output.
size_t
Terminal::write(const uint8_t *buf, size_t len)
{
    if (data_fd < 0)
        panic("Terminal not properly attached.\n");

    ssize_t ret = atomic_write(data_fd, buf, len);
    if (ret < len)
        detach();

    return ret;
}

#define MORE_PENDING (ULL(1) << 61)
#define RECEIVE_SUCCESS (ULL(0) << 62)
#define RECEIVE_NONE (ULL(2) << 62)
#define RECEIVE_ERROR (ULL(3) << 62)

uint8_t
Terminal::in()
{
    bool empty;
    uint8_t c;

    empty = rxbuf.empty();
    assert(!empty);
    rxbuf.read((char *)&c, 1);
    empty = rxbuf.empty();


    DPRINTF(TerminalVerbose, "in: \'%c\' %#02x more: %d\n",
            isprint(c) ? c : ' ', c, !empty);

    return c;
}

uint64_t
Terminal::console_in()
{
    uint64_t value;

    if (dataAvailable()) {
        value = RECEIVE_SUCCESS | in();
        if (!rxbuf.empty())
            value  |= MORE_PENDING;
    } else {
        value = RECEIVE_NONE;
    }

    DPRINTF(TerminalVerbose, "console_in: return: %#x\n", value);

    return value;
}

void
Terminal::out(char c)
{
#if TRACING_ON == 1
    if (DTRACE(Terminal)) {
        static char last = '\0';

        if ((c != '\n' && c != '\r') || (last != '\n' && last != '\r')) {
            if (c == '\n' || c == '\r') {
                int size = linebuf.size();
                char *buffer = new char[size + 1];
                linebuf.read(buffer, size);
                buffer[size] = '\0';
                DPRINTF(Terminal, "%s\n", buffer);
                delete [] buffer;
            } else {
                linebuf.write(c);
            }
        }

        last = c;
    }
#endif

    txbuf.write(c);

    if (data_fd >= 0)
        write(c);

    if (outfile)
        outfile->write(&c, 1);

    DPRINTF(TerminalVerbose, "out: \'%c\' %#02x\n",
            isprint(c) ? c : ' ', (int)c);

}

Terminal *
TerminalParams::create()
{
    return new Terminal(this);
}
