Ovladače vstupně/výstupních zařízení tvoří samostatné komponenty systému, které se do systému Control Web zařazují jako dynamicky linkované knihovny (DLL) až podle potřeby při návrhu aplikace nebo při jejím spuštění. Každá taková knihovna proto musí mít jednotné rozhraní (interface), které je tvořeno skupinou procedur a funkcí. Říkáme, že knihovna tyto procedury a funkce vyváží. Pro ovladače systému Control Web bylo vytvořeno rozhraní, které se postupem času stabilizovalo a které se snaží obsáhnout pokud možno co nejvíce variant v chování připojených zařízení. Při návrhu jednoduchého ovladače je proto možno použít pouze některé procedury a funkce rozhraní, přičemž ostatní musí být nadefinovány a implementovány jako prázdné. U komplexnějších ovladačů pak budou zřejmě využity všechny nebo většina těchto procedur a funkcí. V současné době existují dvě rozhraní ovladačů. První rozhraní bylo definováno pro Control Web verze 3.x. V nové verzi systému Control Web 2000 (verze 4.x) je toto rozhraní rozšířeno. Pro zachování kompatibility zpět musí ovladače s novým rozhraním implementovat všechny procedury a funkce rozhraní původního. Samozřejmé je, že ovladače s rozhraním starým budou pracovat i s novými verzemi produktu Control Web.
Rozhraní ovladače (3.x) je tvořeno následujícími procedurami a funkcemi:
Rozšířené rozhraní (4.x) je doplněno o následující procedury a funkce:
Callback procedura ovladače:
unsigned Version()
Vrací číslo verze rozhraní (API) ovladače. Číslo verze je složeno ze dvou částí (vyšší slovo - major version, nižší slovo - minor version). Pro major version platí, že musí mít hodnotu 3, minor version má různou hodnotu podle toho, jaké rozhraní ovladač implemetuje.
Návratová hodnota:
char Check(unsigned szErrorString, char *ErrorString, unsigned CWVersion, unsigned MajorVersion, unsigned MinorVersion, unsigned APIMajorVersion, unsigned APIMinorVersion);
Volá se po zavedení DLL knihovny pro zjištění kompatibility ovladače s API. Všechny ovladače, které jsou nezávislé na API systému Control Web mohou vrátit hodnotu 1.
Parametry:
Návratová hodnota:
void GetDriverInfo(unsigned szDriverName, char *DriverName);
Vrací jméno ovladače pro zobrazení v inspektoru ovladačů.
Parametry:
HANDLE MakeDriver();
Vytvoří novou instanci ovladače a vrací její handle do systému. Systém pak volá všechny ostatní procedury a funkce ovladače s parametrem hDriver, kterým je právě tento handle. Jako handle může být vrácen např. ukazatel na alokovaná data ovladače nebo ukazatel na objekt ovladače a podobně.
Návratová hodnota:
void DisposeDriver(HANDLE hDriver);
Volá se při ukončení aplikace nebo při odinstalování ovladače, který byl spuštěn samostatně. Toto volání následuje za voláním procedury Done.
Parametry:
char Init(HANDLE hDriver, unsigned szParamFileName, char *ParamFileName, unsigned szInitMessage, char *InitMessage, unsigned LoginLevel, char RunningFlag, HANDLE CBHandle, tDriverCallback DriverCallback );
Volá se po zavedení ovladače do paměti a slouží k inicializaci ovladače. Parametr InitMessage při vstupu do procedury obsahuje symbolické jméno ovladače, pod kterým vystupuje v aplikaci. Procedura vrací hodnotu 1, když inicializace ovladače proběhla korektně. V případě, že se inicializace nezdařila, vrátí hodnotu 0 a parametr InitMessage musí obsahovat hlášení, které bude následně vypsáno v chybovém okně.
Parametry:
Návratová hodnota:
void Done(HANDLE hDriver);
Volá se při ukončení činnosti ovladače, tj. při zastavení aplikace nebo při odinstalování ovladače spuštěného samostatně, ale také po chybě při inicializaci ovladače. Toto volání předchází volání DisposeDriver.
Parametry:
char BufferInfo(HANDLE hDriver, unsigned ChannelNumber, unsigned char BType, unsigned long BLen);
Tato procedura je dotazovací funkcí, ověřující schopnost ovladače spolupracovat s kanálem typu buffer definovaných vlastností. Tyto informace jsou čerpány z bloku definice kanálů (v případě deklarace v grafickém prostředí jsou získány nejprve z příslušného souboru '*.dmf'). V případě, že ovladač podporuje spolupráci s kanálem typu buffer daných vlastností, vrací procedura hodnotu 1, jinak hodnotu 0.
Parametry:
Návratová hodnota:
Poznámka:
Procedura je volána jádrem systému postupně při zpracování sekce definice kanálů.
Pokud procedura vrátí negativní výsledek, je překlad aplikace přerušen a oznámena
chyba.
void SetBufferAddr(HANDLE hDriver, unsigned ChannelNumber, HANDLE PBuffer);
Pro každý ověřený kanál (předchozím voláním BufferInfo) je jádrem systému volána tato procedura. Slouží k předání informace o adrese bufferu ovladači. Tato adresa se za běhu aplikace nemění.
Parametry:
void InputRequest(HANDLE hDriver, unsigned ChannelNumber);
Procedura slouží k předání požadavku na získání hodnoty kanálu ovladače. V rámci právě zpracovávaného časového kroku se volá postupně pro všechny požadované kanály. Zadávání požadavků se ukončí voláním procedury InputRequestCompleted. Další požadavek na stejný kanál může přijít až po dokončení komunikace a potvrzení procedurou InputFinalized.
Parametry:
void InputRequestCompleted(HANDLE hDriver);
Procedura ukončí zadávání požadavků na čtení kanálů ovladače (InputRequest). V tomto okamžiku může ovladač zahájit činnost vedoucí k získání všech požadovaných hodnot (zahájení měření, komunikace apod.).
Parametry:
char InputFinalized(HANDLE hDriver, unsigned ChannelNumber, unsigned *ErrorCode );
Volá se po zadání požadavků na čtení kanálů a zahájení operací čtení (InputRequestCompleted) postupně pro všechny požadované kanály. Vrací hodnotu 1, je-li operace ukončena. Nejsou-li hodnoty kanálů ještě k dispozici, vrátí hodnotu 0 a parametr ErrorCode s hodnotou ceOK. V tomto případě je nutno po doměření nebo po chybě zavolat proceduru DriverCallback s funkčním kódem dcfDriverInputFinalized. To způsobí opětovné volání procedury InputFinalized, která může nyní vrátit hodnotu 1. Dojde-li k chybě, musí být nastaven parametr ErrorCode na hodnotu ceTimeout nebo ceValue a do okna zpráv systému se vypíše chybové hlášení.
Parametry:
Návratová hodnota:
void GetInput(HANDLE hDriver, unsigned ChannelNumber, TValue *ChannelValue);
Pomocí této procedury se přečte hodnota kanálu z ovladače a zapíše se do tabulky aktuálních hodnot kanálů, kde je k dispozici pro všechny virtuální přístroje. Hodnota kanálu se přenáší proměnnou ChannelValue, která je typu TValue. Je to variantní záznam, který je složen z položky Type a podle ní dále z položky obsahující vlastní hodnotu. Před naplněním hodnoty záznamu je nutno otestovat, jestli souhlasí Type. V případě kanálu typu string je nutno dále testovat ukazatel na řetězec ValPString na různost od null. Tento ukazatel nesmí být přepsán ani odalokován. Řetězec, který se přenáší z ovladače do aplikace je nutno zkopírovat na adresu, na kterou ValPString ukazuje.
Tato procedura je volána v případě ovladače s rozhraním 3.x, to znamená v případě, že ovladač nemá implementovány procedury a funkce rozhraní 4.x.
Parametry:
void GetInput2( HANDLE hDriver, unsigned ChannelNumber, TValue *InputValue, unsigned *QOS, timeStamp *TimeStamp );
Pomocí této procedury se přečte hodnota kanálu z ovladače a zapíše se do tabulky aktuálních hodnot kanálů, kde je k dispozici pro všechny virtuální přístroje. Hodnota kanálu se přenáší proměnnou ChannelValue, která je typu TValue. Je to variantní záznam, který je složen z položky Type a podle ní dále z položky obsahující vlastní hodnotu. Před naplněním hodnoty záznamu je nutno otestovat, jestli souhlasí Type. V případě kanálu typu string je nutno dále testovat ukazatel na řetězec ValPString na různost od null. Tento ukazatel nesmí být přepsán ani odalokován. Řetězec, který se přenáší z ovladače do aplikace je nutno zkopírovat na adresu, na kterou ValPString ukazuje. Kromě hodnoty kanálu se pomocí této procedury přenáší do aplikace ještě informace o kvalitě (QOS) a časová značka (TimeStamp), tj. čas, kdy byla hodnota získána. Obě tyto informace jsou dosažitelné jako atributy kanálů.
Tato procedura je volána v případě ovladače s rozhraním 4.x namísto procedury GetInput.
Parametry:
void OutputRequest(HANDLE hDriver, unsigned ChannelNumber, TValue ChannelValue);
Procedura slouží k předání požadavku na zápis hodnoty kanálu do ovladače. V rámci právě zpracovávaného časového kroku se volá postupně pro všechny požadované kanály. Zadávání požadavků se ukončí voláním procedury OutputRequestCompleted. Ovladač musí být schopen přijímat požadavky i v okamžiku, kdy je zaneprázdněn komunikací se zařízením.
Tato procedura je volána v případě ovladače s rozhraním 3.x, to znamená v případě, že ovladač nemá implementovány procedury a funkce rozhraní 4.x.
Parametry:
void OutputRequest2( HANDLE hDriver, unsigned ChannelNumber, TValue OutputValue, unsigned QOS, timeStamp *TimeStamp );
Procedura slouží k předání požadavku na zápis hodnoty kanálu do ovladače. V rámci právě zpracovávaného časového kroku se volá postupně pro všechny požadované kanály. Zadávání požadavků se ukončí voláním procedury OutputRequestCompleted. Ovladač musí být schopen přijímat požadavky i v okamžiku, kdy je zaneprázdněn komunikací se zařízením. Kromě hodnoty kanálu se pomocí této procedury přenáší do ovladače ještě informace o kvalitě (QOS), což je jeden z atributů kanálu a časová značka (TimeStamp), tj. čas, kdy byla hodnota zapsána do ovladače. S kvalitou a časovou značkou může ovladač naložit dle vlastního uvážení.
Tato procedura je volána v případě ovladače s rozhraním 4.x namísto procedury OutputRequest.
Parametry:
void OutputRequestCompleted(HANDLE hDriver);
Procedura ukončí zadávání požadavků na zápis kanálů do ovladače po volání (OutputRequest2) resp. (OutputRequest). V tomto okamžiku může ovladač zahájit činnost vedoucí k zápisu všech požadovaných hodnot (nastavení výstupů, zahájení komunikace apod.).
Parametry:
char OutputFinalized(HANDLE hDriver, unsigned ChannelNumber, unsigned *ErrorCode );
Volá se po zadání požadavků na zápis kanálů a zahájení operace zápis (OutputRequestCompleted) postupně pro všechny požadované kanály. Vrací hodnotu 1, je-li operace ukončena. Nejsou-li hodnoty kanálů ještě zapsány, vrátí hodnotu 0 a parametr ErrorCode s hodnotou ceOK. V tomto okamžiku je nutno po dokončení zápisu nebo po chybě zavolat proceduru DriverCallback s funkčním kódem dcfDriverOutputFinalized. Dojde-li k chybě, musí být nastaven parametr ErrorCode na hodnotu ceTimeout nebo ceValue. V tom případě se vypíše chybové hlášení do okna zpráv.
Parametry:
Návratová hodnota:
void DriverProc(HANDLE hDriver, unsigned Func, unsigned Param1, unsigned Param2, unsigned Param3, unsigned Param4);
Procedura slouží k předání řídicího povelu z aplikace do ovladače. Povel je definován kódem a množinou parametrů, jejichž význam je určen typem povelu.
Parametry:
void QueryProc(HANDLE hDriver, TValue Param1, TValue *Param2);
Procedura slouží k vyvolání obecné uživatelské funkce ovladače prostřednictvím nativní procedury system.DriverQueryProc( DriverName : string; DrvParam1 : any; &DrvParam2 : any ). Parametr DriverName určuje symbolické jméno ovladače, kterému je zavolána procedura QueryProc. Parametr DrvParam1 se předává do ovladače a parametr DrvParam2 slouží jak k předání hodnoty, tak k vrácení hodnoty z ovladače. Funkce nativní procedury je závislá na implementaci procedury QueryProc v ovladači.
Parametry:
unsigned DriverCallback(HANDLE CBHandle, unsigned Func, void *Param);
Tato procedura slouží k tomu, aby ovladač signalizoval do systému dokončení vyvolané akce nebo k vyvolání vyjímky ovladače. Adresa této procedury je předána spolu s jejím handlem procedurou Init. Typ procedury je definován jako:
typedef unsigned (*tDriverCallback)(HANDLE, unsigned, void *);
Parametry:
Návratová hodnota:
Následuje popis typů, použitých v definicích procedur a funkcí rozhraní ovladačů. Kompletní definice najdete v hlavičkovém souboru 'cwdriver.h' v adresáři 'ddk'.
Datový typ TValue je variantní záznam, který obsahuje hodnotu kanálu čtenou z ovladače nebo zapisovanou do ovladače. Obsah tohoto záznamu je modifikován podle typu kanálu, který je představován položkou Type. Předdefinované konstanty určují typ kanálu.
// values #define valueNothing 0 // indicates "not having been used before" #define valueError 1 // error tag #define valueBoolean 2 // 8-bit flag #define valueShortCard 3 // 8-bit unsigned #define valueCardinal 4 // 16-bit unsigned #define valueLongCard 5 // 32-bit unsigned #define valueShortInt 6 // 8-bit signed #define valueInteger 7 // 16-bit signed #define valueLongInt 8 // 32-bit signed #define valueReal 9 // float (dword) #define valueLongReal 10 // double (qword) #define valuePString 11 // char (* pString)[255] #define valueBuffer 12 // buffer #define valueUnknown 13 // unknown value // buffer Header Kinds #define hkStdBuffer 0 // standard buffer format (header+data block) // buffer status - bits // be aware - these value represents bits, not masks #define stEmpty 0 // empty data #define stFillInProgress 1 // filling buffer #define stFull 2 // buffer completely valid #define stError 3 // not completely valid or if something bad occured #define stBusy 4 // if setting channel or something calculating #define stInvalid 5 // 2nd phase after stNonactual (before channels read) #define stNonactual 6 // if exists new (not actually read) data #define stModified 15 // used by instrument to mark modification; // thus can be set channel only if neccessary struct tBufferHeader { // Buffer header struct { unsigned short HeaderKind; union { struct { // in case of HeaderKind == hkStdBuffer unsigned short Channels; // number of channels unsigned NumSamples; // volume of data block unsigned CurSamples; // number of samples currently present double SampFreq; // sampling frequency or 0 (0 indicates "Time" usage) unsigned short SampStruct; // sample structure (0==real data, 1==complex & Channels==2) unsigned short DataType; // type of data (valueXXX) unsigned short Status; // buffer status (stXXX) unsigned short Any1; // not used now; leave 0 float Time; // sampling time, not period }; }; }; }; // size of tBufferHeader must be 32 bytes typedef char tString255[255]; struct TValue { // Value storage struct { unsigned Type; union { // switch (Type) char ValBoolean; // valueBoolean unsigned char ValShortCard; // valueShortCard unsigned short ValCardinal; // valueCardinal unsigned ValLongCard; // valueLongCard signed char ValShortInt; // valueShortInt signed short ValInteger; // valueInteger signed ValLongInt; // valueLongInt float ValReal; // valueReal double ValLongReal; // valueLongReal tString255 *ValPString; // valuePString struct { // valueBuffer unsigned char BType; unsigned short BLen256; void *PBuffer; }; }; }; };
Tento typ je tvořen záznamem složeným z následujících položek:
struct timeStamp { // data time stamp unsigned MilisecondsInDay; unsigned char Day; unsigned char Month; unsigned short Year; };