/*
 *
 *  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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <glib.h>

#include "src/plugin.h"
#include "src/adapter.h"
#include "src/device.h"
#include "src/log.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_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) {
		btd_device_set_temporary(device, TRUE);
		btd_adapter_remove_device(adapter, device);
	}

	device = btd_adapter_get_device(adapter, &bdaddr, bdaddr_type);
	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_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;
	}

	/* 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);
}

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