/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2005-2010  Marcel Holtmann <marcel@holtmann.org>
 *  Copyright (c) 2010, Code Aurora Forum. All rights reserved.
 *
 *
 *  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 <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <termios.h>
#include <time.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/uio.h>

#include "lib/bluetooth.h"
#include "lib/hci.h"
#include "lib/hci_lib.h"

#include "hciattach.h"

#define FAILIF(x, args...) do { \
	if (x) { \
		fprintf(stderr, ##args); \
		return -1; \
	} \
} while (0)

typedef struct {
	uint8_t uart_prefix;
	hci_event_hdr hci_hdr;
	evt_cmd_complete cmd_complete;
	uint8_t status;
	uint8_t data[16];
} __attribute__((packed)) command_complete_t;

static int read_command_complete(int fd,
					unsigned short opcode,
					unsigned char len)
{
	command_complete_t resp;
	unsigned char vsevent[512];
	int n;

	/* Read reply. */
	n = read_hci_event(fd, vsevent, sizeof(vsevent));
	FAILIF(n < 0, "Failed to read response");

	FAILIF(vsevent[1] != 0xFF, "Failed to read response");

	n = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
	FAILIF(n < 0, "Failed to read response");

	/* event must be event-complete */
	FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE,
		"Error in response: not a cmd-complete event, "
		"but 0x%02x!\n", resp.hci_hdr.evt);

	FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */
		"Error in response: plen is not >= 4, but 0x%02x!\n",
		resp.hci_hdr.plen);

	/* cmd-complete event: opcode */
	FAILIF(resp.cmd_complete.opcode != 0,
		"Error in response: opcode is 0x%04x, not 0!",
		resp.cmd_complete.opcode);

	return resp.status == 0 ? 0 : -1;
}

static int qualcomm_load_firmware(int fd, const char *firmware, const char *bdaddr_s)
{

	int fw = open(firmware, O_RDONLY);

	fprintf(stdout, "Opening firmware file: %s\n", firmware);

	FAILIF(fw < 0,
		"Could not open firmware file %s: %s (%d).\n",
		firmware, strerror(errno), errno);

	fprintf(stdout, "Uploading firmware...\n");
	do {
		/* Read each command and wait for a response. */
		unsigned char data[1024];
		unsigned char cmdp[1 + sizeof(hci_command_hdr)];
		hci_command_hdr *cmd = (hci_command_hdr *) (cmdp + 1);
		int nr;

		nr = read(fw, cmdp, sizeof(cmdp));
		if (!nr)
			break;

		FAILIF(nr != sizeof(cmdp),
			"Could not read H4 + HCI header!\n");
		FAILIF(*cmdp != HCI_COMMAND_PKT,
			"Command is not an H4 command packet!\n");

		FAILIF(read(fw, data, cmd->plen) != cmd->plen,
				"Could not read %d bytes of data \
				for command with opcode %04x!\n",
				cmd->plen, cmd->opcode);

		if ((data[0] == 1) && (data[1] == 2) && (data[2] == 6)) {
			bdaddr_t bdaddr;
			if (bdaddr_s != NULL) {
				str2ba(bdaddr_s, &bdaddr);
				memcpy(&data[3], &bdaddr, sizeof(bdaddr_t));
			}
		}

		{
			int nw;
			struct iovec iov_cmd[2];
			iov_cmd[0].iov_base = cmdp;
			iov_cmd[0].iov_len = sizeof(cmdp);
			iov_cmd[1].iov_base = data;
			iov_cmd[1].iov_len = cmd->plen;
			nw = writev(fd, iov_cmd, 2);
			FAILIF(nw != (int) sizeof(cmdp) + cmd->plen,
				"Could not send entire command \
				(sent only %d bytes)!\n",
				nw);
		}

		/* Wait for response */
		if (read_command_complete(fd, cmd->opcode, cmd->plen) < 0)
			return -1;
	} while (1);
	fprintf(stdout, "Firmware upload successful.\n");

	close(fw);

	return 0;
}

int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr)
{
	struct timespec tm = {0, 50000};
	char cmd[5];
	unsigned char resp[100];		/* Response */
	char fw[100];
	int n;

	memset(resp, 0, 100);

	/* Get Manufacturer and LMP version */
	cmd[0] = HCI_COMMAND_PKT;
	cmd[1] = 0x01;
	cmd[2] = 0x10;
	cmd[3] = 0x00;

	do {
		n = write(fd, cmd, 4);
		if (n < 4) {
			perror("Failed to write init command");
			return -1;
		}

		/* Read reply. */
		if (read_hci_event(fd, resp, 100) < 0) {
			perror("Failed to read init response");
			return -1;
		}

		/* Wait for command complete event for our Opcode */
	} while (resp[4] != cmd[1] && resp[5] != cmd[2]);

	/* Verify manufacturer */
	if ((resp[11] & 0xFF) != 0x1d)
		fprintf(stderr,
			"WARNING : module's manufacturer is not Qualcomm\n");

	/* Print LMP version */
	fprintf(stderr,
		"Qualcomm module LMP version : 0x%02x\n", resp[10] & 0xFF);

	/* Print LMP subversion */
	{
		unsigned short lmp_subv = resp[13] | (resp[14] << 8);

		fprintf(stderr, "Qualcomm module LMP sub-version : 0x%04x\n",
								lmp_subv);
	}

	/* Get SoC type */
	cmd[0] = HCI_COMMAND_PKT;
	cmd[1] = 0x00;
	cmd[2] = 0xFC;
	cmd[3] = 0x01;
	cmd[4] = 0x06;

	do {
		n = write(fd, cmd, 5);
		if (n < 5) {
			perror("Failed to write vendor init command");
			return -1;
		}

		/* Read reply. */
		if ((n = read_hci_event(fd, resp, 100)) < 0) {
			perror("Failed to read vendor init response");
			return -1;
		}

	} while (resp[3] != 0 && resp[4] != 2);

	snprintf(fw, sizeof(fw), "/etc/firmware/%c%c%c%c%c%c_%c%c%c%c.bin",
				resp[18], resp[19], resp[20], resp[21],
				resp[22], resp[23],
				resp[32], resp[33], resp[34], resp[35]);

	/* Wait for command complete event for our Opcode */
	if (read_hci_event(fd, resp, 100) < 0) {
		perror("Failed to read init response");
		return -1;
	}

	qualcomm_load_firmware(fd, fw, bdaddr);

	/* Reset */
	cmd[0] = HCI_COMMAND_PKT;
	cmd[1] = 0x03;
	cmd[2] = 0x0C;
	cmd[3] = 0x00;

	do {
		n = write(fd, cmd, 4);
		if (n < 4) {
			perror("Failed to write reset command");
			return -1;
		}

		/* Read reply. */
		if ((n = read_hci_event(fd, resp, 100)) < 0) {
			perror("Failed to read reset response");
			return -1;
		}

	} while (resp[4] != cmd[1] && resp[5] != cmd[2]);

	nanosleep(&tm, NULL);

	return 0;
}
