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

#include <windows.h>
#include <stdio.h>

#pragma hdrstop

#include "MagAPI.h"
#define ESC                 0x1b
#define Code_SetCommPortErr -1

HANDLE		idComDev;		//通讯资源句柄
DCB         lpDCB;          //含有串口的设置信息
COMMTIMEOUTS TIMETEST;      //含有要设置的超时信息
COMSTAT Comstate;
DWORD dwErrorMask;
DWORD DWOutData;
DWORD DWInData;

unsigned char ver[] = "FrMag API v1.0";
//---------------------------------------------------------------------------
//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
    return 1;
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
int _stdcall MSR_GetDLL_Ver(char *rVER)
{
    unsigned char i;
    unsigned char ch;

    for (i=0; i<32; i++)
    {
        ch = ver[i];
        if (ch == 0) break;
        rVER[i] = ver[i];
    }
    rVER[i] = 0;

    return 0;
}

int _stdcall MSR_InitComm(char *portname, unsigned long baud)//打开与读写器相联的端口
{
    idComDev = CreateFile(portname, GENERIC_READ|GENERIC_WRITE,
		        	0, NULL, OPEN_EXISTING, 0, NULL);
    if (idComDev==INVALID_HANDLE_VALUE)
		return Code_SetCommPortErr;						// 初使化串口错
	if (GetCommState(idComDev,&lpDCB)==FALSE)
		return Code_SetCommPortErr;						//获取串口配置错
	lpDCB.BaudRate =baud;
	lpDCB.ByteSize  =8;
    lpDCB.Parity =NOPARITY;
	lpDCB.StopBits =ONESTOPBIT;
	if (SetCommState(idComDev,&lpDCB)==FALSE)
        return Code_SetCommPortErr;		            //配置DCB结构错
    if (SetupComm(idComDev,1024,1024)==FALSE)
        return Code_SetCommPortErr;		            //配置缓冲区错

    if (GetCommTimeouts(idComDev,&TIMETEST)==FALSE)
        return Code_SetCommPortErr;		            //读取超时错
	TIMETEST.ReadIntervalTimeout = 100;              //读时间间隔超时 = 100 ms
	TIMETEST.ReadTotalTimeoutMultiplier = 1;        //读总超时系数 = 1ms
    TIMETEST.ReadTotalTimeoutConstant = 1000;       //读总超时常数 = 1000 ms
    TIMETEST.WriteTotalTimeoutConstant =100;        //写总超时常数
	TIMETEST.WriteTotalTimeoutMultiplier =100;      //写总超时系数
    if (SetCommTimeouts(idComDev,&TIMETEST)==FALSE)
	    return Code_SetCommPortErr;		            //配置超时参数错
    else
		return 0;
}

int _stdcall MSR_ExitComm()         //关闭与读写器相联的端口
{
    CloseHandle(idComDev);
    return 0;
}

int _stdcall MSR_SetRecvTimeout(unsigned int timeout)
{
    DWORD DWInData;

    if (GetCommTimeouts(idComDev,&TIMETEST)==FALSE)
        return Code_SetCommPortErr;		            //读取超时错

    TIMETEST.ReadTotalTimeoutConstant = timeout;    //读总超时常数

    if (SetCommTimeouts(idComDev,&TIMETEST)==FALSE)
        return Code_SetCommPortErr;                 //配置超时参数错
    else
        return 0;
}
//------------------------------------------------------------------------------------------------------------
int _stdcall MSR_SendCmd(unsigned int cmdlen, unsigned char *buff)
{
	PurgeComm(idComDev,PURGE_TXCLEAR);
	PurgeComm(idComDev,PURGE_RXCLEAR);
	if (WriteFile(idComDev,&buff[0],cmdlen,&DWOutData,NULL)==FALSE) return -1;
	if (DWOutData < DWORD(cmdlen)) return -1;
    return 0;
}
//------------------------------------------------------------------------------------------------------------
int _stdcall MSR_Reset()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'a';
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_DoCancel()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'a';
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Read()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'r';
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Write(unsigned char *TK1Dat, unsigned char *TK2Dat, unsigned char *TK3Dat)
{
    int i;
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'w';

    buff[len++] = ESC;
    buff[len++] = 's';

    buff[len++] = ESC;              // Track1
    buff[len++] = 1;
    i = 0;
    while(TK1Dat[i] != 0)
    {
        buff[len++] = TK1Dat[i++];
    }
    buff[len++] = ESC;              // Track2
    buff[len++] = 2;
    i = 0;
    while(TK2Dat[i] != 0)
    {
        buff[len++] = TK2Dat[i++];
    }
    buff[len++] = ESC;              // Track3
    buff[len++] = 3;
    i = 0;
    while(TK3Dat[i] != 0)
    {
        buff[len++] = TK3Dat[i++];
    }

    buff[len++] = '?';
    buff[len++] = 0x1c;

    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_CommTest()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'e';  // 0x65
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if ((buff[0]==ESC)&&(buff[1]=='y')) return '0';
    return -2;
}

int _stdcall MSR_All_LED_Off()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x81;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_All_LED_On()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x82;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Green_LED_On()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x83;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Yellow_LED_On()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x84;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Red_LED_On()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x85;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Sensor_Test()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x86;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Ram_Test()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 0x87;
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return buff[1];
}

int _stdcall MSR_Set_Leading_Zero(int lead210, int lead75)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'z';	// 0x7a
    buff[len++] = lead210;
    buff[len++] = lead75;
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return buff[1];
}

int _stdcall MSR_Check_Leading_Zero(int *lead210, int *lead75)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'l';	// 0x6c
    MSR_SendCmd(len, buff);

    len = 3;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    *lead210 = buff[1];
    *lead75 = buff[2];
    return '0';
}

int _stdcall MSR_Erase(int SelectTrack)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'c';	// 0x63
    buff[len++] = SelectTrack;
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Select_BPI(unsigned char TK2Density)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'b';	// 0x62
    buff[len++] = TK2Density;
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return buff[1];
}

int _stdcall MSR_Raw_Read()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'm';	// 0x6d
    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Raw_Write(unsigned char *TK1Dat, unsigned char *TK2Dat, unsigned char *TK3Dat)
{
    int i;
    int len;
    unsigned char buff[512];
    int tklen1, tklen2, tklen3;

    tklen1 = TK1Dat[0];
    for (; tklen1>1; tklen1--)	// 去掉尾部0
    {
		if (TK1Dat[tklen1]) break;	// if (BinBuff[len-1]) break;
    }
    TK1Dat[0] = tklen1;
    //
    tklen2 = TK2Dat[0];
    for (; tklen2>1; tklen2--)	// 去掉尾部0
    {
		if (TK2Dat[tklen2]) break;	// if (BinBuff[len-1]) break;
    }
    TK2Dat[0] = tklen2;
    //
    tklen3 = TK3Dat[0];
    for (; tklen3>1; tklen3--)	// 去掉尾部0
    {
		if (TK3Dat[tklen3]) break;	// if (BinBuff[len-1]) break;
    }
    TK3Dat[0] = tklen3;



    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'n';	// 0x6e

    buff[len++] = ESC;
    buff[len++] = 's';

    buff[len++] = ESC;              // Track1
    buff[len++] = 1;
    buff[len++] = TK1Dat[0];
    for (i=0; i<tklen1; i++)
    {
		buff[len++] = TK1Dat[i+1];
    }
    buff[len++] = ESC;              // Track2
    buff[len++] = 2;
    buff[len++] = TK2Dat[0];
    for (i=0; i<tklen2; i++)
    {
		buff[len++] = TK2Dat[i+1];
    }
    buff[len++] = ESC;              // Track3
    buff[len++] = 3;
    buff[len++] = TK3Dat[0];
    for (i=0; i<tklen3; i++)
    {
		buff[len++] = TK3Dat[i+1];
    }

    buff[len++] = '?';
    buff[len++] = 0x1c;

    MSR_SendCmd(len, buff);
    return '0';
}

int _stdcall MSR_Get_Device_Model(unsigned char *model)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 't';	// 0x74
    MSR_SendCmd(len, buff);

    len = 3;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    memcpy(model, &buff[1], 1);
    return '0';
}

int _stdcall MSR_Get_Firmware_Version(unsigned char *version)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'v';	// 0x76
    MSR_SendCmd(len, buff);

    len = 9;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    memcpy(version, &buff[1], 8); version[8] = 0;
    return '0';
}

int _stdcall MSR_Set_BPC(int TK1Bit, int TK2Bit, int TK3Bit)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'o';	// 0x6f
    buff[len++] = TK1Bit;
    buff[len++] = TK2Bit;
    buff[len++] = TK3Bit;
    MSR_SendCmd(len, buff);

    len = 5;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return buff[1];
}

int _stdcall MSR_Set_HiCo()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'x';	// 0x78
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return '0';
}

int _stdcall MSR_Set_LoCo()
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'y';	// 0x79
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return '0';
}

int _stdcall MSR_Get_CoStatus(unsigned char *status)
{
    int len;
    unsigned char buff[512];

    len = 0;
    buff[len++] = ESC;
    buff[len++] = 'd';	// 0x64
    MSR_SendCmd(len, buff);

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    memcpy(status, &buff[1], 1);
    return '0';
}

int _stdcall MSR_Get_Write_Erase_Status()
{
    int len;
    unsigned char buff[512];

    ClearCommError(idComDev,&dwErrorMask,&Comstate); //Get Comstate status
    if(Comstate.cbInQue < 1) return 0;

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    return buff[1];
}

int _stdcall MSR_GetTrackData(unsigned char *TK1Dat, unsigned char *TK2Dat, unsigned char *TK3Dat)
{
    int len, tklen;
    unsigned char buff[512];

    ClearCommError(idComDev,&dwErrorMask,&Comstate); //Get Comstate status
    if(Comstate.cbInQue < 1) return 0;

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    if (buff[1]!='s') return -2;

    // recv track1 data
    len = 5;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
    if (buff[1]!=0x01) return -2;
    memcpy(TK1Dat, &buff[2], 3);
    if (TK1Dat[2]==ESC)
    {
        tklen = 2;
    }
    else
    {
        tklen = 3;
        while (1)
        {
    	    len = 1;
	        if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		    if (DWInData < DWORD(len)) return -1;
            if (buff[0] == ESC) break;
            TK1Dat[tklen++] = buff[0];
        }
    }
    TK1Dat[tklen] = 0;


    // recv track2 data
    len = 4;
    if (ReadFile(idComDev,&buff[1],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[1]!=0x02) return -2;
    memcpy(TK2Dat, &buff[2], 3);

    if (TK2Dat[2]==ESC)
    {
        tklen = 2;
    }
    else
    {
        tklen = 3;
        while (1)
        {
    	    len = 1;
	        if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		    if (DWInData < DWORD(len)) return -1;
            if (buff[0] == ESC) break;
            TK2Dat[tklen++] = buff[0];
        }
    }
    TK2Dat[tklen] = 0;


    // recv track3 data
    len = 4;
    if (ReadFile(idComDev,&buff[1],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[1]!=0x03) return -2;
    memcpy(TK3Dat, &buff[2], 3);
    if (TK3Dat[2]=='?')
    {
        tklen = 2;
    }
    else
    {
        tklen = 3;
        while (1)
        {
    	    len = 1;
	        if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		    if (DWInData < DWORD(len)) return -1;
            if (buff[0] == '?')
            {
                len = 1;
                if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
                if (DWInData < DWORD(len)) return -1;
                if (buff[0] == '?') TK3Dat[tklen++] = '?';
                break;
            }
            TK3Dat[tklen++] = buff[0];
        }
    }
    TK3Dat[tklen] = 0;

    len = 3;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
    if (DWInData < DWORD(len)) return -1;
    if (buff[0] != 0x1c) return -2;
    if (buff[1] != ESC) return -2;
    return buff[2];
}

int _stdcall MSR_Get_RawRead_Data(unsigned char *TK1Dat, unsigned char *TK2Dat, unsigned char *TK3Dat)
{
    int len;
    unsigned char buff[512];
    int tk1len, tk2len, tk3len;
    int CurrentTrack;

    ClearCommError(idComDev,&dwErrorMask,&Comstate); //Get Comstate status
    if(Comstate.cbInQue < 1) return 0;

    len = 2;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    if (buff[0]!=ESC) return -2;
//    if (buff[1]!='s') return -2;

	while(1)
	{
    	len = 1;
	    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		if (DWInData < DWORD(len)) return -1;
    	if (buff[0]=='?') break;
	    if (buff[0]!=ESC) continue;

	    len = 2;
    	if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		if (DWInData < DWORD(len)) return -1;
    	if ((buff[0]<1)&&(buff[0]>3)) return -2;
	    len = buff[1];
    	if (ReadFile(idComDev,&buff[1],len,&DWInData,NULL)==FALSE) return -1;
		if (DWInData < DWORD(len)) return -1;
    	switch (buff[0])
	    {
    	case 1:
	    	TK1Dat[0] = len;
    	    memcpy(&TK1Dat[1], &buff[1], len);
	    	break;
    	case 2:
    		TK2Dat[0] = len;
	        memcpy(&TK2Dat[1], &buff[1], len);
    		break;
	    case 3:
    		TK3Dat[0] = len;
        	memcpy(&TK3Dat[1], &buff[1], len);
	    	break;
    	}
	}
/*
    while(1)
    {
    	len = 1;
	    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		if (DWInData < DWORD(len)) return -1;
    	if (buff[0]==0x1c) break;
    }
*/
// recv status
    while(1)
    {
    	len = 1;
	    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
		if (DWInData < DWORD(len)) return -1;
    	if (buff[0]==ESC) break;
    }
   	len = 1;
    if (ReadFile(idComDev,&buff[0],len,&DWInData,NULL)==FALSE) return -1;
	if (DWInData < DWORD(len)) return -1;
    return buff[0];
}

int _stdcall MSR_CtrlBUZZ(unsigned char *sound, unsigned char slen)
{
	slen = sound[0];
    return '0';
}





//---------------------------------------------------------------------------
unsigned char _stdcall ASCII_HEX(unsigned char *Value)
{
	unsigned char i;
	i=*Value;
	if(i >= 0x30 && i <=0x39)	i-=0x30;
	else
	{
		switch(i)
		{
		case 'a':
		case 'A':	i=0x0A;
		break;

		case 'b':
		case 'B':	i=0x0B;
		break;

		case 'c':
		case 'C':	i=0x0C;
		break;

		case 'd':
		case 'D':	i=0x0D;
		break;

		case 'e':
		case 'E':	i=0x0E;
		break;

		case 'f':
		case 'F':	i=0x0F;
		break;

		case ',':	i=0x20;
		break;
		case ' ':	i=0x20;
		break;

		default:	i=0xff;
		break;
		} //end of switch
	}//end of else
	return(i);
}

int _stdcall CaulaHex(char *str,unsigned char *HexStr)
{
	int i=0;
	unsigned char buffer;

	if(*str == 0)return(-1);
	while(*str != 0x00)
	{
		if(*str == ':')break;
		if((*HexStr=ASCII_HEX(str)) > 0x10)return(-1);
		else
		{
			str++;
			if(*str == ':')	break;
			if((buffer=ASCII_HEX(str)) > 0x10)return(-1);
			*HexStr=(*HexStr<<4)+buffer;
			HexStr++;
			i++;
			str++;
			if(*str != 00)str++;
			while(*str == 0x20)str++;  //Check the space
		}
	}
	return(i);
}
//---------------------------------------------------------------------------



