/*
 *
 *  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 oui[3];
	uint8_t bdaddr_type;
	uint16_t vid;
	uint16_t pid;
};

static struct gfrm_device gfrm_devs[] = {
	{ "GFRM100", {0x00, 0x24, 0x1C}, BDADDR_BREDR, 0x58, 0x2000 },
	{ "GFRM200", {0x88, 0x33, 0x14}, BDADDR_LE_PUBLIC, 0x471, 0x2210 },
	{ "HID AdvRemote", {0x90, 0x59, 0xAF}, BDADDR_LE_PUBLIC, 0xD, 0x0 },
};

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 struct gfrm_device *gfrm_find_dev_by_oui(uint8_t oui0, uint8_t oui1,
								uint8_t oui2)
{
	uint16_t i;

	for (i = 0; i < G_N_ELEMENTS(gfrm_devs); ++i) {
		if (oui0 == gfrm_devs[i].oui[0] &&
		    oui1 == gfrm_devs[i].oui[1] &&
		    oui2 == gfrm_devs[i].oui[2]) {
			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;
	bdaddr_t bdaddr_be;
	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_be, sizeof(bdaddr_be)) != 6) {
		DBG("read failed");
		goto reopen;
	}

	baswap(&bdaddr, &bdaddr_be);
	ba2str(&bdaddr, bdaddr_str);

	gfrm_dev = gfrm_find_dev_by_oui(bdaddr.b[5], bdaddr.b[4], bdaddr.b[3]);
	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, gfrm_dev->bdaddr_type);
	if (device) {
		btd_device_set_temporary(device, TRUE);
		btd_adapter_remove_device(adapter, device);
	}

	device = btd_adapter_get_device(adapter, &bdaddr, gfrm_dev->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)
