/* Attempt to bring up and say hi to the BCM2045 bluetooth chip on the IPAQ214
*/

#define NOIO

#define MAX_PACKET_SIZE 1024

#define N_BT_GPIOS 6
int btio[] = 		{ 124, 114, 81, 84,  71, 53 };
int lastGPIOState[] = 	{ -2,   -2, -2, -2, -2, -2 };

//UART registers (for get/setUARTReg() of gpios.c)
#define		RBR	0	// receive
#define		THR	0	// transmit holding
#define 	IER	1	// int enable
#define		IIR	2	// int ident
#define		LCR	3	// line ctrl
#define		MCR	4	// modem ctrl
#define		LSR	5	// line state
#define		MSR	6	// modem state

#include <stdio.h>
#include "gpios.h"	

#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <stdarg.h>

void runBluez();

#ifndef NOIO
void dumpBTgpios(){
	int i;

	printf("state 1: ");
	for(i=0;i<N_BT_GPIOS;i++)
		printf("%i=%i ",btio[i],gpioGet(btio[i]));
	printf("\n");
	fflush(stdout);
}

void dumpUARTRegs(){
	int i;

	printf("UART: IER=%02x, IIR=%02x, LCR=%02x, MCR=%02x, LSR=%02x, MSR=%02x.\n",
		getUARTReg(IER),getUARTReg(IIR),getUARTReg(LCR),getUARTReg(MCR),getUARTReg(LSR),getUARTReg(MSR));
	fflush(stdout);
}

#else
void dumpUARTRegs(){};
void dumpUARTRegs(){
#endif

void setupSerialPort(int portFD, speed_t speed){
	struct termios options;
	
	tcgetattr(portFD, &options); //get current optinosa

	cfmakeraw(&options);
	
	cfsetispeed(&options, speed);
	cfsetospeed(&options, speed);	

	options.c_cflag |= (CLOCAL | CREAD); //enabled and local - err, yea
	
	options.c_cflag &= ~PARENB;	//no parity
	options.c_cflag &= ~CSTOPB;	//a stop bit
	options.c_cflag &= ~CSIZE;	//0 the character size bits
	options.c_cflag |= CS8;		//and select 8 data bits
	
	options.c_cflag |= CRTSCTS; //we DO want hardware flow control

	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);	//no local rubbish

	tcsetattr(portFD, TCSANOW, &options); //apply

	tcgetattr(portFD, &options); //get options backa again

}



int main(int argc, char **argv) {
	int portFD;
	int i,j,k;	
	unsigned char data[1024];
#ifndef NOIO
	gpioInit();
#endif
	printf("Init.\n");
	dumpUARTRegs();
	dumpBTgpios();	
	
	portFD = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

	if(portFD == -1){
		printf("No port descriptor, giving up\n");
		return 0;		
	}

	fcntl(portFD, F_SETFL, 0);

	printf("Setting port to 9600, LCR=");
	setupSerialPort(portFD,B9600); //once in 9600
	tcflush(portFD, TCIOFLUSH);  //go for a flush
	printf("%02x\n",getUARTReg(LCR));
	
	printf("Setting port to 115200, LCR=");	
	setupSerialPort(portFD,B115200); //and again in 115200
	tcflush(portFD, TCIOFLUSH); //why not another?
	printf("%02x\n",getUARTReg(LCR));
	
	//the pxa27x_uart driver doesn't seem to know about the auto-flow bits
	//so set them ourself
	setUARTReg(MCR, getUARTReg(MCR) | 0x00000022); //enable both CTS and RTS auto flow control
	
	dumpUARTRegs();
	
	printf("Setting all low ... "); fflush(stdout);
	gpioSet(81,0);
	gpioSet(3,0);
	gpioSet(53,0);
	gpioSet(71,0);
	gpioSet(124,0);
	gpioSet(114,0);
	printf("ok, now 5s sleep.\n"); fflush(stdout);

	tcflush(portFD, TCIOFLUSH); //flush buffers again

	
	sleep(5); //wait 1 sec
	
	dumpBTgpios();	
	dumpUARTRegs();

	printf("Bringing up 53,71 and 124\n"); fflush(stdout);
	gpioSet(53,1);
	gpioSet(71,1);
	gpioSet(124,1);
	//printf(" ok, now 6ms sleep.\n"); fflush(stdout);
	
	dumpBTgpios();
	//dumpUARTRegs();
	usleep(5000); //at least 5ms sleep
	
	gpioSet(114,1);		//raise 114
	//dumpBTgpios();		
	usleep(3000);		//wait 3ms	
	gpioSet(114,0);		//drop it again
	//dumpBTgpios();
	usleep(3000);		//wait 3ms
	gpioSet(81,1);		//raise 81 and 114
	gpioSet(114,1);

	dumpBTgpios();
	dumpUARTRegs();
	
	usleep(500000);		//wait 500ms

	doHCIComms();
	
	//runBluez();
		

	//ok, we're done, clear it all
	/*printf("Setting all low ... "); fflush(stdout);
	gpioSet(81,0);
	gpioSet(3,0);
	gpioSet(53,0);
	gpioSet(71,0);
	gpioSet(124,0);
	gpioSet(114,0);*/


#ifndef NOIO
	printf("LED: ");
	for(i=0;i<10;i++){
		gpioSet(3,1);
		usleep(100000);
		printf("%i ",gpioGet(3));
		gpioSet(3,0);
		usleep(100000);
		printf("%i ",gpioGet(3));
	}
	printf("\n");

	gpioCleanup();
#endif

	return 0;
}

void runBluez(){
	printf("Attach:\n");
	system("/usr/local/sbin/hciattach -p /dev/ttyS0 bcm2035 115200 flow");
	dumpUARTRegs();

	printf("config up:\n");
	system("/usr/local/sbin/hciconfig hci0 up");
	dumpUARTRegs();
}

int output(FILE *logFile, const char *fmt, ...){
	char *outStr[1024];

	va_list args;
	int r;

	//output to file and screen
	va_start(args, fmt);
	r = vfprintf(logFile, fmt, args);
	va_end(args);

	va_start(args, fmt);
	r = vprintf(fmt, args);
	va_end(args);

	return r;
}
	

/* open text file, read pcakets, send them and wait for responses and write back to ouput file */
void doHCIComms(){
	FILE *out,*in;
	int data[MAX_PACKET_SIZE];
	int i,ret;

	in=fopen("packets.txt","rt");
	out=fopen("bthello.log","wt");
	
	while(!feof(in)){
		//read 2xOpcode and 1xLength
		ret = fscanf("%x %x %x",&data[0],&data[1],&data[2]); 
		if(ret != 3){ sprintf(outStr,"
		
		


	}

	

	

	//attempt to transmit the reset code at it (and set RTS hopefully)
	data[0] = 0x01;
	data[1] = 0x03;
	data[2] = 0x0c;
	data[3] = 0x00;
	i = write(portFD, data, 4);

	printf("reset1: write returned %i\n",i);
		
	fcntl(portFD, F_SETFL, FNDELAY);
	dumpBTgpios();	
	dumpUARTRegs();
		
	printf("reset1: attempting read every 500ms...\n");
 	for(i=0;i<4;i++){
		j = read(portFD, data, 64);
		printf("reset1: read %i returned %i\n",i,j);
		if(j > 0){
			for(k=0;k<j;k++)
				printf("%02x ",data[k]);
			printf("\n");
		}

		dumpBTgpios();	
		dumpUARTRegs();
		usleep(1000000); //dump 3 lots of 
	}
	
	sleep(10); //and a long one



}




