![]() |
CT - Api / Chipkarten
Hallo Leute,
ich sitze hier an einem Delphi Projekt und komme einfach nicht so recht weiter. Ich muss die Daten einer Chipkarte auslesen ( Krankenkassenkarte ) Eine Verbindung zum Cardreader stelle ich über die bekannte CT-Api Schnittstelle her. Die CT-Api dll habe ich eingebunden und über eine import unit die berühmten Funktionen CT_init, CT_data und CT_close nach Delphi geholt. Das alles klappt auch ohne Probleme, daher gehe ich davon aus, das ich bei der Definition der Funktionen keine Fehler gemacht habe. Das initalisieren über CT_init und der Close über CT_close funktionieren auch ohne Probleme. Nur mit dem CT_data Befehl tue ich mir schwer. Sobald ich den meiner Meinung nach richtigen Befehl starte bekomme ich regelmäßig eine Access Violation . Ich gehe davon aus, daß der Fehler in der Definition des commands liegt. Laut Beschreibung wird hier ein Zeiger ( Pointer ) auf eine Adresse mit dem command verlangt. Die Variable soll laut Beschreibung von der Form "byte" sein. Also habe ich ein Array of Byte definiert . Darin dann die einzelnen Hex Angaben ( in der Form $00 ) abgelegt . In der Doku ist leider nur ein VB Beispiel. Dort wird in der command Sektion einfach ein Verweis auf das erste Element des Byte Arrays gesetzt. Also in der Command Sektion einfach command [0] angegeben. Das funktioniert aber offensichtlich nicht. Dann versuchte ich, einen Pointer auf das Byte Array zu setzen und diesen anzugeben. Auch das wurde mit gleicher Fehlermeldung quittiert. Lange Rede, kurzer Unsinn: Weiss jemand wie man einen command für die Funktion CT_data richtig angibt ? Ich bin in Pointersachen leider ziemlich unerfahren. Bin für jeden Hinweis dankbar, Bis dann, Stephan PS: Wer bis hierhin gelesen hat, bekommt eine öfffentlich Belobigung ! Ich verspreche meine weiteren Beiträge hier werden kürzer !!! :mrgreen: |
Re: CT - Api / Chipkarten
poste mal 'n Stück Code - macht es leichter Käfer zu suchen, auch wenn ich Dir wahrscheinlich nicht helfen kann, so doch für Andere
Gruß |
Re: CT - Api / Chipkarten
Hallo Leuselator !
Hm, dachte ich mir ja, Problem ist nur, das ich im Moment den Code zu Hause habe und hier in der Mittagspause auf der Arbeit sitze. Schiebe heute abend die Codeparts nach. Vielleicht fällt Dir ja was dazu ein. Bis dann, Stephan |
Re: CT - Api / Chipkarten
Ich riskiere hier jetzt einfach mal nen Blindschuss... ich habe kein CardTerminal und deshalb auch keine ct-api... Und da das SDK kostenpflichtig zu sein scheint, ist es irgendwie auch nicht so einfach, nähere Informationen zu bekommen.
Das was ich jetzt hier mal testweise zusammengefummelt habe, fusst alles auf Informationen aus ![]()
Delphi-Quellcode:
Wie gesagt, ist ein "kalt" geschriebenes Programm, da ich es nicht testen kann.
// Ich vermute, die Funktionen müssten so oder so ähnlich deklariert sein bzw. werden
function CT_Init(const ctn, pn: Word): ShortInt; function CT_Data(const ctn: Word; var dad, sad: Byte; const lenc: Word; command: Pointer; var lenr: Word; response: Pointer): ShortInt; function CT_Close(const ctn: Word): ShortInt; procedure TestCT; const OK = 0; // Fehlercodes stehen noch mehr im Dokument var ctn, lenr: Word; dad, sad: Byte; command: Array of Byte; response: Array[0..1000] of Byte; Res: ShortInt; begin ctn := 1; // Terminal 1 an Comport 2... if CT_Init(ctn, 2) = OK then begin sad := 2; // Source = Host dad := 1; // Destination = Terminal lenr := SizeOf(response); command[0] := $20; // Commandobytes command[1] := $12; {...usw...} Res := CT_Data(ctn, dad, sad, SizeOf(command), @command, lenr, @response); CT_Close(ctn); end; end; Ich hoffe, das das eher hilfreich als verwirrend ist - mich würde dann am Ende auch mal interessieren, wie weit ich denn nun daneben lag. :mrgreen: Gruß Wormid |
Re: CT - Api / Chipkarten
Hallo Wormid,
danke für die rasche und ausführliche Hilfe ! Leider hat es nicht funktioniert. Wenn ich bei CT_data mein commando[0] durch Dein @commando ersetze funktioniert zwar die Compilierung aber der Fehler bleibt der gleiche: "EAccessViolation bei Adresse 10016D9 in Modul CTORG32.DLL" (Die Dll ist die CT-Api) Habe ich eine Chance irgendwie zu ermitteln welche Stelle genau den Fehler verursacht ? In einer Dll wohl weniger oder ? Hier mein Code mit dem ich es versuche: ************************************************** ******************** procedure TForm1.Button3Click(Sender: TObject); var daten:kdaten; rueckgabe:word; commando:array of byte; speicher:array of byte; begin // Select file legt die zu empfangende Datensection fest ! setlength(speicher,2); setlength(commando,8); commando[0]:=$00; commando[1]:=$04; commando[2]:=$00; commando[3]:=$88; commando[4]:=$02; commando[5]:=$3F; commando[6]:=$00; rueckgabe:=CT_data(1,02,01,Sizeof(commando),@comma ndo,2,@speicher); showmessage(inttostr(rueckgabe)); end; ************************************************** ******************* Wie gesagt, davor funktioniert der CT_init, der Terminal sollte also bereit sein. Die ganze Zeit bin ich davon ausgegangen, daß wenn ich die Funktion aus der Dll geholt habe und das Programm compiliert bei der Angabe der Parameter kein Fehler mehr vorliegen kann. Durch Probieren habe ich nun gemerkt, daß man sehr wohl völlig falsche Parameter definieren kann ( Byte statt Pointer ) und keine Exception beim Programmstart auftritt. Es könnte also sein das es schon an der Definition liegt. ***************** function CT_init(ctn:word;pn:word):word;stdcall; external 'CTORG32.DLL' function CT_data(ctn:word;dad:byte;sad:byte;lenc:word;comma nd:pointer;lenr:word;response:pointer):word;stdcal l;external 'CTORG32.DLL'; function CT_close(ctn:word):shortint;stdcall; external 'CTORG32.DLL' ***************** ´ So langsam werde ich ziemlich hilflos. Das muss doch irgendwie zu machen sein...... Stephan |
Re: CT - Api / Chipkarten
Wie sieht das mit der Variable "speicher" aus? Ist die mit 2 Bytes groß genug für die Rückgabe? Außerdem muss "lenr" als Variable übergeben werden, weil CT_Data wohl die tatsächliche länge der Antwort in "speicher" angibt.
Gruß Wormid P.S. Ansonsten weiss ich allerdings auch nicht weiterr.... :( |
Re: CT - Api / Chipkarten
Zitat:
Statt Sizeof(Command) nimm Length(Command), da Command als dynamisches array of Byte deklariert wurde. @Command = @Array of Byte = @Pointer = Zeiger auf Zeiger ist ebenfalls falsch. Die CT Library überschreibt somit die internen Verwaltungsdaten des dynamischen Arrays. Statt @Command benutze bitte @Command[0] oder Pointer(Command). Gruß Hagen PS: Ich wusste garnicht das man mir dem CT API Speicherkarten auslesen kann ? Normalerweise konnte man früher nur echte Prozessorkarten über deren ADPU ansprechen ! |
Re: CT - Api / Chipkarten
Öhm... merkt man das, das ich mir im Umgang mit Pointer auch nicht sicher genug bin, um damit auf dem Papier zu programmieren... :oops:
Aber man lernt ja nie aus. :hi: |
Re: CT - Api / Chipkarten
Halli Hallo !
@wormid : He, das war doch garnicht so schlecht. Trotzdem Danke .... @Hagen : Hm, ich habe Deine Änderungen eingebunden aber die Fehlermeldung bleibt die gleiche. Da scheint irgendwas generelles nicht zu stimmen. Hast Du mit der CT-Api gearbeitet ? Könntest Du mir einfach mal eine Rountine geben wie Du CT_data angesprochen hast ? Ich komme einfach nicht auf meinen Fehler. Ich schätze mal es ist mittlerweile ein ganz trivialer, ich komme nur nicht dahinter. Schon mal Danke, Stephan |
Re: CT - Api / Chipkarten
Nein, ich habe nicht mit der CT API gearbeitet, ich habe sie nur überflogen und analysiert. Für meine Zwecke war sie damals unzureichend und zu kompliziert. Nach meinem Wissenstand konnte die CT API damals überhaupt keine Speicherkarten o.ä. Nicht-Prozessorkarten ansteuern.
Chipkarte ist nicht gleich Chipkarte. Eine Speicherkarte hat ein echt primitiven Aufbau im Vergleich zu Prozessorkarten. Gruß Hagen |
Re: CT - Api / Chipkarten
Schade,
aber trotzdem vielen Dank für die Hilfestellung. Vielleicht bin ich auch einfach zu blöd dafür. Es ist warscheinlich irgendwas total einfaches...... So,Also : irgendjemand da draussen der jemanden kennt der einen kennt der schon mal mit der CT-Api und Delphi gearbeitet hat :zwinker: ? Das wäre toll...... Stephan |
Re: CT - Api / Chipkarten
Ich habe mal in die CT-API geschaut und da ist mir aufgefallen, dass sowohl
command als auch response als Variablentyp iu8 haben, und das ja eigentlich nicht direkt dem Typ Pointer entspricht!? Peter |
Re: CT - Api / Chipkarten
Hallo Peter,
hm, bei mir in der Beschreibung der CT-Api steht command : Referenzadresse eines Feldes mit Elementen vom Typ IU8. Das Gleiche bei response. Wo hast Du das gefunden ? Vielleicht habe ich ja eine falsche Doku..... Obwohl, ich sehe gerade in der Beschreibung direkt vom Hersteller des Readers steht: valid memory adress of field variable holding the chipcard Terminal command. Stephan |
Re: CT - Api / Chipkarten
Ich habe gerade gesehen, dass das je nach Beschreibung etwas
unterschiedlich ausfällt! Aber ein Blick in die Ctapi.h bringt für mich endgültige Verwirrung, denn da steht: char MSWIN_API CT_data (unsigned short ctn, unsigned char * dad, unsigned char * sad, unsigned short lenc, unsigned char * command, unsigned short * lenr, unsigned char * response ); Und als Beschreibung: Input Paramter: 'dad' = Pointer / memory address of variable holding the "Destination ADdress". ( pointer to "IU8" ("integer unsigned, 8 bit") ) MUST NOT BE 'NULL'! 'sad' = Pointer / memory address of vatiable holding the "Source ADdress". ( pointer to "IU8" ("integer unsigned, 8 bit") ) MUST NOT BE 'NULL'! 'lenr' = Pointer / memory address of variable holding the "LENgth Response". Length of 'reponse'-buffer in bytes. ( pointer to "IU16" ("integer unsigned, 16 bit") ) MUST NOT BE 'NULL'! u.s.w. Das heißt also dad, sad, lenr sind auch Pointer auf einen iu8 oder iu16 Typ!? Leider bin ich des Visual Basic nicht mächtig genug um das an dem Beispielprogramm abzuchecken, aber die Zeile: Private Declare Function CT_data Lib "CTORG32.DLL" Alias "CTDEORGT1_data" ( _ ByVal ctn As Integer, dad As Byte, sad As Byte, ByVal lenc As Integer, _ command As Byte, lenr As Integer, response As Byte) As Byte sieht meiner Ansicht nach auch danach aus! Peter |
Re: CT - Api / Chipkarten
Hm,
das wäre natürlich ein Ding. Bei mir in der Beschreibung steht definitiv drin das diese Angaben keine Pointer sind. Den Header habe ich mir nicht angeschaut, weil ich in den Sprachen sowieso nicht so fit bin. Ich werde es aber heute abend mal ausprobieren. Könnte natürlich die Lösung sein. Würde die EAccessviolation erklären. Falls es das ist hast Du was bei mir gut !!!! Stephan |
Re: CT - Api / Chipkarten
Ja,
was soll ich sagen, es sieht wirklich so aus, als ob da meine Beschreibung was verschweigt. Nachdem ich mir den header genau angesehen habe muss ich Dir absolut Recht geben, sowohl dad als auch sad und lenr sind wohl pointer. Also, das alles flux nach bestem Wissen und Gewissen umgesetzt und siehe da: Keine EAccessviolation mehr ! Aber es funzt immer noch nicht. Jetzt bekomme ich als Rückmeldung von 65585. Als letzte Bitte an alle hier noch einmal über die Pointerdefinitionen zu schauen, da ich dort echt absoluter Anfänger bin:
Delphi-Quellcode:
Ist das alles logisch ?
// Einbinden der Dll Funktion CT_data
function CT_data(ctn:word;dad:pointer;sad:pointer;lenc:word;command:pointer;lenr:pointer;response:pointer):word;stdcall;external 'CTORG32.DLL'; procedure TForm1.Button3Click(Sender: TObject); var daten:kdaten; rueckgabe:word; sad,dad:byte; lenr:word; commando:array of byte; speicher:array of byte; begin // Select file legt die zu empfangende Datensection fest ! setlength(speicher,22); setlength(commando,28); commando[0]:=$00; commando[1]:=$A4; commando[2]:=$00; commando[3]:=$88; commando[4]:=$02; commando[5]:=$3F; commando[6]:=$00; dad:=02; sad:=01; lenr:=28; rueckgabe:=CT_data(1,@dad,@sad,length(commando),@commando[0],@lenr,@speicher[0]); showmessage(inttostr(rueckgabe)); end; Danke und versprochen, ich werde euch dann nicht mehr nerven. Werde dann alleine weiter kämpfen. Gruß, Stephan |
Re: CT - Api / Chipkarten
Hallo Stephan,
der Rückgabewert ist nicht word sondern shortint! Und wenn ich mich recht erinnere, solltest du dann statt 255 den Rückgabewert 0 (OK) bekommen. Peter |
Re: CT - Api / Chipkarten
Ich hatte das Problem auch. Hast du auch alles mit stdcall aufgerufen? Auf jeden Fall hatte ich ne Zeit lang nur Exceptions. Mein Ansatz war, alles dynamisch aufzurufen und ein simples Exception Handling drüber zu stülpen. Ach, und übrigens: Du darfst die ctapi.dll NICHT UNLOADEN. Mache dein FreeLibrary in den finally-Term der Hauptprozedur! Denn intern wird die ctn gelöscht, sobald du die dll befreist. Dann greift der Aufruf immer ins Leere.
Ich hätte ein paar fertige Stücke Code zu dem Thema (Karte auslesen etc. funktioniert reibungslos), jedoch würde ich vorher gerne erfahren, worin dein Projekt besteht. :?: Grüße, Chris |
Re: CT - Api / Chipkarten
Hallo Chris,
na da ist ja mal einer der das schon mal unter Delphi gemacht hat. Ich habe schon tagelang das Netz durchforstet nach Delphi / CT-Api Kombinationen aber wenn gibt es die Infos nur in VB oder für Linux und das kann ich alles nicht so gut portieren. Mit stdcall habe ich schon alles aufgerufen, das stimmt wohl. Das Problem beschränkt sich auf die Funktion CT_data. CT_init und CT_close liefert jeweils die 0 als Rückgabewert. Hm, klar an einer Hilfe in Form von Code wäre ich natürlich sehr interessiert. Und verständlich ist, das Du vorher wissen willst um was es geht, am Ende gibst Du Deinen Code her und ein anderer verdient sich damit eine goldene Nase: Ein Bekannter hat ein Programm für Ärzte entwickelt. Da werden jetzt überall diese Chipcardreader eingesetzt. Er braucht die Daten für sein Programm und fragte mich, ob ich da nicht was programmieren könnte. Weil es mich brennend interessiert hat habe ich ja gesagt. Leider bin ich in Sachen Pointer, Dll Aufrufe etc ziemlich unerfahren. Ich habe mich da jetzt schon ganz schön reingelesen, aber an manchen Stellen happert es einfach noch ein wenig mit dem Verständnis. Geld: Es wird wohl dafür nicht viel Geld geben. Ich hatte mir sowieso schon überlegt, der Community hier was zu spenden (wenn das geht) falls ich das Problem mit Hilfe von Delphipraxis gelöst bekomme. Man kann ja nicht immer nur einfach den Honig saugen und dann nichts zurückgeben. (Ich weiss garnicht ob das geht, aber Geld für neue Hardware oder anderes wird wohl immer gebraucht) Wenn Du damit leben kannst kommen wir da zusammen. Das wird dann ganz offiziell gemacht. Aber wenn Du sagst "ich hätte auch gerne was davon" ist das auch kein Problem. Nur im Moment kann ich Dir noch nicht sagen ob und wenn ja wie viel es dafür gibt. Es kann sein, daß ich da was fertig habe und mein Bekannter dann sagt " Ne hat mir zu lange gedauert, habe es wo anders machen lassen". Wie gesagt, ich mache es in erster Linie aus Interesse an der Technik und um einfach Erfahrung zu sammeln. Bis dann, Stephan PS: Code wäre richtig cool !!! |
Re: CT - Api / Chipkarten
Also gut, mein Code ist auch noch nicht fertig, ich bin momentan dabei, den ATR auszuwerten und dann daraus dynamisch auf das korrekte Ausleseverfahren (bzw. Parserfunktion) für die Karte zu schließen. (ASN.1 oder Festform).
Ich kann dir jedoch die korrekten Header Files als .pas geben. Die sind eh' öffentlich und unterliegen der GPL. OK, die C-Version unterliegt der GPL, aber wir woll'n mal nich so sein. Das eigentliche Programm kann ich dir aber nicht geben, da ich ebenfalls für einen Kumpel ein kommerzielles Plugin schreibe. Beachte, dass ich eine im Ordner vorhandene ctorg32.dll voraussetze. Somit ist das Programm oberflächlich nur zu Orga kompatibel. Die eigentlichen Funktionen sind jedoch alle generisch, so dass eine Änderung des Dateinams genügen sollte. Ich poste hier mal einen Teil des Codes, den Rest gibts wenn du mir ne PN mit deiner Mailaddi schickst. |
Re: CT - Api / Chipkarten
Einmal die CT_data:
Delphi-Quellcode:
Und der DLL-Aufruf zu Beginn der Hauptprozedur:
function CT_data( ctn: Word;
dad, sad: PByte; lenc: Word; command: PByte; lenr: PWord; response: PByte ): ShortInt; begin Result := ERR_TRANS; if @Function_CTdata <> nil // now calling function from driver DLL then try Result := Function_CTdata(ctn,dad,sad,lenc,command,lenr,response); except Result := ERR_INCOMPATIBLE; end; end;
Delphi-Quellcode:
function CTAPI_Load(path: PChar): Integer;
begin Result := ERR_UNKNOWN; DLLHandle := LoadLibrary(path); if DLLHandle <> 0 then begin @Function_CTinit := GetProcAddress(DLLHandle, 'CT_init'); @Function_CTdata := GetProcAddress(DLLHandle, 'CT_data'); @Function_CTclose:= GetProcAddress(DLLHandle, 'CT_close'); if (@Function_CTinit = nil) or (@Function_CTdata = nil) or (@Function_CTclose = nil) then Result := ERR_INCOMPATIBLE; end else Result := ERR_LIBRARY; end; |
Re: CT - Api / Chipkarten
Hi. Vielleicht wär's auch ganz sinnvoll, wenn du nicht sofort mit dem Select File um dich schlagen würdest. Ohne einen Reset der Karte wird der eh nur Fehlercodes ausgeben.
Also: Mühsam ernährt sich das Eichhörnchen. Fang doch lieber erst mal damit an, das CT zu resetten und den Status abzufragen. Die Definitionen zu den Befehlen findest du im Netz, u.a. bei Sourceforge! |
Re: CT - Api / Chipkarten
Halli Hallo !
Mit einigen Änderungen die ich aus Deinem Code ersehen konnte habe ich das erste Mal bei CT_data und einem Reset des Gerätes ein result von 0 !!! COOL!Vielen Dank ! Ich werde mich jetzt erst mal aufs Ohr hauen, bin nämlich ziemlich erkältet. Morgen werde ich mal weiter machen. Hast Du meine PP bekommen ? Ich war mir da nämlich nicht so sicher ob das alles funktioniert hat. Egal, danke, Stephan |
Re: CT - Api / Chipkarten
Äh,
ich meine natürlich PN !! Ah, ab ins Bett..... ;-) |
Re: CT - Api / Chipkarten
Ist angekommen. Morgen oder übermorgen bekommst du den Code. Hab momentan etwas viel zu tun.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz