/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2005-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 <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 <sys/time.h>
#include <sys/poll.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/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;
	/* Read reply. */
	FAILIF(read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0,
		   "Failed to read response");

	/* Parse speed-change reply */
	FAILIF(resp.uart_prefix != HCI_EVENT_PKT,
		   "Error in response: not an event packet, but 0x%02x!\n",
		   resp.uart_prefix);

	FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE, /* event must be event-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 != (uint16_t)opcode,
		   "Error in response: opcode is 0x%04x, not 0x%04x!",
		   resp.cmd_complete.opcode, opcode);

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

typedef struct {
	uint8_t uart_prefix;
	hci_command_hdr hci_hdr;
	uint32_t speed;
} __attribute__((packed)) texas_speed_change_cmd_t;

static int texas_change_speed(int fd, struct termios *ti, uint32_t speed)
{
        /* Send a speed-change request */
        texas_speed_change_cmd_t cmd;
        int n;

        cmd.uart_prefix = HCI_COMMAND_PKT;
        cmd.hci_hdr.opcode = 0xff36;
        cmd.hci_hdr.plen = sizeof(uint32_t);
        cmd.speed = speed;

        fprintf(stderr, "Setting speed to %d\n", speed);
        n = write(fd, &cmd, sizeof(cmd));
        if (n < 0) {
                perror("Failed to write speed-set command");
                return -1;
        }
        if (n < (int)sizeof(cmd)) {
                fprintf(stderr, "Wanted to write %d bytes, could only write %d. "
                "Stop\n", (int)sizeof(cmd), n);
                return -1;
        }
        /* Parse speed-change reply */
        if (read_command_complete(fd, cmd.hci_hdr.opcode, cmd.hci_hdr.plen) < 0) {
                return -1;
        }
        if (set_speed(fd, ti, speed) < 0) {
                perror("Can't set baud rate");
                return -1;
        }
        return 0;
}

static int texas_load_firmware(int fd, const char *firmware) {

	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);

		{
			int nw;
#if 0
			fprintf(stdout, "\topcode 0x%04x (%d bytes of data).\n",
					cmd->opcode,
					cmd->plen);
#endif
			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(cmd) +	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 texasalt_init(int fd, int speed, struct termios *ti)
{
	struct timespec tm = {0, 50000};
	char cmd[4];
	unsigned char resp[100];		/* Response */
	int n;

	memset(resp,'\0', 100);

	/* It is possible to get software version with manufacturer specific
	   HCI command HCI_VS_TI_Version_Number. But the only thing you get more
	   is if this is point-to-point or point-to-multipoint module */

	/* 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 < 0) {
			perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");
			return -1;
		}
		if (n < 4) {
			fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);
			return -1;
		}

		/* Read reply. */
		if (read_hci_event(fd, resp, 100) < 0) {
			perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");
			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) != 0x0d)
		fprintf(stderr,"WARNING : module's manufacturer is not Texas Instrument\n");

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

	/* Print LMP subversion */
	{
		unsigned short lmp_subv = resp[13] | (resp[14] << 8);
		unsigned short brf_chip = (lmp_subv & 0x7c00) >> 10;
		static const char *c_brf_chip[8] = {
			"unknown",
			"unknown",
			"brf6100",
			"brf6150",
			"brf6300",
			"brf6350",
			"unknown",
			"wl1271"
		};
		char fw[100];

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

		fprintf(stderr,
				"\tinternal version freeze: %d\n"
				"\tsoftware version: %d\n"
				"\tchip: %s (%d)\n",
				lmp_subv & 0x7f,
				((lmp_subv & 0x8000) >> (15-3)) | ((lmp_subv & 0x380) >> 7),
				((brf_chip > 7) ? "unknown" : c_brf_chip[brf_chip]),
				brf_chip);

		sprintf(fw, "/etc/firmware/%s.bin", c_brf_chip[brf_chip]);
		texas_change_speed(fd, ti, speed);
		texas_load_firmware(fd, fw);
	}
	nanosleep(&tm, NULL);
	return 0;
}
