/*
 *
 *  Connection Manager
 *
 *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>

#include "connman.h"

enum rfkill_type {
	RFKILL_TYPE_ALL = 0,
	RFKILL_TYPE_WLAN,
	RFKILL_TYPE_BLUETOOTH,
	RFKILL_TYPE_UWB,
	RFKILL_TYPE_WWAN,
	RFKILL_TYPE_GPS,
	RFKILL_TYPE_FM,
	NUM_RFKILL_TYPES,
};

enum rfkill_operation {
	RFKILL_OP_ADD = 0,
	RFKILL_OP_DEL,
	RFKILL_OP_CHANGE,
	RFKILL_OP_CHANGE_ALL,
};

struct rfkill_event {
	uint32_t idx;
	uint8_t  type;
	uint8_t  op;
	uint8_t  soft;
	uint8_t  hard;
};

static enum connman_service_type convert_type(uint8_t type)
{
	switch (type) {
	case RFKILL_TYPE_WLAN:
		return CONNMAN_SERVICE_TYPE_WIFI;
	case RFKILL_TYPE_BLUETOOTH:
		return CONNMAN_SERVICE_TYPE_BLUETOOTH;
	case RFKILL_TYPE_WWAN:
		return CONNMAN_SERVICE_TYPE_CELLULAR;
	}

	return CONNMAN_SERVICE_TYPE_UNKNOWN;
}

static enum rfkill_type convert_service_type(enum connman_service_type type)
{
	switch (type) {
	case CONNMAN_SERVICE_TYPE_LOWPAN:
	case CONNMAN_SERVICE_TYPE_WIFI:
		return RFKILL_TYPE_WLAN;
	case CONNMAN_SERVICE_TYPE_BLUETOOTH:
		return RFKILL_TYPE_BLUETOOTH;
	case CONNMAN_SERVICE_TYPE_CELLULAR:
		return RFKILL_TYPE_WWAN;
	case CONNMAN_SERVICE_TYPE_GPS:
		return RFKILL_TYPE_GPS;
	case CONNMAN_SERVICE_TYPE_SYSTEM:
	case CONNMAN_SERVICE_TYPE_ETHERNET:
	case CONNMAN_SERVICE_TYPE_VPN:
	case CONNMAN_SERVICE_TYPE_GADGET:
	case CONNMAN_SERVICE_TYPE_P2P:
	case CONNMAN_SERVICE_TYPE_UNKNOWN:
		return NUM_RFKILL_TYPES;
	}

	return NUM_RFKILL_TYPES;
}

static GIOStatus rfkill_process(GIOChannel *chan)
{
	unsigned char buf[32];
	struct rfkill_event *event = (void *) buf;
	enum connman_service_type type;
	gsize len;
	GIOStatus status;

	DBG("");

	memset(buf, 0, sizeof(buf));

	status = g_io_channel_read_chars(chan, (gchar *) buf,
			sizeof(struct rfkill_event), &len, NULL);

	if (status != G_IO_STATUS_NORMAL)
		return status;

	if (len != sizeof(struct rfkill_event))
		return status;

	DBG("idx %u type %u op %u soft %u hard %u", event->idx,
						event->type, event->op,
						event->soft, event->hard);

	type = convert_type(event->type);

	switch (event->op) {
	case RFKILL_OP_ADD:
		__connman_technology_add_rfkill(event->idx, type,
						event->soft, event->hard);
		break;
	case RFKILL_OP_DEL:
		__connman_technology_remove_rfkill(event->idx, type);
		break;
	case RFKILL_OP_CHANGE:
		__connman_technology_update_rfkill(event->idx, type,
						event->soft, event->hard);
		break;
	default:
		break;
	}

	return status;
}

static gboolean rfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data)
{
	if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
		return FALSE;

	if (rfkill_process(chan) == G_IO_STATUS_ERROR)
		return FALSE;

	return TRUE;
}

static guint watch = 0;

int __connman_rfkill_block(enum connman_service_type type, bool block)
{
	uint8_t rfkill_type;
	struct rfkill_event event;
	ssize_t len;
	int fd, err = 0;

	DBG("type %d block %d", type, block);

	rfkill_type = convert_service_type(type);
	if (rfkill_type == NUM_RFKILL_TYPES)
		return -EINVAL;

	fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC);
	if (fd < 0)
		return -errno;

	memset(&event, 0, sizeof(event));
	event.op = RFKILL_OP_CHANGE_ALL;
	event.type = rfkill_type;
	event.soft = block;

	len = write(fd, &event, sizeof(event));
	if (len < 0) {
		err = -errno;
		connman_error("Failed to change RFKILL state");
	}

	close(fd);

	return err;
}

int __connman_rfkill_init(void)
{
	GIOChannel *channel;
	GIOFlags flags;
	int fd;

	DBG("");

	fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC);
	if (fd < 0) {
		connman_error("Failed to open RFKILL control device");
		return -EIO;
	}

	channel = g_io_channel_unix_new(fd);
	g_io_channel_set_close_on_unref(channel, TRUE);

	g_io_channel_set_encoding(channel, NULL, NULL);
	g_io_channel_set_buffered(channel, FALSE);

	flags = g_io_channel_get_flags(channel);
	flags |= G_IO_FLAG_NONBLOCK;
	g_io_channel_set_flags(channel, flags, NULL);

	/* Process current RFKILL events sent on device open */
	while (rfkill_process(channel) == G_IO_STATUS_NORMAL);

	watch = g_io_add_watch(channel,
				G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
				rfkill_event, NULL);

	g_io_channel_unref(channel);

	return watch ? 0 : -EIO;
}

void __connman_rfkill_cleanup(void)
{
	DBG("");

	if (watch) {
		g_source_remove(watch);
		watch = 0;
	}
}
