/*
 *
 *  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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

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

#define BTPROTO_HCI	1

struct hci_dev_stats {
	uint32_t err_rx;
	uint32_t err_tx;
	uint32_t cmd_tx;
	uint32_t evt_rx;
	uint32_t acl_tx;
	uint32_t acl_rx;
	uint32_t sco_tx;
	uint32_t sco_rx;
	uint32_t byte_rx;
	uint32_t byte_tx;
};

struct hci_dev_info {
	uint16_t dev_id;
	char     name[8];
	uint8_t  bdaddr[6];
	uint32_t flags;
	uint8_t  type;
	uint8_t  features[8];
	uint32_t pkt_type;
	uint32_t link_policy;
	uint32_t link_mode;
	uint16_t acl_mtu;
	uint16_t acl_pkts;
	uint16_t sco_mtu;
	uint16_t sco_pkts;
	struct   hci_dev_stats stat;
};

#define HCIDEVUP	_IOW('H', 201, int)
#define HCIDEVDOWN	_IOW('H', 202, int)
#define HCIGETDEVINFO	_IOR('H', 211, int)

#define HCI_UP		(1 << 0)

#define HCI_BREDR	0x00
#define HCI_AMP		0x01

static struct hci_dev_info hci_info;
static uint8_t hci_type;
static struct bt_hci *hci_dev;

static bool reset_on_init = false;
static bool reset_on_shutdown = false;

static void shutdown_timeout(int id, void *user_data)
{
	mainloop_remove_timeout(id);

	mainloop_quit();
}

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

	shutdown_timeout(id, NULL);
}

static void shutdown_device(void)
{
	unsigned int id;

	bt_hci_flush(hci_dev);

	if (reset_on_shutdown) {
		id = mainloop_add_timeout(5, shutdown_timeout, NULL, NULL);

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

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

	printf("HCI version: %u\n", rsp->hci_ver);
	printf("HCI revision: %u\n", le16_to_cpu(rsp->hci_rev));

	switch (hci_type) {
	case HCI_BREDR:
		printf("LMP version: %u\n", rsp->lmp_ver);
		printf("LMP subversion: %u\n", le16_to_cpu(rsp->lmp_subver));
		break;
	case HCI_AMP:
		printf("PAL version: %u\n", rsp->lmp_ver);
		printf("PAL subversion: %u\n", le16_to_cpu(rsp->lmp_subver));
		break;
	}

	printf("Manufacturer: %u\n", le16_to_cpu(rsp->manufacturer));
}

static void local_commands_callback(const void *data, uint8_t size,
							void *user_data)
{
	shutdown_device();
}

static void local_features_callback(const void *data, uint8_t size,
							void *user_data)
{
	bt_hci_send(hci_dev, BT_HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0,
					local_commands_callback, NULL, NULL);
}

static bool cmd_local(int argc, char *argv[])
{
	if (reset_on_init)
		bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0,
						NULL, NULL, NULL);

	bt_hci_send(hci_dev, BT_HCI_CMD_READ_LOCAL_VERSION, NULL, 0,
					local_version_callback, NULL, NULL);

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

	return true;
}

typedef bool (*cmd_func_t)(int argc, char *argv[]);

static const struct {
	const char *name;
	cmd_func_t func;
	const char *help;
} cmd_table[] = {
	{ "local", cmd_local, "Print local controller details" },
	{ }
};

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)
{
	int i;

	printf("btinfo - Bluetooth device testing tool\n"
		"Usage:\n");
	printf("\tbtinfo [options] <command>\n");
	printf("options:\n"
		"\t-i, --index <num>      Use specified controller\n"
		"\t-h, --help             Show help options\n");
	printf("commands:\n");
	for (i = 0; cmd_table[i].name; i++)
		printf("\t%-25s%s\n", cmd_table[i].name, cmd_table[i].help);
}

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

int main(int argc, char *argv[])
{
	cmd_func_t func = NULL;
	uint16_t index = 0;
	const char *str;
	bool use_raw = false;
	bool power_down = false;
	sigset_t mask;
	int fd, i, exit_status;

	for (;;) {
		int opt;

		opt = getopt_long(argc, argv, "i:rRvh", 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 'r':
			reset_on_init = true;
			break;
		case 'R':
			use_raw = true;
			break;
		case 'v':
			printf("%s\n", VERSION);
			return EXIT_SUCCESS;
		case 'h':
			usage();
			return EXIT_SUCCESS;
		default:
			return EXIT_FAILURE;
		}
	}

	if (argc - optind < 1) {
		fprintf(stderr, "Missing command argument\n");
		return EXIT_FAILURE;
	}

	for (i = 0; cmd_table[i].name; i++) {
		if (!strcmp(cmd_table[i].name, argv[optind])) {
			func = cmd_table[i].func;
			break;
		}
	}

	if (!func) {
		fprintf(stderr, "Unsupported command specified\n");
		return EXIT_FAILURE;
	}

	mainloop_init();

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

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

	printf("Bluetooth information utility ver %s\n", VERSION);

	fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
	if (fd < 0) {
		perror("Failed to open HCI raw socket");
		return EXIT_FAILURE;
	}

	memset(&hci_info, 0, sizeof(hci_info));
	hci_info.dev_id = index;

	if (ioctl(fd, HCIGETDEVINFO, (void *) &hci_info) < 0) {
		perror("Failed to get HCI device information");
		close(fd);
		return EXIT_FAILURE;
	}

	if (use_raw && !(hci_info.flags & HCI_UP)) {
		printf("Powering on controller\n");

		if (ioctl(fd, HCIDEVUP, hci_info.dev_id) < 0) {
			perror("Failed to power on controller");
			close(fd);
			return EXIT_FAILURE;
		}

		power_down = true;
	}

	close(fd);

	hci_type = (hci_info.type & 0x30) >> 4;

	if (use_raw) {
		hci_dev = bt_hci_new_raw_device(index);
		if (!hci_dev) {
			fprintf(stderr, "Failed to open HCI raw device\n");
			return EXIT_FAILURE;
		}
	} else {
		hci_dev = bt_hci_new_user_channel(index);
		if (!hci_dev) {
			fprintf(stderr, "Failed to open HCI user channel\n");
			return EXIT_FAILURE;
		}

		reset_on_init = true;
		reset_on_shutdown = true;
	}

	if (!func(argc - optind - 1, argv + optind + 1)) {
		bt_hci_unref(hci_dev);
		return EXIT_FAILURE;
	}

	exit_status = mainloop_run();

	bt_hci_unref(hci_dev);

	if (use_raw && power_down) {
		fd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
		if (fd >= 0) {
			printf("Powering down controller\n");

			if (ioctl(fd, HCIDEVDOWN, hci_info.dev_id) < 0)
				perror("Failed to power down controller");

			close(fd);
		}
	}

	return exit_status;
}
