Hallo,
Das kommt darauf an. Was für eine Chipkarte. Was für ein Leser. Was für ein Protokoll.
Nein, kommt nicht unbedingt drauf an. (Bin übrigens von LPT auf COM gegangen.)
Ok, grobe Einschränkung der Chipkarte: Eine kontaktbehaftete Speicherkarte. (Telefonkarte, Gesundheitskarte, Bankkarte etc. Andere müßten aber theoretisch auch gehen. Eigentlich müssten alle Speicherkarten relativ gleich zu lesen sein. Einziger Unterschied: in welchem Bereich des Buffers welche Werte stehen.)
BTW: Leser und Karten sind genormt.
Das kommt auf's OS an.
Naja...
FYI, habe da was ausgegraben. Etwas länger, aber da Du mir ja sonst bestimmt nicht glaubst....Kannst ja mal ausprobieren. ;o)
Gruß, LeKuchen
PS: Ab hier nur für Interessierte....
#include <windows.h>
#define DLLExport __declspec( dllexport ) WINAPI
HANDLE hCom; unsigned char InBuff[255]; char SendSeqNr;
void ProtError (LPSTR Meld) { char szBuff[255]; wsprintf(szBuff,"%s, Error %u\n",Meld,GetLastError()); MessageBox(NULL,szBuff,"Cardreader",MB_ICONHAND); }
int OpenComm (void) { DCB dcb; COMMTIMEOUTS CTO; DWORD dwError; BOOL fSuccess;
hCom = CreateFile("COM2", GENERIC_READ | GENERIC_WRITE, 0, /* comm devices must be opened w/exclusive-access / NULL, / no security attrs / OPEN_EXISTING, / comm devices must use OPEN_EXISTING / 0, / not overlapped I/O / NULL / hTemplate must be NULL for comm devices */ );
if (hCom == INVALID_HANDLE_VALUE) { dwError = GetLastError(); /* handle error */ return(0); }
/* * Omit the call to SetupComm to use the default queue sizes. * Get the current configuration. */
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess) { /* Handle the error. */ return(0); }
/* Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit. */
dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = EVENPARITY; dcb.StopBits = ONESTOPBIT; dcb.fNull = FALSE; dcb.fRtsControl=RTS_CONTROL_DISABLE;
fSuccess = SetCommState(hCom, &dcb); if (!fSuccess) { /* Handle the error. / return(0); } CTO.ReadIntervalTimeout=MAXDWORD; CTO.ReadTotalTimeoutMultiplier=0; CTO.ReadTotalTimeoutConstant=0; CTO.WriteTotalTimeoutMultiplier=0; CTO.WriteTotalTimeoutConstant=0; fSuccess = SetCommTimeouts(hCom, &CTO); if (!fSuccess) { / Handle the error. */ return(0); }
return(1); }
int SendRec (unsigned char * SendStr , int len) { int chksum=0; unsigned char *RdBuff=InBuff; int i, RestToRead, TotalRead=0; DWORD nBytesRead, nBytesToWrite, nBytesWritten;
for (i=0;i<len;i++) { chksum^=(int)(*(SendStr+i)); } *(SendStr+len)=(unsigned char)chksum; nBytesToWrite=len+1; if (WriteFile(hCom,(void *)SendStr,nBytesToWrite,&nBytesWritten,NULL)==0) { ProtError("Send in Sendrec"); return(0); } RestToRead=4; while (RestToRead>0) { if (ReadFile(hCom,(void )RdBuff,RestToRead,&nBytesRead,NULL)==0) { ProtError("Rec2 in Sendrec"); return(0); } RdBuff+=nBytesRead; TotalRead+=nBytesRead; RestToRead-=nBytesRead; } RestToRead=(InBuff+2)-TotalRead+4; while (RestToRead>0) { if (ReadFile(hCom,(void *)RdBuff,RestToRead,&nBytesRead,NULL)==0) { ProtError("Rec2 in Sendrec"); return(0); } RdBuff+=nBytesRead; RestToRead-=nBytesRead; } return(1); }
void ReSynch (void) { unsigned char OutBuff[255];
OutBuff[0]=0x12; OutBuff[1]=0xC0; OutBuff[2]=0x0; SendSeqNr=0; if (SendRec(OutBuff,3)) { if ((InBuff[0]==0x21)&&(InBuff[1]==0xE0)&&(InBuff[2]==0)) return; } ProtError("Resync gescheitert"); }
int CardCtrlComm (unsigned char *CtrlComm, int clclen, unsigned char *SendStr, int strlen) { int i; unsigned char SendBuff[255], *sd=&SendBuff[0], *lb=&SendBuff[2];
*(sd++)=0x12; *(sd++)=SendSeqNr; sd++; *(sd++)=0x20; *lb=1; for (i=0;i<clclen;i++) { *(sd++)=CtrlComm[i]; (*lb)++; } if (strlen) { *(sd++)=strlen; (*lb)++; for (i=0;i<strlen;i++) { *(sd++)=SendStr[i]; (*lb)++; } } if (!SendRec(SendBuff,SendBuff[2]+3)) return(0); if ((InBuff[0]!=0x21)&&(InBuff[1]!=SendSeqNr)) { ProtError("Req- ICC Fehler"); return(0); }
if (SendSeqNr==0) SendSeqNr=64; else SendSeqNr=0; return(1); }
int CardAnwComm (unsigned char *AnwComm, int anwlen, unsigned char *SendStr, int strlen, int *rlen) { int i; unsigned char SendBuff[255], *sd=&SendBuff[0], *lb=&SendBuff[2];
*(sd++)=2; *(sd++)=SendSeqNr; sd++; *(sd++)=0; *lb=1; for (i=0;i<anwlen;i++) { *(sd++)=AnwComm[i]; (*lb)++; } if (strlen) { *(sd++)=strlen; (*lb)++; for (i=0;i<strlen;i++) { *(sd++)=SendStr[i]; (*lb)++; } } if (!SendRec(SendBuff,SendBuff[2]+3)) return(0); if ((InBuff[0]!=0x20)&&(InBuff[1]!=SendSeqNr)) { ProtError("Req- ANW Fehler"); return(0); }
if (SendSeqNr==0) SendSeqNr=64; else SendSeqNr=0; rlen=(InBuff+2); if (*AnwComm==0xB0) (*rlen)-=3; return(1); }
int DLLExport ReadCard (unsigned char *Buffer) { unsigned char S1[5], S2[10], *Resp; int i, rlen;
ReSynch(); S1[0]=0x12; S1[1]=1; S1[2]=0; S2[0]=1; if (!CardCtrlComm(S1,3,S2,1)) return(0); Resp=InBuff+3; if ((Resp[0]==0x62)&&(Resp[1]==0)) { MessageBox(NULL,"keine Karte eingelegt !","Cardreader",MB_ICONHAND); return(0); } if ((Resp[0]!=0x90)&&(Resp[1]!=0)) { MessageBox(NULL,"noch mal versuchen !","Cardreader",MB_ICONHAND); return(0); } S1[0]=0xA4; S1[1]=4; S1[2]=0; S2[0]=0xD2; S2[1]=0x76; S2[2]=0; S2[3]=0; S2[4]=1; S2[5]=1; if (!CardAnwComm(S1,3,S2,6,&rlen)) return(0); Resp=InBuff+3; if ((Resp[0]==0x6A)&&(Resp[1]==0x82)) { ProtError("Appl. not found or Data incorrect"); return(0); } if ((Resp[0]!=0x90)&&(Resp[1]!=0)) { ProtError("Select incorrect !"); return(0); } S1[0]=0xB0; S1[1]=0; S1[2]=0; S1[3]=0; if (!CardAnwComm(S1,4,S2,0,&rlen)) return(0); // Resp=InBuff+3; Resp=InBuff+rlen+4; if ((Resp[0]==0x62)&&(Resp[1]==0x82)) { // end of data before ... OKAY ! } else if ((Resp[0]==0x65)&&(Resp[1]==1)) { ProtError("Memory corrupted !"); return(0); } else if ((Resp[0]==0x6B)&&(Resp[0]==1)) { ProtError("Wrong offset !"); return(0); } else if ((Resp[0]!=0x90)&&(Resp[1]!=0)) { ProtError("Read false response"); return(0); } if (rlen>256) rlen=256; for (i=0; i<rlen; i++) { switch(InBuff[i+3]) { case 0x8E: Buffer[i]=196; break; case 0x99: Buffer[i]=214; break; case 0x9A: Buffer[i]=220; break; case 0x84: Buffer[i]=228; break; case 0x94: Buffer[i]=246; break; case 0x81: Buffer[i]=252; break; case 0x7E: Buffer[i]=223; break; default : Buffer[i]=InBuff[i+3]; } } return(rlen); }
BOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL, // handle to DLL module DWORD fdwReason, // reason for calling function LPVOID lpReserved ) // reserved { // Perform actions based on the reason for calling. switch( fdwReason ) { case DLL_PROCESS_ATTACH: // Initialize once for each new process. // Return FALSE to fail DLL load. break;
case DLL_THREAD_ATTACH: // Do thread-specific initialization. break;
case DLL_THREAD_DETACH: // Do thread-specific cleanup. break;
case DLL_PROCESS_DETACH: // Perform any necessary cleanup. break; } return TRUE; // Successful DLL_PROCESS_ATTACH. }