#include "tap.h"
#include "usbcmd.h"

#define ID_USBTEST 0x8000010B

TAP_ID( ID_USBTEST );
TAP_PROGRAM_NAME("USBTEST");
TAP_AUTHOR_NAME("TOPFIELD");
TAP_DESCRIPTION("USB");
TAP_ETCINFO(__DATE__);

bool _exitFlag = FALSE;
volatile byte _received = 0;
byte *_usbBuf;

#define SIZE_BUF    (0xffff)

void WriteCallback( word size );
word ReadCallback( word size );

void Put16bit(void *p, word data)
{
	*((byte*)p + 0) = data >> 8;
	*((byte*)p + 1) = data;
} 

void Put32bit( void *p, dword data )
{
	*((byte*)p + 0) = (data >> 24)&0xff;
	*((byte*)p + 1) = (data >> 16)&0xff;
	*((byte*)p + 2) = (data >>  8)&0xff;
	*((byte*)p + 3) = (data      )&0xff;
}

word Get16bit( void *p )
{
    word r;

    r = *((byte*)p + 0);
    r = (r<<8) + *((byte*)p + 1);
    return r;
}

dword Get32bit( void *p )
{
    dword r;

    r = *((byte*)p + 0);
    r = (r<<8) + *((byte*)p + 1);
    r = (r<<8) + *((byte*)p + 2);
    r = (r<<8) + *((byte*)p + 3);
    return r;
}
    
    
const	word	_crc16Tbl[256] =
{
	0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
	0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
	0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
	0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
	0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
	0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
	0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
	0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
	0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
	0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
	0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
	0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
	0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
	0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
	0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
	0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
	0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
	0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
	0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
	0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
	0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
	0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
	0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
	0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
	0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
	0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
	0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
	0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
	0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
	0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
	0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
	0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
};

word GetCrc16(byte *p, dword n)
{
	word	crc;

	crc = 0;
	while (n--)
		crc = (crc >> 8) ^ _crc16Tbl[(crc ^ *p++) & 0xff];

	return crc;
}  /* GetCrc16 */


// -----------------------------------------------------------------------------
// full path 에서 이름만 얻어낸다.
void UsbFileGetName( char *pFullPath, char *saveBuff )
{
	short int i, k;

	if (!pFullPath || !saveBuff)
		return;

	for (i=strlen(pFullPath)-1; i>=0; i--)
	{
		if (pFullPath[i] == '\\' && strlen(&pFullPath[i+1]) > 0)
		{
			memcpy( saveBuff, &pFullPath[i+1], strlen(&pFullPath[i+1])+1 );
			for (k=strlen(saveBuff)-1; k>=0; k--)
			{
				if (saveBuff[k] == '\\')
					saveBuff[k] = NULL;
				else 
					break;
			}
			return;
		}
	}
	memcpy( saveBuff, pFullPath, strlen(pFullPath)+1 );
	for (k=strlen(saveBuff)-1; k>=0; k--)
	{
		if (saveBuff[k] == '\\')
			saveBuff[k] = NULL;
		else 
			break;
	}
	return;
}


void UsbReceive( byte *packet )
{
	dword	msg[4], cmd;
	word	nameSize, dataSize, error;
	dword   hOffset, lOffset;
	TYPE_File file;
    char name[64];
    byte *pBuff;
    dword i;
    byte end = 0;
 
//    TAP_Print(" packet size = %d\r\n", Get16bit( packet ) );
//    TAP_Print(" crc = %x\r\n", Get16bit( &packet[2] ) );

    while( end == 0 )
    {
        if( _received == 0 )
            continue;

       	TAP_Usb_PacketWrite( NULL, 0, WriteCallback, USB_Success );
        
        _received = 0;
        
        cmd = Get32bit( &packet[4] );
    	dataSize = (word)Get16bit( &packet[0] ) - 8;

        switch( cmd )
        {
            case USB_CmdHddFileSend :
            	//--------------------------------------------------------------------------
            	// get file name
            	nameSize = (word)Get16bit( &packet[9] );
                TAP_Print( "File = %s\r\n", &packet[11] );
            	
            	UsbFileGetName( &packet[11], name );
            	TAP_Print( "GetFileName : %s\r\n", name );

                TAP_Usb_PacketRead( _usbBuf, SIZE_BUF, ReadCallback );
                break;
                
            case USB_DataHddFileStart :
    			// get file info!
    			pBuff = &packet[8];
    			file.mjd = Get16bit( &pBuff[0] );
                file.hour = pBuff[2];
                file.min = pBuff[3];
                file.sec = pBuff[4];
                file.attr = pBuff[5];
    			
    			hOffset = Get32bit( &pBuff[6] );
    			lOffset = Get32bit( &pBuff[10] );
    			
    			file.size = hOffset;
    			file.size <<= 32;
    			file.size |= lOffset;

                TAP_Usb_PacketRead( _usbBuf, SIZE_BUF, ReadCallback );
    			break;

    		case USB_DataHddFileData:
            	hOffset = Get32bit( &packet[8] );
            	lOffset = Get32bit( &packet[12] );
                
    			TAP_Print( "Offset/size => %x/%x\r\n", lOffset, dataSize-8 );
                TAP_Usb_PacketRead( _usbBuf, SIZE_BUF, ReadCallback );
                break;

    		case USB_DataHddFileEnd:
                TAP_Usb_PacketRead( _usbBuf, SIZE_BUF, ReadCallback );
                end = 1;
                break;
        }
    }
}
 

void WriteCallback( word size )
{
//    TAP_Print(" Write complete!\r\n");
}
 
word ReadCallback( word size )
{
    int i;
	dword	cmd;

    cmd = Get32bit( &_usbBuf[4] );

    if( cmd == USB_CmdHddFileSend ||
        cmd == USB_DataHddFileStart ||
        cmd == USB_DataHddFileData ||
        cmd == USB_DataHddFileEnd )
    {
        _received = 1;
        return 0;
    }
    else
    {
        _received = 2;
    }

    return 1;
}

dword TAP_EventHandler( word event, dword param1, dword param2 )
{
    if( event == EVT_IDLE )
    {
        if( _exitFlag )
        {
        	TAP_Exit();
            return 0;
        }
    }

    if( _received == 1 )
    {
        UsbReceive( _usbBuf );
    }
    ef( _received == 2 )
    {
        _received = FALSE;
        TAP_Usb_PacketRead( _usbBuf, SIZE_BUF, ReadCallback );
    }
    return param1;
}

int TAP_Main(void)
{
    _usbBuf = malloc( SIZE_BUF );
    memset( _usbBuf, 0, SIZE_BUF );
    TAP_Usb_PacketRead( _usbBuf, SIZE_BUF, ReadCallback );
    free( _usbBuf );
    return 1;
}


