/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2011-2012  Intel 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 <ctype.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include "monitor/bt.h"
#include "src/shared/mainloop.h"
#include "src/shared/timeout.h"
#include "src/shared/util.h"
#include "src/shared/hci.h"

static int urandom_fd;
static struct bt_hci *hci_dev;

static bool shutdown_timeout(void *user_data)
{
	mainloop_quit();

	return false;
}

static void shutdown_complete(const void *data, uint8_t size, void *user_data)
{
	unsigned int id = PTR_TO_UINT(user_data);

	timeout_remove(id);
	mainloop_quit();
}

static void shutdown_device(void)
{
	uint8_t enable = 0x00;
	unsigned int id;

	bt_hci_flush(hci_dev);

	id = timeout_add(5000, shutdown_timeout, NULL, NULL);

	bt_hci_send(hci_dev, BT_HCI_CMD_LE_SET_ADV_ENABLE,
					&enable, 1, NULL, NULL, NULL);

	bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0,
				shutdown_complete, UINT_TO_PTR(id), NULL);
}

static void set_random_address(void)
{
	struct bt_hci_cmd_le_set_random_address cmd;
	ssize_t len;

	len = read(urandom_fd, cmd.addr, sizeof(cmd.addr));
	if (len < 0 || len != sizeof(cmd.addr)) {
		fprintf(stderr, "Failed to read random data\n");
		return;
	}

	/* Clear top most significant bits */
	cmd.addr[5] &= 0x3f;

	bt_hci_send(hci_dev, BT_HCI_CMD_LE_SET_RANDOM_ADDRESS,
					&cmd, sizeof(cmd), NULL, NULL, NULL);
}

static void set_adv_parameters(void)
{
	struct bt_hci_cmd_le_set_adv_parameters cmd;

	cmd.min_interval = cpu_to_le16(0x0800);
	cmd.max_interval = cpu_to_le16(0x0800);
	cmd.type = 0x03;		/* Non-connectable advertising */
	cmd.own_addr_type = 0x01;	/* Use random address */
	cmd.direct_addr_type = 0x00;
	memset(cmd.direct_addr, 0, 6);
	cmd.channel_map = 0x07;
	cmd.filter_policy = 0x00;

	bt_hci_send(hci_dev, BT_HCI_CMD_LE_SET_ADV_PARAMETERS,
					&cmd, sizeof(cmd), NULL, NULL, NULL);
}

static void set_adv_enable(void)
{
	uint8_t enable = 0x01;

	bt_hci_send(hci_dev, BT_HCI_CMD_LE_SET_ADV_ENABLE,
					&enable, 1, NULL, NULL, NULL);
}

static void adv_data_callback(const void *data, uint8_t size,
							void *user_data)
{
	uint8_t status = *((uint8_t *) data);

	if (status) {
		fprintf(stderr, "Failed to set advertising data\n");
		shutdown_device();
		return;
	}

	set_random_address();
	set_adv_parameters();
	set_adv_enable();
}

static void adv_tx_power_callback(const void *data, uint8_t size,
							void *user_data)
{
	const struct bt_hci_rsp_le_read_adv_tx_power *rsp = data;
	struct bt_hci_cmd_le_set_adv_data cmd;

	if (rsp->status) {
		fprintf(stderr, "Failed to read advertising TX power\n");
		shutdown_device();
		return;
	}

	cmd.data[0] = 0x02;		/* Field length */
	cmd.data[1] = 0x01;		/* Flags */
	cmd.data[2] = 0x04;		/* BR/EDR Not Supported */

	cmd.data[3] = 0x1a;		/* Field length */
	cmd.data[4] = 0xff;		/* Vendor field */
	cmd.data[5] = 0x4c;		/* Apple (76) - LSB */
	cmd.data[6] = 0x00;		/* Apple (76) - MSB */
	cmd.data[7] = 0x02;		/* iBeacon type */
	cmd.data[8] = 0x15;		/* Length */
	memset(cmd.data + 9, 0, 16);	/* UUID */
	cmd.data[25] = 0x00;		/* Major - LSB */
	cmd.data[26] = 0x00;		/* Major - MSB */
	cmd.data[27] = 0x00;		/* Minor - LSB */
	cmd.data[28] = 0x00;		/* Minor - MSB */
	cmd.data[29] = 0xc5;		/* TX power level */

	cmd.data[30] = 0x00;		/* Field terminator */

	cmd.len = 1 + cmd.data[0] + 1 + cmd.data[3];

	bt_hci_send(hci_dev, BT_HCI_CMD_LE_SET_ADV_DATA, &cmd, sizeof(cmd),
					adv_data_callback, NULL, NULL);
}

static void local_features_callback(const void *data, uint8_t size,
							void *user_data)
{
	const struct bt_hci_rsp_read_local_features *rsp = data;

	if (rsp->status) {
		fprintf(stderr, "Failed to read local features\n");
		shutdown_device();
		return;
	}

	if (!(rsp->features[4] & 0x40)) {
		fprintf(stderr, "Controller without Low Energy support\n");
		shutdown_device();
		return;
	}

	bt_hci_send(hci_dev, BT_HCI_CMD_LE_READ_ADV_TX_POWER, NULL, 0,
					adv_tx_power_callback, NULL, NULL);
}

static void start_ibeacon(void)
{
	bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0, NULL, NULL, NULL);

	bt_hci_send(hci_dev, BT_HCI_CMD_READ_LOCAL_FEATURES, NULL, 0,
					local_features_callback, NULL, NULL);
}

static void signal_callback(int signum, void *user_data)
{
	static bool terminated = false;

	switch (signum) {
	case SIGINT:
	case SIGTERM:
		if (!terminated) {
			shutdown_device();
			terminated = true;
		}
		break;
	}
}

static void usage(void)
{
	printf("ibeacon - Low Energy iBeacon testing tool\n"
		"Usage:\n");
	printf("\tibeacon [options]\n");
	printf("Options:\n"
		"\t-i, --index <num>      Use specified controller\n"
		"\t-h, --help             Show help options\n");
}

static const struct option main_options[] = {
	{ "index",   required_argument, NULL, 'i' },
	{ "version", no_argument,       NULL, 'v' },
	{ "help",    no_argument,       NULL, 'h' },
	{ }
};

int main(int argc, char *argv[])
{
	uint16_t index = 0;
	const char *str;
	sigset_t mask;
	int exit_status;

	for (;;) {
		int opt;

		opt = getopt_long(argc, argv, "i:vh", main_options, NULL);
		if (opt < 0)
			break;

		switch (opt) {
		case 'i':
			if (strlen(optarg) > 3 && !strncmp(optarg, "hci", 3))
				str = optarg + 3;
			else
				str = optarg;
			if (!isdigit(*str)) {
				usage();
				return EXIT_FAILURE;
			}
			index = atoi(str);
			break;
		case 'v':
			printf("%s\n", VERSION);
			return EXIT_SUCCESS;
		case 'h':
			usage();
			return EXIT_SUCCESS;
		default:
			return EXIT_FAILURE;
		}
	}

	if (argc - optind > 0) {
		fprintf(stderr, "Invalid command line parameters\n");
		return EXIT_FAILURE;
	}

	urandom_fd = open("/dev/urandom", O_RDONLY);
	if (urandom_fd < 0) {
		fprintf(stderr, "Failed to open /dev/urandom device\n");
		return EXIT_FAILURE;
	}

	mainloop_init();

	sigemptyset(&mask);
	sigaddset(&mask, SIGINT);
	sigaddset(&mask, SIGTERM);

	mainloop_set_signal(&mask, signal_callback, NULL, NULL);

	printf("Low Energy iBeacon utility ver %s\n", VERSION);

	hci_dev = bt_hci_new_user_channel(index);
	if (!hci_dev) {
		fprintf(stderr, "Failed to open HCI user channel\n");
		exit_status = EXIT_FAILURE;
		goto done;
	}

	start_ibeacon();

	exit_status = mainloop_run();

	bt_hci_unref(hci_dev);

done:
	close(urandom_fd);

	return exit_status;
}
