//--------------------------------------------------------------------------- #include #include #include #include "stdio.h" #pragma hdrstop #include "crd_ctrl.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TCardCtrl *CardCtrl; //--------------------------------------------------------------------------- __fastcall TCardCtrl::TCardCtrl(TComponent* Owner) : TForm(Owner) { LM_opened = false; char COMM[][10] = { "COM1", "COM2", "COM3", "COM4" }; IDcard = 0; TbCards->Active = true; Height = 270; // Recuperamos la configuración TIniFile *ini; ini = new TIniFile( ExtractFileDir( Application->ExeName ) + "\\CAP.INI" ); // General PuertoE = ini->ReadInteger( "CAP_w", "PuertoEscritor", 1 ); AbrePuerto( COMM[PuertoE]); cb_PosP = ini->ReadInteger( "CAP_w", "PosPrefijo", 0 ); cb_LenP = ini->ReadInteger( "CAP_w", "LenPrefijo", 2 ); cb_PosC = ini->ReadInteger( "CAP_w", "PosCodigo", 2 ); cb_LenC = ini->ReadInteger( "CAP_w", "LenCodigo", 8 ); cb_PosR = ini->ReadInteger( "CAP_w", "PosRevision", 10 ); cb_LenR = ini->ReadInteger( "CAP_w", "LenRevision", 2 ); cb_PosFd = ini->ReadInteger( "CAP_w", "PosFechaDesde", 12 ); cb_PosFh = ini->ReadInteger( "CAP_w", "PosFechaHasta", 18 ); delete ini; } //--------------------------------------------------------------------------- int __fastcall TCardCtrl::LocateCard( int idc, int owner ) { int dev = idc; int version = 0; if ( !TbCards->Locate( "id", idc, TLocateOptions() << loCaseInsensitive << loPartialKey ) ) { Height = 270; noCardFound->Visible = true; TbCards->Insert(); TbCards->FieldByName("idowner")->AsInteger = owner; TbCards->FieldByName("idCard")->AsInteger = 0+((version&0x1F)<<1)+(owner<<6); TbCards->FieldByName("vCard")->AsInteger = version; TbCards->Post(); dev = TbCards->FieldByName( "id" )->AsInteger; } return dev; } //--------------------------------------------------------------------------- void __fastcall TCardCtrl::BitBtn2Click(TObject *Sender) { if ( TbCards->FieldByName("idCard")->AsInteger & 0x0001 ) { ShowMessage( "La tarjeta pertenece a un ABONADO TEMPORAL, por lo que su version no puede ser incrementada"); } else { int newVersion, idCard; if ( Application->MessageBox("Reasignación código tarjeta, inutilizará la tarjeta actual. ¿Realmente desea continuar?", "CRD: cambio de tarjetra", MB_OKCANCEL) != IDOK) return; newVersion = (TbCards->FieldByName("vCard")->AsInteger+1)%32; idCard = TbCards->FieldByName("idCard")->AsInteger; TbCards->Edit(); TbCards->FieldByName("vCard")->AsInteger = newVersion; TbCards->FieldByName("idCard")->AsInteger = (idCard & 0xFFC1) + ((newVersion&0x1F)<<1); TbCards->Post(); } } //--------------------------------------------------------------------------- //----------------------- ESCRITOR DE TARJETAS ------------------------------ int __fastcall TCardCtrl::AbrePuerto(LPTSTR lpszPortName) { DWORD dwError; DCB PortDCB; COMMTIMEOUTS CommTimeouts; if ( LM_opened ) return true; LM_opened = false; // Open the serial port. LM_handle = CreateFile (lpszPortName, // Pointer to the name of the port GENERIC_READ | GENERIC_WRITE, // Access (read/write) mode 0, // Share mode NULL, // Pointer to the security attribute OPEN_EXISTING,// How to open the serial port 0, // Port attributes NULL); // Handle to port with attribute // to copy // If it fails to open the port, return FALSE. if ( LM_handle == INVALID_HANDLE_VALUE ) { dwError = GetLastError (); return false; } else { LM_opened = true; } PortDCB.DCBlength = sizeof (DCB); // Get the default port setting information. GetCommState (LM_handle, &PortDCB); // Change the DCB structure settings. PortDCB.BaudRate = 9600; // Current baud PortDCB.fBinary = TRUE; // Binary mode; no EOF check PortDCB.fParity = TRUE; // Enable parity checking. PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx PortDCB.fOutX = FALSE; // No XON/XOFF out flow control PortDCB.fInX = FALSE; // No XON/XOFF in flow control PortDCB.fErrorChar = FALSE; // Disable error replacement. PortDCB.fNull = FALSE; // Disable null stripping. PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on // error. PortDCB.ByteSize = 7; // Number of bits/bytes, 4-8 /* PortDCB.ByteSize = 8; // Number of bits/bytes, 4-8 */ PortDCB.Parity = EVENPARITY; // 0-4=no,odd,even,mark,space PortDCB.StopBits = 0; // 0,1,2 = 1, 1.5, 2 // Configure the port according to the specifications of the DCB // structure. if (!SetCommState (LM_handle, &PortDCB)) { // Could not configure the serial port. ///*-*/ printf( "Unable to configure the serial port\n%s\n" ); dwError = GetLastError (); return FALSE; } // Retrieve the time-out parameters for all read and write operations // on the port. GetCommTimeouts (LM_handle, &CommTimeouts); // Change the COMMTIMEOUTS structure settings. CommTimeouts.ReadIntervalTimeout = MAXDWORD; // CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutMultiplier = 1000; CommTimeouts.ReadTotalTimeoutConstant = 1000; CommTimeouts.WriteTotalTimeoutMultiplier = 10; CommTimeouts.WriteTotalTimeoutConstant = 1000; // Set the time-out parameters for all read and write operations // on the port. if (!SetCommTimeouts (LM_handle, &CommTimeouts)) { // Could not set the time-out parameters. ///*-*/ printf( "Unable to set the time-out parameters" ); dwError = GetLastError (); return FALSE; } // Direct the port to perform extended functions SETDTR and SETRTS. // SETDTR: Sends the DTR (data-terminal-ready) signal. // SETRTS: Sends the RTS (request-to-send) signal. EscapeCommFunction (LM_handle, SETDTR); EscapeCommFunction (LM_handle, SETRTS); return LM_opened; }; void __fastcall TCardCtrl::CierraPuerto(void) { if ( LM_opened ) { CloseHandle( LM_handle ); } }; // ObtenerRespuesta // Lee del puerto los datos pendientes del buffer // (solo lee lo que expulse el LM) // // char * __fastcall TCardCtrl::ObtenerRespuesta( char *rcv ) { bool waitingResp = true; DWORD CHK, chkF = 0; int i = 0; DWORD dwCommModemStatus; if ( LM_opened ) { /* // Specify a set of events to be monitored for the port. SetCommMask (LM_handle, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING); // Wait for an event to occur for the port. WaitCommEvent (LM_handle, &dwCommModemStatus, 0); // Re-specify the set of events to be monitored for the port. SetCommMask (LM_handle, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING); */ // Recogemos la respuesta del lector while( i < 75 ) { ReadFile( LM_handle, &(rcv[i]), 1, &CHK, NULL ); if ( CHK == 1 ) { if ( waitingResp ) { if ( rcv[i] != 0x06) waitingResp = false; // ACK // printf( "Esperando a la tarjeta\n" ); } if ( rcv[i] == 13 ) break; else { if ( !waitingResp || i==0 ) i++; } } else if ( CHK == 0 ) { chkF++; if ( chkF == 20 ) { sprintf( rcv, "ERROR: Respuesta fuera de tiempo" ); return rcv; } } } rcv[i+1] = '\0'; } else { sprintf( rcv, "ERROR: LM no abierto" ); } #ifdef _verbose ///*-*/ printf( "Recibido: %s\n", rcv ); #endif return rcv; }; // EnviarComando // Envia el comando CMD al lector ID, devolviendo la respuesta 'rcv' // // // char * __fastcall TCardCtrl::EnviaCMD1( char *CMD, char *rcv, char mlen ) { DWORD CHK; if ( LM_opened ) { #ifdef _verbose ///*-*/ printf( "Enviado: %s\n", CMD ); #endif WriteFile( LM_handle, CMD, strlen(CMD)+mlen, &CHK, NULL ); ObtenerRespuesta( rcv ); } else sprintf( rcv, "ERROR: LM no abierto" ); return rcv; } char * __fastcall TCardCtrl::EnviaCMD( char *CMD, char *rcv ) { EnviaCMD1( CMD, rcv, 0 ); return rcv; } #define ZT_ClearCommand "/CL0/" // #define ZT_ReadCommand "/RD3/" #define ZT_ReadCommand "/RD1/" #define ZT_WriteCommand "/WR1/" #define ACK 0x06 #define STX 0x02 #define NAK 0x15 #define ETX 0x03 #define EOT 0x04 #define CR 0x0D char __fastcall TCardCtrl::CalculaBCC( char *cadena ) { int i, dev=0; for ( i=0; cadena[i] != ETX; i++ ) { dev ^= cadena[i]; } dev ^= cadena[i]; return dev; } char * __fastcall TCardCtrl::LeeTarjeta( char *rcv ) { // Leemos una tarjeta char buff[3], buff2[80]; EnviaCMD( ZT_ReadCommand, rcv ); if ( rcv[0] == ACK && rcv[1] == 0x0D ) { // Ahora si se ha recibido Leemos la tarjeta que pasemos sndPlaySound("snd\\inserta_card_leer.wav", SND_ASYNC | SND_FILENAME); ObtenerRespuesta( rcv ); // Vemos si es la tarjeta o un error if ( rcv[0] == STX && rcv[1] == '/' && rcv[2] == 'E' && rcv[3] == 'R' ) { //es un error #ifdef _verbose ///*-*/ printf( "Error: %d", rcv[1] ); #endif } else { char len = 0; while( rcv[len]!=CR )len++; char BCC = CalculaBCC( &rcv[1] ), BCCr = rcv[ len-1 ]; if ( BCC != BCCr ) { sprintf( rcv, "Error: BCC recibido es incorrecto BCC(%x) != R(%x)\n", BCC, BCCr ); } } buff[0] = ACK; buff[1] = '\0'; EnviaCMD( buff, buff2 ); } else { sprintf( rcv, "ERROR: Commando no aceptado\n"); } return rcv; } char * __fastcall TCardCtrl::EscribeTarjeta( char *datos, char *rcv ) { // Leemos una tarjeta char env[140], buff[140], BCC; EnviaCMD( ZT_WriteCommand, rcv ); if ( rcv[0] == ACK && rcv[1] == CR ) { sprintf( env, "%s%c", datos, ETX ); BCC = CalculaBCC( env ); sprintf( buff, "%c%s%c", STX, env, BCC ); if ( BCC ) EnviaCMD( buff, rcv ); else EnviaCMD1( buff, rcv, 1 ); if ( rcv[0] == ACK && rcv[1] == CR ) { // Ahora si se ha recibido Leemos la tarjeta que pasemos sndPlaySound("snd\\inserta_card_grabar.wav", SND_ASYNC | SND_FILENAME); ObtenerRespuesta( rcv ); // Vemos si es la tarjeta o un error if ( !(rcv[0] == EOT && rcv[1] == CR) ) { //es un error sprintf( rcv, "Error: %s\n", rcv ); #ifdef _verbose ///*-*/ printf( "Error: %s\n", rcv ); #endif } buff[0] = ACK; buff[1] = CR; buff[2] = '\0'; EnviaCMD( buff, rcv ); } else { sprintf( rcv, "ERROR: No se recibio respuesta despues de los datos\n" ); } } else { sprintf( rcv, "ERROR: Commando no aceptado\n"); } return rcv; } void __fastcall TCardCtrl::GrabaTarjeraClick(TObject *Sender) { char rcv[140]; statusOK = false; if ( LM_opened ) { // Inicializamos el ZT-2300 EnviaCMD( ZT_ClearCommand, rcv ); if ( rcv[0] == 'E' ) { ShowMessage( "Error inicializando el GRABADOR" ); } else { char rcv[80], card[140]; ObtenCadenaTarjeta(card); EscribeTarjeta( card, rcv ); statusOK = !( rcv[0] == 'E' && rcv[5] == ':' ); } } else { ShowMessage("El Puerto no pudo ser ABIERTO" ); } } //--------------------------------------------------------------------------- char * __fastcall TCardCtrl::ObtenCadenaTarjeta(char *dev) { int Prefijo = 20, Rev = 0; //----- if ( IDcard != 0 ) sprintf( dev, "%02d%08d%02d", Prefijo, IDcard, Rev ); else sprintf( dev, "%02d%08d%02d", Prefijo, TbCards->FieldByName("idCard")->AsInteger, Rev ); return dev; } void __fastcall TCardCtrl::VerificarTarjetaClick(TObject *Sender) { char rcv[140]; if ( LM_opened ) { // Inicializamos el ZT-2300 EnviaCMD( ZT_ClearCommand, rcv ); if ( rcv[0] == 'E' ) { ShowMessage( AnsiString( rcv ) + "Error inicializando el GRABADOR" ); } else { char rcv[80], buff[80], card[140]; ObtenCadenaTarjeta(card); LeeTarjeta( rcv ); int i; for( i=1; rcv[i] != ETX; i++ ) buff[i-1]=rcv[i]; buff[i-1]='\0'; if ( strcmp( buff, card ) != 0 ) { sndPlaySound("snd\\card_verify_error.wav", SND_ASYNC | SND_FILENAME); ShowMessage("La tarjeta pasada, no se corresponde"); } else { sndPlaySound("snd\\card_verify_ok.wav", SND_ASYNC | SND_FILENAME); ShowMessage("La tarjeta pasada, es correcta"); } } } else { ShowMessage("El Puerto no pudo ser ABIERTO" ); } } //--------------------------------------------------------------------------- void __fastcall TCardCtrl::FormClose(TObject *Sender, TCloseAction &Action) { if ( LM_opened ) CierraPuerto(); } //---------------------------------------------------------------------------