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