/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2008  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 <errno.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hidp.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

#include <gdbus.h>

#include "logging.h"
#include "textfile.h"
#include "../src/adapter.h"
#include "../src/device.h"

#include "device.h"
#include "server.h"
#include "manager.h"
#include "storage.h"

static int idle_timeout = 0;

static DBusConnection *connection = NULL;

static void epox_endian_quirk(unsigned char *data, int size)
{
	/* USAGE_PAGE (Keyboard)	05 07
	 * USAGE_MINIMUM (0)		19 00
	 * USAGE_MAXIMUM (65280)	2A 00 FF   <= must be FF 00
	 * LOGICAL_MINIMUM (0)		15 00
	 * LOGICAL_MAXIMUM (65280)	26 00 FF   <= must be FF 00
	 */
	unsigned char pattern[] = { 0x05, 0x07, 0x19, 0x00, 0x2a, 0x00, 0xff,
						0x15, 0x00, 0x26, 0x00, 0xff };
	int i;

	if (!data)
		return;

	for (i = 0; i < size - sizeof(pattern); i++) {
		if (!memcmp(data + i, pattern, sizeof(pattern))) {
			data[i + 5] = 0xff;
			data[i + 6] = 0x00;
			data[i + 10] = 0xff;
			data[i + 11] = 0x00;
		}
	}
}

static void extract_hid_record(sdp_record_t *rec, struct hidp_connadd_req *req)
{
	sdp_data_t *pdlist, *pdlist2;
	uint8_t attr_val;

	pdlist = sdp_data_get(rec, 0x0101);
	pdlist2 = sdp_data_get(rec, 0x0102);
	if (pdlist) {
		if (pdlist2) {
			if (strncmp(pdlist->val.str, pdlist2->val.str, 5)) {
				strncpy(req->name, pdlist2->val.str, 127);
				strcat(req->name, " ");
			}
			strncat(req->name, pdlist->val.str, 127 - strlen(req->name));
		} else
			strncpy(req->name, pdlist->val.str, 127);
	} else {
		pdlist2 = sdp_data_get(rec, 0x0100);
		if (pdlist2)
			strncpy(req->name, pdlist2->val.str, 127);
 	}

	pdlist = sdp_data_get(rec, SDP_ATTR_HID_PARSER_VERSION);
	req->parser = pdlist ? pdlist->val.uint16 : 0x0100;

	pdlist = sdp_data_get(rec, SDP_ATTR_HID_DEVICE_SUBCLASS);
	req->subclass = pdlist ? pdlist->val.uint8 : 0;

	pdlist = sdp_data_get(rec, SDP_ATTR_HID_COUNTRY_CODE);
	req->country = pdlist ? pdlist->val.uint8 : 0;

	pdlist = sdp_data_get(rec, SDP_ATTR_HID_VIRTUAL_CABLE);
	attr_val = pdlist ? pdlist->val.uint8 : 0;
	if (attr_val)
		req->flags |= (1 << HIDP_VIRTUAL_CABLE_UNPLUG);

	pdlist = sdp_data_get(rec, SDP_ATTR_HID_BOOT_DEVICE);
	attr_val = pdlist ? pdlist->val.uint8 : 0;
	if (attr_val)
		req->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);

	pdlist = sdp_data_get(rec, SDP_ATTR_HID_DESCRIPTOR_LIST);
	if (pdlist) {
		pdlist = pdlist->val.dataseq;
		pdlist = pdlist->val.dataseq;
		pdlist = pdlist->next;

		req->rd_data = g_try_malloc0(pdlist->unitSize);
		if (req->rd_data) {
			memcpy(req->rd_data, (unsigned char *) pdlist->val.str,
								pdlist->unitSize);
			req->rd_size = pdlist->unitSize;
			epox_endian_quirk(req->rd_data, req->rd_size);
		}
	}
}

/*
 * Stored inputs registration functions
 */

static int load_stored(const char *source, const char *destination,
			struct hidp_connadd_req *hidp)
{
	char filename[PATH_MAX + 1];
	char *value;

	/* load the input stored */
	create_name(filename, PATH_MAX, STORAGEDIR, destination, "input");

	value = textfile_get(filename, destination);
	if (!value)
		return -EINVAL;

	memset(&hidp, 0, sizeof(hidp));

	return parse_stored_device_info(value, hidp);
}

static void input_remove(struct btd_device *device, const char *uuid)
{
	const gchar *path = device_get_path(device);

	DBG("path %s", path);

	input_device_unregister(path, uuid);
}

static int hid_device_probe(struct btd_device *device, GSList *records)
{
	struct btd_adapter *adapter = device_get_adapter(device);
	const gchar *path = device_get_path(device);
	const char *source, *destination;
	struct hidp_connadd_req hidp;
	bdaddr_t src, dst;

	DBG("path %s", path);

	memset(&hidp, 0, sizeof(hidp));

	source = adapter_get_address(adapter);
	destination = device_get_address(device);

	if (load_stored(source, destination, &hidp) == 0)
		goto done;

	hidp.idle_to = idle_timeout * 60;

	extract_hid_record(records->data, &hidp);

done:
	str2ba(source, &src);
	str2ba(destination, &dst);

	store_device_info(&src, &dst, &hidp);

	if (hidp.rd_data)
		g_free(hidp.rd_data);

	return input_device_register(connection, path, &src, &dst,
				HID_UUID, hidp.idle_to);
}

static void hid_device_remove(struct btd_device *device)
{
	input_remove(device, HID_UUID);
}

static int headset_probe(struct btd_device *device, GSList *records)
{
	struct btd_adapter *adapter = device_get_adapter(device);
	const gchar *path = device_get_path(device);
	sdp_record_t *record = records->data;
	sdp_list_t *protos;
	uint8_t ch;
	const char *source, *destination;
	bdaddr_t src, dst;

	DBG("path %s", path);

	if (sdp_get_access_protos(record, &protos) < 0) {
		error("Invalid record");
		return -EINVAL;
	}

	ch = sdp_get_proto_port(protos, RFCOMM_UUID);
	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
	sdp_list_free(protos, NULL);

	if (ch <= 0) {
		error("Invalid RFCOMM channel");
		return -EINVAL;
	}

	source = adapter_get_address(adapter);
	destination = device_get_address(device);

	str2ba(source, &src);
	str2ba(destination, &dst);

	return fake_input_register(connection, path, &src, &dst,
				HSP_HS_UUID, ch);
}

static void headset_remove(struct btd_device *device)
{
	input_remove(device, HSP_HS_UUID);
}

static int hid_server_probe(struct btd_adapter *adapter)
{
	const char *addr;
	bdaddr_t src;

	addr = adapter_get_address(adapter);
	str2ba(addr, &src);

	return server_start(&src);
}

static void hid_server_remove(struct btd_adapter *adapter)
{
	const char *addr;
	bdaddr_t src;

	addr = adapter_get_address(adapter);
	str2ba(addr, &src);

	server_stop(&src);
}

static struct btd_device_driver input_hid_driver = {
	.name	= "input-hid",
	.uuids	= BTD_UUIDS(HID_UUID),
	.probe	= hid_device_probe,
	.remove	= hid_device_remove,
};

static struct btd_device_driver input_headset_driver = {
	.name	= "input-headset",
	.uuids	= BTD_UUIDS(HSP_HS_UUID),
	.probe	= headset_probe,
	.remove	= headset_remove,
};

static struct btd_adapter_driver input_server_driver = {
	.name   = "input-server",
	.probe  = hid_server_probe,
	.remove = hid_server_remove,
};

int input_manager_init(DBusConnection *conn, GKeyFile *config)
{
	GError *err = NULL;

	if (config) {
		idle_timeout = g_key_file_get_integer(config, "General",
						"IdleTimeout", &err);
		if (err) {
			debug("input.conf: %s", err->message);
			g_error_free(err);
		}
	}

	connection = dbus_connection_ref(conn);

	btd_register_adapter_driver(&input_server_driver);

	btd_register_device_driver(&input_hid_driver);
	btd_register_device_driver(&input_headset_driver);

	return 0;
}

void input_manager_exit(void)
{
	btd_unregister_device_driver(&input_hid_driver);
	btd_unregister_device_driver(&input_headset_driver);

	btd_unregister_adapter_driver(&input_server_driver);

	dbus_connection_unref(connection);

	connection = NULL;
}
