/***************************************************************************
**
**    $Header:  
**
**    $Log:   
** 
** Initial revision.
**
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name:  FLSDOWN.CPP
//
//  Description:The implement file for the class: CDOWNLOAD
//
//  Author:     Jerry Yan
//
//  Date:       03/20/96
//
//  Modification:
//
//     
//
//
//  Copyright (C) 1996 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////
// flsdown.cpp : implementation file
//

#include "stdafx.h"
#include <ctype.h>
#include "flsdown.h" 
#include "abitype.h"
 
/////////////////////////////////////////////////////////////////////////////
// Macro definitions.
#define MEM_SIZE 8192 
hexrecord LastRec;
/////////////////////////////////////////////////////////////////////////////
// External function prototypes.                                        
extern STATUS AbiSwitchFlash();
extern STATUS AbiEraseFlash();
extern STATUS AbiProgramFlash(UCHAR,UCHAR,UCHAR*, UINT);                                       
unsigned int ctoi(char temp); 


/////////////////////////////////////////////////////////////////////////////
// External variables.                         
extern BOOL NeedCheck; 

/////////////////////////////////////////////////////////////////////////////
// Debug flags.
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
 
         
CDownload::CDownload()
{   
    recordnum=0;                        
    m_pProStatus=NULL;
}   


CDownload::~CDownload()
{   
}      
 
 

            
            
/* 	int CheckLegal( )
    implementation:  Check the checksum of the hex file

	input : None
    return: 0 OK;           
    		1 checksum error.
*/                                         
            
int CDownload::CheckLegal()
{
    DWORD lOffset=0;
    hexrecord hexrec;    
    char buffer[524];   
    int  result; 
   	m_file.Seek(0,CFile::begin);
    m_file.Read( buffer, 523 ); 
    if(buffer[0]!=':')  return 1;
    while(buffer[0]==':')
    {
    	result=hex_sum(buffer,&hexrec);
    	if( result )
    	  	{
    	  		m_file.Close();
    	  		return result;
    	  	 }
       	recordnum++;    	  
    	if(hexrec.rtype!=0) break;
    	lOffset+=13+hexrec.leth*2;
    	m_file.Seek(lOffset,CFile::begin);
    	m_file.Read(buffer,523);
     }  
    return 0;
}       

            
/* 	int Download( )
    implementation:  download the records 

	input : None
    return: TRUE OK;           
    		FALSE download error.
*/                                         
 
BOOL CDownload::Download()
{    
    unsigned int k,i,adr;
    DWORD lOffset=0;
    char buffer[524];   
    int  result;                     
    unsigned int sta_mod, sta_sha,end_mod,end_sha,len;
    hexrecord cksum;
    unsigned char far *table;
    HGLOBAL hglb;
	if( (hglb = GlobalAlloc(GPTR,MEM_SIZE+1))==NULL)  
	{
	    m_file.Close();
	    return FALSE;
	 }   
	   
	table = (unsigned char far*) GlobalLock(hglb);
    
#ifndef _VIR
    if( AbiSwitchFlash()!=ICE_OK )
     {
        AfxMessageBox("Program switched Error !",MB_OK);
 		GlobalUnlock(hglb);
 		GlobalFree(hglb);
		m_file.Close();
	    return  FALSE;
     } 
     
    if(AbiEraseFlash()!=ICE_OK)
    {
        AfxMessageBox("Program Erase Error !",MB_OK);
 		GlobalUnlock(hglb);
		GlobalFree(hglb);
		m_file.Close();
     	return  FALSE;
	 }
#endif                         
     m_pProStatus=new CProStatus;  
     m_pProStatus->m_nRecordNum=recordnum;
     m_pProStatus->Create(); 

     m_file.Seek(0,CFile::begin);
     m_file.Read( buffer, 523 ); 
     int recnum=1;
     while(buffer[0]==':')
     {
    	result=hex_sum(buffer,&cksum);
    	if(cksum.rtype!=0) break;
#ifndef _VIR 
          if(ICE_OK!=AbiProgramFlash(cksum.adrh,cksum.adrl,cksum.rdata, cksum.leth))
	      {                   
             m_file.Close();
		     m_pProStatus->DestroyWindow(); 
             GlobalUnlock(hglb);
			 GlobalFree(hglb);
             return FALSE;   
           }
#endif 
    	   recnum++;          
           adr=cksum.adrh*256+cksum.adrl;
           sta_sha=adr>>3; 
           sta_mod=adr%8;
           adr=adr+cksum.leth-1;
           end_sha=adr/8;
           end_mod=adr%8;  
		   len=end_sha-sta_sha;          

           if(len==0)
              table[sta_sha]=table[sta_sha]|( (0xff>>sta_mod)-( 0xff>>(1+end_mod) ) );
           else
           {
             table[sta_sha]|=0xff>>sta_mod;
             for(i=sta_sha+1;i<end_sha;i++)
               table[i]=0xff;
             table[end_sha]|=0xff-(0xff>>(1+end_mod) );
           } 
             
   	       if( (recnum%(recordnum/20)==0)&&(recnum!=0) )
   	       {
             m_pProStatus->m_nDoneRecords=recnum;
             DrawProBar();
           }
//          } 
           lOffset+=13+cksum.leth*2;
    	   m_file.Seek(lOffset,CFile::begin);
    	   m_file.Read(buffer,523);
   }                  
   m_pProStatus->m_nRecordDone=1; 
   m_pProStatus->Invalidate();
   m_pProStatus->UpdateWindow();
   unsigned int start,p;
   BOOL Done=TRUE;
   unsigned char ktmp,ptmp;                   
   unsigned int leth;  
   i=0;
   while (i<MEM_SIZE)
     {  
     	k=0;ktmp=0x80;p=0;
        if( (i==MEM_SIZE-1)&&( table[i]=0xff) )
           break;
        while ( table[i]==0xff )    
          i++;
        if(i==MEM_SIZE)  break; 
        do{
            while( ((table[i]&ktmp)!=0)&&(ktmp!=0) )
            {
              k++;
              ktmp= (ktmp>>1);
             }
             if(ktmp!=0)
              {
                start=i;
                Done=FALSE;
                ptmp=ktmp;
                adr=(start<<3)+k;
               }
             else
               break;
             while( ( (table[i]&ptmp)==0)&&(ptmp!=0) ) 
               {
                  p++; ptmp=ptmp>>1;
                }  
             ktmp=ptmp;
             if( (ptmp!=0)||( (table[i+1]&0x80)!=0 ) )
              {
                 leth=p;
                 k=k+p; p=0;Done=TRUE;
                 cksum.leth=leth;
		         cksum.adrh=adr>>8;
        		 cksum.adrl=adr%256;

#ifndef _VIR
        if(ICE_OK!=AbiProgramFlash(cksum.adrh,cksum.adrl,cksum.rdata, cksum.leth))
	    {                   
            m_file.Close();
		    m_pProStatus->DestroyWindow(); 
        	GlobalUnlock(hglb);
			GlobalFree(hglb);
            return FALSE;   
         }
#endif           
//				recnum++;
               }
                 
          }while(ktmp!=0);
          i++;
          if(!Done)
          {
              while( ( table[i]==0 )&&(i!=MEM_SIZE-1) )  
              	i++; 
              ktmp=0x80;k=0;
              while ( (table[i]&ktmp)==0&&ktmp!=0)
                {
                    k++; table[i]|=ktmp;
                    ktmp=ktmp>>1;
                 }  
              leth=( (i-start-1)<<3) +p+k;
              Done=TRUE; 
              do
              {
            	  cksum.leth=(leth>MAX_REC_LEN)?MAX_REC_LEN:leth;
            	  cksum.adrh=adr>>8;
            	  cksum.adrl=adr%256;  
            	  if(leth>MAX_REC_LEN)
          	      {
          	       adr+=MAX_REC_LEN; 
          	       leth=leth-MAX_REC_LEN;
          	      }
          	      else leth=0;
#ifndef _VIR
        if(ICE_OK!=AbiProgramFlash(cksum.adrh,cksum.adrl,cksum.rdata, cksum.leth))
	    {                   
            m_file.Close();
		    m_pProStatus->DestroyWindow(); 
        	GlobalUnlock(hglb);
			GlobalFree(hglb);
            return FALSE;   
         } 
#endif                      
//				  recnum++;
               }while(leth>0) ;
             }  
       } 
      m_pProStatus->DestroyWindow(); 
      m_file.Close();
   	  GlobalUnlock(hglb);
	  GlobalFree(hglb); 
  	  return TRUE;  
}

BOOL CDownload::check_ver()
{
    char buffer[524];          
    int i,j; 
    UINT nt;
    unsigned char leth,adrh,adrl,rtype,value,tempi,rdata[300];
    LONG lOffset=0;
    int result=0; //if result!=2, the Fireware is not compatible

    m_file.Read( buffer, 523 ); 
    if(buffer[0]!=':')  return FALSE;;
    while(buffer[0]==':')
    {   
    	i=1;
		leth=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;    	
    	adrh=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;
    	adrl=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;   
    	rtype=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;

//version check
		if((adrh*256+adrl>0xffc0-255)&&(adrh*256+adrl<0xffc1))
        {
           nt=adrh*256+adrl+leth-1;
           if(nt>=0xffc8)
           {    
                j=0;
           		int nInd=(0xffc8-adrh*256-adrl);
        	  	for(tempi=0;tempi<leth;tempi++)
	      		{
		    		value=ctoi(buffer[nInd*2+9+j])*16+ctoi(buffer[2*nInd+j+10]);j+=2;
    	        	rdata[tempi] = value;
        	 	}
                
                if(nInd+5>leth)
                {   
                	char rdataT[5];
                	for( j=0;j<leth-nInd;j++)
                	   rdataT[j]=rdata[+j];
//                	rdataT[0]=
                	lOffset+=13+leth*2;
			    	m_file.Seek(lOffset,CFile::begin);
    				m_file.Read(buffer,523);
			    	i=1;
					leth=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;    	
    				adrh=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;
    				adrl=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;   
    				rtype=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;
               	  	for(tempi=0;tempi<leth;tempi++)
		      		{
			    		value=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;
    		        	rdata[tempi] = value;
        	 		}
                    for(int m=j;m<5;m++)  rdataT[m]=rdata[m-j];
                    m_uchMajor=ctoi(rdataT[0])*16+ctoi(rdataT[1]);
                    m_uchMinor=ctoi(rdataT[3])*16+ctoi(rdataT[4]);          
                    
                }
                else 
                {  m_uchMajor=ctoi(rdata[0])*16+ctoi(rdata[1]);   
                   m_uchMinor=ctoi(rdata[3])*16+ctoi(rdata[4]);
                }  
                result++;       
           }     
        }
         	  
//search file supported cpu id list

        if(adrh*256+adrl==0xff00) 
        {  
          UINT uCPUByte,uDoneByte,uDoneByte2,addr_tmp,k=0;   
          unsigned char next_addr_l,next_addr_h;
          unsigned char tempstart=0,tempbuf[256]="";
          uCPUByte=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2; 
		  m_puCPUId[0]=uCPUByte/2;
		  uDoneByte=leth-1; 
	      do{
          	uDoneByte2=uDoneByte*2;
          	while(k<uDoneByte2)                  
          	{
            	 tempbuf[k]=buffer[i];
             	k++;i++;
          	}
         	 if(uDoneByte<uCPUByte)
          	 {
		    	lOffset+=13+leth*2;
    			m_file.Seek(lOffset,CFile::begin);
    			m_file.Read(buffer,523);
    			if(buffer[0]!=':')  return FALSE;
		    	i=1;
		    	addr_tmp=adrl+leth;
		    	next_addr_l=addr_tmp&0x00ff;
		    	next_addr_h=adrh+(addr_tmp>>8);
				leth=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;    	
    			adrh=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;
    			adrl=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;   
    			rtype=ctoi(buffer[i])*16+ctoi(buffer[i+1]);i+=2;
                uDoneByte+=leth; 
				if( (next_addr_h!=adrh)||(next_addr_l!=adrl) ) return FALSE;
             } 
             else break;
           }while(uDoneByte-leth<uCPUByte);
                
          i=0;
          for(tempi=1;tempi<uCPUByte/2+1;tempi++)
	      {
	        value=ctoi(tempbuf[i])*16+ctoi(tempbuf[i+1]);i+=2;
	        m_puCPUId[tempi] =(UINT)value+256*(UINT)( ctoi(tempbuf[i])*16+ctoi(tempbuf[i+1]));
	        i+=2;                      
           }      
           result++;
      }  


// Check string "EP-SLD Flash Fir"   
     if((adrh*256+adrl>0xffe0-255)&&(adrh*256+adrl<0xffe1))
     {                  
     
        nt=adrh*256+adrl+leth-1;
        if(nt>=0xffe0)
        {
          j=0;
          int Ind=(0xffe0-adrh*256-adrl);
          result++;
          for(tempi=0;tempi<leth;tempi++)
	      {
	    	value=ctoi(buffer[Ind*2+9+j])*16+ctoi(buffer[Ind*2+j+10]);j+=2;
            rdata[tempi] = value;
           }  
           rdata[tempi]=0;
           if(NULL==strstr((char*)rdata,"EP-SLD Flash Fir"))
           {  m_file.Close();
              return FALSE;
            }      
          } 
       }   
    	if(rtype!=0) break;
    	lOffset+=13+leth*2;
    	m_file.Seek(lOffset,CFile::begin);
    	m_file.Read(buffer,523);
     }
	 if(result!=3) {m_file.Close(); return FALSE;}
	 else  return TRUE;                    
}     

// analysis records and checksum
int CDownload::hex_sum(char* temp,hexrecord* pcksum)
{
    unsigned char total,tempi,value;
	total=0;
    int i=0;
	i++;
    pcksum->leth=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
    pcksum->adrh=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
    pcksum->adrl=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
    pcksum->rtype=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
	if(pcksum->leth==0){
		pcksum->rsum=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
    	total=total%256;
   	} 
	else{                         
           for(tempi=0;tempi<pcksum->leth;tempi++)
	      {
	    	value=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
            pcksum->rdata[tempi] = value;
        	total=total+value;
	      }
	      pcksum->rsum=ctoi(temp[i])*16+ctoi(temp[i+1]);i+=2;
          total=total%256+pcksum->leth+pcksum->adrh+pcksum->adrl
		        +pcksum->rtype+pcksum->rsum;
		  total=total%256;
		}
  
	if(total) 
	   return 3;
	else return 0;
}


// draw the process status bar

void CDownload::DrawProBar()
{

	m_pProStatus->InvalidateRect(&(m_pProStatus->m_ProRect));
	m_pProStatus->InvalidateRect(&(m_pProStatus->m_IconRect));
//	m_pProStatus->Invalidate();
	m_pProStatus->UpdateWindow();

}	 


/*
      Module name : unsigned int ctoi(temp)
      funtion : convert single ascii to hex value (0 to 15)
      input : single ascii (char)
      output : 1. if ascii is '0' to '9', or 'a' to 'z', or 'A' to 'Z'
                  return it's hex value : 0 to 15
	       2. if ascii is not in above range
                  return 16.
*/

unsigned int ctoi(char temp)
{
	unsigned int retvalue;
	if(isxdigit(temp)){
		if( temp<='9' && temp>='0') retvalue=temp-'0';
		if( temp<='z' && temp>='a') retvalue=10+temp-'a';
		if( temp<='Z' && temp>='A') retvalue=10+temp-'A';
		}
	else{
		retvalue=16;
		}	
	return retvalue;
}


              		 