Rozhraní ovladačů pro Control Web

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.

Procedury a funkce rozhraní ovladačů

Rozhraní ovladače (3.x) je tvořeno následujícími procedurami a funkcemi:

Version
Check
GetDriverInfo
MakeDriver
DisposeDriver
Init
Done
BufferInfo
SetBufferAddr
InputRequest
InputRequestCompleted
InputFinalized
GetInput
OutputRequest
OutputRequestCompleted
OutputFinalized
DriverProc
QueryProc

Rozšířené rozhraní (4.x) je doplněno o následující procedury a funkce:

GetInput2
OutputRequest2

Callback procedura ovladače:

DriverCallback


Popis jednotlivých procedur a funkcí rozhraní ovladačů pro Control Web


Version


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:


Check


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:


GetDriverInfo


void GetDriverInfo(unsigned szDriverName,
                   char *DriverName);

Vrací jméno ovladače pro zobrazení v inspektoru ovladačů.

Parametry:


MakeDriver


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:


DisposeDriver


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:


Init


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:


Done


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:


BufferInfo


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.


SetBufferAddr


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:


InputRequest


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:


InputRequestCompleted


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:


InputFinalized


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:


GetInput


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:


GetInput2


 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:


OutputRequest


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:


OutputRequest2


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:


OutputRequestCompleted


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:


OutputFinalized


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:


DriverProc


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:


QueryProc


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:


DriverCallback


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:


Definice použitých typů

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'.


Typ TValue

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;
              };
          };
      };
  };

Typ timeStamp

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;
         };