/***************************************************************************
 *   Copyright (C) 2008 by Megawin Technology Co., Ltd.                    *
 *																																				 *
 *   Author : Thomas Liu                                                   *
 *   Version: USB2COM-V.0.1					                                       *
 *   Mail   : thomasliu@megawin.com.tw                                     *
 *     																																		 *
 *	 This code is based on the libcssl developed by                        *
 *	 Marcin Siennicki <m.siennicki@cloos.pl>				  										 *
 *		                                                                     *
 *   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.             *
 ***************************************************************************/
 
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gtk/gtk.h>
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "callbacks.h"
#include "interface.h"
#include "support.h"

#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>

#include "cssl.h"

#define PORTNAMELEN 20
#define PORTPATH	"/dev/"


int GetBaudRate   (GString rate);
gint BeforeWrite  (void);
gint BeforeRead   (void);
gint BeforeWriteRead(void);
void RunWrite     (Info info);
void RunRead	  (Info info);
void RunWriteRead (Info info, Info info2);

void *WriteThread (void *arg);
void *ReadThread  (void *arg);
void initialInfo(Info *info, gint method);

static void readcallback(int id,
						 uint8_t *buf,
	  					 int length
						);
//-------------------------------------------//

static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
static GByteArray *ReadArray;
GString *ReadString;
int callbackindex =0;
 static GMutex *mutex2;
 static GCond *cond2;
 static gboolean readComplete = 0;
//-------------------------------------------//

extern Trans DTransfer;


int msleep(unsigned long milisec)
{
	struct timespec req={0};
	time_t sec=(int)(milisec/1000);
	milisec=milisec-(sec*1000);
	req.tv_sec=sec;
	req.tv_nsec=milisec*1000000L;
	while(nanosleep(&req,&req)==-1)
		continue;
	return 1;
}

int getwritedelaytime(void)
{
	double ret=0.0;
	
	ret = (TRANSFERSIZE*10 * 1000 / DTransfer.baudrate);
	
	if ( ret <= 6.0 )
		return 6;
	
	return (int) ret;

}
int msleep2(unsigned long milisec)
{
	struct timespec req={0};
	
	req.tv_sec=0;
	req.tv_nsec=milisec*1000L;
	while(nanosleep(&req,&req)==-1)
		continue;
	return 1;
}

glong getwritedelaytime2(void)
{
	glong ret=0.0;
	
	
	ret = (TRANSFERSIZE * 1000 * 1000 / DTransfer.baudrate*20);

	if ( DTransfer.baudrate <= 9600 ){
		ret = ((TRANSFERSIZE * 1000 * 1000 / 9600 )*20);
	}
	
	return (glong) ret;
	
}
int msleep4 (){
	if ( DTransfer.baudrate >= 9600 )
		msleep2( getwritedelaytime2() /10);
	else
		msleep2( 5000 );
				
}
//---------------------------------------------------------//
/*
	Check parameters before Do Write function.
	Check:
			baudrate -- default 9600
			filename -- -1 no filename
			usbline	 -- -2 no usbline
			ttyline  -- -3 no ttyline

	return 0 as no problem
*/
gint BeforeWrite(void)
{
	// 
	// ttyS#  at least 5 characters
	gint ret = 0;
	gint len=0;
	
	if ( NULL == DTransfer.filename )
		ret = -1;
	
	len = strlen(DTransfer.usbline);
	if ( len < 5) ret = -2;
	
		
	return ret ;
}
void PrintInfo( Info info)
{
	printf("info.filename: %s\n", info.filename);
	printf("info.line : %s \n", info.line);
	printf("info.baudrate : %d\n", info.baudrate);
	printf("info.filesize: %d\n", info.filesize);
	
}
//---------------------------------------------------------//

void RunWrite(Info info)
{
	
	char portpath[20];
	int res;
	cssl_t *serial;	
		
	printf("create read thread now \n");
	cssl_start();
	
	sprintf(portpath, "%s%s",PORTPATH, info.line);
		
	printf("portpath is :%s \n", portpath);
	
	serial=cssl_open(	portpath,
						NULL,
						1, 
						info.baudrate,
						DTransfer.databit,
					    DTransfer.parity,
					    DTransfer.stopbit
					 );

	if (!serial) {
		printf("----- no serial\n");
		printf("%s\n in write",cssl_geterrormsg());
		return -1;
	}

	
	info.serial = serial;
		
	WriteThread( &info );
	
	cssl_close(serial);
	cssl_stop();
	
	MessageBox("write finished");
	
	
	
}
//---------------------------------------------------------//

void RunRead(Info info)
{
	gchar err[256];
	char portpath[20];
	int res;
	cssl_t *serial;		
	
	
	cssl_start();
	
	sprintf(portpath, "%s%s",PORTPATH, info.line);
		
	printf("portpath is :%s \n", portpath);
	
	serial=cssl_open(	portpath,
						readcallback,
						1, 
					    info.baudrate,
					   DTransfer.databit,
					    DTransfer.parity,
					    DTransfer.stopbit
					 );


	if (!serial) {
		printf("----- no serial\n");
		printf("%s\n in write",cssl_geterrormsg());
		return -1;
	}
	
	
	ReadArray = g_byte_array_sized_new (info.filesize);
	
	info.serial = serial;
	
	ReadThread( &info );
	
	cssl_close(info.serial);
	cssl_stop();
	
	guint *free_array;
	g_byte_array_remove_range  ( ReadArray,
								 0,
		 						ReadArray->len
							   );
 
	gboolean freearray= TRUE;
	free_array = g_byte_array_free( ReadArray, 
									freearray);
	
		
	MessageBox("Read finished");
	printf("------Run Read End ---\n");
	
	
}

//---------------------------------------------------------//
void RunWriteRead (Info info, Info info2 )
{
	GThread          *Thread1, *Thread2;
	GError           *err1 = NULL ;
	cssl_t *serial, *serial2;	
	char portpath[20];
	cssl_start();
	
	sprintf(portpath, "%s%s",PORTPATH, info.line);
		
	printf("portpath is :%s \n", portpath);
	
	serial=cssl_open(	portpath,
						readcallback,
						2, 
	 					 info.baudrate,
					   DTransfer.databit,
					    DTransfer.parity,
					    DTransfer.stopbit
					 );

	if (!serial) {
		printf("----- no serial\n");
		printf("%s\n in write",cssl_geterrormsg());
		return -1;
	}
	serial2=cssl_open(	portpath,
						NULL,
						2, 
					info.baudrate,
					DTransfer.databit,
					    DTransfer.parity,
					    DTransfer.stopbit
					 );

	if (!serial2) {
		printf("----- no serial\n");
		printf("%s\n in write",cssl_geterrormsg());
		return -1;
	}
	if( !g_thread_supported() )
	{
		g_thread_init(NULL);
		gdk_threads_init();                   // Called to initialize internal mutex "gdk_threads_mutex".
		printf("g_thread supported\n");
	}
	else
	{
		printf("g_thread NOT supported\n");
	}
	mutex2 =g_mutex_new();
	cond2 = g_cond_new();	
	
	printf("create read thread now \n");
	
	ReadArray = g_byte_array_sized_new (info2.filesize);
		
	info.serial = serial2; // write
	info2.serial = serial;// read
    	if( (Thread1 = g_thread_create((GThreadFunc)ReadThread, (void *)&info2, TRUE, &err1)) == NULL)
    	{
    		printf("\t Read Thread create failed: %s!!\n", err1->message );
    		g_error_free ( err1 ) ;
    	}
	

	if( (Thread2 = g_thread_create((GThreadFunc)WriteThread, (void *)&info, TRUE, &err1)) == NULL)
	{
		printf("\t Write Thread create failed: %s!!\n", err1->message );
		g_error_free ( err1 ) ;
	}	
	
//	ReadThread(&info2 );
	
	g_thread_join(Thread2);
	g_thread_join(Thread1);
	
	g_mutex_free( mutex2);
	g_cond_free (cond2 );
	guint *free_array;
	g_byte_array_remove_range  ( ReadArray,
								 0,
		 						ReadArray->len
							   );

	gboolean freearray= TRUE;
	free_array = g_byte_array_free( ReadArray, 
									freearray);
	cssl_close(serial);
	cssl_close(serial2);
	cssl_close(info.serial);
	cssl_close(info2.serial);
	//cssl_close(serial);
	cssl_stop();	
	printf("\t\t --------- RunWriteRead -------- Done \n");
	return;
}

//---------------------------------------------------------//

void *WriteThread( void *information )
{

	FILE *rfile;
	gchar *buffer=NULL;
	int readfilelen;
	int stop =0;
	int index=0;
	char err[256];
	int lastpacketsize;
	int lastpacket;
	Info	*info = (Info *) information;
	GTimeVal timer;
	
	printf("\n------beginning of Write Thread ------\n");
 	
	PrintInfo( *info);
	
	
	rfile = fopen( info->filename, "r"); 
	if ( rfile == NULL){
		perror("not able to open file to read ");
		goto WriteThread_err;
	}
	
	buffer = g_malloc( info->filesize );
	if ( buffer == NULL){
		perror("not able to allocate enough buffer");
		goto WriteThread_err;
	}
	bzero(buffer, info->filesize);
	
	readfilelen = fread ( buffer, 1,info->filesize, rfile);
	printf("fread() return %d \n", readfilelen);
	fclose(rfile);
	
	int last2=0;
	lastpacketsize = info->filesize % TRANSFERSIZE;
	if ( lastpacketsize == 0 ){
		last2 = info->filesize - TRANSFERSIZE;
	}
	
	lastpacket = info->filesize / TRANSFERSIZE;
	int byteleft = info->filesize-lastpacketsize;
	printf(" bytes left is %d \n", byteleft);
	printf("transferisze is : %d\n", TRANSFERSIZE);
			
	//------------//
	/*
		first write packet, this is for dual programs read/write together	
	*/
	if (DTransfer.method == WriteReadType){
		cssl_putdata(info->serial, buffer, TRANSFERSIZE);
		cssl_drain(info->serial);
		index +=TRANSFERSIZE;
		
		g_mutex_lock( mutex2);
 		timer.tv_sec = 0;
 		timer.tv_usec = getwritedelaytime2();
 		g_cond_timed_wait ( cond2,
 							mutex2,
 						   &timer
 						  );
 		g_mutex_unlock(mutex2);
		
	
	}
long i=0;
int input_bytes =0;
	//----------------------------------------------------------//
	while( !stop ) { // read 250 each time
	
		//------------------------------------------------//
		// lock
		if ( DTransfer.method == WriteReadType){
			g_mutex_lock( mutex2 );
			
			ioctl ( info->serial->fd, FIONREAD, &input_bytes );
			if ( input_bytes >0 ) {
			
				g_mutex_unlock( mutex2);
				raise(0);
				msleep4();
				continue;
		
			}
		}
		//------------------------------------------------//
		cssl_putdata(info->serial, buffer+index,TRANSFERSIZE );
		cssl_drain(info->serial);
		
		if ( DTransfer.method == WriteType ){
			cssl_drain(info->serial);
		
		}
		index +=TRANSFERSIZE;
	
		i++;
		if ( (i%1000)==0 )
			printf("index now is :%d \n", index );

		//------------------------------------------------//
		// unlock
		if ( DTransfer.method == WriteReadType){
					
			timer.tv_sec = 0;
			if ( ( i % 500) == 0 )
				timer.tv_usec = (getwritedelaytime2() )*2 ;
			else
				timer.tv_usec = getwritedelaytime2();
			if ( readComplete == 0 )
				g_cond_timed_wait ( cond2,
									mutex2,
									&timer
								  );
			g_mutex_unlock(mutex2);
			//msleep4();
		}

		//------------------------------------------------//
		
		// last packet
		if ( index == byteleft || ( index == last2) ){
			//------------------------------------------------//
			// lock
			if ( DTransfer.method == WriteReadType){
			
				g_mutex_lock ( mutex2 );
			}
			//------------------------------------------------//
			printf("last packet is : %d in write \n", lastpacketsize);
			printf(" index now is : %d , and last2 is : %d in write \n", index, last2 );
			
			if ( index == info->filesize) {
				if ( DTransfer.method == WriteReadType )
					g_mutex_unlock(mutex2);
				stop =1;
				break;
			}
			if ( index == last2 )
				cssl_putdata(info->serial, buffer+index, TRANSFERSIZE);
			else
				cssl_putdata(info->serial, buffer+index, lastpacketsize);
			
			cssl_drain(info->serial);
			
			if ( DTransfer.method == WriteType ){
				cssl_drain(info->serial);
				msleep(getwritedelaytime() );
			}
			
			//------------------------------------------------//
			// unlock
			if ( DTransfer.method == WriteReadType){
						
				timer.tv_sec = 0;
				timer.tv_usec = getwritedelaytime2()*2;
				g_cond_timed_wait ( cond2,
									mutex2,
		 							&timer
								  );
				g_mutex_unlock(mutex2);
				
			}
			//------------------------------------------------//
			
			stop = 1;
			break;
		}// if
		
		while( gtk_events_pending())
			gtk_main_iteration();
	}//while
	
		
WriteThread_err:

	if ( DTransfer.method == WriteReadType )
		printf("ReadArray->len is %d by WriteThread  \n", ReadArray->len );
	g_free(buffer);
	buffer = NULL;
	readComplete =0;
	tcflush(info->serial->fd,TCOFLUSH);
	printf("--------write thread end -----------\n");
	
	if (DTransfer.method == WriteReadType )
		g_thread_exit(0);
	
			
	
}
static void handle_error( GError *error)
{
	if ( error != NULL)
	{
		g_printf(error->message);
		g_clear_error(&error);	
		
	}
	
}

static void readcallback(int id,
					      uint8_t *buf,
	  			     	int length)
{ 
	static int i=0;
	
  	g_byte_array_append(ReadArray, 
 						(guint8 *)buf,
 						length
 						);
				
				
				
	
	i++;
	if ((i % 1000) == 0 ){
			printf("\t\t ReadArrya now has : %d \n", ReadArray->len);
	}
	if ( ReadArray->len >= DTransfer.filesize ){
		readComplete = 1;
		
	}
								 
}


void *ReadThread( void *information )
{
	int fd;
	
	int stop =0;
	int readLen=0;
	int packetsize=0;
	int bytesleft=0;
	int index=0;
	Info *info = (Info *) information;
	gchar *rBuffer=NULL;
	FILE *fdsave;
	GError *error=NULL;
	GIOChannel *writefile;
	
	
	printf("\t\t ------beginning of Read Thread------\n");
	PrintInfo(*info);
		
	printf("\t going to allocate %d in read \n", info->filesize);
	
	
		
	bytesleft = info->filesize % TRANSFERSIZE;
	int endingsize = info->filesize - bytesleft;
	readLen=0;
	packetsize=0;
	readComplete = 0;
	while(!stop){
       
 	  	if ( ReadArray->len >= info->filesize){
 			stop =1;
 			break;
 		}
		
		while( gtk_events_pending())
			gtk_main_iteration();
		
		
	}// while
	
	printf("\t reading %d and now is :%d after while\n", readLen,packetsize);
	
	printf("\t finished in %s \n", info->line);
	printf("\t file name is :%s \n", info->filename);
 	
	int i;
	
	
	gsize bytewritten;
	
	writefile = g_io_channel_new_file(	info->filename, 
										"w+",
		  								&error);
	if ( writefile == NULL){
		perror("fail to create new io channel");
		g_free(rBuffer);
		pthread_exit(0);
	}
	
 	g_io_channel_write( writefile, 
 						ReadArray->data, 
 	  					ReadArray->len, 
 						&bytewritten);

						
	printf("bytes written is :%d\n", bytewritten);
	g_io_channel_flush(	writefile, 
						&error);
	handle_error(error);
	g_io_channel_close(writefile);
	
	tcflush(info->serial->fd,TCIFLUSH);
	printf("\t\t ------- End Read Thread ------\n");
	
//  	if ( DTransfer.method == WriteReadType )
//  	g_thread_exit(0);
	
	

}


//---------------------------------------------------------//
/*
	Check parameters before Do Write function.
	Check:
			baudrate -- default 9600
			filename -- -1 no filename
			usbline	 -- -2 no usbline
			
			
			ttyline  -- -3 no ttyline

	return 0 as no problem
*/
gint BeforeRead(void)
{
	gint ret = 0;
	gint len=0;
	
	len = strlen(DTransfer.usbline);
	if ( len < 5) ret = -3;
	
	if ( NULL == DTransfer.filename )
		ret = -1;
	
	
	return ret;
}

//---------------------------------------------------------//
/*
	Check parameters before Do Write function.
	Check:
			baudrate -- default 9600
			filename -- -1 no filename
			filename2 -- -2 no filename2
			usbline	 -- -3 no usbline
			ttyline  -- -4 no ttyline

	return 0 as no problem
*/
gint BeforeWriteRead(void)
{
	gint ret = 0;
	gint len=0;
	
	
	if ( NULL == DTransfer.filename2)
		ret = -1;
	
	if ( NULL == DTransfer.filename )
		ret = -2;
	
	len = strlen(DTransfer.usbline);
	if ( len < 5) ret = -3;
	
	
	
	return ret;
}
//---------------------------------------------------------//
/*
	initialInfo construct the transfer information
	before passing the arguments to thread
	
	method:
		0: WriteRead_Read
		1: WriteRead_Write
		-1: Write, Read

*/
void initialInfo(Info *info, gint method)
{
	gchar err[256];
	struct stat file_status;
	
	if ( DTransfer.method != ReadType){
		
		if(stat(DTransfer.filename, &file_status) != 0){
			g_sprintf(err,"could not stat %s size", DTransfer.filename);
			perror(err);
			return;
		}
		
		DTransfer.filesize = file_status.st_size;
		
		
	}
	info->filesize = DTransfer.filesize;
	
	if ( DTransfer.method == WriteType){
		info->line = g_strdup( DTransfer.usbline);
		info->filename = g_strdup( DTransfer.filename);
	}
	else if ( DTransfer.method == ReadType){
		info->line = g_strdup( DTransfer.usbline);
		info->filename = g_strdup( DTransfer.filename);
	}
	else{
		GString tname;
		tname.str = g_strdup(DTransfer.filename);
		
		// info	
		// WriteRead_Read section, usb read
		if ( method == 0){
			info->line = g_strdup( DTransfer.usbline);
			info->filename = g_strdup( DTransfer.filename);
			
		}
		else if (method == 1){  // WriteRead_write, usb write
			info->line = g_strdup( DTransfer.usbline);
			info->filename = g_strdup( DTransfer.filename2);
		}
	}
	info->baudrate = DTransfer.baudrate;
	
	printf("--- Setting ---\n");
	printf(" databit is : %d \n", DTransfer.databit );
	printf(" stopbit is : %d \n", DTransfer.stopbit );
	printf(" parity  is : %d \n", DTransfer.parity );
	
	
}
//---------------------------------------------------------//

void
on_btn_Write_clicked                   (GtkButton       *button,
                                        gpointer         user_data)
{
	gchar out[256];
	Info info, info2;
	GtkWidget *entryStart, *entryEnd;
	gchar timestr[6];
	gchar timestr2[5];
	entryStart = lookup_widget( GTK_WIDGET(button), "lbl_WriteStartTime");	
	entryEnd = lookup_widget( GTK_WIDGET(button), "lbl_WriteEndTime");	
	
	gtk_label_set_text( GTK_LABEL(entryStart), "0");
	gtk_label_set_text( GTK_LABEL(entryEnd), "0");
	GTimer *writetime;
	gint ok_before_write;
	DTransfer.method = WriteType;
	
	ok_before_write = BeforeWrite();
	switch (ok_before_write)
	{
		
		case -1:
			g_sprintf(out,"fail: %s", "no file name");
			MessageBox(out);
			break;
		case -2:
			g_sprintf(out,"fail: %s", "no usbline ");
			MessageBox(out);
			break;
		case -3:
			g_sprintf(out,"fail: %s", "no ttyline");
			MessageBox(out);
			break;
		
		
		
	}
	if ( 0 != ok_before_write) return;
	while( gtk_events_pending())
		gtk_main_iteration();
		/* record start time     */
		
		
		initialInfo( &info ,-1);
		
		writetime =g_timer_new();
		
		RunWrite( info);
		
		/*  record end time      */
		g_timer_stop(writetime);
		gdouble timeelapsed;
		gulong timefriction;
		timeelapsed = g_timer_elapsed(writetime, &timefriction);
		msleep(1);
		gtk_label_set_text( GTK_LABEL(entryStart), g_ascii_dtostr(timestr, 6, timeelapsed));
		gtk_label_set_text( GTK_LABEL(entryEnd), g_ascii_dtostr(timestr2, 5, timefriction));
				
		printf("---- btn_Write_cliecked END ---\n");
		while( gtk_events_pending())
			gtk_main_iteration();
	
		g_timer_destroy(writetime);

	
}

//---------------------------------------------------------//
void
on_bnt_Read_clicked (GtkButton       *button,
                     gpointer         user_data)
{
	gchar out[256];
	gint ok_before_read;
	Info info;
	GtkWidget *entryStart, *entryEnd, *entryfilename,*entrysize;
	gchar *filesizestr;
	long filesize;
	gchar *endptr;
	GTimer *writetime;
	gchar timestr[6];
	gchar timestr2[5];
	entryStart = lookup_widget( GTK_WIDGET(button), "lbl_ReadStartTime");	
	entryEnd = lookup_widget( GTK_WIDGET(button), "lbl_ReadEndTime");	
	entryfilename = lookup_widget( GTK_WIDGET(button), "txt_ReadFile");	
	gtk_label_set_text( GTK_LABEL(entryStart), "0");
	gtk_label_set_text( GTK_LABEL(entryEnd), "0");		
	entrysize = lookup_widget( GTK_WIDGET(button), "txt_ReadSize");	
	filesizestr = g_strdup( gtk_entry_get_text(entrysize)); 
	
	if ( strlen( gtk_entry_get_text( entryfilename)) > 0 ) 
		DTransfer.filename =  g_strdup (gtk_entry_get_text(entryfilename));
	else
		DTransfer.filename = NULL;
	
	filesize = strtol( filesizestr, &endptr, 10);
	printf("file is %s \n", DTransfer.filename);
	printf(" filesize is : %d\n", filesize);
	
    DTransfer.filesize = filesize;
	
	DTransfer.method = ReadType;
	ok_before_read = BeforeRead();
	
	switch (ok_before_read)
	{
		
		case -1:
			g_sprintf(out,"fail: %s", "no file name");
			MessageBox(out);
			break;
		case -2:
			g_sprintf(out,"fail: %s", "no usbline ");
			MessageBox(out);
			break;
		case -3:
			g_sprintf(out,"fail: %s", "no ttyline");
			MessageBox(out);
			break;
		
		
		
	}
	if ( ok_before_read != 0 ) return;
	while( gtk_events_pending())
		gtk_main_iteration();
		
		
	initialInfo( &info, -1);
		
	writetime=g_timer_new();
		
	RunRead(info);
		
	g_timer_stop(writetime);
	gdouble timeelapsed;
	gulong timefriction;
	timeelapsed = g_timer_elapsed(writetime, &timefriction);
	msleep(1);	
	gtk_label_set_text( GTK_LABEL(entryStart), g_ascii_dtostr(timestr, 6,timeelapsed ));
	gtk_label_set_text( GTK_LABEL(entryEnd), g_ascii_dtostr(timestr2, 5,timefriction ));
		
	while( gtk_events_pending())
		gtk_main_iteration();

	
	g_timer_destroy(writetime);
	
}

//---------------------------------------------------------//

void
on_window1_destroy                     (GtkObject       *object,
                                        gpointer         user_data)
{
	if ( NULL != DTransfer.filename)
		g_free( DTransfer.filename);
	if ( NULL != DTransfer.filename2)
		g_free( DTransfer.filename2);
	
		
	gtk_main_quit();
}
//---------------------------------------------------------//

void
on_btn_WriteRead_clicked               (GtkButton       *button,
                                        gpointer         user_data)
{
	gchar out[256];
	gint ok_before_writeread;
	Info info,  info_1 ;
	GtkWidget *entryStart, *entryEnd, *entryfilename,*entrysize;
	gint ret;
	gchar timestr[7];
	gchar timestr2[6];
	gchar *filesizestr;
	long filesize;
	gchar *endptr;
	GTimer *writetime;
	
	entryStart = lookup_widget( GTK_WIDGET(button), "lbl_WriteRead_StartTime");	
	entryEnd = lookup_widget( GTK_WIDGET(button), "lbl_WriteRead_EndTime");	
	entryfilename = lookup_widget( GTK_WIDGET(button), "txt_WriteRead_Read");	
	entrysize = lookup_widget( GTK_WIDGET(button), "txt_WriteRead_ReadSize");	
	filesizestr = gtk_entry_get_text(entrysize); 
	gtk_label_set_text( GTK_LABEL(entryStart), "0");
	gtk_label_set_text( GTK_LABEL(entryEnd), "0");
	
	if ( strlen( gtk_entry_get_text( entryfilename)) > 0 ) 
		DTransfer.filename2 =  g_strdup (gtk_entry_get_text(entryfilename));
	else
		DTransfer.filename2 = NULL;
	
	filesize = strtol( filesizestr, &endptr, 10);
	printf("file is %s \n", DTransfer.filename2);
	printf(" filesize is : %d\n", filesize);
	
	DTransfer.filesize2 = filesize;
	DTransfer.method = WriteReadType;
	
	
	
	ok_before_writeread = BeforeWriteRead();
	switch (ok_before_writeread)
	{
		
		case -1:
			g_sprintf(out,"fail: %s", "no Read File name");
			MessageBox(out);
			break;
		case -2:
			g_sprintf(out,"fail: %s", "no Write File name ");
			MessageBox(out);
			break;
		case -3:
			g_sprintf(out,"fail: %s", "no usbline");
			MessageBox(out);
			break;
		
		case -4:
			g_sprintf(out,"fail: %s", "no ttyline");
			MessageBox(out);
			break;
		
	}
	if ( 0 != ok_before_writeread) return;
	while( gtk_events_pending())
		gtk_main_iteration();
	
	initialInfo( &info, 0);
	initialInfo ( &info_1, 1);
	writetime =g_timer_new();
		
		
	RunWriteRead( info, info_1);
	
	g_timer_stop(writetime);
	gdouble timeelapsed;
	gulong timefriction;
	timeelapsed = g_timer_elapsed(writetime, &timefriction);
	msleep(1);
	gtk_label_set_text( GTK_LABEL(entryStart), g_ascii_dtostr(timestr, 7,timeelapsed ));
	gtk_label_set_text( GTK_LABEL(entryEnd), g_ascii_dtostr(timestr2, 6,timefriction ));
	while( gtk_events_pending())
		gtk_main_iteration();	
	
	g_timer_destroy(writetime);
	g_free ( info.filename );
	g_free ( info.line );
	g_free ( info_1.filename );
	g_free ( info_1.line );

}

//---------------------------------------------------------//
void
on_chk_LoopBack_toggled                (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{

}

//---------------------------------------------------------//
void
on_combobox1_changed                   (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
	
	GString rate;
	
	rate.str = gtk_combo_box_get_active_text  (combobox);
	DTransfer.baudrate = GetBaudRate(rate);
	
}
void
on_cbo_Parity_changed                  (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
	GString parity;
	
	parity.str = gtk_combo_box_get_active_text  (combobox);
	DTransfer.parity = GetParity(parity);
	//MessageBox(parity.str);
}


void
on_cbo_StopBit_changed                 (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
	GString stop;
	
	stop.str = gtk_combo_box_get_active_text  (combobox);
	DTransfer.stopbit = GetStopBit(stop);
	//MessageBox (stop.str );
}


void
on_cbo_DataBit_changed                 (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
	GString data;
	
	data.str = gtk_combo_box_get_active_text  (combobox);
	DTransfer.databit = GetDataBit(data);
	//MessageBox(data.str);
}

//---------------------------------------------------------//

void
on_cbo_UsbTty_changed   (GtkComboBox     *combobox,
							gpointer         user_data)
{
	GString portstr;
		
	portstr.str = gtk_combo_box_get_active_text  (combobox);
	g_strlcpy(DTransfer.usbline, portstr.str, PORTNAMELEN);
	
}

//---------------------------------------------------------//
void
on_cbo_Tty_changed  (GtkComboBox     *combobox,
					 gpointer         user_data)
{
	GString portstr;
	
	portstr.str = gtk_combo_box_get_active_text  (combobox);
	g_strlcpy(DTransfer.ttyline, portstr.str, PORTNAMELEN);
	
		
}


	
//---------------------------------------------------------//

void on_btn_WriteOpen_clicked (GtkButton       *button,
								gpointer         win)
{
	GtkWidget *dialog;
	GtkWidget *entry, *entry2;
	struct stat file_status;
	gchar err[256];
	gdouble filesize;
	gchar sizestr[10];
	
	entry = lookup_widget( GTK_WIDGET(button), "txt_FileName");
	entry2 = lookup_widget( GTK_WIDGET(button), "txt_WriteSize");
	dialog = gtk_file_chooser_dialog_new ("Open File",
										  (GtkWindow *)win,
										  GTK_FILE_CHOOSER_ACTION_OPEN,
										  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
										  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
										  NULL);

	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
	{
		if ( DTransfer.filename != NULL)
			g_free(DTransfer.filename);
		DTransfer.filename = NULL;
		DTransfer.filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		gtk_entry_set_text( GTK_ENTRY(entry), DTransfer.filename);
		
		
		if(stat(DTransfer.filename, &file_status) != 0){
			g_sprintf(err,"could not stat %s size", DTransfer.filename);
			perror(err);
			return;
		}
	
		filesize = file_status.st_size;
		
		
		gtk_entry_set_text( GTK_ENTRY(entry2), g_ascii_dtostr(sizestr, 10, filesize));
	}

	gtk_widget_destroy (dialog);
}



//---------------------------------------------------------//
void on_btn_WriteRead_WriteOpen_clicked(GtkButton       *button,
										GtkWindow *         win)
{
	GtkWidget *dialog;
	GtkWidget *entry, *entrysize;
	gdouble filesize;
	gchar sizestr[10];
	struct stat file_status;
	gchar err[256];
	
	entry = lookup_widget( GTK_WIDGET(button), "txt_WriteRead_Write");
	entrysize = lookup_widget( GTK_WIDGET(button), "txt_WriteRead_ReadSize");

	dialog = gtk_file_chooser_dialog_new ("Open File",
										//(GtkWindow *)win,
										  win,
			GTK_FILE_CHOOSER_ACTION_OPEN,
   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
   NULL);
	
	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
	{
		if ( DTransfer.filename != NULL)
			g_free(DTransfer.filename);	
		DTransfer.filename = NULL;
		DTransfer.filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		gtk_entry_set_text( GTK_ENTRY(entry), DTransfer.filename);
		
		if(stat(DTransfer.filename, &file_status) != 0){
			g_sprintf(err,"could not stat %s size", DTransfer.filename);
			perror(err);
			return;
		}
	
		filesize = file_status.st_size;
		
		gtk_entry_set_text( GTK_ENTRY(entrysize), g_ascii_dtostr(sizestr, 10, filesize));
		
	}

	gtk_widget_destroy (dialog);
	
	
	
}

//---------------------------------------------------------//
void on_btn_ReadOpen_clicked(GtkButton       *button,
							 gpointer         win)
{
	GtkWidget *dialog;
	GtkWidget *entry;

	entry = lookup_widget( GTK_WIDGET(button), "txt_ReadFile");
	
	dialog = gtk_file_chooser_dialog_new ("Open File",
										(GtkWindow *)win,
										GTK_FILE_CHOOSER_ACTION_OPEN,
										GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 										GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
										NULL);

	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
	{
		if ( DTransfer.filename != NULL)
			g_free(DTransfer.filename);
		DTransfer.filename = NULL;
		DTransfer.filename= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		gtk_entry_set_text( GTK_ENTRY(entry), DTransfer.filename);
		
		
		
	}

	gtk_widget_destroy (dialog);
}

//---------------------------------------------------------//
int GetBaudRate( GString rate)
{
	if ( 0 == g_strcasecmp( rate.str, "1200"))
		return 1200;
	
	if ( 0 == g_strcasecmp( rate.str, "2400"))
		return 2400;
	
	if ( 0 == g_strcasecmp( rate.str, "4800"))
		return 4800;
	
	if ( 0 == g_strcasecmp( rate.str, "9600"))
		return 9600;
	
	if ( 0 == g_strcasecmp( rate.str, "19200"))
		return 19200;
	
	if ( 0 == g_strcasecmp( rate.str, "38400"))
		return 38400;
	
	if ( 0 == g_strcasecmp( rate.str, "57600"))
		return 57600;
	
	if ( 0 == g_strcasecmp( rate.str, "115200"))
		return 115200;
	
	
	
}
//----------------------------------------------------------//
gint GetDataBit ( GString databit )
{
	if ( 0 == g_strcasecmp( databit.str, "8"))
		return 8;
	
	
}

//----------------------------------------------------------//
gint GetStopBit ( GString stopbit )
{
	
	if ( 0 == g_strcasecmp( stopbit.str, "1"))
		return 1;
	
	if ( 0 == g_strcasecmp( stopbit.str, "2"))
		return 2;
	
}
//----------------------------------------------------------//
gint GetParity ( GString parity )
{
	
	if ( 0 == g_strcasecmp( parity.str, "None"))
		return 0;
	
	if ( 0 == g_strcasecmp( parity.str, "Odd"))
		return 1;
	
	if ( 0 == g_strcasecmp( parity.str, "Even"))
		return 2;
	
	
}
//---------------------------------------------------------//
/*
	when switch page, clear the DTransfer data structure

*/
void
on_notebook1_switch_page               (GtkNotebook     *notebook,
                                        GtkNotebookPage *page,
                                        guint            page_num,
                                        gpointer         user_data)
{
	GtkWidget *entry;
	switch ( page_num)
	{
		case 0:
			entry = lookup_widget( GTK_WIDGET(notebook), "txt_FileName");
			//gtk_entry_set_text(entry, "this is write");
				
			break;
			
		case 1:
			entry = lookup_widget( GTK_WIDGET(notebook), "txt_ReadFile");
			//gtk_entry_set_text(entry, "this is Read");
			
			break;
		case 2:
			entry = lookup_widget( GTK_WIDGET(notebook), "txt_WriteRead_Read");
			//gtk_entry_set_text(entry, "this is writeread read");
			
			break;
		
	}
	
}


void
on_txt_WriteSize_changed               (GtkEditable     *editable,
                                        gpointer         user_data)
{

}


void
on_txt_ReadSize_changed                (GtkEditable     *editable,
                                        gpointer         user_data)
{

}

