/*
 *  User Mode Init manager - For TI shared transport
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <poll.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/utsname.h>

#include <unistd.h>
#include <time.h>

#include "uim.h"

/* Maintains the exit state of UIM*/
static int exiting;
static int line_discipline;
static int dev_fd;

/* BD address as string and a pointer to array of hex bytes */
char uim_bd_address[BD_ADDR_LEN];
bdaddr_t *bd_addr;

/* kim Sysfs path */
static char *sysfs_install_entry = INSTALL_SYSFS_ENTRY;
static char *sysfs_dev_name = DEV_NAME_SYSFS;
static char *sysfs_baud_rate = BAUD_RATE_SYSFS;
static char *sysfs_flow_ctrl = FLOW_CTRL_SYSFS;

/*****************************************************************************/
#ifdef UIM_DEBUG
/*  Function to Read the firmware version
 *  module into the system. Currently used for
 *  debugging purpose, whenever the baud rate is changed
 */
void read_firmware_version(int dev_fd)
{
	int index = 0;
	char resp_buffer[20] = { 0 };
	unsigned char buffer[] = { 0x01, 0x01, 0x10, 0x00 };

	UIM_START_FUNC();
	UIM_VER(" wrote %d bytes", (int)write(dev_fd, buffer, 4));
	UIM_VER(" reading %d bytes", (int)read(dev_fd, resp_buffer, 15));

	for (index = 0; index < 15; index++)
		UIM_VER(" %x ", resp_buffer[index]);

	printf("\n");
}
#endif

void sysfs_entry_fallback(void)
{
	sysfs_install_entry = INSTALL_SYSFS_ENTRY_OLD;
	sysfs_dev_name = DEV_NAME_SYSFS_OLD;
	sysfs_baud_rate = BAUD_RATE_SYSFS_OLD;
	sysfs_flow_ctrl = FLOW_CTRL_SYSFS_OLD;
}

/*****************************************************************************/
/* Function to read the HCI event from the given file descriptor
 *
 * This will parse the response received and returns error
 * if the required response is not received
 */
int read_hci_event(int fd, unsigned char *buf, int size)
{
	int remain, rd;
	int count = 0;
	int reading = 1;
	int rd_retry_count = 0;
	struct timespec tm = {0, 50*1000*1000};

	UIM_START_FUNC();

	UIM_VER(" read_hci_event");
	if (size <= 0)
		return -1;

	/* The first byte identifies the packet type. For HCI event packets, it
	 * should be 0x04, so we read until we get to the 0x04. */
	while (reading) {
		rd = read(fd, buf, 1);
		if (rd <= 0 && rd_retry_count++ < 4) {
			nanosleep(&tm, NULL);
			continue;
		} else if (rd_retry_count >= 4) {
			return -1;
		}

		if (buf[0] == RESP_PREFIX) {
			break;
		}
	}
	count++;

	/* The next two bytes are the event code and parameter total length. */
	while (count < 3) {
		rd = read(fd, buf + count, 3 - count);
		if (rd <= 0)
			return -1;
		count += rd;
	}

	/* Now we read the parameters. */
	if (buf[2] < (size - 3))
		remain = buf[2];
	else
		remain = size - 3;

	while ((count - 3) < remain) {
		rd = read(fd, buf + count, remain - (count - 3));
		if (rd <= 0)
			return -1;
		count += rd;
	}

	return count;
}

/* Function to read the Command complete event
 *
 * This will read the response for the change speed
 * command that was sent to configure the UART speed
 * with the custom baud rate
 */
static int read_command_complete(int fd, unsigned short opcode)
{
	command_complete_t resp;

	UIM_START_FUNC();

	UIM_VER(" Command complete started");
	if (read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0) {
		UIM_ERR("Invalid response");
		return -1;
	}

	/* Response should be an event packet */
	if (resp.uart_prefix != HCI_EVENT_PKT) {
		UIM_ERR	("Error in response: not an event packet, 0x%02x!",
			 resp.uart_prefix);
		return -1;
	}

	/* Response should be a command complete event */
	if (resp.hci_hdr.evt != EVT_CMD_COMPLETE) {
		/* event must be event-complete */
		UIM_ERR("Error in response: not a cmd-complete event,0x%02x!",
			 resp.hci_hdr.evt);
		return -1;
	}

	if (resp.hci_hdr.plen < 4) {
		/* plen >= 4 for EVT_CMD_COMPLETE */
		UIM_ERR("Error in response: plen is not >= 4, but 0x%02x!",
				resp.hci_hdr.plen);
		return -1;
	}

	if (resp.cmd_complete.opcode != (unsigned short)opcode) {
		UIM_ERR("Error in response: opcode is 0x%04x, not 0x%04x!",
				resp.cmd_complete.opcode, opcode);
		return -1;
	}

	UIM_DBG("Command complete done");
	return resp.status == 0 ? 0 : -1;
}

/* Function to set the default baud rate
 *
 * The default baud rate of 115200 is set to the UART from the host side
 * by making a call to this function.This function is also called before
 * making a call to set the custom baud rate
 */
static int set_baud_rate(int dev_fd)
{
	UIM_START_FUNC();
	struct termios ti;

	tcflush(dev_fd, TCIOFLUSH);

	/* Get the attributes of UART */
	if (tcgetattr(dev_fd, &ti) < 0) {
		UIM_ERR(" Can't get port settings");
		return -1;
	}

	/* Change the UART attributes before
	 * setting the default baud rate*/
	cfmakeraw(&ti);

	ti.c_cflag |= 1;
	ti.c_cflag |= CRTSCTS;

	/* Set the attributes of UART after making
	 * the above changes
	 */
	tcsetattr(dev_fd, TCSANOW, &ti);

	/* Set the actual default baud rate */
	cfsetospeed(&ti, B115200);
	cfsetispeed(&ti, B115200);
	tcsetattr(dev_fd, TCSANOW, &ti);

	tcflush(dev_fd, TCIOFLUSH);
	UIM_DBG("set_baud_rate() done");

	return 0;
}


/* Function to set the UART custom baud rate.
 *
 * The UART baud rate has already been
 * set to default value 115200 before calling this function.
 * The baud rate is then changed to custom baud rate by this function*/
static int set_custom_baud_rate(int dev_fd, int baud_rate, int flow_ctrl)
{
	UIM_START_FUNC();

	struct termios ti;
	struct termios2 ti2;

	tcflush(dev_fd, TCIOFLUSH);
	/* Get the attributes of UART */
	if (tcgetattr(dev_fd, &ti) < 0) {
		UIM_ERR(" Can't get port settings");
		return -1;
	}

	/*Set the UART flow control */
	if (flow_ctrl)
		ti.c_cflag |= CRTSCTS;
	else
		ti.c_cflag &= ~CRTSCTS;

	/*
	 * Set the parameters associated with the UART
	 * The change will occur immediately by using TCSANOW
	 */
	if (tcsetattr(dev_fd, TCSANOW, &ti) < 0) {
		UIM_ERR(" Can't set port settings");
		return -1;
	}

	tcflush(dev_fd, TCIOFLUSH);

	/*Set the actual baud rate */
	ioctl(dev_fd, TCGETS2, &ti2);
	ti2.c_cflag &= ~CBAUD;
	ti2.c_cflag |= BOTHER;
	ti2.c_ospeed = baud_rate;
	ioctl(dev_fd, TCSETS2, &ti2);

	return 0;
}

/* Function to configure the UART
 * on receiving a notification from the ST KIM driver to install the line
 * discipline, this function does UART configuration necessary for the STK
 */
int st_uart_config(unsigned char install)
{
	int ldisc, len, fd, flow_ctrl;
	unsigned char buf[UART_DEV_NAME_LEN];
	uim_speed_change_cmd cmd;
	char uart_dev_name[UART_DEV_NAME_LEN];
	unsigned int cust_baud_rate;

	uim_bdaddr_change_cmd addr_cmd;

	UIM_START_FUNC();

	if (install == '1') {
		memset(buf, 0, UART_DEV_NAME_LEN);
		fd = open(sysfs_dev_name, O_RDONLY);
		if (fd < 0) {
			UIM_ERR("Can't open %s", sysfs_dev_name);
			return -1;
		}
		len = read(fd, buf, UART_DEV_NAME_LEN);
		if (len < 0) {
			UIM_ERR("read err (%s)", strerror(errno));
			close(fd);
			return len;
		}
		sscanf((const char*)buf, "%s", uart_dev_name);
		close(fd);

		memset(buf, 0, UART_DEV_NAME_LEN);
		fd = open(sysfs_baud_rate, O_RDONLY);
		if (fd < 0) {
			UIM_ERR("Can't open %s", sysfs_baud_rate);
			return -1;
		}
		len = read(fd, buf, UART_DEV_NAME_LEN);
		if (len < 0) {
			UIM_ERR("read err (%s)", strerror(errno));
			close(fd);
			return len;
		}
		close(fd);
		sscanf((const char*)buf, "%d", &cust_baud_rate);

		memset(buf, 0, UART_DEV_NAME_LEN);
		fd = open(sysfs_flow_ctrl, O_RDONLY);
		if (fd < 0) {
			UIM_ERR("Can't open %s", sysfs_flow_ctrl);
			close(fd);
			return -1;
		}
		len = read(fd, buf, UART_DEV_NAME_LEN);
		if (len < 0) {
			UIM_ERR("read err (%s)", strerror(errno));
			close(fd);
			return len;
		}
		close(fd);
		sscanf((const char*)buf, "%d", &flow_ctrl);

		UIM_VER(" signal received, opening %s", uart_dev_name);

		dev_fd = open(uart_dev_name, O_RDWR);
		if (dev_fd < 0) {
			UIM_ERR("Can't open %s", uart_dev_name);
			return -1;
		}

		/*
		 * Set only the default baud rate.
		 * This will set the baud rate to default 115200
		 */
		if (set_baud_rate(dev_fd) < 0) {
			UIM_ERR("set_baudrate() failed");
			close(dev_fd);
			return -1;
		}

		fcntl(dev_fd, F_SETFL,fcntl(dev_fd, F_GETFL) | O_NONBLOCK);
		/* Set only the custom baud rate */
		if (cust_baud_rate != 115200) {

			UIM_VER("Setting speed to %d", cust_baud_rate);
			/* Forming the packet for Change speed command */
			cmd.uart_prefix = HCI_COMMAND_PKT;
			cmd.hci_hdr.opcode = HCI_HDR_OPCODE;
			cmd.hci_hdr.plen = sizeof(unsigned int);
			cmd.speed = cust_baud_rate;

			/* Writing the change speed command to the UART
			 * This will change the UART speed at the controller
			 * side
			 */
			len = write(dev_fd, &cmd, sizeof(cmd));
			if (len < 0) {
				UIM_ERR("Failed to write speed-set command");
				close(dev_fd);
				return -1;
			}

			/* Read the response for the Change speed command */
			if (read_command_complete(dev_fd, HCI_HDR_OPCODE) < 0) {
				close(dev_fd);
				return -1;
			}

			UIM_VER("Speed changing to %d, %d", cust_baud_rate, flow_ctrl);
			/* Set the actual custom baud rate at the host side */
			if (set_custom_baud_rate(dev_fd, cust_baud_rate, flow_ctrl) < 0) {
				UIM_ERR("set_custom_baud_rate() failed");
				close(dev_fd);
				return -1;
			}

			/* Set the uim BD address */
			if (uim_bd_address[0] != 0) {

				memset(&addr_cmd, 0, sizeof(addr_cmd));
				/* Forming the packet for change BD address command*/
				addr_cmd.uart_prefix = HCI_COMMAND_PKT;
				addr_cmd.hci_hdr.opcode = WRITE_BD_ADDR_OPCODE;
				addr_cmd.hci_hdr.plen = sizeof(bdaddr_t);
				memcpy(&addr_cmd.addr, bd_addr, sizeof(bdaddr_t));

				/* Writing the change BD address command to the UART
				 * This will change the change BD address  at the controller
				 * side
				 */
				len = write(dev_fd, &addr_cmd, sizeof(addr_cmd));
				if (len < 0) {
					UIM_ERR("Failed to write BD address command");
					close(dev_fd);
					return -1;
				}

				/* Read the response for the change BD address command */
				if (read_command_complete(dev_fd, WRITE_BD_ADDR_OPCODE) < 0) {
					close(dev_fd);
					return -1;
				}
				UIM_VER("BD address changed to %s", uim_bd_address);
			}
#ifdef UIM_DEBUG
			read_firmware_version(dev_fd);
#endif
		}

		/* After the UART speed has been changed, the IOCTL is
		 * is called to set the line discipline to N_TI_WL
		 */
		ldisc = N_TI_WL;
		if (ioctl(dev_fd, TIOCSETD, &ldisc) < 0) {
			UIM_ERR(" Can't set line discipline");
			close(dev_fd);
			return -1;
		}
		UIM_DBG("Installed N_TI_WL Line displine");
	}
	else {
		UIM_DBG("Un-Installed N_TI_WL Line displine");
		/* UNINSTALL_N_TI_WL - When the Signal is received from KIM */
		/* closing UART fd */
		close(dev_fd);
	}
	return 0;
}

/* Function to convert the BD address from ascii to hex value */
bdaddr_t *strtoba(const char *str)
{
        const char *ptr = str;
        int i;

        uint8_t *ba = malloc(sizeof(bdaddr_t));
        if (!ba)
                return NULL;

        for (i = 0; i < 6; i++) {
                ba[i] = (uint8_t) strtol(ptr, NULL, 16);
                if (i != 5 && !(ptr = strchr(ptr, ':')))
                        ptr = ":00:00:00:00:00";
                ptr++;
        }

        return (bdaddr_t *) ba;
}

/*****************************************************************************/
int main(int argc, char *argv[])
{
	int st_fd, err,trials;
	unsigned char install;
	struct pollfd 	p;

	UIM_START_FUNC();
	err = 0;
	trials = 5;

	/* Parse the user input */
	if ((argc > 2)) {
		UIM_ERR("Invalid arguements");
		UIM_ERR("Usage: uim <bd address>");
		return -1;
	}
	if (argc == 2) {
		if (strlen(argv[2]) != BD_ADDR_LEN) {
			UIM_ERR("Usage: uim XX:XX:XX:XX:XX:XX");
			return -1;
		}
		/* BD address passed as string in xx:xx:xx:xx:xx:xx format */
		strncpy(uim_bd_address, argv[2], sizeof(uim_bd_address));
		bd_addr = strtoba(uim_bd_address);
	}

	line_discipline = N_TI_WL;

	/* sysfs entry may get populated after service is started so we retry if it fails*/
	while (trials > 0) {
		st_fd = open(sysfs_install_entry, O_RDONLY);
		if(st_fd > 0)
			break;
		if (trials == 3)
			sysfs_entry_fallback();
		else
			usleep(500000);
		--trials;
		}
	if (st_fd < 0) {
		UIM_DBG("unable to open %s(%s)", sysfs_install_entry, strerror(errno));
		return -1;
	}

RE_POLL:
	/* read to start proper poll */
	err = read(st_fd, &install, 1);
	/* special case where bluetoothd starts before the UIM, and UIM
	 * needs to turn on bluetooth because of that.
	 */
	if ((err > 0) && install == '1') {
		UIM_DBG("install set previously...");
		st_uart_config(install);
	}

	UIM_DBG("begin polling...");

	memset(&p, 0, sizeof(p));
	p.fd = st_fd;
	p.events = POLLERR | POLLPRI;

	while (!exiting) {
		p.revents = 0;
		err = poll(&p, 1, -1);
		UIM_DBG("poll broke due to event %d(PRI:%d/ERR:%d)\n", p.revents, POLLPRI, POLLERR);
		if (err < 0 && errno == EINTR)
			continue;
		if (err)
			break;
	}

	close(st_fd);
	st_fd = open(sysfs_install_entry, O_RDONLY);
	if (st_fd < 0) {
		UIM_DBG("unable to open %s (%s)", sysfs_install_entry, strerror(errno));
		return -1;
	}

	if (!exiting)
	{
		err = read(st_fd, &install, 1);
		UIM_DBG("read %c from install \n", install);
		if (err > 0)
			st_uart_config(install);
		goto RE_POLL;
	}

	close(st_fd);
	return 0;
}
