/***************************************************************************
 *   Copyright (C) 2008 by Megawin Technology Co., Ltd. *
 *														*
 *   Author : Thomas Liu     *
 *   Version: V.01  *
 *   Mail   : thomasliu@megawin.com.tw  *
 *     									*
 *   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 <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>

#define DEVICEPATH   "/dev"
#define COMNUMBER    "ttyS%d"
#define COMNAME      "ttyS"
#define RULESNAME    "mwusb2com.rules"
#define PROGRAMNAME  "Install-MwRules"
#define RULESPATH    "/etc/udev/rules.d"
#define PROGRAMPATH	 "/bin"

int GetLastComNumber( void );
void WriteRulesFile( void);
void CopyFile(void);
void RmTmpFile(void);

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

int GetLastComNumber(void)
{
	int comlist[64]={0};
	int i;
	DIR * dp;
	struct dirent *filename;
	char tmpName[6];

	dp = opendir(DEVICEPATH);
	if (!dp)
	{
		fprintf(stderr,"open directory error\n");
		return 0;
	}
	while (filename=readdir(dp)) // read file name
	{
		
		// is it ttyS#
		if ( 0 == strncmp( filename->d_name,
					COMNAME,
	 				4 )){
			// identify the ttyS# number
			int len;
			len = strlen ( filename->d_name);
			// ttyS#
			if ( len == 5 ){
		
				int num=0;
				num = atoi(filename->d_name+4);
		
				comlist[num] = 1;
				
			}
			// ttyS##
			if ( len == 6){
		
				int num=0;
				num = atoi(filename->d_name+4);
		
				if ( num <= 63)
					comlist[num] = 1;
			}
			
			
							
		}// if
	}
	closedir(dp);
	for ( i=0; i < 64; i++)
	{
		if ( comlist[i] != 1 )
			return i;
	}
	return 64;
	
	
}

int CheckDir(char *dir)
{
	int comlist[64]={0};
	int i;
	DIR * dp;
	struct dirent *filename;
	char tmpName[6];

	dp = opendir(dir);
	if (!dp)
	{
		fprintf(stderr,"open directory error: %s\n", dir);
		return -1;
	}
	while (filename=readdir(dp)) // read file name
	{
		
		// find /bin/Install-MwRules ?
		if ( 0 == strncmp( filename->d_name,
			 				PROGRAMNAME,
							15 )){
		
			closedir(dp);
			//printf("find file in %s \n", dir );
			return 1;
		}// if
		
		if ( 0 == strncmp( filename->d_name,
			 				RULESNAME,
							15 )){
		
		closedir(dp);
		//printf("find file in %s \n", dir );
		return 1;
		}// if
		
	}
	closedir(dp);
	return 0;
	
	
	
}

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

void WriteRulesFile( void )
{
	FILE *out;
	out = fopen( RULESNAME, "w");
	char lastCom[6];
	char rules[256];
	char fileHeader[]={"#*****************************************************************************\n"
					   "# \n"
					   "# Module Name:  mwusb2com rules \n"
					   "#\n"
					   "# Function: \n"
					   "#	udev rules for Megawin USB Virtual COM device \n"
					   "#\n"
					   "# Version:\n"
					   "#	0.0.0.1\n"
					   "#\n"
					   "# Copyright (c) 1999-2008 Megawin Technology Co., Ltd.\n"
					   "#\n"
					   "#\n"
					   "#\n"
					   "#\n"
					   "#*****************************************************************************\n\n" };
					   
	fwrite( fileHeader, sizeof(char), strlen(fileHeader), out);
	
	//PROGRAM="/etc/udev/Install-MwRules", SYMLINK+="%c"
	
	sprintf(rules,"KERNEL==\"ttyACM[0-64]*\",PROGRAM=\"/bin/Install-MwRules\",SUBSYSTEM==\"tty\",SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"0e6a\""
			", ATTRS{idProduct}==\"0316\", MODE=\"666\",  SYMLINK+=\"%%c\"");
	
	fwrite( rules, 1, strlen(rules), out);
			
			
	fclose(out);
	
						
	
	
}
//-----------------------------------------------//

void CopyFile(void)
{
	char cmd[50];
	
	// copy program
	sprintf(cmd, "cp %s %s", PROGRAMNAME, PROGRAMPATH);
	system(cmd);
	
	bzero ( cmd, 50 );
	// copy rules to /etc/udev/rules.d
	sprintf(cmd, "cp %s %s", RULESNAME, RULESPATH);
	system(cmd);
	
}
//-----------------------------------------------//

void RmTmpFile(void)
{
	
	char cmd[50];
	sprintf(cmd, "rm %s", RULESNAME);
	system(cmd);	
	
}

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

int CheckApRules(void )
{
	int ret=0, ret2 = 0;
	
	// "/bin"
	ret = CheckDir( PROGRAMPATH );
	ret2 = CheckDir( RULESPATH );
	
	if ( (ret == 1) && (ret2 == 1) ) // both place has our file
		return 0;					 // just return port number
	else
		return 1;					// install our Ap and files
	
}

//-----------------------------------------------//
void PrintfInfo(void)
{

	char info[1024]={0};
	char infoHeader[] 
		            = {"#*****************************************************************************\n"
					   "# \n"
					   "# \n"
					   "#\n"
					   "# \n"
					   "#					Megawin Technology Co., Ltd. \n"
					   "#\n"
					   "#\n"
					   "#\n"
					   "#\n"
					   "#\n"
					   "#   This program writes itself into /bin directory and will response to udev. \n"
					   "#	Also, it writes a device rules, mwusb2com.rules, in /etc/udev/rules.d\n"
					   "#\n"
					   "#\n"
					   "# Version:\n"
					   "#	0.0.0.1\n"
					   "#\n"
					   "# Copyright (c) 1999-2008 Megawin Technology Co., Ltd.\n"
					   "#\n"
					   "#\n"
					   "#*****************************************************************************\n\n" };

	sprintf(info, "%s",infoHeader);
	printf(info);

}

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

int main(int argc,char *argv[])
{
	int inPath=0;
	int lastcomnumber ;
	char lastCom[6]={0};
	int ret =0;
	
	

	// Check if /bin and /etc/udev/rules.d has our Ap and rules
	ret = CheckApRules();
	
	
	// check which directory we are calling
	
	lastcomnumber = GetLastComNumber();
	
	if ( ret == 0 ){
		sprintf(lastCom,COMNUMBER, lastcomnumber);
		printf("%s\n", lastCom );
	}
	else{
		PrintfInfo();
 		WriteRulesFile();
 		CopyFile();
 		RmTmpFile();
		
		
	}
	
	return 0;
}
