/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2014 Google Inc.
 *
 *
 *  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 <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib.h>

#include "lib/bluetooth.h"
#include "lib/sdp.h"
#include "lib/uuid.h"

#include "src/adapter.h"
#include "src/device.h"
#include "src/log.h"
#include "src/plugin.h"

#define BD_ADDR_FIFO "/tmp/bd-addr-fifo"

struct gfrm_device {
	char *name;
	uint8_t bdaddr_type;
	uint16_t vid;
	uint16_t pid;
};

static struct gfrm_device gfrm_devs[] = {
	{ "GFRM100", BDADDR_BREDR, 0x58, 0x2000 },
	{ "GFRM200", BDADDR_LE_PUBLIC, 0x471, 0x2210 },
	{ "HID AdvRemote", BDADDR_LE_PUBLIC, 0xD, 0x0 },
};

static struct gfrm_device *gfrm_find_dev_by_bdaddr_type(uint8_t bdaddr_type)
{
	uint16_t i;

	for (i = 0; i < G_N_ELEMENTS(gfrm_devs); ++i) {
		if (bdaddr_type == gfrm_devs[i].bdaddr_type) {
			return &gfrm_devs[i];
		}
	}

	return NULL;
}

static struct gfrm_device *gfrm_find_dev_by_vid_pid(uint16_t vid, uint16_t pid)
{
	uint16_t i;

	for (i = 0; i < G_N_ELEMENTS(gfrm_devs); ++i) {
		if (vid == gfrm_devs[i].vid && pid == gfrm_devs[i].pid) {
			return &gfrm_devs[i];
		}
	}

	return NULL;
}

static ssize_t gfrm_pincb(struct btd_adapter *adapter, struct btd_device *device,
			  char *pinbuf, bool *display, unsigned int attempt)
{
	uint16_t vid, pid;
	char addr[18], name[25];

	/*
	 * Only try the pin code once per device.
	 * If it's not correct then it's an unknown device.
	 */
	if (attempt > 1)
		return 0;

	ba2str(device_get_address(device), addr);

	vid = btd_device_get_vendor(device);
	pid = btd_device_get_product(device);
	DBG("vendor 0x%x product 0x%x", vid, pid);

	device_get_name(device, name, sizeof(name));
	name[sizeof(name) - 1] = 0;

	if (gfrm_find_dev_by_vid_pid(vid, pid)) {
		DBG("Forcing PIN 0000 on %s at %s", name, addr);
		memcpy(pinbuf, "0000", 4);
		return 4;
	}

	return 0;
}

static void gfrm_disconnect_cb(struct btd_device *device, uint8_t reason)
{
	bdaddr_t bdaddr;
	uint8_t bdaddr_type;
	uint16_t vid, pid;
	char addr[18], name[25];

	memcpy(&bdaddr, device_get_address(device), sizeof(bdaddr));
	ba2str(&bdaddr, addr);
	bdaddr_type = btd_device_get_bdaddr_type(device);

	vid = btd_device_get_vendor(device);
	pid = btd_device_get_product(device);

	device_get_name(device, name, sizeof(name));
	name[sizeof(name) - 1] = 0;

	if (gfrm_find_dev_by_vid_pid(vid, pid)) {
		DBG("%s [%s] disconnected: reason %u", name, addr, reason);
	}
}

static void gfrm_conn_fail_cb(struct btd_device *device, uint8_t reason)
{
	bdaddr_t bdaddr;
	uint8_t bdaddr_type;
	uint16_t vid, pid;
	char addr[18], name[25];

	memcpy(&bdaddr, device_get_address(device), sizeof(bdaddr));
	ba2str(&bdaddr, addr);
	bdaddr_type = btd_device_get_bdaddr_type(device);

	vid = btd_device_get_vendor(device);
	pid = btd_device_get_product(device);

	device_get_name(device, name, sizeof(name));
	name[sizeof(name) - 1] = 0;

	if (gfrm_find_dev_by_vid_pid(vid, pid)) {
		DBG("%s [%s] connection failed: reason %u", name, addr, reason);
	}
}

static void gfrm_start_bd_addr_fifo_watch(
		gboolean (*callback)(GIOChannel *, GIOCondition, gpointer))
{
	int fd;
	GIOChannel *io;

	if ((fd = open(BD_ADDR_FIFO, O_RDONLY | O_NONBLOCK)) < 0) {
		DBG("open failed");
		return;
	}

	if ((io = g_io_channel_unix_new(fd)) == NULL) {
		DBG("g_io_channel_unix_new failed");
		close(fd);
		return;
	}

	if (!g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
			    callback, NULL)) {
		DBG("g_io_add_watch failed");
	}

	g_io_channel_set_close_on_unref(io, TRUE);
	g_io_channel_unref(io);
}

static gboolean gfrm_add_device(GIOChannel *io, GIOCondition condition,
				gpointer data)
{
	int fd;
	uint8_t bdaddr_and_type[7] = { 0 };
	uint8_t bdaddr_type;
	bdaddr_t bdaddr;
	char bdaddr_str[18];
	struct gfrm_device *gfrm_dev;
	struct btd_adapter *adapter;
	struct btd_device *device;

	if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
		DBG("io error: condition %u", condition);
	}

	if (!(condition & (G_IO_IN))) {
		DBG("pipe has no data to read");
		goto reopen;
	}

	/* Read BD address from FIFO */
	fd = g_io_channel_unix_get_fd(io);

	if (read(fd, &bdaddr_and_type, sizeof(bdaddr_and_type)) != 7) {
		DBG("read failed");
		goto reopen;
	}

	bdaddr_type = bdaddr_and_type[6];
	baswap(&bdaddr, (bdaddr_t*) bdaddr_and_type);
	ba2str(&bdaddr, bdaddr_str);

	gfrm_dev = gfrm_find_dev_by_bdaddr_type(bdaddr_type);
	if (!gfrm_dev)
		goto reopen;

	DBG("Discovered %s at %s", gfrm_dev->name, bdaddr_str);

	/* Add device to BlueZ stack */
	adapter = btd_adapter_get_default();
	if (!adapter) {
		DBG("btd_adapter_get_default failed");
		goto reopen;
	}

	device = btd_adapter_find_device(adapter, &bdaddr, bdaddr_type);
	if (device) {
		DBG("device %p paired %d bonded %d bonding %d", device,
		    device_is_paired(device, bdaddr_type),
		    device_is_bonded(device, bdaddr_type),
		    device_is_bonding(device, NULL));

		if (device_is_bonding(device, NULL))
			goto reopen;

		DBG("Removing %s @ %s", gfrm_dev->name, bdaddr_str);
		btd_device_set_temporary(device, TRUE);
		btd_adapter_remove_device(adapter, device);
	}

	DBG("Adding %s @ %s", gfrm_dev->name, bdaddr_str);
	device = btd_adapter_get_device(adapter, &bdaddr, bdaddr_type);
	if (device) {
		btd_device_device_set_name(device, gfrm_dev->name);
		btd_device_set_pnpid(device, 0x1, gfrm_dev->vid,
			gfrm_dev->pid, 0x0);
		btd_device_set_temporary(device, FALSE);
	}

	/*
	 * Pairing the remote is handled in Python script:
	 * test/gfiber-agent
	 */

reopen:
	/* Reopen the FIFO (new fd, io channel, and watch) */
	gfrm_start_bd_addr_fifo_watch(gfrm_add_device);

	/*
	 * Return FALSE, so that the watch on the old io channel is removed.
	 * That, in turn, triggers closing of io channel and file descriptor.
	 */
	return FALSE;
}

static int gfrm_probe(struct btd_adapter *adapter)
{
	btd_adapter_register_pin_cb(adapter, gfrm_pincb);
}

static void gfrm_remove(struct btd_adapter *adapter)
{
	btd_adapter_unregister_pin_cb(adapter, gfrm_pincb);
}

static struct btd_adapter_driver gfrm_driver = {
	.name	= "gfrm",
	.probe	= gfrm_probe,
	.remove	= gfrm_remove,
};

static int gfrm_init(void)
{
	btd_add_disconnect_cb(gfrm_disconnect_cb);
	btd_add_conn_fail_cb(gfrm_conn_fail_cb);
	btd_register_adapter_driver(&gfrm_driver);

	/* Create FIFO for IR-assisted pairing */
	if (mkfifo(BD_ADDR_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
		   S_IROTH | S_IWOTH) < 0 && errno != EEXIST) {
		DBG("mkfifo failed");
		return 0;
	}
	/* Set file mode bits on the fifo since umask clears group/other */
	chmod(BD_ADDR_FIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
				S_IROTH | S_IWOTH);

	/* Start watching the FIFO */
	gfrm_start_bd_addr_fifo_watch(gfrm_add_device);

	return 0;
}

static void gfrm_exit(void)
{
	btd_unregister_adapter_driver(&gfrm_driver);
	btd_remove_conn_fail_cb(gfrm_conn_fail_cb);
	btd_remove_disconnect_cb(gfrm_disconnect_cb);
}

BLUETOOTH_PLUGIN_DEFINE(gfrm, VERSION,
			BLUETOOTH_PLUGIN_PRIORITY_HIGH, gfrm_init, gfrm_exit)
