/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2006-2010  Nokia Corporation
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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

#include <glib.h>
#include <dbus/dbus.h>

#include "adapter.h"
#include "plugin.h"
#include "log.h"
#include "gdbus.h"

/* from mce/mode-names.h */
#define MCE_RADIO_STATE_BLUETOOTH	(1 << 3)

/* from mce/dbus-names.h */
#define MCE_SERVICE			"com.nokia.mce"
#define MCE_REQUEST_IF			"com.nokia.mce.request"
#define MCE_SIGNAL_IF			"com.nokia.mce.signal"
#define MCE_REQUEST_PATH		"/com/nokia/mce/request"
#define MCE_SIGNAL_PATH			"/com/nokia/mce/signal"
#define MCE_RADIO_STATES_CHANGE_REQ	"req_radio_states_change"
#define MCE_RADIO_STATES_GET		"get_radio_states"
#define MCE_RADIO_STATES_SIG		"radio_states_ind"

static guint watch_id;
static DBusConnection *conn = NULL;
static gboolean mce_bt_set = FALSE;
static gboolean collision = FALSE;

static gboolean mce_signal_callback(DBusConnection *connection,
					DBusMessage *message, void *user_data)
{
	DBusMessageIter args;
	uint32_t sigvalue;
	struct btd_adapter *adapter = user_data;

	DBG("received mce signal");

	if (!dbus_message_iter_init(message, &args))
		error("message has no arguments");
	else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
		error("argument is not uint32");
	else {
		dbus_message_iter_get_basic(&args, &sigvalue);
		DBG("got signal with value %u", sigvalue);

		/* set the adapter according to the mce signal
		   and remember the value */
		mce_bt_set = sigvalue & MCE_RADIO_STATE_BLUETOOTH ?
								TRUE : FALSE;

		if (mce_bt_set)
			btd_adapter_switch_online(adapter);
		else
			btd_adapter_switch_offline(adapter);
	}

	return TRUE;
}

static void read_radio_states_cb(DBusPendingCall *call, void *user_data)
{
	DBusError err;
	DBusMessage *reply;
	dbus_uint32_t radio_states;
	struct btd_adapter *adapter = user_data;

	reply = dbus_pending_call_steal_reply(call);

	dbus_error_init(&err);
	if (dbus_set_error_from_message(&err, reply)) {
		error("mce replied with an error: %s, %s",
				err.name, err.message);
		dbus_error_free(&err);
		goto done;
	}

	dbus_error_init(&err);
	if (dbus_message_get_args(reply, &err,
				DBUS_TYPE_UINT32, &radio_states,
				DBUS_TYPE_INVALID) == FALSE) {
		error("unable to parse get_radio_states reply: %s, %s",
							err.name, err.message);
		dbus_error_free(&err);
		goto done;
	}

	DBG("radio_states: %d", radio_states);

	mce_bt_set = radio_states & MCE_RADIO_STATE_BLUETOOTH ? TRUE : FALSE;

	/* check if the adapter has not completed the initial power
	 * cycle, if so delay action to mce_notify_powered */
	collision = mce_bt_set && adapter_powering_down(adapter);

	if (collision)
		goto done;

	if (mce_bt_set)
		btd_adapter_switch_online(adapter);
	else
		btd_adapter_switch_offline(adapter);

done:
	dbus_message_unref(reply);
}

static void adapter_powered(struct btd_adapter *adapter, gboolean powered)
{
	DBusMessage *msg;
	dbus_uint32_t radio_states = 0;
	dbus_uint32_t radio_mask = MCE_RADIO_STATE_BLUETOOTH;

	DBG("adapter_powered called with %d", powered);

	/* check if the plugin got the get_radio_states reply from the
	 * mce when the adapter was not yet down during the power
	 * cycling when bluetoothd is started */
	if (collision) {
		error("maemo6: powered state collision");
		collision = FALSE;

		if (mce_bt_set)
			btd_adapter_switch_online(adapter);

		return;
	}

	/* nothing to do if the states match */
	if (mce_bt_set == powered)
		return;

	/* set the mce value according to the state of the adapter */
	msg = dbus_message_new_method_call(MCE_SERVICE, MCE_REQUEST_PATH,
				MCE_REQUEST_IF, MCE_RADIO_STATES_CHANGE_REQ);

	if (powered)
		radio_states = MCE_RADIO_STATE_BLUETOOTH;

	dbus_message_append_args(msg, DBUS_TYPE_UINT32, &radio_states,
				DBUS_TYPE_UINT32, &radio_mask,
				DBUS_TYPE_INVALID);

	if (dbus_connection_send(conn, msg, NULL))
		mce_bt_set = powered;
	else
		error("calling %s failed", MCE_RADIO_STATES_CHANGE_REQ);

	dbus_message_unref(msg);
}

static int mce_probe(struct btd_adapter *adapter)
{
	DBusMessage *msg;
	DBusPendingCall *call;

	DBG("path %s", adapter_get_path(adapter));

	msg = dbus_message_new_method_call(MCE_SERVICE, MCE_REQUEST_PATH,
					MCE_REQUEST_IF, MCE_RADIO_STATES_GET);

	if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
		error("calling %s failed", MCE_RADIO_STATES_GET);
		dbus_message_unref(msg);
		return -1;
	}

	dbus_pending_call_set_notify(call, read_radio_states_cb, adapter, NULL);
	dbus_pending_call_unref(call);
	dbus_message_unref(msg);

	watch_id = g_dbus_add_signal_watch(conn, NULL, MCE_SIGNAL_PATH,
					MCE_SIGNAL_IF, MCE_RADIO_STATES_SIG,
					mce_signal_callback, adapter, NULL);

	btd_adapter_register_powered_callback(adapter, adapter_powered);

	return 0;
}

static void mce_remove(struct btd_adapter *adapter)
{
	DBG("path %s", adapter_get_path(adapter));

	if (watch_id > 0)
		g_dbus_remove_watch(conn, watch_id);

	btd_adapter_unregister_powered_callback(adapter, adapter_powered);
}

static struct btd_adapter_driver mce_driver = {
	.name	= "mce",
	.probe	= mce_probe,
	.remove	= mce_remove,
};

static int maemo6_init(void)
{
	DBG("init maemo6 plugin");

	conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
	if (conn == NULL) {
		error("Unable to connect to D-Bus");
		return -1;
	}

	return btd_register_adapter_driver(&mce_driver);
}

static void maemo6_exit(void)
{
	DBG("exit maemo6 plugin");

	if (conn != NULL)
		dbus_connection_unref(conn);

	btd_unregister_adapter_driver(&mce_driver);
}

BLUETOOTH_PLUGIN_DEFINE(maemo6, VERSION,
		BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, maemo6_init, maemo6_exit)
