Das IOWKIT2 API

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Post Reply
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Das IOWKIT2 API

Post by Robert Marquardt »

Hier will ich das neue IOWKIT2 API vorstellen. Es ist noch etwas im Fluss, aber eventuelle Aenderungen duerften eher klein sein.
Es kann jeder hier mitdiskutieren, wenn auch die Betatester natuerlich im Vorteil sind, da sie die Sourcen haben.
Bei guten Vorschlaegen aendern oder ergaenzen wird das 2.0 API gerne.

Gerade ist die Entscheidung gefallen das das alte API in einer Version 1.5 und das neue API 2.0 in einer DLL leben werden.
Ein Programm kann nur das eine oder das andere API verwenden. Gleichzeitig geht nicht.
Die Aenderungen von 1.4 zu 1.5 sind nur geringfuegig und beziehen sich auf einige Feinheiten des 2.0 APIs. Z. B. werden intern nun 128 Reports gepuffert statt der 8 des 1.4 APIs.
Das 1.5 API wird binaerkompatibel zum 1.4 API sein, d. h. die bisherigen Programme werden nach Tausch der DLL weiterhin funktionieren.

Es werden gerne weitere Betatester aufgenommen, besonders um das 1.5 API auf Kompatibilitaet zu testen.

Nun aber zum 2.0 API. Hier ein Ausschnitt der entscheidenden Teile des APIs.

Code: Select all

// This is a max report which can hold any IO-Warrior report
typedef struct _IOWKIT2_REPORT
 {
  UCHAR ReportID;
  UCHAR Bytes[IOWKIT2_REPORT_PAYLOAD_SIZE];
 }
  IOWKIT2_REPORT, *PIOWKIT2_REPORT;

typedef BOOL (IOWKIT2_API *IOWKIT2_DATA_EVENT)(IOWKIT2_HANDLE devHandle, ULONG numPipe, PIOWKIT2_REPORT report,
  ULONG size, ULONG Context);
typedef void (IOWKIT2_API *IOWKIT2_DEVICECHANGE_EVENT)(ULONG action, IOWKIT2_HANDLE devHandle, ULONG Context);

DWORD IOWKIT2_API IowKit2Initialize(IOWKIT2_DEVICECHANGE_EVENT Event, ULONG Context);
void IOWKIT2_API IowKit2Finalize(void);
ULONG IOWKIT2_API IowKit2Write(IOWKIT2_HANDLE devHandle, ULONG numPipe, PIOWKIT2_REPORT report);
int IOWKIT2_API IowKit2Read(IOWKIT2_HANDLE devHandle, ULONG numPipe, PIOWKIT2_REPORT report);
int IOWKIT2_API IowKit2ReadImmediate(IOWKIT2_HANDLE devHandle, ULONG numPipe, PIOWKIT2_REPORT report);
ULONG IOWKIT2_API IowKit2GetNumDevs(void);
ULONG IOWKIT2_API IowKit2GetProductId(IOWKIT2_HANDLE iowHandle);
ULONG IOWKIT2_API IowKit2GetRevision(IOWKIT2_HANDLE iowHandle);
HANDLE IOWKIT2_API IowKit2GetThreadHandle(IOWKIT2_HANDLE iowHandle, ULONG numPipe);
ULONG IOWKIT2_API IowKit2GetSerialNumber(IOWKIT2_HANDLE iowHandle);
BOOL IOWKIT2_API IowKit2SetTimeout(IOWKIT2_HANDLE devHandle, ULONG timeout);
BOOL IOWKIT2_API IowKit2SetWriteTimeout(IOWKIT2_HANDLE devHandle, ULONG timeout);
PCHAR IOWKIT2_API IowKit2Version(void);
BOOL IOWKIT2_API IowKit2Register(IOWKIT2_HANDLE devHandle, ULONG numPipe, IOWKIT2_DATA_EVENT Event, ULONG Context);
BOOL IOWKIT2_API IowKit2GetDeviceUse(IOWKIT2_HANDLE devHandle);
BOOL IOWKIT2_API IowKit2SetDeviceUse(IOWKIT2_HANDLE devHandle, BOOL Use);
void IOWKIT2_API IowKit2Enumerate(void);
int IOWKIT2_API IowKit2PendingReports(IOWKIT2_HANDLE devHandle, ULONG numPipe);
Es ist doch ziemlich aehnlich geblieben, obwohl es deutlich anders funktioniert.

Das erste neue Konzept sind Callbacks. Diese sind noetig, da die IO-Warrior nun dynamisch verwaltet werden, sprich die DLL bekommt mit ob ein IO-Warrior an- oder abgesteckt wird.
Die neue Initialisierungsfunktion IowKit2Initialize() hat deshalb den Funktions-Parameter Event. Jedes Mal wenn ein IO-Warrior an- oder abgesteckt wird, wird diese Event-Funktion aufgerufen. Fuer alle IO-Warrior, die beim Aufruf von IowKit2Initialize() bereits angesteckt sind, wird einfach ein Anstecken simuliert.

Das naechste neue Konzept ist das man einen IO-Warrior in Benutzung nehmen muss bevor man ihn zugreifen kann.
IowKit2SetDeviceUse() ist dafuer zustaendig. Der Grund dafuer ist das An- und Abstecken. Die interne Datenstruktur die einen IO-Warrior repraesentiert (IOWKIT2_HANDLE) darf ja nicht einfach geloescht werden, wenn der zugehoerige IO-Warrior abgesteckt wird. Es kann ja sein das der IO-Warrior vom Programm benutzt wird.
Bei unbenutzten IO-Warriors wird die Datenstruktur geloescht, waehrend sie bei benutzten IO-Warriors als Zombie-Struktur erhalten wird bis sie mit IowKit2SetDeviceUse() als unbenutzt gekennzeichnet wird.
Das bietet auch den Vorteil das bis zu 128 bereits gelesene und gecachte Reports auch nach dem Abstecken noch gelesen werden koennen.

IowKit2PendingReports() ist zum API dazugekommen um die Anzahl gerade gecachter Reports abzufragen. Es laesst sich nun mit IowKitReadImmediate() dieser Cache leerlesen, da man ja nun weiss wieviele Reports aus dem Cache erhaeltlich sind.

Der zweite Callback erlaubt es die Reports statt ueber IowKit2Read() oder IowKit2ReadImmediate() ueber einen Callback zu erhalten.
IowKit2Register() ist dafuer zustaendig. Es laufen nun auf allen Pipes interne Lesethreads, die die Report-Caches fuettern.
Bevor ein Report in den Cache eingefuegt wird, wird er per Callback gemeldet. Der Callback kann nun den Report begutachten und per Rueckgabewert bestimmen ob der Report in den Cache soll oder nicht.

Mit dieser Herangehensweise kann man nun verschiedene Strategien der Reportverarbeitung implementieren.
Man kann alle Reports im Callback verarbeiten und IowKit2Read() und IowKit2ReadImmediate() komplett unbenutzt lassen.
Man kann nur einige Reports im Callback ausfiltern und den Rest mit IowKit2Read() oder IowKit2ReadImmediate() wie bisher lesen.
Man kann wie bisher IowKit2Read() und IowKit2ReadImmediate() nutzen und keinen Callback verwenden.

Der Rest des APIs ist nur maessig veraendert. Es wurden einige Vereinfachungen vorgenommen. IowKit2Write() z. B. braucht keine Groessenangabe fuer den Report mehr.
Die Reportstruktur ist nun gross genug um jeden IO-Warrior-Report aufnehmen zu koennen. Beim Schreiben an einen bestimmten IO-Warrior ist ja klar welchen Report er erwartet und es kann intern entschieden werden wieviele Bytes zu schreiben sind.

Einige andere weniger augenfaellige Einschraenkungen des APIs wurden durch die Vereinfachungen ebenfalls aufgehoben. Mehr will ich dazu nicht sagen, da es sich auf zukuenftige Produkte bezieht.

Das 2.0 API hat nur eine kleine Einschraenkung in der Anwendbarkeit under Windows.
Es wird intern ein Fenster erstellt, da Windows das An- und Abstecken von Geraeten mit Messages signalisiert. Verarbeitet und verteilt nun das Traegerprogramm der DLL keine Messages, so bekommt die DLL nichts von den Geraeteaenderungen mit und kann nicht funktionieren.
Dies sollte allerdings nur reine Konsolenanwendungen betreffen. Java-Programme sind zwar erst mal Konsolenanwendungen, aber die Java-VM betreibt Messageverarbeitung was das Problem loest.
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Re: Das IOWKIT2 API

Post by wayoda »

Robert Marquardt wrote: Gerade ist die Entscheidung gefallen das das alte API in einer Version 1.5 und das neue API 2.0 in einer DLL leben werden.
Ein Programm kann nur das eine oder das andere API verwenden. Gleichzeitig geht nicht.
Der erste Satz klingt eindeutig, aber trotzdem:
Warum nicht 2 DLL's IowKit.DLL und IowKit2.DLL ?
Soweit ich bisher mitgelesen habe gibt es keine Bug-Reports (mehr) zu Version 1.4 . Der Plegeaufwand von Codemercs-Seite für diese Version sollte in Zukunft also gering sein.

Die Version2.0 benutzt dann das neue Konzept, für die neue Applikationen geschrieben werden müssen.

Das ganze in eine DLL zu packen führt meiner Meinung nach nur zur Verwirrung der Anwendungsprogrammierer und lustigen Fehlern wenn man zwar Gleichzeitig geht nicht. gelesen hat, aber es trotzdem tut.
Das belebt zwar das Forum, aber andererseits macht es nicht wirklich Spaß solche Topics zu beantworten, oder?

Gute Voraussetzungen für ein erfolgreiches Programmieren sind :
Eine klare, einfache Schnittstelle und dazu eine saubere Dokumentation.

Das Zusammenfassen beider Versionen hätte aber zur z.B. Folge das es z.B. 2 Funktionen mit ähnlichem Namen (abgesehen von der 2) IowKitReadImmediate gibt, mit unterschiedlichen Parametern und Rückgabewerten.
Da wird es nicht lange dauern bis ein Anwender der eigentlich mit Version1.4 arbeiten wollte, neidisch auf die 2.0 Version der Funktion schielt, die auch nicht blockierendes Lesen von Special-Mode Daten erlaubt (was unter 1.4 eben nicht geht). Gleichzeitig geht nicht. ist zwar nett, aber ein Compiler (Linker)-Fehler ist eben eindeutiger.

eberhard
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Wie wär's noch mit einer kleinen Entschlackungkur für Version 2.0!

Mir fallen bei Verwendung des neuen API keine guten Gründe für eine weitere Verwendung der blockierenden Lesefunktionen Iowkit2Read ein.
Mit den Optionen Callback und ReadImmediate ist doch eigentlich alles abgedeckt, ob man nun Threads verwendet oder nicht.

Weiterhin erscheint mir auch der einstellbare Timeout bei IowkitWrite überflüssig zu sein. Wenn ich das richtig verstanden habe legt die 2.0 Spezifikation des USB-Bus (Kapitel 9.2.6.1) hier einen maximalen Wert von 5 Sekunden fest. Ob es möglich ist hier einen sinnvollen Wert unterhalb dieser 5 Sekunden festzulegen scheint mir daher auch fraglich.

Nach der Devise Small is beautiful würde ich also mal zur Diskussion stellen, ob die Funktionen
Iowkit2Read
IowKit2SetTimeout
IowKit2SetWriteTimeout
nicht einfach entfallen könnten.

Eberhard
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

Die Sourcen sind leichter zu warten wenn sie in einem Projekt zusammengefasst werden.
Es wird nicht 1.4 sondern 1.5 sein, das intern ueber 2.0 implementiert wird (funktioniert schon fast).

Es gibt zwei getrennte Include-Files. Nur wer beide benutzt kann auch beide APIs aufrufen. Auch in der Dokumentation bleiben die APIs getrennt.
Guido Körber
Site Admin
Posts: 2880
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

D.h. wir legen die 1.5 als Kompatibilitätslayer auf die 2.0 um existierende Programme weiter zu unterstützen. Irgendwann wird die 1.5 API wegfallen.

Wenn wir die 2.0 auf MacOS X aufsetzen wird es da die 1.5 Schnittstelle garnicht erst geben, weil es die vorher da auch nicht gab.
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Guido Körber wrote:D.h. wir legen die 1.5 als Kompatibilitätslayer auf die 2.0 um existierende Programme weiter zu unterstützen. Irgendwann wird die 1.5 API wegfallen.
Das verstehe ich jetzt nicht (möglicherweise weil ich dies unter linux schreibe)!

Ich dachte der Sinn von der gemeinsamen DLL wäre es die binär-kompatiblität von 1.5 zu erhalten. Soweit mir bekannt kann man aber dann doch nicht später mal einfach die 1.5 Funktionen wieder herausnehmen, weil sich damit die Einsprungadressen der 2.0 Version automatisch nach vorne verschieben, oder?

Wie gesagt, das Thema hab ich nur mal angelesen...

Eberhard
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

Eine Funktion in einer DLL unter Windows wird ueber Index oder Name angesprochen.
Das .def File bei Windows regelt die Zuweisung des Index zu der Funktion.
Fuer die 1.5/2.0 DLL gilt das die Indexnummern der 1.4 DLL beibehalten werden muessen, da C/C++ Programme ueblicherweise ueber den Index linken. Waere der Index vorhanden aber einer anderen Funktion zugeordnet, dann gibt es einen Crash.
Faellt irgendwann mal das alte API weg, so bleiben die Indexnummern des neuen API unveraendert und nur die Indexnummern fuer das alte API entfallen.
Programme fuer das alte API starten dann garnicht mehr und melden das sie die Funktionen in der DLL nicht finden.

Bei Linux wird sowieso ueber den Namen der Funktion gelinkt, also finden oder nicht finden anhand des Namens.
Post Reply