/*
 * netconsole.c - network console support
 *
 * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <common.h>
#include <command.h>
#include <fs.h>
#include <linux/stat.h>
#include <errno.h>
#include <malloc.h>
#include <getopt.h>
#include <stringlist.h>
#include <net.h>
#include <kfifo.h>
#include <init.h>
#include <linux/err.h>

/**
 * @file
 * @brief Network console support
 */

struct nc_priv {
	struct console_device cdev;
	struct kfifo *fifo;
	int busy;
	struct net_connection *con;

	uint16_t port;
	IPaddr_t ip;
};

static struct nc_priv *g_priv;

static void nc_handler(void *ctx, char *pkt, unsigned len)
{
	struct nc_priv *priv = g_priv;
	unsigned char *packet = net_eth_to_udp_payload(pkt);

	kfifo_put(priv->fifo, packet, net_eth_to_udplen(pkt));
}

static int nc_init(void)
{
	struct nc_priv *priv = g_priv;

	if (priv->con)
		net_unregister(priv->con);

	priv->con = net_udp_new(priv->ip, priv->port, nc_handler, NULL);
	if (IS_ERR(priv->con)) {
		int ret = PTR_ERR(priv->con);
		priv->con = NULL;
		return ret;
	}

	net_udp_bind(priv->con, priv->port);
	priv->cdev.f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
	return 0;
}

static int nc_getc(struct console_device *cdev)
{
	struct nc_priv *priv = container_of(cdev,
					struct nc_priv, cdev);
	unsigned char c;

	while (!kfifo_len(priv->fifo))
		net_poll();

	kfifo_getc(priv->fifo, &c);

	return c;
}

static int nc_tstc(struct console_device *cdev)
{
	struct nc_priv *priv = container_of(cdev,
					struct nc_priv, cdev);

	if (priv->busy)
		return kfifo_len(priv->fifo) ? 1 : 0;

	net_poll();

	return kfifo_len(priv->fifo) ? 1 : 0;
}

static void nc_putc(struct console_device *cdev, char c)
{
	struct nc_priv *priv = container_of(cdev,
					struct nc_priv, cdev);
	unsigned char *packet;

	if (!priv->con)
		return;

	if (priv->busy)
		return;

	packet = net_udp_get_payload(priv->con);
	*packet = c;

	priv->busy = 1;
	net_udp_send(priv->con, 1);
	priv->busy = 0;
}

static int nc_port_set(struct device_d *dev, struct param_d *param,
		const char *val)
{
	struct nc_priv *priv = g_priv;
	char portstr[16];
	int port;

	if (!val)
		dev_param_set_generic(dev, param, NULL);

	port = simple_strtoul(val, NULL, 10);
	if (port > 65535)
		return -EINVAL;

	priv->port = port;
	nc_init();

	sprintf(portstr, "%d", port);
	dev_param_set_generic(dev, param, portstr);

	return 0;
}

static int nc_remoteip_set(struct device_d *dev, struct param_d *param,
		const char *val)
{
	struct nc_priv *priv = g_priv;
	IPaddr_t ip;
	int ret;

	if (!val)
		dev_param_set_generic(dev, param, NULL);

	if (string_to_ip(val, &ip))
		return -EINVAL;

	priv->ip = ip;
	ret = nc_init();
	if (ret)
		return ret;

	dev_param_set_generic(dev, param, val);

	return 0;
}

static int netconsole_init(void)
{
	struct nc_priv *priv;
	struct console_device *cdev;

	priv = xzalloc(sizeof(*priv));
	cdev = &priv->cdev;
	cdev->tstc = nc_tstc;
	cdev->putc = nc_putc;
	cdev->getc = nc_getc;

	g_priv = priv;

	priv->fifo = kfifo_alloc(1024);

	console_register(cdev);

	dev_add_param(&cdev->class_dev, "ip", nc_remoteip_set, NULL, 0);
	dev_add_param(&cdev->class_dev, "port", nc_port_set, NULL, 0);
	dev_set_param(&cdev->class_dev, "port", "6666");

	printf("registered netconsole as %s%d\n", cdev->class_dev.name, cdev->class_dev.id);

	return 0;
}

device_initcall(netconsole_init);

/** @page net_netconsole Network console

@section net_netconsole Using an UDP based network console

If enabled barebox supports a console via udp networking. There is only
one network console supported registered during init time. It is deactivated
by default because it opens great security holes, so use with care.

To use the network console you have to configure the remote ip and the local
and remote ports. Assuming the network console is registered as cs1, it can be
configured with:

@code
cs1.ip=<remotehost>
cs1.port=<port>
cs1.active=ioe
@endcode

On the remote host call scripts/netconsole with bareboxes ip and port as
parameters. port is initialized to 6666 by default.

*/
