[C con Clase] Codigo fuente de PLC Direct soft, como se hace un script fastAGI para que me controle las salidas del plc desde asterisk?

Jorge Vega Sanchez memmaker650 en gmail.com
Dom Mayo 2 11:38:59 CEST 2010


No sé si me estoy pasando. Pero creo que algo tan profesional esta  
fuera de este Buzón de correo.
Esto  es para dudas con C/C++ e interacciones con algunos S.O. como  
mucho.

On 02/05/2010, at 4:33, Jose Sanchez wrote:

> Files included in this package:
> readme.txt      - The file you are reading
> intrface.c      - The file which should be changed to support a new  
> transport
> hei.c           - Common source for HEI functions
> hei.h           - Header for HEI functions
> defs.h          - Defines used by hei.c
> function.h      - Defines used by hei.c
> /* Some usefull stuff! */
> #if !defined(_DEFS_H)
> #define _DEFS_H
> typedef int  BOOL;
> #define FALSE 0
> #define TRUE 1
>
> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD;
>
> typedef unsigned int UINT;
>
> #define LONG long
> #define ULONG_MAX     0xffffffff    /* maximum unsigned long value */
>
> #define LOBYTE(w) ((BYTE)(w))
> #define HIBYTE(w) ((BYTE)(((UINT)(w) >> 8) & 0xFF))
>
> #define LOWORD(l) ((WORD)(DWORD)(l))
> #define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
>
> #define MAKEWORD(a, b)      ((WORD)(((BYTE)(a)) | ((WORD)((BYTE) 
> (b))) << 8))
> #define MAKELONG(low, high) ((LONG)(((WORD)(low)) | (((DWORD)((WORD) 
> (high))) << 16)))
>
> #define max(a,b) (((a) > (b)) ? (a) : (b))
> #define min(a,b) (((a) < (b)) ? (a) : (b))
>
>
> #define NULL    ((void *)0)
>
> #define TimeDiff(StartTime, EndTime)  (((DWORD)EndTime >  
> (DWORD)StartTime) ? ((DWORD)EndTime - (DWORD)StartTime) :  
> ((DWORD)EndTime + ((DWORD)ULONG_MAX - (DWORD)StartTime) + 1))
>
>
> #endif
>
>
>
> #define UDP_PORT_ID  0x7070
>
> #pragma pack(1)
> typedef struct
>  {
>  char *pOSBegin;
>  char *pOSEnd;
>  char *pOSRun;
>  WORD CRC;
>  WORD BootSignature;
>  WORD OSSignature;
>  BYTE Unused[14];
>  } OSDef;
>
> /* Error/return val List */
> #define HEI_NO_ERROR     0
> #define ICMP_PKT_FOUND    65
> #define ARP_PKT_FOUND    66
> #define TYPE_NOT_HANDLED   67
> #define LINK_SENSE_TRIGGERED  68
> #define UNK_IP_PACKET    100
> #define UNK_ETHERTYPE    101
> #define UNK_PACKET_TYPE    102
> #define UNK_802X_PACKET_TYPE  103
> #define UNK_LLC_TYPE     104
> #define CRC_DOES_NOT_MATCH   105
> #define CRC_NO_DATA     106
> #define ENET_ADDR_REPROGRAMMED 107
> #define NULL_DATA_POINTER   108
> #define SIZE_ERROR     109
> #define NOT_FOUND      110
> #define INVALID_TYPE     111
> #define RAM_ALREADY_LOCKED   112
> #define INVALID_REQUEST    113
> #define TIMEOUT_ERROR    114
> #define FLASH_PROGRAM_ERROR  115
> #define INVALID_OS     116
> #define INVALID_LOCATION   117
> #define INVALID_SLOT_NUMBER  118
> #define INVALID_DATA     119
> #define MODULE_BUSY     120
> #define CHANNEL_FAILURE    121
> #define UNUSED_CHANNELS_EXIST  122
> #define INVALID_UDP_PORT   123
> #define SHUTDOWN_OS     124
> #define NOT_MY_IP_ADDRESS   125
> #define PROTECTION_ERROR   126
> #define UNK_TYPE_ERROR    127
> #define BACKPLANE_INIT_ERROR  128
> #define UNK_RESPONSE     129
> #define UNK_RXWX_FORMAT    130
> #define UNK_ACK      131
> #define UNK_NAK      132
> #define RANGE_ERROR     133
> #define LENGTH_WARNING    134
> #define INVALID_BASE_NUMBER   135
> #define INVALID_MODULE_TYPE   136
> #define INVALID_OFFSET    137
> #define INVALID_BOOT_VER_FOR_OS  138
> #define BROKEN_TRANSMITTER   139
> #define INVALID_ADDRESS    140
> #define CHANNELS_UNUSED_0   200
> #define CHANNELS_UNUSED_1   201
> #define CHANNELS_UNUSED_2        201
> #define CHANNELS_UNUSED_3        203
> #define CHANNELS_UNUSED_4        204
> #define CHANNELS_UNUSED_5        205
> #define CHANNELS_UNUSED_6        206
> #define CHANNELS_UNUSED_7        207
> #define CHANNELS_UNUSED_8        208
> #define CHANNELS_UNUSED_9        209
> #define CHANNELS_UNUSED_10       210
> #define CHANNELS_UNUSED_11       211
> #define CHANNELS_UNUSED_12       212
> #define CHANNELS_UNUSED_13       213
> #define CHANNELS_UNUSED_14       214
> #define CHANNELS_UNUSED_15       215
> #define CHANNELS_UNUSED_16       216
> #pragma pack()
>
> /*
> ** HEI.C - Platform independent code for communicating with Host  
> Automation Products
> **   line of ethernet modules.
> **
> ** Copyright (C) - 1996-1997 Host Automation Products, Inc.
> **
> */
> #include "windows.h"
> #include "defs.h"
> #include <memory.h>
> #include <string.h>
> #include <ctype.h>
> #include "hei.h"
> void (*pAsyncPacketHandler)(HEIDevice *pDevice, BYTE *pResponse, int  
> ResponseLen) = 0;
>
> /* Interface functions */
> int HEIIOpen(void);
> int HEIIClose(void);
> int HEIIOpenDevice(HEITransport *pTransport, HEIDevice *pDevice);
> int HEIICloseDevice(HEIDevice *pDevice);
> int HEIIOpenTransport(HEITransport *pTransport);
> int HEIICloseTransport(HEITransport *pTransport);
> int HEIIReceivePacket(HEIDevice *pDevice, BYTE *pResponse, int  
> *pResponseSize);
> int HEIISendPacket(HEIDevice *pDevice, BYTE *pPacket, WORD  
> PacketSize);
> DWORD HEIIGetCounter(void);
> #define DEBUG_FILE 0
> #if DEBUG_FILE
> #include <stdio.h>
> #include <stdarg.h>
> #include "windows.h"
> FILE *pOutFile=NULL;
> void DebugString(char  *String, ...)
>  {
>  char  Buffer[200];
>  va_list ap;
>  va_start(ap, String);
>  wvsprintf(Buffer, String, ap);
>     //OutputDebugString(Buffer);
>     pOutFile = fopen("c:\\heiout.txt", "a+");
>  if (pOutFile)
>   {
>   fputs("\n", pOutFile);
>   fputs(Buffer, pOutFile);
>   fclose(pOutFile);
>   }
>  va_end(ap);
>  }
>
> #endif
>
> __declspec(dllexport) int HEISetAsyncHandler(void (*pFun)(HEIDevice  
> *pDevice, BYTE *pResponse, int ResponseLen))
>  {
>  pAsyncPacketHandler = pFun;
>  return 0;
>  }
> __declspec(dllexport) int HEIGetAsyncHandler(void (**pFun)(HEIDevice  
> *pDevice, BYTE *pResponse, int ResponseLen))
>  {
>  *pFun = pAsyncPacketHandler;
>  return 0;
>  }
>
> /*
> ** This macro will return the difference between a start time (in  
> milliseconds) and an end time (also in milliseconds).
> ** It handles the fact that a DWORD millisecond indicator will wrap  
> every 49.XXX days.
> */
> #define TimeDiff(StartTime, EndTime)  (((DWORD)EndTime >  
> (DWORD)StartTime) ? ((DWORD)EndTime - (DWORD)StartTime) :  
> ((DWORD)EndTime + ((DWORD)ULONG_MAX - (DWORD)StartTime) + 1))
> #define WordDiff(Start, End)  (((WORD)End > (WORD)Start) ?  
> ((WORD)End - (WORD)Start) : ((WORD)End + ((WORD)0xFFFF -  
> (WORD)Start) + 1))
>
> #ifdef NOCRC
> int DoCRC = 0;
> #else
> int DoCRC = 1;
> #endif
> #define EXTRA_TIME_FOR_SETUP_DATA 10
> int DoEncrypt(Encryption *pEncrypt, BYTE *ptr, WORD Num);
> __declspec(dllexport) int _SendPacket(HEIDevice *pDevice, BYTE  
> *pPacket, WORD PacketSize, BYTE *pResponse, int *pResponseSize, BOOL  
> WaitForResponse, BOOL ReturnWarnings);
>
> #if defined(SUPERVISOR)
> int PrepareSupervisorPacket(HEIDevice *pDevice, BYTE *pPacket, WORD  
> PacketSize);
> #endif /* #if defined(SUPERVISOR) */
>
> WORD CalcCRC(WORD    icrc, BYTE   *icp, WORD    icnt);
>
> int InsertCRC(BYTE *pBuffer, WORD Len)
>  {
>  WORD *pWord = (WORD *) (pBuffer+5);
>
>  if (DoCRC)
>   {
>   (*pWord) = CalcCRC(0, (BYTE *) (pBuffer+PACKET_HEADER_SIZE),  
> (WORD) (Len - PACKET_HEADER_SIZE));
>   }
>  else
>   {
>   (*pWord) = 0;
>   }
>
>  return 0;
>  }
> BOOL CRCCorrect(BYTE *pBuffer, WORD Len)
>  {
>  if (!DoCRC)
>   return TRUE;
>  else if (Len < PACKET_HEADER_SIZE)
>   return FALSE;
>  else
>   {
>   WORD *pCRC = (WORD *) (pBuffer+5);
>   WORD CRC;
>   if (!*pCRC)
>    return TRUE;
>   CRC = CalcCRC(0, (BYTE *) (pBuffer+PACKET_HEADER_SIZE), (WORD)  
> (Len - PACKET_HEADER_SIZE));
>   return (CRC == (*pCRC));
>   }
>  }
>
> /* int GetResponse(HEIDevice *pDevice, BYTE *pResponse, int  
> *pResponseSize, WORD ExtraTime=0, BOOL ProcessTimeout=TRUE, BOOL  
> CheckAppVal=TRUE)*/
> __declspec(dllexport) int GetResponse(HEIDevice *pDevice, BYTE  
> *pResponse, int *pResponseSize, WORD ExtraTime, BOOL ProcessTimeout,  
> BOOL CheckAppVal)
>  {
>  unsigned short ThisAppVal = pDevice->LastAppVal;
>  DWORD DeviceTimeout = pDevice->Timeout;
>  int SavedSize = *pResponseSize;
>  int Error;
>  DWORD Timeout = DeviceTimeout + ExtraTime;
>  DWORD StartTime = HEIIGetCounter();
>  while (1)
>   {
>   *pResponseSize = SavedSize;
>   Error = HEIIReceivePacket(pDevice, pResponse, pResponseSize);
>
>   if (!Error && (*pResponseSize))
>    {
>    /* We have a packet to look at. */
>    /* Check the App Val. */
>    WORD *pWord = (WORD *) (pResponse+3);
>
>    if (*pWord == ThisAppVal || !ThisAppVal || !CheckAppVal)
>     {
>     int Retval;
>
>     if (!CheckAppVal)
>      pDevice->LastAppVal = *pWord;
>     Retval = 0;
>     if (CRCCorrect((BYTE *) pResponse, (WORD) *pResponseSize))
>      {
>      /* We have our response! */
>      }
>     else
>      {
>      pDevice->BadCRCCount++;
>      Retval =  HEIE_CRC_MISMATCH;
>      }
>
>     return Retval;
>     }
>    else
>     {
>     if (pAsyncPacketHandler)
>      {
>      (*pAsyncPacketHandler)(pDevice, pResponse, *pResponseSize);
>      }
>     pDevice->LatePacketCount++;
>     continue;
>     }
>    }
>   else if (Error && Error != HEIE_NO_RESPONSE)
>    {
>    return Error;
>    }
>   else if (!ProcessTimeout)
>    {
>    /* No more packets to look at. */
>    return HEIE_NO_RESPONSE;
>    }
>
>   if (ProcessTimeout && (TimeDiff(StartTime, HEIIGetCounter()) >=  
> Timeout))
>    {
>    /* Timeout! */
>    break;
>    }
>   }
>
>  *pResponseSize = 0;
>  return HEIE_TIMEOUT;
>  }
>
> static unsigned short AppVal = 1;
> __declspec(dllexport) int HEIGetResponse(HEIDevice *pDevice, BYTE  
> *pResponse, int *pResponseSize, BOOL CheckAppVal)
>  {
>  int Retval;
>
> #if DEBUG_FILE
>  DebugString("In GetResponse %u", AppVal);
> #endif
>  Retval = GetResponse(pDevice, pResponse, pResponseSize, 0, FALSE,  
> CheckAppVal);
>
> #if DEBUG_FILE
>  DebugString("Leaving GetResponse %u -> %d (0x%X)", AppVal, Retval,  
> Retval);
> #endif
>  return Retval;
>  }
>
> int WriteERMCommandData(HEIDevice *pDevice, WORD Base, WORD Slot,  
> BYTE *pData, WORD NumBytes, WORD Offset)
>  {
>  return HEIWriteERMData(pDevice, Base, Slot, DATA_COMMAND, pData,  
> NumBytes, Offset);
>  }
> int ReadERMCommandData(HEIDevice *pDevice, WORD Base, WORD Slot,  
> BYTE *pData, WORD NumBytes, WORD Offset)
>  {
>  return HEIReadERMData(pDevice, Base, Slot, DATA_COMMAND, pData,  
> NumBytes, Offset);
>  }
>
> #if HEIAPIVERSION>=3
> int _SendProxyPacket(HEIDevice *pDevice, BYTE *pPacket, WORD  
> PacketSize, BYTE *pResponse, int *pResponseSize, BOOL  
> WaitForResponse, BOOL ReturnWarnings)
>  {
>  int Retval = 0;
>  WORD DataOffset = pDevice->DataOffset;
>  WORD SubTotal = PacketSize - DataOffset;
>  BYTE *pCmd = pPacket+PacketSize-SubTotal;
>  // Disable proxying.
>  pDevice->UseProxy = FALSE;
>  Retval = WriteERMCommandData(pDevice, pDevice->ProxyBase, pDevice- 
> >ProxySlot, pCmd, SubTotal, 0);
>  if (Retval)
>   {
>  // printf("\nError %d (0x%X) from WriteERMCommandData", Retval,  
> Retval);
>   }
>  else
>   {
>   BYTE Extra[10];
>   WORD ExtraLen;
>   WORD *pWord;
>   pWord = (WORD *) &Extra[0];
>   *pWord++ = pDevice->ProxyDevNum;
>   *pWord++ = 0;  // CmdOffset
>   *pWord++ = SubTotal;  // CmdLength
>   *pWord++ = 0;  // RspOffset;
>   *pWord++ = 0x800; // RspLength
>   ExtraLen = 10;
>   Retval = HEIDoERMCommandEx(pDevice, pDevice->ProxyBase, pDevice- 
> >ProxySlot, COMMAND_PROCESS_COMMAND_BUFFER, Extra, ExtraLen);
>   if (Retval)
>    {
>  //  printf("Error %d (0x%X) from call to WPLCDoERMCommandEx",  
> Retval, Retval);
>    }
>   else
>    {
>    // Read response from command buffer.
>    BYTE ResponseBuffer[4];
>    Retval = ReadERMCommandData(pDevice, pDevice->ProxyBase, pDevice- 
> >ProxySlot, ResponseBuffer, 4, 0);
>    if (Retval)
>     {
>  //   printf("\nError %d (0x%X) from ReadERMCommandData", Retval,  
> Retval);
>     }
>    else
>     {
>     WORD *pError = (WORD *) &ResponseBuffer[0];
>     WORD *pLen = (WORD *) &ResponseBuffer[2];
>     if (*pError)
>      {
>  //    printf("\nCommand Error: %d  Len: %d", *pError, *pLen);
>      }
>     else
>      {
>      Retval = ReadERMCommandData(pDevice, pDevice->ProxyBase,  
> pDevice->ProxySlot, pResponse+PACKET_HEADER_SIZE, *pLen, 4);
>      if (Retval)
>       {
>  //     printf("\nError %d (0x%X) from ReadERMCommandData", Retval,  
> Retval);
>       }
>      else
>       {
>       // Fix pResponse[0] - pResponse[PACKET_HEADER_SIZE-1]
>       (*pResponseSize) = (*pLen) + PACKET_HEADER_SIZE;
>       }
>      }
>     }
>    }
>   }
>  // Reenable proxying.
>  pDevice->UseProxy = TRUE;
>  return Retval;
>  }
> #endif
>
> /*int SendPacket(HEIDevice *pDevice, BYTE *pPacket, WORD PacketSize,  
> BYTE *pResponse, int *pResponseSize, BOOL WaitForResponse=TRUE, BOOL  
> ReturnWarnings=FALSE)*/
> __declspec(dllexport) int _SendPacket(HEIDevice *pDevice, BYTE  
> *pPacket, WORD PacketSize, BYTE *pResponse, int *pResponseSize, BOOL  
> WaitForResponse, BOOL ReturnWarnings)
>  {
> #if HEIAPIVERSION>=3
>  if (pDevice->UseProxy == TRUE)
>   {
>   // Proxy this command to the device.
>   //printf("\nUse proxy.");
>   return _SendProxyPacket(pDevice, pPacket, PacketSize, pResponse,  
> pResponseSize, WaitForResponse, ReturnWarnings);
>   }
> #endif
>   {
>   BYTE *ptr;
>   WORD *pWord;
>   unsigned short ThisAppVal;
>   unsigned short *pWordAppVal;
>   BYTE *pBegin = pPacket;
>   WORD PreHeaderBytes = pDevice->DataOffset - PACKET_HEADER_SIZE;
>   WORD Retry;
>   if (pDevice->UseAddressedBroadcast)
>    PreHeaderBytes -= 7;
>
>   pPacket += PreHeaderBytes;
>
>   ptr = pPacket;
>
>   if (pDevice->UseAddressedBroadcast)
>    {
>    pPacket[PACKET_HEADER_SIZE] = FUN_ADDRESSED_BROADCAST;
>    memcpy(&pPacket[PACKET_HEADER_SIZE+1], pDevice->ENetAddress, 6);
>    }
>
>   *ptr++ = 'H';
>   *ptr++ = 'A';
>   *ptr   = 'P';
>
>   /* Calculate CRC */
>   InsertCRC(pPacket, (WORD) (PacketSize-PreHeaderBytes));
>
>   /* Insert the number of bytes which were checksumed. */
>   pWord = (WORD *) (pPacket+7);
>
>   *pWord = (WORD) PacketSize - PreHeaderBytes - PACKET_HEADER_SIZE; / 
> * This is the bytes to follow/checksum */
>
>   /* Do encryption (if required) */
>   if (pDevice->_pTransport->Encrypt.Algorithm)
>    DoEncrypt(&pDevice->_pTransport->Encrypt, pPacket+5, (WORD)  
> (PacketSize-5-PreHeaderBytes));
>
>   pWordAppVal = (unsigned short *) (pPacket+3);
>
>
>  #if defined(SUPERVISOR)
>   PrepareSupervisorPacket(pDevice, pPacket, PacketSize);
>  #endif /* #if defined(SUPERVISOR) */
>   for (Retry = 0; Retry<=pDevice->Retrys; Retry++)
>       {
>    int ResponseSize = *pResponseSize;
>    int Error;
>
>    ThisAppVal = AppVal++;
>    pDevice->LastAppVal = ThisAppVal;
>
>    if (!AppVal)
>     AppVal++;
>
>    if (Retry)
>     pDevice->RetryCount++;
>
>    /* Insert the app value. */
>    *pWordAppVal = ThisAppVal;
>
>    Error = HEIISendPacket(pDevice, pBegin, PacketSize);
>
>    if (Error)
>     {
>     *pResponseSize = 0;
>     return Error;
>     }
>
>    if (!WaitForResponse)
>     {
>     *pResponseSize = 0;
>     return HEIE_NO_RESPONSE;
>     }
>    Error = GetResponse(pDevice, pResponse, &ResponseSize, 0, TRUE,  
> TRUE);
>    if (!Error)
>     {
>     *pResponseSize = ResponseSize;
>     if (Retry != 0 && ReturnWarnings)
>      return HEIW_RETRY;
>     return 0;   /* Success! */
>     }
>    else if (Error != HEIE_TIMEOUT)
>     return Error;
>    }
>
>   *pResponseSize = 0;
>   return HEIE_TIMEOUT;
>   }
>  }
>
> __declspec(dllexport) int SendPacketTwoResponses(HEIDevice *pDevice,  
> BYTE *pPacket, WORD PacketSize, BYTE *pResponse, int *pResponseSize,
>          BOOL WaitForResponse, BOOL ReturnWarnings, WORD  
> Bytes2Verify, BYTE *pVerifyData,
>          WORD ExtraTime, BOOL ProcessTimeout, BOOL CheckAppVal)
>  {
>  WORD SaveRetryCount = pDevice->RetryCount;
>  WORD SaveRetrys = pDevice->Retrys;
>  int SaveResponseSize = *pResponseSize;
> #if HEIAPIVERSION>=3
>  if (pDevice->UseProxy == TRUE)
>   {
>   // Proxy this command to the device.
>   //printf("\nUse proxy.");
>   return _SendProxyPacket(pDevice, pPacket, PacketSize, pResponse,  
> pResponseSize, WaitForResponse, ReturnWarnings);
>   }
> #endif
>  while (TRUE)
>   {
>   int Error = _SendPacket(pDevice, pPacket, PacketSize,pResponse,  
> pResponseSize, WaitForResponse, ReturnWarnings);
>   if (Error && !(Error & HEIW_FIRST_WARNING))
>    {
>    /* Restore retrys value */
>    pDevice->Retrys = SaveRetrys;
>    return Error;
>    }
>   /* Check and make sure we got an ack. */
>   if (Bytes2Verify)
>    {
>    BYTE *pRet = (pResponse+PACKET_HEADER_SIZE);
>
>    while (Bytes2Verify)
>     {
>     if (*pRet++ != *pVerifyData++)
>      {
>      /* Restore retrys value */
>      pDevice->Retrys = SaveRetrys;
>      return HEIE_INVALID_RESPONSE;
>      }
>     Bytes2Verify--;
>     }
>    }
>   /* Restore size of response buffer. */
>   *pResponseSize = SaveResponseSize;
>   Error = GetResponse(pDevice, pResponse, pResponseSize, ExtraTime,  
> ProcessTimeout, CheckAppVal);
>   if (Error == HEIE_TIMEOUT)
>    {
>    WORD TotalRetrys;
>    /* Perform a retry */
>    pDevice->RetryCount++;
>    /* See how many retrys we have already done. */
>    TotalRetrys = WordDiff(SaveRetryCount, pDevice->RetryCount);
>    if (TotalRetrys >= SaveRetrys)
>     {
>     /* Restore retrys value */
>     pDevice->Retrys = SaveRetrys;
>     return Error;
>     }
>    /* Prepare to go again. */
>    *pResponseSize = SaveResponseSize;
>    /* Adjust number of retrys left to do. */
>    pDevice->Retrys = SaveRetrys - TotalRetrys;
>    }
>   else
>    {
>    /* Restore retrys value */
>    pDevice->Retrys = SaveRetrys;
>    if (!Error && pDevice->RetryCount != SaveRetryCount)
>     Error = HEIW_RETRY;
>    if (Error)
>     return Error;
>    return HEIE_NULL;
>    }
>   }
>  }
>
> /* Transport Stuff */
> __declspec(dllexport) int HEIOpenTransport(HEITransport *pTransport,  
> WORD Ver, ENetAddress *pSourceAddress)
> /* __declspec(dllexport) int HEIOpenTransport(HEITransport  
> *pTransport, WORD Ver, DWORD NetworkAddress)*/
>  {
>  int Retval;
>
> #if DEBUG_FILE
>  DebugString("In HEIOpenTransport");
> #endif
>  if (HEIAPIVERSION != Ver)
>   return HEIE_VER_MISMATCH;
>  if (!pTransport)
>   return HEIE_NULL_TRANSPORT;
>
>  pTransport->Encrypt.Algorithm = HEIEN_NONE;
>  /*pTransport->NetworkAddress = NetworkAddress;*/
>  pTransport->pSourceAddress = pSourceAddress;
>
>  Retval = HEIIOpenTransport(pTransport);
>
> #if DEBUG_FILE
>  DebugString("Leaving HEIOpenTransport", Retval);
> #endif
>
>  return Retval;
>  }
>
>
> __declspec(dllexport) int HEICloseTransport(HEITransport *pTransport)
>  {
>  if (!pTransport)
>   return HEIE_NULL_TRANSPORT;
>
>  return HEIICloseTransport(pTransport);
>  }
> __declspec(dllexport) int HEIOpenDevice
>   (
>   HEITransport *pTransport,
>   HEIDevice *pDevice,
>   WORD Ver,
>   WORD iTimeout,
>   WORD iRetrys,
>   BOOL UseBroadcast
>   )
>  {
>  int Retval;
>
> #if 0
>   {
>   char Buffer[200];
>   wsprintf(Buffer, "Timeout: %d  Retrys: %d  UseBroadCast: %d",  
> iTimeout, iRetrys, UseBroadcast);
>   MessageBox(NULL, Buffer, "HEIOpenDevice", 0);
>   }
> #endif
>
> #if DEBUG_FILE
>  DebugString("In HEIOpenDevice");
> #endif
>
>  if (HEIAPIVERSION != Ver)
>   return HEIE_VER_MISMATCH;
>  if (!pTransport)
>   return HEIE_NULL_TRANSPORT;
>
>  if (!pDevice)
>   return HEIE_INVALID_DEVICE;
>  pDevice->_dwParam    = 0;
>  pDevice->Timeout    = iTimeout;
>  pDevice->Retrys    = iRetrys;
>  pDevice->UseAddressedBroadcast = UseBroadcast;
>  pDevice->UseBroadcast  = UseBroadcast;
>  pDevice->pData     = 0;
>  pDevice->SizeOfData   = 0;
>  pDevice->DataOffset   = PACKET_HEADER_SIZE;
>  pDevice->pBuffer    = 0;
>  pDevice->RetryCount   = 0;
>  pDevice->BadCRCCount   = 0;
>  pDevice->LatePacketCount = 0;
>  pDevice->ParallelPackets = FALSE;
>  pDevice->_pTransport = pTransport;
> #if HEIAPIVERSION==3
>  pDevice->UseProxy = 0;
>  pDevice->ProxyBase = 0;
>  pDevice->ProxySlot = 0;
>  pDevice->ProxyDevNum = 0;
>  memset(pDevice->Reserved, 0, sizeof(pDevice->Reserved));  /*  
> Reserved bytes, set to zero */
> #endif
>  if (pDevice->UseAddressedBroadcast)
>   pDevice->DataOffset += 7;
>  Retval = HEIIOpenDevice(pTransport, pDevice);
>
> #if DEBUG_FILE
>  DebugString("Leaving HEIOpenDevice", Retval);
> #endif
>  return Retval;
>  }
> __declspec(dllexport) int HEICloseDevice(HEIDevice *pDevice)
>  {
>  int Retval = HEIE_NULL;
>  if (!pDevice)
>   return HEIE_INVALID_DEVICE;
>
>  if (pDevice->_pTransport)
>   {
>   Retval = HEIICloseDevice(pDevice);
>   pDevice->_pTransport = (HEITransport *) NULL;
>   }
>
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIOpen(WORD Ver)
>  {
>  if (HEIAPIVERSION != Ver)
>   return HEIE_VER_MISMATCH;
>
>  return HEIIOpen();
>  }
> __declspec(dllexport) int HEIClose()
>  {
>  return HEIIClose();
>  }
>
> int DoEncrypt(Encryption *pEncrypt, BYTE *ptr, WORD Num)
>  {
>  switch (pEncrypt->Algorithm)
>   {
>   case 1:  /* Private key encryption (XOR) */
>    {
>    BYTE *keyptr = pEncrypt->Key;
>    WORD x;
>
>    for (x=0; x<Num; x++)
>     {
>     *ptr++ ^= *keyptr++;
>
>     if (!*keyptr)
>      keyptr = pEncrypt->Key;
>     }
>
>    return 0;
>    }
>
>   default:
>    return -1;
>   }
>  }
> int OpenQueryableDevice(HEITransport *pTransport, HEIDevice  
> *pDevice, WORD Ver)
>  {
>  /* Open a device which I can use for broadcasting a packet. */
>  int RetVal = HEIOpenDevice(pTransport, pDevice, Ver, 20, 0, TRUE);
>  if (!RetVal)
>   {
>   pDevice->UseAddressedBroadcast = FALSE;    /* Don't want to use  
> 'Addressed' Broadcast, just Broadcast! */
>   pDevice->DataOffset -= 7;  /* We are not using addressed  
> broadcast. */
>   pDevice->wParam = 0;
>   }
>  return RetVal;
>  }
>
>
> DWORD QueryTimeout = 600;
> __declspec(dllexport) DWORD HEISetQueryTimeout(DWORD NewTimeout)
>  {
>  DWORD Save = QueryTimeout;
>  QueryTimeout = NewTimeout;
>  return Save;
>  }
> __declspec(dllexport) DWORD HEIGetQueryTimeout()
>  {
>  return QueryTimeout;
>  }
>
> int DoQuery(HEITransport *pTransport, HEIDevice *pDevice, HEIDevice  
> *pDevices, WORD *pNumDevices, WORD Ver, BYTE *pBuffer, WORD  
> BufferSize)
>  {
>  BYTE RetBuffer[600];
>  int ResponseSize = sizeof(RetBuffer);
>  BYTE FromAddress[20];
>  int Error;
>  WORD Count = 0;
>  DWORD Timeout = QueryTimeout;
>  DWORD StartTime;
>  int Retval;
>  pDevice->pData = FromAddress;
>  pDevice->SizeOfData = sizeof(FromAddress);
>  Error = _SendPacket(pDevice, pBuffer, BufferSize, RetBuffer,  
> &ResponseSize, TRUE, FALSE);
>  StartTime = HEIIGetCounter();
>  Retval = HEIE_NULL;
>  while (1)
>   {
>   switch ((WORD) Error)
>    {
>    case HEIE_NULL:
>     {
>     /* No Error, so process packet. */
>     if (RetBuffer[0] == 'H' && RetBuffer[1] == 'A' && (RetBuffer[2]  
> == 'P' || RetBuffer[2] == 'A') &&
>      RetBuffer[PACKET_HEADER_SIZE] == 0x55 &&
>      (BYTE) RetBuffer[PACKET_HEADER_SIZE+1] == 0xAA)
>      {
>      if (Count < (*pNumDevices))
>       {
>       memcpy(pDevices[Count].Address.Raw, pDevice->pData, pDevice- 
> >SizeOfData);
>       memcpy(pDevices[Count].ENetAddress, (char *) (RetBuffer 
> +PACKET_HEADER_SIZE+2), 6);
>       if (pTransport->Protocol == HEIP_IP)
>        {
>        if (RetBuffer[PACKET_HEADER_SIZE+8] == 1)
>         pDevices[Count].Address.Raw[19] = 1; /* The modules IP  
> address is not initialized. */
>        else
>         pDevices[Count].Address.Raw[19] = 0;
>        }
>       Count++;
>       }
>      else
>       {
>       Count++;
>       Retval = HEIE_BUFFER_TOO_SMALL;
>       }
>      }
>     break;
>     }
>    case HEIE_TIMEOUT:
>     break;
>
>    case HEIW_RETRY:
>     break;
>    default:
>     {
>     /* Other error, so bail out. */
>     pDevice->pData = 0;
>     pDevice->SizeOfData = 0;
>     return Error;
>     }
>    }
>   if (TimeDiff(StartTime, HEIIGetCounter()) < Timeout)
>    {
>    ResponseSize = sizeof(RetBuffer);
>    pDevice->SizeOfData = sizeof(FromAddress);
>    Error = GetResponse(pDevice, RetBuffer, &ResponseSize, 0, TRUE,  
> TRUE);
>    }
>   else
>    break;
>   }
>  *pNumDevices = Count;
>  pDevice->pData = 0;
>  pDevice->SizeOfData = 0;
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIQueryDevices(HEITransport *pTransport,  
> HEIDevice *pDevices, WORD *pNumDevices, WORD Ver)
>  {
>  HEIDevice qDevice;
>  WORD DataOffset;
>  BYTE Buffer[100];
>  WORD Total;
>  int Retval;
>  int Error;
>  if (pTransport->Protocol == HEIP_SERIAL)
>   {
>   *pNumDevices = 0;
>   return HEIE_NULL;
>   }
>  Error = OpenQueryableDevice(pTransport, &qDevice, Ver);
>
>  if (Error)
>   return Error;
>  /* Build the buffer.   */
>  DataOffset = qDevice.DataOffset;
>  Buffer[DataOffset] = FUN_POLLING_ALL;   /* This is the function  
> code! */
>  Total = DataOffset+1;
>  Retval = DoQuery(pTransport, &qDevice, pDevices, pNumDevices, Ver,  
> Buffer, Total);
>  HEICloseDevice(&qDevice);
>
>  return Retval;
>  }
> __declspec(dllexport) int HEIQueryDeviceData(HEITransport  
> *pTransport, HEIDevice *pDevices, WORD *pNumDevices, WORD Ver, WORD  
> DataType, BYTE *pData, WORD SizeofData)
>  {
>  HEIDevice qDevice;
>  WORD DataOffset;
>  BYTE Buffer[600];
>  WORD *pWord;
>  WORD Total;
>  int Retval;
>
>  int Error = OpenQueryableDevice(pTransport, &qDevice, Ver);
>
>  if (Error)
>   return Error;
>  /* Build the buffer.   */
>  DataOffset = qDevice.DataOffset;
>  Buffer[DataOffset] = FUN_QUERY_SETUP_DATA;   /* This is the  
> function code! */
>  Buffer[DataOffset+1] = 0;
>  pWord = (WORD *) (Buffer+DataOffset+2);
>
>  if (SizeofData > 512)
>    SizeofData = 512;
>  *pWord++ = DataType;
>  *pWord = SizeofData;
>
>  memcpy(Buffer+DataOffset+6, pData, SizeofData);
>  Total = qDevice.DataOffset+6+SizeofData;
>  Retval = DoQuery(pTransport, &qDevice, pDevices, pNumDevices, Ver,  
> Buffer, Total);
>  HEICloseDevice(&qDevice);
>
>  return Retval;
>  }
>
> /* SUPPORT INFORMATION */
> __declspec(dllexport) int HEIReadSupportInfo(HEIDevice *pDevice,  
> BYTE *pSupportInfo, WORD SizeOfSupportInfo)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int NumBytes;
>  int Error;
>  int Retval;
>  Buffer[DataOffset] = (BYTE) FUN_READ_SUPPORT_INFO;    /* This is  
> the function code! */
>  Total = DataOffset+1;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > SizeOfSupportInfo)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = SizeOfSupportInfo;
>    }
>   memcpy(pSupportInfo, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
>
> /* VERSION INFORMATION */
> __declspec(dllexport) int HEIReadVersionInfo(HEIDevice *pDevice,  
> BYTE *pVerInfo, WORD SizeVerInfo)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE) FUN_READ_VER_INFO;    /* This is the  
> function code! */
>  Total = DataOffset+1;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > SizeVerInfo)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = SizeVerInfo;
>    }
>   memcpy(pVerInfo, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
>
> /* BASE DEFINITION */
> __declspec(dllexport) int HEIReadBaseDef(HEIDevice *pDevice, BYTE  
> *pBaseDefInfo, WORD *pSizeOfBaseDefInfo)
>  {
>  BYTE Buffer[300];
>  BYTE RetBuffer[1000];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_READ_BASE_DEF;    /* This is the function  
> code! */
>  Total = DataOffset+1;
>  if (pBaseDefInfo && *pBaseDefInfo == 0xB1)
>   {
>   Buffer[DataOffset+1] = *pBaseDefInfo;
>   Total++;
>   }
>  NumBytes = sizeof(RetBuffer);
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > *pSizeOfBaseDefInfo)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *pSizeOfBaseDefInfo;
>    }
>   memcpy(pBaseDefInfo, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   (*pSizeOfBaseDefInfo) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*pSizeOfBaseDefInfo) = 0;
>   }
>  return Retval;
>  }
> __declspec(dllexport) int HEIRescanBase(HEIDevice *pDevice, DWORD  
> Flags, BYTE *pBaseDefInfo, WORD *pSizeOfBaseDefInfo)
>  {
>  BYTE Buffer[300];
>  BYTE RetBuffer[1000];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  DWORD *pDWord;
>  Buffer[DataOffset] = FUN_INIT_BASE_DEF;    /* This is the function  
> code! */
>  pDWord = (DWORD *) &Buffer[DataOffset+1];
>  *pDWord = Flags;
>  Total = DataOffset+5;
>  NumBytes = sizeof(RetBuffer);
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > *pSizeOfBaseDefInfo)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *pSizeOfBaseDefInfo;
>    }
>   memcpy(pBaseDefInfo, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   (*pSizeOfBaseDefInfo) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*pSizeOfBaseDefInfo) = 0;
>   }
>  return Retval;
>  }
> __declspec(dllexport) int HEIInitBaseDef(HEIDevice *pDevice, BYTE  
> *pBaseDefInfo, WORD *pSizeOfBaseDefInfo)
>  {
>  BYTE Buffer[300];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_INIT_BASE_DEF;    /* This is the function  
> code! */
>  Total = DataOffset+1;
>  NumBytes = sizeof(RetBuffer);
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > *pSizeOfBaseDefInfo)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *pSizeOfBaseDefInfo;
>    }
>   memcpy(pBaseDefInfo, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   (*pSizeOfBaseDefInfo) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*pSizeOfBaseDefInfo) = 0;
>   }
>  return Retval;
>  }
> __declspec(dllexport) int HEIWriteBaseDef(HEIDevice *pDevice, BYTE  
> *pInputBaseDef, WORD SizeOfInputBaseDef, BYTE *pOutputBaseDef, WORD  
> *pSizeOfOutputBaseDef)
>  {
>  BYTE Buffer[600];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  WORD *pWord;
>  Buffer[DataOffset] = FUN_WRITE_BASE_DEF;    /* This is the function  
> code! */
>  Buffer[DataOffset+1] = 0;
>
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = SizeOfInputBaseDef;
>  Total = DataOffset+4+SizeOfInputBaseDef;
>  if (Total > sizeof(Buffer))
>   {
>   return HEIE_DATA_TOO_LARGE;
>   }
>
>  memcpy(Buffer+DataOffset+4, pInputBaseDef, SizeOfInputBaseDef);
>
>  NumBytes = sizeof(RetBuffer);
>  Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>          TRUE, FALSE,
>          0, NULL,
>          30000, TRUE, TRUE);
>
> #if 0
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>
>  NumBytes = sizeof(RetBuffer);
>  Error = GetResponse(pDevice, RetBuffer, &NumBytes, 30000, TRUE,  
> TRUE);
> #endif
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>
>   if (*pInt)
>    Retval = *pInt;
>   else if (pOutputBaseDef)
>    {
>    NumBytes -= (PACKET_HEADER_SIZE+2);
>
>    if ((WORD) NumBytes > *pSizeOfOutputBaseDef)
>     {
>     Retval = HEIE_BUFFER_TOO_SMALL;
>     NumBytes = *pSizeOfOutputBaseDef;
>     }
>
>    memcpy(pOutputBaseDef, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>    (*pSizeOfOutputBaseDef) = NumBytes;
>    }
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>
>   if (pOutputBaseDef && pSizeOfOutputBaseDef)
>    (*pSizeOfOutputBaseDef) = 0;
>   }
>  return Retval;
>  }
> /* DEVICE DEFINITION */
> __declspec(dllexport) int HEIReadDeviceDef(HEIDevice *pDevice, BYTE  
> *pDeviceDefInfo, WORD SizeOfDeviceDefInfo)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE) FUN_READ_DEVICE_INFO;    /* This is the  
> function code! */
>  Total = DataOffset+1;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > SizeOfDeviceDefInfo)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = SizeOfDeviceDefInfo;
>    }
>   memcpy(pDeviceDefInfo, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
>
> /* SETUP */
> __declspec(dllexport) int HEIReadSetupData(HEIDevice *pDevice, WORD  
> SetupType, BYTE *pData, WORD *pSizeofData)
>  {
>  BYTE Buffer[100];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  WORD *pWord;
>  Buffer[DataOffset] = (BYTE) FUN_READ_SETUP_DATA;    /* This is the  
> function code! */
>  Buffer[DataOffset+1] = 0;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = SetupType;
>  Total = DataOffset+4;
>  NumBytes = sizeof(RetBuffer);
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   NumBytes -= (PACKET_HEADER_SIZE+2);
>   if ((WORD) NumBytes > *pSizeofData)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *pSizeofData;
>    }
>   if (*pInt)
>    Retval = *pInt;
>   (*pSizeofData) = NumBytes;
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
> __declspec(dllexport) int HEIWriteSetupData(HEIDevice *pDevice, WORD  
> SetupType, BYTE *pData, WORD SizeofData)
>  {
>  BYTE Buffer[600];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD *pWord;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE) FUN_WRITE_SETUP_DATA;    /* This is the  
> function code! */
>  Buffer[DataOffset+1] = 0;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = SetupType;
>  Total = DataOffset+4+SizeofData;
>  if (Total > sizeof(Buffer))
>   {
> #if 0
>   BYTE Text[200];
>   wsprintf(Text, "Total=%d  DataOffset=%d  SizeofData=%d   
> SizeofBuffer=%d",
>    Total, DataOffset, SizeofData, sizeof(Buffer));
>   MessageBox(NULL, Text, "HEIWriteSetupData", 0);
> #endif
>   return HEIE_DATA_TOO_LARGE;
>   }
>  memcpy(&Buffer[DataOffset+4], pData, SizeofData);
>  NumBytes = sizeof(RetBuffer);
>
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>  Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>          TRUE, FALSE,
>          0, NULL,
>          30000, TRUE, TRUE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
> #if 0
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  NumBytes = sizeof(RetBuffer);
>  Error = GetResponse(pDevice, RetBuffer, &NumBytes, 30000, TRUE,  
> TRUE);
> #endif
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   if (*pInt)
>    Retval = *pInt;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
> __declspec(dllexport) int HEIDeleteSetupData(HEIDevice *pDevice,  
> WORD SetupType)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD *pWord;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE) FUN_DELETE_SETUP_DATA;    /* This is  
> the function code! */
>  Buffer[DataOffset+1] = 0;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = SetupType;
>  Total = DataOffset+4;
>  NumBytes = sizeof(RetBuffer);
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>  Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>          TRUE, FALSE,
>          0, NULL,
>          30000, TRUE, TRUE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>
>
> #if 0
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  NumBytes = sizeof(RetBuffer);
>  Error = GetResponse(pDevice, RetBuffer, &NumBytes, 30000, TRUE,  
> TRUE);
> #endif
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   if (*pInt)
>    Retval = *pInt;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
> __declspec(dllexport) int HEIEnumSetupData(HEIDevice *pDevice, WORD  
> *pData, WORD *pSizeofDataInWords)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE) FUN_ENUM_SETUP_DATA;    /* This is the  
> function code! */
>  Total = DataOffset+1;
>  NumBytes = sizeof(RetBuffer);
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   /*int NumWords; */
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   short int *pNumWords = (short int *) (RetBuffer+PACKET_HEADER_SIZE 
> +2);
>   if ((WORD) *pNumWords > *pSizeofDataInWords)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    *pNumWords = *pSizeofDataInWords;
>    }
>   if (*pInt)
>    Retval = *pInt;
>   (*pSizeofDataInWords) = *pNumWords;
>   memcpy((char *) pData, (char *) (RetBuffer+PACKET_HEADER_SIZE+4),  
> *pNumWords * 2);
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
>
> /* IO ACCESS */
> __declspec(dllexport) int HEIReadIO(HEIDevice *pDevice, BYTE *pData,  
> WORD *DataSize)
>  {
>  BYTE Buffer[100];
>  BYTE RetBuffer[1200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>
>  Buffer[DataOffset] = FUN_READ_IO; /* This is the function code! */
>  Total = DataOffset+1;
>  if (pData && *pData == 0xB1)
>   {
>   Buffer[DataOffset+1] = *pData;
>   Total++;
>   }
>  NumBytes = sizeof(RetBuffer);
>  //NumBytes = *DataSize;
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) &RetBuffer[PACKET_HEADER_SIZE];
>   NumBytes -= PACKET_HEADER_SIZE;
>   NumBytes -= 2;
>   if ((WORD) NumBytes > *DataSize)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *DataSize;
>    }
>   if (*pInt)
>    Retval = (*pInt) | 0x8000;
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>   (*DataSize) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*DataSize) = 0;
>   }
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIWriteIO(HEIDevice *pDevice, BYTE  
> *pData, WORD SizeofData, BYTE *pReturnData, WORD *pSizeofReturnData)
>  {
>  BYTE Buffer[1200];
>  BYTE RetBuffer[1200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_WRITE_IO;    /* This is the function code!  
> */
>
>  Total = DataOffset+1+SizeofData;
>  if (Total > sizeof(Buffer))
>   return HEIE_DATA_TOO_LARGE;
>  memcpy(Buffer+DataOffset+1, pData, SizeofData);
>  NumBytes = sizeof(RetBuffer);
>  //NumBytes = *pSizeofReturnData;
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) &RetBuffer[PACKET_HEADER_SIZE];
>   if (pReturnData && pSizeofReturnData)
>    {
>    NumBytes -= PACKET_HEADER_SIZE;
>    NumBytes -= 2;
>    if ((WORD) NumBytes > *pSizeofReturnData)
>     {
>     Retval = HEIE_BUFFER_TOO_SMALL;
>     NumBytes = *pSizeofReturnData;
>     }
>    memcpy(pReturnData, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>    (*pSizeofReturnData) = NumBytes;
>    }
>   if (*pInt)
>    Retval = (*pInt) | 0x8000;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   if (pSizeofReturnData)
>    (*pSizeofReturnData) = 0;
>   }
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIWriteIONoRead(HEIDevice *pDevice, BYTE  
> *pData, WORD SizeofData)
>  {
>  BYTE Buffer[1200];
>  BYTE RetBuffer[1200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_WRITE_IO_NO_READ;    /* This is the  
> function code! */
>
>  Total = DataOffset+1+SizeofData;
>  if (Total > sizeof(Buffer))
>   return HEIE_DATA_TOO_LARGE;
>  memcpy(Buffer+DataOffset+1, pData, SizeofData);
>  NumBytes = sizeof(RetBuffer);
>  //NumBytes = *pSizeofReturnData;
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) &RetBuffer[PACKET_HEADER_SIZE];
>   if (*pInt)
>    Retval = (*pInt) | 0x8000;
>   }
>  else
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIPetDevice(HEIDevice *pDevice)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_PET_LINK;
>  Buffer[DataOffset+1] = 0;
>  Total = DataOffset+2;
>  NumBytes = sizeof(RetBuffer);
>  return _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  }
> __declspec(dllexport) int HEIReadEthernetStats(HEIDevice *pDevice,  
> BYTE *pData, WORD *DataSize, BOOL Clear)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_READ_ETHERNET_STATS;   /* This is the  
> function code! */
>  Buffer[DataOffset+1] = 0;
>  Buffer[DataOffset+2] = Clear ? 1 : 0;
>  Total = DataOffset+3;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   NumBytes -= PACKET_HEADER_SIZE;
>   if ((WORD) NumBytes > *DataSize)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *DataSize;
>    }
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE, NumBytes);
>   (*DataSize) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*DataSize) = 0;
>   }
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIReadModuleStatus(HEIDevice *pDevice,  
> BYTE *pData, WORD *DataSize, BOOL Reset)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_READ_MODULE_STATUS;   /* This is the  
> function code! */
>  if (pData && *pData == 0xB1)
>   Buffer[DataOffset+1] = 1;
>  else
>   Buffer[DataOffset+1] = 0;
>  Buffer[DataOffset+2] = Reset ? 1 : 0;
>  Total = DataOffset+3;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) &RetBuffer[PACKET_HEADER_SIZE];
>   NumBytes -= PACKET_HEADER_SIZE;
>   NumBytes -= 2;
>   if ((WORD) NumBytes > *DataSize)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *DataSize;
>    }
>   if (*pInt)
>    Retval = *pInt;
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>   (*DataSize) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*DataSize) = 0;
>   }
>  return Retval;
>  }
>
>
> /* CCM STUFF */
> #define CCM_READ   0x1E
> #define CCM_WRITE   0x20
>
> __declspec(dllexport) int HEICCMRequest(HEIDevice *pDevice, BOOL  
> bWrite, BYTE DataType, WORD Address, WORD DataLen, BYTE *pData)
>  {
>  BYTE Buffer[320];
>  BYTE RetBuffer[320];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  BYTE *pRet;
>  short int *pError;
>  BYTE VerifyData[2];
>
> #if DEBUG_FILE
>  DebugString("In HEICCMRequest %u", AppVal);
> #endif
>  if(DataLen > 256)
>   return HEIE_INVALID_REQUEST;
>
>    /* Function */
>  Buffer[DataOffset] = FUN_CCM_REQUEST;
>
>  /* Unused */
>  Buffer[DataOffset+1] = 0;
>  /* Request Code. */
>  Buffer[DataOffset+2] = 0x01;
>
>  /* Direction */
>  Buffer[DataOffset+3] = bWrite ? CCM_WRITE : CCM_READ;
>
>  /* Length */
>  Buffer[DataOffset+4] = (DataLen == 256) ? 0 : (BYTE)DataLen;
>
>  /* LSB of Address */
>  Buffer[DataOffset+5] = (BYTE) (Address & 0xFF);
>
>  /* MSB of Address */
>  Buffer[DataOffset+6] = (BYTE) ((Address>>8) & 0xFF);
>
>  /* Data Type */
>  Buffer[DataOffset+7] = DataType;
>  Total = DataOffset+8;
>  if (bWrite)
>   {
>   /* We are writing. */
>   memcpy(&Buffer[DataOffset+8], pData, DataLen);
>   Total += DataLen;
>   }
>  NumBytes = sizeof(RetBuffer);
>
>  VerifyData[0] = FUN_ACK;
>  VerifyData[1] = FUN_CCM_REQUEST;
>  Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>          (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE,
>          2, VerifyData,
>          0, TRUE, TRUE);
>  if (Error == HEIE_INVALID_RESPONSE)
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
> #if DEBUG_FILE
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", *pError,  
> *pError, AppVal);
> #endif
>   return *pError;
>   }
>
> #if 0
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   {
> #if DEBUG_FILE
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", Error, Error,  
> AppVal);
> #endif
>   return Error;
>   }
>  /* Check and make sure we got an ack. */
>  pRet = (RetBuffer+PACKET_HEADER_SIZE);
>
>  if (*pRet != FUN_ACK || (*(pRet+1) != FUN_CCM_REQUEST))
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
> #if DEBUG_FILE
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", *pError,  
> *pError, AppVal);
> #endif
>   return *pError;
>   }
>  NumBytes = sizeof(RetBuffer);
>  Error = GetResponse(pDevice, RetBuffer, &NumBytes, 0, TRUE, TRUE);
> #endif
>
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   {
> #if DEBUG_FILE
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", Error, Error,  
> AppVal);
> #endif
>   return Error;
>   }
>  NumBytes -= PACKET_HEADER_SIZE;
>  pRet = (RetBuffer + PACKET_HEADER_SIZE);
>  if (*pRet != FUN_RESPONSE || *(pRet+1) != FUN_CCM_REQUEST)
>   {
> #if DEBUG_FILE
>   Error = HEIE_INVALID_RESPONSE;
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", Error, Error,  
> AppVal);
> #endif
>   return HEIE_INVALID_RESPONSE;
>   }
>
>  pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
>
>  if (*pError)
>   {
> #if DEBUG_FILE
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", *pError,  
> *pError, AppVal);
> #endif
>   return *pError;
>   }
>
>  NumBytes -= 4;
>  if(!bWrite && NumBytes != (int)DataLen)
>   {
> #if DEBUG_FILE
>   Error = HEIE_INVALID_REQUEST;
>   DebugString("Error %d (0x%X) from HEICCMRequest %u", Error, Error,  
> AppVal);
> #endif
>   return HEIE_INVALID_REQUEST;
>   }
>
>  memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+4, DataLen);
> #if DEBUG_FILE
>  DebugString("Leaving HEICCMRequest %u", AppVal);
> #endif
>
>  return HEIE_NULL;
>  }
>
> __declspec(dllexport) int HEIKSEQRequest(HEIDevice *pDevice, WORD  
> DataLenIn, BYTE *pData, WORD *pDataLen)
>  {
>  BYTE Buffer[320];
>  BYTE RetBuffer[320];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  BYTE *pRet;
>  short int *pError;
>  int Retval;
>  BYTE VerifyData[2];
> #if DEBUG_FILE
>  DebugString("In HEIKSEQRequest %u", AppVal);
> #endif
>  if(DataLenIn > 256)
>   return HEIE_INVALID_REQUEST;
>  /* Function */
>  Buffer[DataOffset] = FUN_KSEQ_REQUEST;
>
>  /* Unused */
>  Buffer[DataOffset+1] = 0;
>  /* Request Code. */
>  Buffer[DataOffset+2] = (DataLenIn == 256) ? 0 : (BYTE)DataLenIn;
>
>  /* Unused */
>  Buffer[DataOffset+3] = 0;
>
>  /* Copy task code data. */
>  memcpy(&Buffer[DataOffset+4], pData, DataLenIn);
>  Total = DataOffset+4+DataLenIn;
>  NumBytes = sizeof(RetBuffer);
>
>  VerifyData[0] = FUN_ACK;
>  VerifyData[1] = FUN_KSEQ_REQUEST;
>  Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>          (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE,
>          2, VerifyData,
>          0, TRUE, TRUE);
>  if (Error == HEIE_INVALID_RESPONSE)
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
>   return *pError;
>   }
> #if 0
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  /* Check and make sure we got an ack. */
>  pRet = (RetBuffer+PACKET_HEADER_SIZE);
>
>  if (*pRet != FUN_ACK || (*(pRet+1) != FUN_KSEQ_REQUEST))
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
>   return *pError;
>   }
>  NumBytes = sizeof(RetBuffer);
>  Error = GetResponse(pDevice, RetBuffer, &NumBytes, 0, TRUE, TRUE);
> #endif
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>
>  NumBytes -= PACKET_HEADER_SIZE;
>  pRet = (RetBuffer + PACKET_HEADER_SIZE);
>  if (*pRet != FUN_RESPONSE || *(pRet+1) != FUN_KSEQ_REQUEST)
>   {
>   return HEIE_INVALID_RESPONSE;
>   }
>
>  pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
>
>  if (*pError)
>   return *pError;
>
>  NumBytes -= 4;
>
>   Retval = HEIE_NULL;
>  if ((WORD) NumBytes > *pDataLen)
>   {
>   Retval = HEIE_BUFFER_TOO_SMALL;
>   NumBytes = *pDataLen;
>   }
>
>  memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+4, NumBytes);
>  *pDataLen = NumBytes;
>
> #if DEBUG_FILE
>  DebugString("Leaving HEIKSEQRequest", Retval);
> #endif
>
>  return Retval;
>  }
> // Returns number of bytes not written.
> __declspec(dllexport) int HEIWriteComm(HEIDevice *pDevice, WORD  
> Num2Write, BYTE *pData)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  WORD *pWord;
>  int Error;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_WRITE_COMM;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = Num2Write;
>  if (Num2Write > (sizeof(Buffer) - DataOffset - 4))
>   return HEIE_DATA_TOO_LARGE;
>  memcpy(Buffer+DataOffset+4, pData, Num2Write);
>  Total = DataOffset+4+Num2Write;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEIReadComm(HEIDevice *pDevice, WORD  
> *pNum2Read, BYTE *pData)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  WORD *pWord;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_READ_COMM;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = *pNum2Read;
>  Total = DataOffset+4;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   short int *pNumReturned = (short int *) (RetBuffer 
> +PACKET_HEADER_SIZE+2);
>   if (*pInt)
>    Retval = *pInt;
>   (*pNum2Read) = *pNumReturned;
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+4, *pNumReturned);
>   }
>  else
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>  return Retval;
>  }
> __declspec(dllexport) int HEIGetRXAvailable(HEIDevice *pDevice, WORD  
> *pAvailable)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_RX_AVAILABLE;
>  Total = DataOffset+2;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   {
>   *pAvailable = *((WORD *) (RetBuffer+PACKET_HEADER_SIZE+2));
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEIFlushRXQueue(HEIDevice *pDevice)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_RX_FLUSH;
>  Total = DataOffset+2;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
>
> __declspec(dllexport) int HEISetupSerialPort(HEIDevice *pDevice,  
> SerialSetup *pSetup, BOOL WriteToFlash)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_SETUP;
>  Buffer[DataOffset+2] = (BYTE) WriteToFlash;
>  Buffer[DataOffset+3] = 0;
>  memcpy(Buffer+DataOffset+4, pSetup, sizeof(SerialSetup));
>  Total = DataOffset+4+sizeof(SerialSetup);
>  NumBytes = sizeof(RetBuffer);
>  if (WriteToFlash)
>   {
>   pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>   Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>           TRUE, FALSE,
>           0, NULL,
>           30000, TRUE, TRUE);
>   pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>   }
>  else
>   {
>   Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>   }
>  //if (Error)
>  // return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
> #if 0
>  if (WriteToFlash)
>   pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  if (WriteToFlash)
>   pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>  if (Error) return Error;
>  if (WriteToFlash)
>   {
>   NumBytes = sizeof(RetBuffer);
>   Error = GetResponse(pDevice, RetBuffer, &NumBytes, 30000, TRUE,  
> TRUE);
>   }
> #endif
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
>
> __declspec(dllexport) int HEIReadSerialPortSetup(HEIDevice *pDevice,  
> SerialSetup *pSetup)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_READ_SETUP;
>  Buffer[DataOffset+2] = 0;
>  Buffer[DataOffset+3] = 0;
>  Total = DataOffset+4;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   {
>   // Copy data into user buffer.
>   memcpy(pSetup, RetBuffer+PACKET_HEADER_SIZE, sizeof(SerialSetup));
>   return 0;
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
>
> __declspec(dllexport) int HEIGetTXLeft(HEIDevice *pDevice, WORD  
> *pLeft)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  //int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_TX_LEFT;
>  Total = DataOffset+2;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  //Retval = Error;
>  if (NumBytes)
>   {
>   *pLeft = *((WORD *) (RetBuffer+PACKET_HEADER_SIZE+2));
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> /* PLC MEMORY STUFF */
> __declspec(dllexport) int HEIReadMemory(HEIDevice *pDevice, WORD  
> Type, DWORD Offset, WORD NumBytes, BYTE *pBuffer)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Num;
>  WORD *pWord;
>  DWORD *pDWord;
>  Buffer[DataOffset] = FUN_READ_MEMORY;
>  Buffer[DataOffset+1] = 0;
>
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord++ = Type;
>  *pWord++ = NumBytes;
>  pDWord = (DWORD *) &Buffer[DataOffset+6];
>  *pDWord++ = Offset;
>  Total = DataOffset+10;
>  Num = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &Num, TRUE,  
> FALSE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  //if (Error)
>  // return Error;
>  if (Num)
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>
>   if (!((*pError) & 0x0FFF) || (*pError == HEIE_LENGTH_WARNING))
>    {
>    // Copy the memory.
>    memcpy(pBuffer, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>    }
>
>   return *pError;
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>
> /* return 0; */
>  }
>
> __declspec(dllexport) int HEIWriteMemory(HEIDevice *pDevice, WORD  
> Type, DWORD Offset, WORD NumBytes, BYTE *pBuffer)
>  {
>  BYTE Buffer[600];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Num;
>  WORD *pWord;
>  DWORD *pDWord;
>  if (NumBytes > 512)
>   return HEIE_DATA_TOO_LARGE;
>  Buffer[DataOffset] = FUN_WRITE_MEMORY;
>  Buffer[DataOffset+1] = 0;
>
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord++ = Type;
>  *pWord++ = NumBytes;
>  pDWord = (DWORD *) &Buffer[DataOffset+6];
>  *pDWord++ = Offset;
>
>  memcpy(Buffer+DataOffset+10, pBuffer, NumBytes);
>  Total = DataOffset+10+NumBytes;
>  Num = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &Num, TRUE,  
> FALSE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  //if (Error) return Error;
>  if (Num)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>
>  /* return 0; */
>  }
>
> __declspec(dllexport) int HEIAccessMemory(HEIDevice *pDevice, MemRef  
> MemRefs[], WORD NumRefs)
>  {
>  WORD DataOffset = pDevice->DataOffset;
>  BYTE Buffer[600];
>  BYTE RetBuffer[600];
>  BYTE *pSendData;
>  WORD x;
>  WORD *pWord;
>  WORD ReadSize = 2 + 2;     // Returned error value is 2 bytes long
>            // Returned num MemRefs is 2 bytes long
>  WORD TotalSize = 4 + DataOffset;  // Header info is 4 bytes long
>  int Num;
>  int Error;
>  Buffer[DataOffset] = FUN_ACCESS_MEMORY;
>  Buffer[DataOffset+1] = 0;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = NumRefs;
>  pSendData = &Buffer[DataOffset+4];
>  for (x=0; x<NumRefs; x++)
>   {
>   memcpy(pSendData, &MemRefs[x], sizeof(MemRefDetail));
>   TotalSize += sizeof(MemRefDetail);
>   pSendData += sizeof(MemRefDetail);
>   if (MemRefs[x].Detail.Direction == ACCESS_READ)
>    {
>    // Read request.
>    ReadSize += (MemRefs[x].Detail.NumBytes + sizeof(MemRefDetail));
>    }
>   else if (MemRefs[x].Detail.Direction == ACCESS_WRITE)
>    {
>    // Write request.
>    memcpy(pSendData, MemRefs[x].pBuffer, MemRefs[x].Detail.NumBytes);
>    TotalSize += MemRefs[x].Detail.NumBytes;
>    pSendData += MemRefs[x].Detail.NumBytes;
>    }
>   else
>    {
>    return HEIE_INVALID_REQUEST;
>    }
>   if ((TotalSize > sizeof(Buffer)) || (ReadSize > sizeof(RetBuffer)))
>    {
>    return HEIE_DATA_TOO_LARGE;
>    }
>   }
>  // Ready to send.
>  Num = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, TotalSize, RetBuffer, &Num,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (Num)
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   short int *pNum = (short int *) (RetBuffer+PACKET_HEADER_SIZE+2);
>
>   //if (!*pError && *pNum)
>   if (!((*pError) & 0x0FFF) && *pNum)
>    {
>    // No errors, and we have some read requests returned.
>    WORD x;
>    MemRefDetail *pReturnDetail = (MemRefDetail *) (RetBuffer 
> +PACKET_HEADER_SIZE+4);
>    for (x=0; x<NumRefs; x++)
>     {
>     // Find a read request.
>     if (MemRefs[x].Detail.Direction == ACCESS_READ)
>      {
>      // Read request; Make sure it matches.
>      if (MemRefs[x].Detail.Type  == pReturnDetail->Type &&
>       MemRefs[x].Detail.Offset == pReturnDetail->Offset &&
>       MemRefs[x].Detail.NumBytes == pReturnDetail->NumBytes)
>       {
>       // Requests match, so copy data.
>       BYTE *pData = (BYTE *) pReturnDetail;
>       pData += sizeof(MemRefDetail);
>       memcpy(MemRefs[x].pBuffer, pData, MemRefs[x].Detail.NumBytes);
>       // Reset for next one.
>       pData += MemRefs[x].Detail.NumBytes;
>       pReturnDetail = (MemRefDetail *) pData;
>       }
>      else
>       {
>       // Requests don't match, so return error.
>       return HEIE_INVALID_RESPONSE;
>       }
>      }
>     }
>    }
>
>   return *pError;
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
>
> __declspec(dllexport) int HEIENumMemory(HEIDevice *pDevice, WORD  
> *pSizeofDataInTypes, MemoryTypeDef *pData)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE) FUN_ENUM_MEMORY;    /* This is the  
> function code! */
>  Total = DataOffset+1;
>  NumBytes = sizeof(RetBuffer);
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  /* Check for error and not warning. */
>  //if (Error)
>  // return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   /*int NumTypes; */
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   short int *pNumTypes = (short int *) (RetBuffer+PACKET_HEADER_SIZE 
> +2);
>   if ((WORD) *pNumTypes > *pSizeofDataInTypes)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    *pNumTypes = *pSizeofDataInTypes;
>    }
>   if (*pInt)
>    Retval = *pInt;
>   (*pSizeofDataInTypes) = *pNumTypes;
>   memcpy((char *) pData, (char *) (RetBuffer+PACKET_HEADER_SIZE+4),  
> (*pNumTypes) * sizeof(MemoryTypeDef));
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
> //BYTE SharedRamArea = 0;
> __declspec(dllexport) int HEIReadSharedRAM(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Address, WORD Bytes2Read, BYTE *pBuffer)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[600];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Num;
>  WORD *pWord;
>  BYTE SharedRamArea = 0;
>  Buffer[DataOffset] = FUN_READ_SHARED_RAM;
>  if (Address & 0x8000)
>   {
>   SharedRamArea = 1;
>   Address &= 0x7FFF;
>   }
>  Buffer[DataOffset+1] = SharedRamArea;
>
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord++ = Base;
>  *pWord++ = Slot;
>  *pWord++ = Address;
>  *pWord++ = Bytes2Read;
>  Total = DataOffset+10;
>  Num = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &Num, TRUE,  
> FALSE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  //if (Error)
>  // return Error;
>  if (Num)
>   {
>   short int *pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>
>   //if (!*pError || (*pError == LENGTH_WARNING))
>   if (!((*pError) & 0x0FFF) || (*pError == HEIE_LENGTH_WARNING))
>    {
>    // Copy the memory.
>    memcpy(pBuffer, RetBuffer+PACKET_HEADER_SIZE+2, Bytes2Read);
>    }
>
>   return *pError;
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>
>  /* return 0; */
>  }
>
> __declspec(dllexport) int HEIWriteSharedRAM(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Address, WORD Bytes2Write, BYTE *pBuffer)
>  {
>  BYTE Buffer[600];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Num;
>  WORD *pWord;
>  BYTE SharedRamArea = 0;
>  if (Bytes2Write > 256)
>   return HEIE_DATA_TOO_LARGE;
>  Buffer[DataOffset] = FUN_WRITE_SHARED_RAM;
>  if (Address & 0x8000)
>   {
>   SharedRamArea = 1;
>   Address &= 0x7FFF;
>   }
>  Buffer[DataOffset+1] = SharedRamArea;
>
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord++ = Base;
>  *pWord++ = Slot;
>  *pWord++ = Address;
>  *pWord++ = Bytes2Write;
>
>  memcpy(Buffer+DataOffset+10, pBuffer, Bytes2Write);
>  Total = DataOffset+10+Bytes2Write;
>  Num = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &Num, TRUE,  
> FALSE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  //if (Error) return Error;
>  if (Num)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>
>  /* return 0; */
>  }
>
> /*
> ** Calculate, 16 Bit CRC
> */
> /* number of bits in CRC: don't change it.  */
> #define W 16
> /* this the number of bits per char: don't change it. */
> #define B 8
> static unsigned short crctab[1<<B] = {
>     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,   
> 0x70e7,
>     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,   
> 0xf1ef,
>     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,   
> 0x62d6,
>     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,   
> 0xe3de,
>     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,   
> 0x5485,
>     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,   
> 0xd58d,
>     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,   
> 0x46b4,
>     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,   
> 0xc7bc,
>     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,   
> 0x3823,
>     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,   
> 0xb92b,
>     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,   
> 0x2a12,
>     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,   
> 0xab1a,
>     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,   
> 0x1c41,
>     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,   
> 0x9d49,
>     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,   
> 0x0e70,
>     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,   
> 0x8f78,
>     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,   
> 0xe16f,
>     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,   
> 0x6067,
>     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,   
> 0xf35e,
>     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,   
> 0x7256,
>     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,   
> 0xc50d,
>     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,   
> 0x4405,
>     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,   
> 0xd73c,
>     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,   
> 0x5634,
>     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,   
> 0xa9ab,
>     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,   
> 0x28a3,
>     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,   
> 0xbb9a,
>     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,   
> 0x3a92,
>     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,   
> 0x8dc9,
>     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,   
> 0x0cc1,
>     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,   
> 0x9ff8,
>     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,   
> 0x1ef0
>     };
> WORD CalcCRC(WORD    icrc,
>             BYTE   *icp,
>             WORD    icnt)
>  {
>  register WORD crc = icrc;
>  register BYTE *cp = icp;
>  register WORD cnt = icnt;
>  while( cnt-- )
>   crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
>  return( crc );
>  }
>
> /*
> **
> ** WinPLC Specific Functions
> **
> */
> __declspec(dllexport) int WPLCSetOSLoad(HEIDevice *pDevice, int Val)
>  {
>  BYTE Buffer[100];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_SET_OS_LOAD;
>  Buffer[DataOffset+1] = ~FUN_SET_OS_LOAD;
>  memcpy(&Buffer[DataOffset+2], &Val, sizeof(int));
>  Total = DataOffset+2+sizeof(int);
>  NumBytes = sizeof(RetBuffer);
>  return _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  }
>
> __declspec(dllexport) int WPLCReboot(HEIDevice *pDevice)
>  {
>  BYTE Buffer[100];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_REBOOT;
>  Buffer[DataOffset+1] = ~FUN_REBOOT;
>  Total = DataOffset+2;
>  NumBytes = sizeof(RetBuffer);
>  return _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  }
> __declspec(dllexport) int HEIReboot(HEIDevice *pDevice)
>  {
>  BYTE Buffer[100];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_REBOOT;
>  Buffer[DataOffset+1] = ~FUN_REBOOT;
>  Total = DataOffset+2;
>  NumBytes = sizeof(RetBuffer);
>  return _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  }
>
> __declspec(dllexport) int WPLCRunProgram(HEIDevice *pDevice, BYTE  
> *pProgram)
>  {
>  BYTE Buffer[500];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  BYTE *pArgs, *pData;
>  WORD Total;
>  int NumBytes;
>  short int *pError;
>  memset(Buffer, 0, sizeof(Buffer));
>  Buffer[DataOffset] = FUN_RUN_PROGRAM;
>  Buffer[DataOffset+1] = ~FUN_RUN_PROGRAM;
>  pArgs = pProgram;
>  if (!*pArgs)
>   return -1;
>  // Skip whitespace at front.
>  while (*pArgs == ' ')
>   pArgs++;
>  pData = &Buffer[DataOffset+2];
>  // Copy program name.
>  while (*pArgs && (*pArgs != ' '))
>   {
>   *pData++ = *pArgs++;
>   }
>  while (isspace(*pArgs))
>   pArgs++;
>  strcpy((char *) &Buffer[DataOffset+66], (char *) pArgs);
>  Total = DataOffset+2+64+strlen((char *) pArgs)+1;
>  NumBytes = sizeof(RetBuffer);
>  _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes, TRUE,  
> FALSE);
>  pError = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>  return *pError;
>  }
>
> /*
> **
> ** THIS IS THE MODIFIED SERIAL PORT FUNCTIONS THAT ACCEPT A BYTE FOR  
> THE PORT NUMBER
> **
> */
> __declspec(dllexport) int HEIWriteCommEx(HEIDevice *pDevice, BYTE  
> Port, WORD Num2Write, BYTE *pData)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  WORD *pWord;
>  int Error;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_WRITE_COMM + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  pWord = (WORD *) &Buffer[DataOffset+3];
>  *pWord = Num2Write;
>  if (Num2Write > (sizeof(Buffer) - DataOffset - 5))
>   return HEIE_DATA_TOO_LARGE;
>  memcpy(Buffer+DataOffset+5, pData, Num2Write);
>  Total = DataOffset+5+Num2Write;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEIReadCommEx(HEIDevice *pDevice, BYTE  
> Port, WORD *pNum2Read, BYTE *pData)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  WORD *pWord;
>  int Error;
>  int Retval;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_READ_COMM + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  pWord = (WORD *) &Buffer[DataOffset+3];
>  *pWord = *pNum2Read;
>  Total = DataOffset+5;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   short int *pNumReturned = (short int *) (RetBuffer 
> +PACKET_HEADER_SIZE+2);
>   if (*pInt)
>    Retval = *pInt;
>   (*pNum2Read) = *pNumReturned;
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+4, *pNumReturned);
>   }
>  else
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>  return Retval;
>  }
> __declspec(dllexport) int HEIGetRXAvailableEx(HEIDevice *pDevice,  
> BYTE Port, WORD *pAvailable)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_RX_AVAILABLE + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  Total = DataOffset+3;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   {
>   *pAvailable = *((WORD *) (RetBuffer+PACKET_HEADER_SIZE+2));
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEIFlushRXQueueEx(HEIDevice *pDevice, BYTE  
> Port)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_RX_FLUSH + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  Total = DataOffset+3;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEIFlushTXQueueEx(HEIDevice *pDevice, BYTE  
> Port)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_TX_FLUSH + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  Total = DataOffset+3;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEISetupSerialPortEx(HEIDevice *pDevice,  
> BYTE Port, SerialSetup *pSetup, BOOL WriteToFlash)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_SETUP + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  Buffer[DataOffset+3] = (BYTE) WriteToFlash;
>  Buffer[DataOffset+4] = 0;
>  memcpy(Buffer+DataOffset+5, pSetup, sizeof(SerialSetup));
>  Total = DataOffset+5+sizeof(SerialSetup);
>  NumBytes = sizeof(RetBuffer);
>  if (WriteToFlash)
>   {
>   pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>   Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>           TRUE, FALSE,
>           0, NULL,
>           30000, TRUE, TRUE);
>   pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>   }
>  else
>   {
>   Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>   }
>  //if (Error)
>  // return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
>
> __declspec(dllexport) int HEIReadSerialPortSetupEx(HEIDevice  
> *pDevice, BYTE Port, SerialSetup *pSetup)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_READ_SETUP + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  Buffer[DataOffset+3] = 0;
>  Buffer[DataOffset+4] = 0;
>  Total = DataOffset+5;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  if (NumBytes)
>   {
>   // Copy data into user buffer.
>   memcpy(pSetup, RetBuffer+PACKET_HEADER_SIZE, sizeof(SerialSetup));
>   return 0;
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
>
> __declspec(dllexport) int HEIGetTXLeftEx(HEIDevice *pDevice, BYTE  
> Port, WORD *pLeft)
>  {
>  BYTE Buffer[200];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  //int Retval;
>  int NumBytes;
>  //Port = (Port - 1) << 4;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_TX_LEFT + 0x80; //Port;
>  Buffer[DataOffset+2] = Port-1;
>  Total = DataOffset+3;
>  NumBytes = sizeof(RetBuffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> TRUE, FALSE);
>  //if (Error) return Error;
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  //Retval = Error;
>  if (NumBytes)
>   {
>   *pLeft = *((WORD *) (RetBuffer+PACKET_HEADER_SIZE+2));
>   return *((short int *) (RetBuffer+PACKET_HEADER_SIZE));
>   }
>  else
>   return HEIE_ZERO_BYTES_RECEIVED;
>  }
> __declspec(dllexport) int HEIAccessComm(HEIDevice *pDevice, WORD  
> SendDataSize, BYTE *pSendData, WORD *pReturnDataSize, BYTE  
> *pReturnData)
>  {
>  BYTE Buffer[1500];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  WORD *pWord;
>  int Error;
>  int NumBytes;
>  int Retval;
>  Buffer[DataOffset] = FUN_SERIAL_PORT;
>  Buffer[DataOffset+1] = SPF_ACCESS_COMM;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  *pWord = SendDataSize;
>  if (SendDataSize > (sizeof(Buffer) - DataOffset - 4))
>   return HEIE_DATA_TOO_LARGE;
>  memcpy(Buffer+DataOffset+4, pSendData, SendDataSize);
>  Total = DataOffset+4+SendDataSize;
>  NumBytes = sizeof(Buffer);
>
>  Error = _SendPacket(pDevice, Buffer, Total, Buffer, &NumBytes,  
> TRUE, FALSE);
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (Buffer+PACKET_HEADER_SIZE);
>   short int *pNumReturned = (short int *) (Buffer+PACKET_HEADER_SIZE 
> +2);
>   if (*pInt)
>    Retval = *pInt;
>   if (pReturnData && pReturnDataSize)
>    {
>    if (*pNumReturned > *pReturnDataSize)
>     {
>     Retval = HEIE_BUFFER_TOO_SMALL;
>     }
>    else
>     {
>     (*pReturnDataSize) = *pNumReturned;
>     }
>    memcpy(pReturnData, Buffer+PACKET_HEADER_SIZE+4, *pReturnDataSize);
>    }
>   }
>  else
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIWriteEZethernetPgmSpace(HEIDevice  
> *pDevice, BYTE *pData, WORD SizeofData)
>  {
>  BYTE Buffer[600];
>  BYTE RetBuffer[200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD *pWord;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = (BYTE)FUN_USER_CONFIG_PANEL; /* This is the  
> function code! */
>  Buffer[DataOffset+1] = 0;
>  pWord = (WORD *) &Buffer[DataOffset+2];
>  Total = DataOffset+4+SizeofData;
>  // FYI: Incoming size should never be greater than 316 bytes.
>  //      60 bytes control + 255 Max AVG packet size + 1 byte for
>  //      the start character.
>  if (Total > sizeof(Buffer) || SizeofData > 316)
>   return HEIE_DATA_TOO_LARGE;
>  (void)memcpy(&Buffer[DataOffset+4], pData, SizeofData);
>  NumBytes = sizeof(RetBuffer);
>
>  pDevice->Timeout += EXTRA_TIME_FOR_SETUP_DATA;
>  Error = SendPacketTwoResponses(pDevice, Buffer, Total, RetBuffer,  
> &NumBytes,
>          TRUE, FALSE,
>          0, NULL,
>          30000, TRUE, TRUE);
>  pDevice->Timeout -= EXTRA_TIME_FOR_SETUP_DATA;
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) (RetBuffer+PACKET_HEADER_SIZE);
>   if (*pInt)
>    Retval = *pInt;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   }
>  return Retval;
>  }
>
> /*
> ** ERM Functions.
> */
> #define FUN_COMMAND  6
> #define FUN_READ_DATA 7
> #define FUN_WRITE_DATA 8
> #define FUN_STATUS_INWORK 1
> #define FUN_STATUS_DONE  2
> #define FUN_STATUS_ERROR 3
> __declspec(dllexport) int HEIWriteERMData(HEIDevice *pDevice, WORD  
> Base, WORD Slot, BYTE DataType, BYTE *pData, WORD NumBytes, WORD  
> Offset)
>  {
>  WORD Data[6];
>  WORD *pOffset;
>  WORD *pExtended;
>  WORD *pNumBytes;
>  int Index = 0;
>  // Common header
>  Data[Index++] = 0;      // Function + Status (ClearFunction until  
> all other data is written)
>  Data[Index++] = 0;      // Error
>  // Function specific header
>  Data[Index++] = DataType;    // Data type
>  pOffset = (WORD *) &Data[Index++]; // Pointer to Offset
>  pNumBytes = (WORD *) &Data[Index++];// Pointer to num bytes
>  pExtended = (WORD *) &Data[Index++]; // Pointer to extended
>  *pOffset = Offset;
>  *pNumBytes = 256;
>  *pExtended = 0;
>
>  while (NumBytes)
>   {
>   int Error;
>   //memcpy(&Data[11], pOutputData, *pNumBytes);
>   if (*pNumBytes > NumBytes)
>    *pNumBytes = NumBytes;
>   Data[0] = 0;
>   Data[1] = 0;
>   // Write Header first.
>   Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30 + 0x8000,  
> sizeof(Data), (BYTE *) Data);
>   if (Error)
>    {
>    //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>    return Error;
>    }
>   // Next write data.
>   Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30+sizeof(Data) +  
> 0x8000, *pNumBytes, pData);
>   if (Error)
>    {
>    //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>    return Error;
>    }
>   // Now write the REAL command.
>   Data[0] = FUN_WRITE_DATA;
>   Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30+ 0x8000, 1,  
> (BYTE *) Data);
>   if (Error)
>    {
>    //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>    return Error;
>    }
>   else
>    {
>    // Wait for it to complete.
>    DWORD StartTime = HEIIGetCounter();
>    BOOL Done = FALSE;
>    do
>     {
>     BYTE bData[4];
>     Error = HEIReadSharedRAM(pDevice, Base, Slot, 0x30+ 0x8000, 4,  
> (BYTE *) bData);
>     if (Error)
>      {
>      //printf("\nError %d (0x%X) from HEIReadSharedRAM", Error,  
> Error);
>      return Error;
>      }
>     else
>      {
>      if ((bData[1] & 0xFF) == FUN_STATUS_DONE)
>       {
>       Done = TRUE;
>       }
>      else if ((bData[1] & 0xFF) == FUN_STATUS_ERROR)
>       {
>       return bData[2];  // Return Error
>       }
>      }
>     } while (!Done && TimeDiff(StartTime, HEIIGetCounter()) <  
> pDevice->Timeout);
>    if (!Done)
>     {
>     //printf("\nTimeout waiting for request to complete.");
>     return HEIE_TIMEOUT;
>     }
>    }
>   pData += *pNumBytes;
>   (*pOffset) += *pNumBytes;
>   NumBytes -= *pNumBytes;
>   }
> #if 0
>  if ((DataType == DATA_OUTPUT) && (Flags & 0x01))
>   {
>   return WPLCDoERMCommand(Base, Slot, COMMAND_PROCESS_IO, 0, 0);
>   }
> #endif
>  return 0;
>  }
> __declspec(dllexport) int HEIReadERMData(HEIDevice *pDevice, WORD  
> Base, WORD Slot, BYTE DataType, BYTE *pData, WORD NumBytes, WORD  
> Offset)
>  {
>  WORD Data[6];
>  WORD *pOffset;
>  WORD *pNumBytes;
>  WORD *pExtended;
>  int Index = 0;
>  // Common header
>  Data[Index++] = 0;      // Function + Status (ClearFunction until  
> all other data is written)
>  Data[Index++] = 0;      // Error
>  // Function specific header
>  Data[Index++] = DataType;    // Data type
>  pOffset = (WORD *) &Data[Index++]; // Pointer to Offset
>  pNumBytes = (WORD *) &Data[Index++];// Pointer to num bytes
>  pExtended = (WORD *) &Data[Index++]; // Pointer to extended
>  *pOffset = Offset;
>  *pNumBytes = 256;
>  *pExtended = 0;
>  //RETAILMSG(1, (TEXT("\r\nWPLCReadERMData Base: %d Slot: %d  Type:  
> %d  Num: %d"), Base, Slot, DataType, NumBytes));
>  while (NumBytes)
>   {
>   int Error;
>   Data[0] = 0;
>   Data[1] = 0;
>   if (*pNumBytes > NumBytes)
>    {
>    *pNumBytes = NumBytes;
>    }
>   Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30+0x8000,  
> sizeof(Data), (BYTE *) Data);
>   if (Error)
>    {
>    //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>    return Error;
>    }
>   // Now write the REAL command.
>   Data[0] = FUN_READ_DATA;
>   Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30+0x8000, 2,  
> (BYTE *) Data);
>   if (Error)
>    {
>    //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>    return Error;
>    }
>   else
>    {
>    // Wait for it to complete.
>    DWORD StartTime = HEIIGetCounter();
>    BOOL Done = FALSE;
>    do
>     {
>     BYTE bData[4];
>     Error = HEIReadSharedRAM(pDevice, Base, Slot, 0x30+0x8000, 4,  
> bData);
>     if (Error)
>      {
>      //printf("\nError %d (0x%X) from HEIReadSharedRAM", Error,  
> Error);
>      return Error;
>      }
>     else
>      {
>    //RETAILMSG(1, (TEXT("\r\nbData: 0x%X 0x%X 0x%X 0x%X"), bData[0],  
> bData[1], bData[2], bData[3]));
>      //if (((Data[0]>>8) & 0xFF) == FUN_STATUS_DONE)
>      if (bData[1] == FUN_STATUS_DONE)
>       {
>       // Read the rest of the data.
>       Error = HEIReadSharedRAM(pDevice, Base, Slot, 0x30+sizeof(Data) 
> +0x8000, *pNumBytes, pData);
>       if (Error)
>        {
>        //printf("\nError %d (0x%X) from HEIReadSharedRAM", Error,  
> Error);
>        return Error;
>        }
>       Done = TRUE;
>       }
>      //else if (((Data[0]>>8) & 0xFF) == FUN_STATUS_ERROR)
>      else if (bData[1] == FUN_STATUS_ERROR)
>       {
>       return Data[2];
>      // memcpy(pInputData, &Data[11], *pNumBytes);
>       }
>      }
>     } while (!Done && TimeDiff(StartTime, HEIIGetCounter()) <  
> pDevice->Timeout);
>    if (!Done)
>     {
>     //printf("\nTimeout waiting for request to complete.");
>     return HEIE_TIMEOUT;
>     }
>    }
>   pData += *pNumBytes;
>   (*pOffset) += *pNumBytes;
>   NumBytes -= *pNumBytes;
>   }
>  return 0;
>  }
> __declspec(dllexport) int HEIDoERMCommand(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Command)
>  {
>  DWORD StartTime;
>  WORD Data[3];
>  int Index = 0;
>  int Error;
>  // Common header
>  Data[Index++] = 0; // Command and Status (Set Command to zero until  
> rest of data is written)
>  Data[Index++] = 0;      // Error
>
>  // Function specific header
>  Data[Index++] = Command;
>  Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30 + 0x8000,  
> sizeof(Data), (BYTE *) Data);
>  if (Error)
>   {
>   //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>   return Error;
>   }
>  // Now write the REAL command.
>  Data[0] = FUN_COMMAND;
>  Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30+0x8000, 2,  
> (BYTE *) Data);
>  if (Error)
>   {
>   //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>   return Error;
>   }
>   // Wait for it to complete.
>  StartTime = HEIIGetCounter();
>  while (TimeDiff(StartTime, HEIIGetCounter()) < pDevice->Timeout)
>   {
>   BYTE bData[4];
>   Error = HEIReadSharedRAM(pDevice, Base, Slot, 0x30+0x8000, 4,  
> (BYTE *) bData);
>   if (!Error)
>    {
>    if ((bData[1] & 0xFF) == FUN_STATUS_DONE)
>     return 0;
>    else if ((bData[1] & 0xFF) == FUN_STATUS_ERROR)
>     return bData[2];
>    }
>   }
>  return HEIE_TIMEOUT;
>  }
>
> __declspec(dllexport) int HEIDoERMCommandEx(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Command, BYTE *pExtra, WORD ExtraLen)
>  {
>  DWORD StartTime;
>  BYTE Data[300];
>  int Index = 0;
>  int Error;
>  WORD *pCommand;
>  BOOL Done;
>  // Common header
>  Data[Index++] = 0; // Command and Status (Set Command to zero until  
> rest of data is written)
>  Data[Index++] = 0;      // Error
>  Data[Index++] = 0; // Command and Status (Set Command to zero until  
> rest of data is written)
>  Data[Index++] = 0;      // Error
>
>  // Function specific header
>  pCommand = (WORD *) &Data[Index];
>  *pCommand = Command;
>  Index += 2;
>  memcpy(&Data[Index], pExtra, ExtraLen);
>  Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30 + 0x8000,   
> (WORD)(ExtraLen + 6), Data);
>  if (Error)
>   {
>   //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>   return Error;
>   }
>  // Now write the REAL command.
>  Data[0] = FUN_COMMAND;
>  Data[1] = 0;
>  Error = HEIWriteSharedRAM(pDevice, Base, Slot, 0x30+0x8000, 2,  
> (BYTE *) Data);
>  if (Error)
>   {
>   //printf("\nError %d (0x%X) from HEIWriteSharedRAM", Error, Error);
>   return Error;
>   }
>   // Wait for it to complete.
>  Done = FALSE;
>  StartTime = HEIIGetCounter();
>  do
>   {
>   BYTE bData[4];
>   Error = HEIReadSharedRAM(pDevice, Base, Slot, 0x30+0x8000, 4,  
> bData);
>   if (!Error)
>    {
>    if (bData[1] == FUN_STATUS_DONE)
>     Done = TRUE;
>    else if (bData[1] == FUN_STATUS_ERROR)
>     return (int) (((WORD) bData[2]) + (((WORD) bData[3]) << 8));
>    }
>   } while (!Done && TimeDiff(StartTime, HEIIGetCounter()) < pDevice- 
> >Timeout);
>  if (!Done)
>   return HEIE_TIMEOUT;
>  return 0;
>  }
>
> NODELIST *EZGetNodeList(unsigned short int *TotalEZ)
> {
>     static NODELIST EZList[200];
>     static HEIDevice HEIDevices[100];
>     static HEITransport   TP;
>     unsigned short int i, j;   // Index variables
>     int Error, MaxDevices, MaxEZDevices;
>     WORD  Timeout   = 100;
>     WORD  Retrys    = 2;
>     WORD  SizeofData;
>     BOOL  Broadcast = FALSE;
>     BYTE  Data[500];
>  BYTE *pData = Data;
>     DeviceDef dd;
>   WORD NumDevices;
>     HEITransport *tp = &TP;
>     ENetAddress  *pSourceAddress = (ENetAddress *)NULL;
>  tp->Transport = HEIT_WINSOCK;
>     tp->Protocol  = HEIP_IPX;
>     *TotalEZ = 0;   // Set to zero until proven otherwise.
>  Error = HEIOpenTransport(tp, HEIAPIVERSION, pSourceAddress);
>     if (Error)
>  {
>         //printf("Error returned from HEIOpenTransport()\n");
>         return (NODELIST *)NULL;
>  }
>     MaxDevices   = sizeof(HEIDevices) / sizeof(HEIDevice);
>     MaxEZDevices = sizeof(EZList)     / sizeof(NODELIST);
>  NumDevices = MaxEZDevices;
>  Error = HEIQueryDevices(tp, HEIDevices, &NumDevices, HEIAPIVERSION);
>  if (Error)
>  {
>         //printf("Error returned from HEIQueryDevices()\n");
>         (void)HEIClose();
>         return (NODELIST *)NULL;
>  }
>
>     j = 0;
>     for (i = 0; i < NumDevices; i++)
>     {
>         if (i > MaxDevices)
>         {
>             goto ReturnIncompleteList;
>         }
>         Error = HEIOpenDevice(tp, &HEIDevices[i], HEIAPIVERSION,  
> Timeout, Retrys, Broadcast);
>         if (Error)
>         {
>             //printf("IsDeviceEZEthernet: Error %d returned from  
> HEIOpenDevice\n", Error);
>             return (NODELIST *)NULL;
>         }
>      Error = HEIReadDeviceDef(&HEIDevices[i], (BYTE *) &dd,  
> sizeof(dd));
>         if (Error)
>         {
>             //printf("IsDeviceEZEthernet: Error returned from  
> HEIReadDeviceDef\n");
>             goto ErrorHandler;
>         }
>         if (dd.ModuleType == MT_AVG_DISP)
>         {
>             if (j >= MaxEZDevices)
>                 goto ErrorHandler;
>             SizeofData = sizeof(WORD);
>             Error = HEIReadSetupData( &HEIDevices[i],  
> DT_NODE_NUMBER, pData, &SizeofData);
>       if (Error)
>       {
>                 //printf("Error %d returned from  
> HEIReadSetupData1\n", Error);
>                 goto ErrorHandler;
>             }
>       else
>             {
>                  (void)memcpy(EZList[j].Node_ID, pData, sizeof(WORD));
>       }
>             // Get the Node Name
>       SizeofData = sizeof(EZList[0].Name);
>             Error = HEIReadSetupData(&HEIDevices[i], DT_NODE_NAME,  
> pData, &SizeofData);
>       if (Error)
>       {
>                 //printf("Error returned from HEIReadSetupData2\n");
>                 goto ErrorHandler;
>             }
>             else
>             {
>              (void)memcpy(EZList[j].Name, pData, SizeofData);
>             }
>             EZList[j].pDevice = &HEIDevices[i];
>             j++;
>         }
>         else
>         {
>             // Close the device since it is not an EZ_Ethernet.
>             (void)HEICloseDevice(&HEIDevices[i]);
>         }
>     }   // End of for
>
>     if (j == 0)
>     {
>         goto ErrorHandler;
>     }
>     else
>     {
>         (void)HEIClose();
>         *TotalEZ = j;
>         return EZList;
>     }
>
>     ReturnIncompleteList:
>         // If we have process the maximum number of devices we can
>         // do, return a list of what we got.
>         (void)HEIClose();
>         *TotalEZ = j;
>      return EZList;
>     ErrorHandler:
>         (void)HEICloseDevice(&HEIDevices[i]);
>         (void)HEIClose();
>      return (NODELIST *)NULL;
> }
>
> BOOL EZSendPacket(HEIDevice *pDevice, PGM_BUF *pBuffer, BYTE  
> *Error_message, unsigned short int Len)
> {
>     int Error;
> #if TC_DEBUG
>     int i;
>     printf("EZSendPacket: Incoming buffer has:\n");
>     for (i = 0; i < Len; i++)
>         printf("%c", pBuffer->PgmData[i]);
>     printf("\n");
> #endif
>     Error = HEIWriteEZethernetPgmSpace(pDevice, (BYTE *)pBuffer- 
> >PgmData, Len );
>  switch (Error)
>     {
>         case HEIE_DATA_TOO_LARGE:
>         {
>             (void)memcpy(&Error_message, "Message size too large",  
> 81);
>             return FALSE;
>         }
>
>         case HEIE_ZERO_BYTES_RECEIVED:
>         {
>             (void)memcpy(&Error_message, "Attempted to send zero- 
> length message", 81);
>              return FALSE;
>         }
>         case -1:
>         {
>             // printf("Error %X returned from   
> HEIWriteEZethernetPgmSpace!\n", Error);
>              (void)memcpy(&Error_message,  
> "HEIWriteEZethernetPgmSpace call failed with -1", 81);
>              return FALSE;
>         }
>         case NO_ERROR:
>         {
>               //printf("Successfull send from  
> HEIWriteEZethernetPgmSpace\n");
>               Error_message[0] = '\0';
>               return TRUE;
>         }
>
>         default:
>         {
>              //printf("Error %X returned from   
> HEIWriteEZethernetPgmSpace!\n", Error);
>              (void)memcpy(&Error_message,  
> "HEIWriteEZethernetPgmSpace call failed with unknown error", 81);
>              return FALSE;
>         }
>     }
>  return TRUE;
> }
>
> int WPLCWriteERMData(HEIDevice *pDevice, WORD Base, WORD Slot, BYTE  
> DataType, BYTE *pData, WORD NumBytes, WORD Offset)
>  {
>  return HEIWriteERMData(pDevice, Base, Slot, DataType, pData,  
> NumBytes, Offset);
>  }
> int WPLCReadERMData(HEIDevice *pDevice, WORD Base, WORD Slot, BYTE  
> DataType, BYTE *pData, WORD NumBytes, WORD Offset)
>  {
>  return HEIReadERMData(pDevice, Base, Slot, DataType, pData,  
> NumBytes, Offset);
>  }
> int WPLCDoERMCommand(HEIDevice *pDevice, WORD Base, WORD Slot, WORD  
> Command)
>  {
>  return HEIDoERMCommand(pDevice, Base, Slot, Command);
>  }
> int WPLCDoERMCommandEx(HEIDevice *pDevice, WORD Base, WORD Slot,  
> WORD Command, BYTE *pExtra, WORD ExtraLen)
>  {
>  return HEIDoERMCommandEx(pDevice, Base, Slot, Command, pExtra,  
> ExtraLen);
>  }
>
> __declspec(dllexport) int SetCRCMode(int Mode)
>  {
>  int Old = DoCRC;
>  DoCRC = Mode;
>  return Old;
>  }
>
> /* CONFIG DATA ACCESS */
> __declspec(dllexport) int HEIReadConfigData(HEIDevice *pDevice, BYTE  
> *pData, WORD *DataSize)
>  {
>  BYTE Buffer[100];
>  BYTE RetBuffer[1200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>
>  Buffer[DataOffset] = FUN_READ_CONFIG_DATA; /* This is the function  
> code! */
>  Total = DataOffset+1;
>  if (pData && *pData == 0xB1)
>   {
>   Buffer[DataOffset+1] = *pData;
>   Total++;
>   }
>  NumBytes = sizeof(RetBuffer);
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) &RetBuffer[PACKET_HEADER_SIZE];
>   NumBytes -= PACKET_HEADER_SIZE;
>   NumBytes -= 2;
>   if ((WORD) NumBytes > *DataSize)
>    {
>    Retval = HEIE_BUFFER_TOO_SMALL;
>    NumBytes = *DataSize;
>    }
>   if (*pInt)
>    Retval = (*pInt) | 0x8000;
>   memcpy(pData, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>   (*DataSize) = NumBytes;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   (*DataSize) = 0;
>   }
>  return Retval;
>  }
>
> __declspec(dllexport) int HEIWriteConfigData(HEIDevice *pDevice,  
> BYTE *pData, WORD SizeofData, BYTE *pReturnData, WORD  
> *pSizeofReturnData)
>  {
>  BYTE Buffer[1200];
>  BYTE RetBuffer[1200];
>  WORD DataOffset = pDevice->DataOffset;
>  WORD Total;
>  int Error;
>  int Retval;
>  int NumBytes;
>  Buffer[DataOffset] = FUN_WRITE_CONFIG_DATA;    /* This is the  
> function code! */
>
>  Total = DataOffset+1+SizeofData;
>  if (Total > sizeof(Buffer))
>   return HEIE_DATA_TOO_LARGE;
>  memcpy(Buffer+DataOffset+1, pData, SizeofData);
>  NumBytes = sizeof(RetBuffer);
>  //NumBytes = *pSizeofReturnData;
>
>  Error = _SendPacket(pDevice, Buffer, Total, RetBuffer, &NumBytes,  
> (pDevice->ParallelPackets) ? FALSE : TRUE, TRUE);
>  /* Check for error and not warning. */
>  if (Error && !(Error & HEIW_FIRST_WARNING))
>   return Error;
>  Retval = Error;
>  if (NumBytes)
>   {
>   short int *pInt = (short int *) &RetBuffer[PACKET_HEADER_SIZE];
>   if (pReturnData && pSizeofReturnData)
>    {
>    NumBytes -= PACKET_HEADER_SIZE;
>    NumBytes -= 2;
>    if ((WORD) NumBytes > *pSizeofReturnData)
>     {
>     Retval = HEIE_BUFFER_TOO_SMALL;
>     NumBytes = *pSizeofReturnData;
>     }
>    memcpy(pReturnData, RetBuffer+PACKET_HEADER_SIZE+2, NumBytes);
>    (*pSizeofReturnData) = NumBytes;
>    }
>   if (*pInt)
>    Retval = (*pInt) | 0x8000;
>   }
>  else
>   {
>   Retval = HEIE_ZERO_BYTES_RECEIVED;
>   if (pSizeofReturnData)
>    (*pSizeofReturnData) = 0;
>   }
>  return Retval;
>  }
>
> /*
> **
> **  HOST ETHERNET INTERFACE (HEI) - HEADER FILE
> **
> ** Copyright 1996-2001 - Host Automation Products, Inc.
> *
> */
> #if !defined(__HEI_H)
> #define __HEI_H
>
> /* Force structure alignment on single byte boundary */
> #pragma pack(1)
> #if !defined(P_ERMA) & !defined(P_ECOM)  & !defined(EBC) & ! 
> defined(P_ERMA) & !defined(BOOTER) & !defined(PROFIBUS)
> typedef struct
>  {
>  unsigned IgnoreUserMain : 1;
>  unsigned IgnoreVbUserMain : 1;
>  unsigned IgnoreDebugMsg : 1;
>  unsigned UnusedBits : 29;
>  BYTE UnusedBytes[28];
>  } StartupSettings;
> #endif
> typedef struct
>  {
>  WORD SizeofEthernetStats;
>  DWORD MissedFrameCount;
>  DWORD TransmitCollisionCount;
>  DWORD DiscardedPackets;
>  DWORD BadCRCCount;
>
>  DWORD UnknownTypeCount;
>  DWORD SendErrorCount;
>  } EthernetStats;
> typedef struct
>  {
>  BYTE Version;
>  BYTE Bytes2Follow;
>
> #if defined (ANSI_C)
>  BYTE UnusedBytess[16];       /* Support Info */
> #else
>  BYTE SUP_FUN_POLLING     : 1;   /* Polling one base */
>  BYTE SUP_FUN_READ_VER_INFO   : 1;    /* Version Info */
>  BYTE SUP_FUN_READ_SUPPORT_INFO  : 1;   /* Support Info */
>  BYTE SUP_FUN_READ_DEVICE_INFO  : 1;   /* Device Info  */
>  BYTE SUP_FUN_POLLING_ALL   : 1;    /* Polling all bases (returns  
> ethernet address) */
>  BYTE SUP_FUN_WRITE_IO    : 1;   /* Write IO base */
>  BYTE SUP_FUN_READ_IO    : 1;   /* Read IO Base */
>  BYTE SUP_FUN_READ_BASE_DEF   : 1;    /* ReadBaseDef */
>
>  BYTE SUP_FUN_ENUM_SETUP_DATA  : 1;   /* Enumerate setup data */
>  BYTE SUP_FUN_READ_SETUP_DATA     : 1;   /* Read setup data */
>  BYTE SUP_FUN_WRITE_SETUP_DATA  : 1;   /* Write setup data */
>  BYTE SUP_FUN_DELETE_SETUP_DATA  : 1;    /* Delete setup data */
>  BYTE SUP_FUN_READ_ETHERNET_STATS : 1;    /* Read ethernet  
> statistics */
>  BYTE SUP_FUN_PET_LINK    : 1;    /* Used to keep the link sense  
> timer from firing in the absense of ReadIO or WriteIO messages */
>  BYTE SUP_FUN_ADDRESSED_BROADCAST : 1;    /* Used to broadcast to a  
> particular ethernet address. */
>  BYTE SUP_FUN_READ_MODULE_STATUS  : 1;   /* Read module status short  
> BYTEs */
>
>  BYTE SUP_FUN_EXTENDED    : 1;   /* Extended function */
>  BYTE SUP_FUN_QUERY_SETUP_DATA  : 1;   /* Query for particular data  
> type/value */
>  BYTE SUP_FUN_INIT_BASE_DEF    : 1;   /* Initialize base def from  
> backplane. */
>  BYTE SUP_FUN_DATA_BROADCAST   : 1;   /* Broadcast to a particular  
> data type */
>  BYTE SUP_FUN_CCM_REQUEST   : 1;   /* Perform CCM Request */
>  BYTE SUP_FUN_KSEQ_REQUEST   : 1;   /* Perform KSEQ Request */
>  BYTE SUP_FUN_BACKPLANE_REQUEST  : 1;   /* Perform backplane request  
> */
>  BYTE SUP_FUN_WRITE_BASE_DEF   : 1;   /* Write Base Def */
>
>  BYTE SUP_FUN_EXTEND_RESPONSE  : 1;   /* Extends the response  
> packet. */
>  BYTE SUP_FUN_ACK     : 1;   /* Acknowledge */
>  BYTE SUP_FUN_NAK     : 1;   /* NOT Acknowledge */
>  BYTE SUP_FUN_RESPONSE     : 1;   /* Response */
>  BYTE SUP_FUN_SERIAL_PORT   : 1;   /* Execute serial port function  
> (see below) */
>  BYTE SUP_FUN_WRITE_MEMORY   : 1;   /* Write a particular memory  
> type */
>  BYTE SUP_FUN_READ_MEMORY   : 1;   /* Read a particular memory type */
>  BYTE SUP_FUN_ENUM_MEMORY   : 1;   /* Get list of all memory types */
>  BYTE SUP_FUN_READ_SHARED_RAM  : 1;   /* Read shared ram */
>  BYTE SUP_FUN_WRITE_SHARED_RAM  : 1;   /* Write shared ram */
>  BYTE SUP_FUN_ACCESS_MEMORY   : 1;   /* Access (read/write) multiple  
> memory types */
>  BYTE SUP_FUN_COMM_RESPONSE   : 1;   /* Response to PLC generated  
> COMM request */
>  BYTE SUP_FUN_COMM_REQ_ACK   : 1;   /* Function from PLC generated  
> COMM request */
>  BYTE SUP_FUN_WRITE_IO_NO_READ  : 1;   /* Write IO base with  
> returned read */
>  BYTE SUP_FUN_COMM_NO_REQ_ACK  : 1;  /* Function from PLC generated  
> COMM request */
>  BYTE SUP_FUN_RUN_PROGRAM   : 1;   /* Function to execute a program */
>  BYTE SUP_FUN_REMOTE_API    : 1;  /* Function to execute a function  
> on remote device */
>  BYTE SUP_FUN_NOTIFY     : 1;  /* Indicates a notification */
>  BYTE SUP_FUN_COMPLETION    : 1;  /* Indicates completion of some  
> activity */
>  BYTE SUP_FUN_SET_OS_LOAD   : 1;  /* Set Load OS Parm. */
>  BYTE SUP_FUN_REBOOT     : 1;  /* Reboot OS   */
>  BYTE SUP_FUN_EXTEND_RESPONSE_FIX : 1; /* Fixed version that extends  
> the response packet. */
>  BYTE SUP_NEW_STYLE_IO    : 1; /* This device supports new style I/O  
> requests */
>  BYTE SUP_HOT_SWAP      : 1; /* True if this device supports hot  
> swap */
>  BYTE SUP_TCP_IP      : 1;  /* TRUE if this device supports TCP/IP */
>  BYTE SUP_HTTP       : 1;  /* TRUE if this device supports HTTP */
>  BYTE Reserved       : 6;
>
>  BYTE UnusedBytes[9];       /* Unused */
> #endif
>  } SupportDef;
>
> /* Defines for Flags in WPLCSystemInformation structure */
> #define WPLC_FLAG_BATT_LOW 0x01
> /* Masks for LED indicator */
> #define WPLC_LED_POWER 0x01
> #define WPLC_LED_RUN  0x02
>
> typedef struct
>  {
>  DWORD Flags;   /* Bit 0: Battery Low indicator.  */
>         /* Bit 1-31: Unused      */
>  DWORD RAMSize;   /* Total size of RAM in WinPLC */
>  DWORD FlashSize;  /* Total size of Flash memory in WinPLC */
>  DWORD BattRAMSize; /* Total size of Battery-backed ram in WinPLC */
>  DWORD DipSwitches; /* Status of dip switches */
>         /* Note: Dip Switches #6 & #7 are reserved for system use. */
>  DWORD LEDs;    /* LED status indicator (see WPLC_LED_XXXX defines) */
>  DWORD OSSize;   /* Size of the WinPLC OS Image */
>  DWORD FFSTotal;  /* Total size of the WinPLC flashed based file  
> system */
>  DWORD FFSFree;   /* Free size of the WinPLC flashed based file  
> system */
>  DWORD RAMPercentFree; /* Percent of RAM that is free. */
>  DWORD RAMPhysicalFree; /* Physical RAM that is free.  */
>  DWORD VendorID;   /* Vendor ID from the WinPLC */
>  DWORD CPUClockFrequency;
>  BYTE  ENetAddress[6];
>  BYTE Unused[198];
>  } WPLCSystemInformation;
>
>
> /* ERM Defs */
> #define BIT_INPUT  0
> #define BIT_OUTPUT 1
> #define WORD_INPUT 2
> #define WORD_OUTPUT 3
> /* sERMDevice (128 bytes each) */
> typedef struct
>  {
>  BYTE AddressMode;  /* Defines format of address field (see AM_XXX  
> below)    */
>  BYTE Protocol;   /* HEIP_HOST, HEIP_IPX, or HEIP_IP, 0 ==  
> Unused      */
>  struct
>   {
>   union
>    {
>    /* Use this for AM_ETHER addressing (Protocol: HEIP_IPX or  
> HEIP_HOST) */
>    BYTE EtherAddr[6];  /* Ethernet network address */
>    /* Use this for AM_NODENUM addressing (Protocol: HEIP_IPX or  
> HEIP_HOST or HEIP_IP) */
>    DWORD Nodenum;
>    /* Use this for AM_IPADDR addressing (Protocol: HEIP_IPX or  
> HEIP_HOST or HEIP_IP) */
>    BYTE IPAddr[4];
> #if defined (ANSI_C)
>    } AM;
> #else
>    };
> #endif
>   BYTE Netnum[4]; /* Used for HEIP_IPX protocol; HEIP_IP   */
>   WORD Port;   /* Used for HEIP_IPX and HEIP_IP protocols */
>   union
>    {
>    BYTE FrameType; /* Used for HEIP_IPX protocol (See FT_XXXX) */
>    BYTE GatewayAddress[4]; /* Gateway to use for this device (0's  
> for no gateway) */
> #if defined (ANSI_C)
>    } AM2;
> #else
>    };
> #endif
>   /* BYTE Reserved[3];*/
>   } Address;
>  WORD Timeout;      /* Timeout time for this device           */
>  WORD Retrys;      /* Number of time to retry a request before  
> reporting error.   */
>  BYTE ModuleIDs[32];    /* Module ID's for each slot in the  
> device       */
>  WORD Flags;       /* See ERM_FLAG_??? defines            */
>  WORD DataOffsets[4];    /* Data offsets for each type (BIT_INPUT,  
> BIT_OUTPUT,    */
>            /* WORD_INPUT, WORD_OUTPUT) if with a PLC        */
>  WORD DataSizes[4];    /* Data sizes (in bytes) for each type if  
> with a PLC    */
>  WORD WatchDog;      /* Watchdog timeout value to use for this  
> device     */
>  WORD PetFrequency;    /* Freq to pet the device to keep WatchDog  
> from firing   */
>            /* Specified in milliseconds.  If zero no pets will be  
> done  */
>  WORD FailuresBeforeStandby; /* Number of consecutive failures to  
> put device in     */
>            /* standby mode.                */
>  BYTE Reserved[50];    /* Reserved (set to zero)             */
>  } sERMDevice;
> /* Address mode 0 is undefined */
> #define AM_NODENUM 1
> #define AM_NAME    2  /* Not supported in ERM module. */
> #define AM_IPADDR  3
> #define AM_ETHER   4
> /* Interface defines */
> #define IF_UNDEFINED  0 /* ERM I/F not defined / detected         */
> #define IF_PLC    1 /* ERM will use a PLC style interface        */
> #define IF_WINPLC   2 /* ERM will use a WinPLC style interface        
> */
> #define ERM_FLAG_IGNORE_WARNINGS  1  /* If set, warnings from this  
> device are ignored */
> #define ERM_FLAG_AUTO_HOT_SWAP  2  /* If set, terminator hot swap is  
> automatic   */
> /* Frame type defines */
> #define FT_802_2       1
> #define FT_802_3       2
> #define FT_ETHER_II    3
>
> typedef struct sERMConfig
>  {
>  BYTE Version;      /* Version of sERMConfig 0=Unconfigured; 1=  
> Current Version */
>  BYTE Interface;     /* See IF_XXX above.              */
>  WORD PLCAddresses[4];   /* Address for each type. (BIT_INPUT,  
> BIT_OUTPUT,    */
>            /* WORD_INPUT, WORD_OUTPUT) if with a PLC       */
>  WORD PLCDataSizes[4];   /* Size (in bytes) for each type if with a  
> PLC.     */
>  DWORD StandbyCycleTime;   /* Time to wait when a module is not  
> responding before      */
>            /* trying to access the module again        */
>            /* If zero, the module will not be accessed again    */
>  DWORD NotSupportedCycleTime; /* Time to wait when a module is not  
> supported before       */
>            /* trying to access the module again        */
>            /* If zero, the module will not be accessed again    */
>  WORD AssumePLCScanTime;   /* PLC Scan time to assume for timeout  
> purposes if zero,       */
>            /* default is used               */
>  BYTE Unused[228];
>  } sERMConfig;
> #define MAX_ERM_DEVICES  16
>
> typedef struct sERMDeviceInfo
>  {
>  BYTE State;
>  BYTE Supported      : 1;
>  BYTE GotAddressInfo    : 1;
>  BYTE ARPReplyPending    : 1;
>  BYTE GotBaseDef     : 1;
>  BYTE GotSupportInfo    : 1;
>  BYTE GotWatchDogSetupAck  : 1;
>  BYTE GotWatchDogSetupComplete : 1;
>  WORD TotalRetrys;
>  WORD LastError;
>  } sERMDeviceInfo;
>
> typedef struct sERMInfo
>  {
>  BYTE Version;      /* Version of sERMInfo 1 = current version    */
>  BYTE AutoDetectedInterface; /* Interface which was auto detected by  
> Hx-ERM module */
>  BYTE PLCType;      /* PLC Type that Hx-ERM module is in rack with    
> */
>  BYTE BytesInUsedByERM;   /* Number of Input bytes that Hx-ERM  
> uses     */
>            /* Currently 32 Bits (4 Bytes) of Error Info    */
>  BYTE BytesOutUsedByERM;   /* Number of Output bytes that Hx-ERM  
> uses    */
>            /* Currently 16 Bits (2 Bytes) of disable bits   */
>  sERMDeviceInfo DeviceInfo[MAX_ERM_DEVICES];
>  WORD Error;       /* Error value from ERM           */
>  WORD Status;      /* Bit per device error status        */
>  BYTE RunMode : 1;    /* 1 if in Run Mode; 0 if not         */
>  BYTE ERMState;
>  WORD MinScan;      /* Minimum scan time in ms          */
>  WORD MaxScan;      /* Miximum scan time in ms          */
>  DWORD TotalScans;     /* Total Number of scans          */
>  DWORD TotalTime;     /* Total Time for TotalScans         */
>  DWORD ReadRetrys;     /* Number of PLC Read Retrys         */
>  DWORD WriteRetrys;    /* Number of PLC Write Retrys         */
>  DWORD DeviceRetrys;    /* Number of Device Retrys          */
>  DWORD DeviceTime;     /* Total Time spent on device comm       */
>  BYTE Base;       /* Base number that Hx-ERM module is in     */
>  BYTE Slot;       /* Slot number that Hx-ERM module is in     */
>  BYTE EthernetAddress[6];  /* Ethernet address of controlling WinPLC  
> (0 for PLC) */
>  BYTE Unused[113];
>  } sERMInfo;
> typedef struct sDevCommand
>  {
>  BYTE Version;      /* Version of sDevCommand 1 = current version     
> */
>  BYTE Command;      /* Command to give to Device (see DEV_CMD_XXX  
> values) */
>  BYTE Data[254];     /* Command specific data           */
>  } sDevCommand;
> #define DEV_CMD_REINIT   1  /* Used to tell Device to do a  
> reinitialization    */
> #define DEV_CMD_RESET_STATS 2  /* Used to tell Device to clear  
> error / stat info   */
> #define DEV_CMD_RESET_ERROR 3  /* Used to clear LastError value for  
> one or more devices */
>             /*   Data[0]: bits 0-7 correspond to devies num 0-7  */
>             /*   Data[1]: bits 0-7 correspond to devies num 8-15  */
>
> /* Hx-ERM Errors.     */
> #define ERM_CONFIG_ERROR_BITS_IN_TOO_FEW     1 /* Config error: Bits  
> In configured not enough    */
> #define ERM_CONFIG_ERROR_BITS_OUT_TOO_FEW     2 /* Config error:  
> Bits Out configured not enough    */
> #define ERM_CONFIG_ERROR_BITS_IN_OVERLAPS_SYS_DATA  3 /* Configured  
> Bit Inputs overlap system input bits   */
> #define ERM_CONFIG_ERROR_BITS_OUT_OVERLAPS_SYS_DATA 4 /* Configured  
> Bit Outputs overlap system output bits  */
> #define ERM_MULTIPLE_DEVICES_WITH_SAME_NODE_NUM   5 /* More than one  
> device found with same node number  */
> #define ERM_MULTIPLE_DEVICES_WITH_SAME_IP_ADDRESS  6 /* More than  
> one device foudn with same IP address   */
> #define ERM_MODULE_NOT_RESPONDING       7 /* Device is not  
> responding to a function request   */
> #define ERM_MODULE_NOT_SUPPORTED        8 /* Device not supported;  
> may be firmware or cfg error  */
> #define ERM_MODULE_TIMEOUT          9 /* Device timed out on a  
> function request (after retrys) */
> #define ERM_MODULE_NO_GATEWAY_ADDRESS      13 /* Gateway address  
> needed, but not specified     */
> #define ERM_NO_SUBNET_MASK          14 /* Subnet mask needed, but  
> not specified      */
> #define ERM_MODULE_MISMATCHED_MODULE_IDS     15 /* Configured module  
> Id's don't match modules in device */
> #define ERM_MODULE_INCORRECT_BITS_IN      16 /* Number of bit inputs  
> specified is less than actual  */
> #define ERM_MODULE_INCORRECT_BITS_OUT      17 /* Number of bit  
> outputs specified is less than actual */
> #define ERM_MODULE_INCORRECT_WORDS_IN      18 /* Number of word  
> inputs specified is less than actual */
> #define ERM_MODULE_INCORRECT_WORDS_OUT      19 /* Number of word  
> outputs specified is less than actual */
> #define ERM_MODULE_BASE_DEF_ERROR       20 /* Invalid base def for  
> this device        */
> #define ERM_CONFIG_MISSING          21 /* Hx-ERM hasn't been  
> configured         */
> #define ERM_MODULE_BASE_DEF_BUFFER_OVERFLOW    22 /* Overflow of  
> entire BaseDefBuffer        */
> #define ERM_MODULE_BASE_DEF_OVERFLOW      23 /* Overflow of previous  
> Device BaseDef       */
> #define ERM_MODULE_WRITE_PACKET_BUFFER_OVERFLOW   24 /* Overflow of  
> entire WritePacketBuffer      */
> #define ERM_MODULE_WRITE_PACKET_OVERFLOW     25 /* Overflow of  
> previous WritePacketBuffer      */
> #define ERM_CONFIG_IO_BUFFER_OVERFLOW      26 /* Overflow of entire  
> IO buffer         */
> #define ERM_CONFIG_ERROR_WORDS_IN_TOO_FEW     27 /* Config error:  
> Words In configured not enough    */
> #define ERM_CONFIG_ERROR_WORDS_OUT_TOO_FEW    28 /* Config error:  
> Words Out configured not enough   */
> /* ERM Backplane errors */
> #define ERM_BPERROR_OBJ_NOT_FOUND           221 /* Internal  
> backplane error          */
> #define ERM_BPERROR_UNK_PLC_FAMILY       223 /* PLC Family  
> unknown            */
> #define ERM_BPERROR_INVALID_STATUS       224 /* Invalid backplane  
> status value        */
> #define ERM_BPERROR_CCM_CODEERROR       225 /* Code Error returned  
> from PLC         */
> #define ERM_BPERROR_CCM_ERROR         226 /* General Error returned  
> from PLC        */
> #define ERM_BPERROR_TIMEOUT         227 /* Timeout on PLC backplane  
> request        */
> #define ERM_BPERROR_NO_MORE_OBJECTS       228 /* Backplane queue  
> full            */
> #define ERM_BPERROR_INVALID_REQUEST       231 /* Internal request  
> error           */
> /* Serial port defines */
> #define SERIAL_1_STOP_BIT 0
> #define SERIAL_2_STOP_BITS  1
> #define SERIAL_7_DATA_BITS 0
> #define SERIAL_8_DATA_BITS 1
> #define SERIAL_NO_PARITY 0
> #define SERIAL_ODD_PARITY 2
> #define SERIAL_EVEN_PARITY 3
> #define SERIAL_SLAVE  0
> #define SERIAL_MASTER  1
> #define SERIAL_PROXY  1
> #define SERIAL_NO_RTS  0
> #define SERIAL_USE_RTS  1
>
> typedef struct
>  {
>  DWORD BaudRate;    /* Baud rate to use i.e. 9600 */
>           /* If Baud rate == 0 then serial port is disabled */
>
> #if defined (ANSI_C)
>  BYTE  ConfigData;
> #else
>  BYTE StopBits  : 1;    /* 0 == 1 Stop bit;  1 == 2 Stop bits */
>  BYTE  DataBits : 1;    /* 0 == 7 Data bits;  1 == 8 Data bits */
>  BYTE Parity  : 2;    /* 0 == 1 == None; 2 == Odd;  3 == Even */
>  BYTE Mode  : 1;    /* 0 == Slave;  1 == Master/Proxy */
>  BYTE UseRTS  : 1; /* 0 == Don't use RTS line;  1 == Use RTS line */
>  BYTE Reserved : 2;    /* Reserved locations */
> #endif
>  BYTE PreTransmitDelay; /* If UseRTS == 1 delay this many ms (times  
> 2) before starting transmit */
>  BYTE PostTransmitDelay;  /* If UseRTS == 1 delay this many ms  
> (times 2) after ending transmit */
>  BYTE  Unused;  /* Unused byte (set to zero) */
>  } SerialSetup;
> /* Flags for IPSetup */
> #define IPF_USE_BRAM_SETUP 0x00000001
> #define IPF_USE_ZERO_BCAST 0x00000002
> #define IPF_ENABLE_DHCP  0x00000004
> #define IPF_USE_DNS   0x00000008
> #define IPF_USE_WINS   0x00000010
> typedef struct
>  {
>  DWORD  Flags;    /* Flags see IPF_XXX above */
>  BYTE  Gateway[16];  /* Gateway address   */
>  BYTE  IPAddress[16];  /* IP Address     */
>  BYTE  Subnet[16];   /* Subnet address    */
>  BYTE  DNSAddr[16];  /* Primary DNS (used if IPF_USE_DNS flag is  
> set) */
>  BYTE  WINSAddr[16];  /* Primary WINS (used if IPF_USE_WINS flag is  
> set) */
>  BYTE  Unused[172];  /* Unused (clear to zero)         */
>  } IPSetup;
>
> typedef struct
>  {
>  WORD Mode;     /* Mode for ErrorLightSetup see ELS_XXXX below   */
>  WORD InitVal;    /* Initial value used for ELS_SET and ELS_CYCLE   */
>  WORD OnTime;    /* OnTime used for ELS_CYCLE         */
>  WORD OffTime;    /* OffTime used for ELS_CYCLE         */
>  WORD Num;     /* Number of times to loop for ELS_CYCLE     */
>  WORD Val1;     /* Unused value             */
>  WORD Val2;     /* Unused value             */
>  WORD Val3;     /* Unused value             */
>  } ErrorLightSetup;
>
> #define ELS_OFF  0  /* Turns the error light off         */
> #define ELS_SET  1  /* Sets the error light to the value of  
> InitVal   */
> #define ELS_CYCLE  2  /* Cycles error light.  Begins with value of  
> InitVal  */
>          /* When light is turned on, it stays on for OnTime  */
>          /* When light is turned off, it stays off for OffTime */
>          /* Cycles lights Num times          */
> typedef struct
>  {
>  BYTE MajorVersion;
>  BYTE MinorVersion;
>  WORD BuildVersion;
>  } VersionDef;
>
> typedef struct
>  {
>  BYTE SizeofVersionInfo;
>  VersionDef BootVersion;
>  VersionDef OSVersion;
>  BYTE NumOSExtensions;
>  VersionDef OSExt[10];
>  } VersionInfoDef;
>
> /* Module type defines */
> #define MT_EBC   0   /* Ethernet base controller   */
> #define MT_ECOM  1   /* Ethernet communications module */
> #define MT_WPLC  2   /* WinPLC         */
> #define MT_DRIVE  3   /* Drive card        */
> #define MT_ERMA  4   /* Ethernet remote master    */
> #define MT_CTRIO  5   /* Counter I/O card      */
> #define MT_AVG_DISP 6   /* AVG Display Adapter card   */
> #define MT_PBC   7   /* Profibus controller     */
> #define MT_PBCC  8   /* Profibus IO coprocessor    */
> #define MT_UNK   0xFF
> /* Module Family defines for MT_EBC, MT_ECOM, MT_WPLC, MT_ERMA */
> #define MF_005    0
> #define MF_205    2
> #define MF_305    3
> #define MF_405    4
> #define MF_TERM   10
> /* Module Family defines for MT_DRIVE */
> #define MF_100_SERIES 1  /* Hitachi L100 and SJ100 drives */
> #define MF_J300   2  /* Hitachi J300 drive */
> #define MF_300_SERIES 3  /* Hitachi SJ300 drive */
> #define MF_GS    4  /* GS Series drives  GS-EDRV*/
> /* Module Family defines for MT_AVG_DISP */
> #define MF_EZ_TOUCH  1  /* AVG EZ-Touch Ethernet adapter */
> typedef struct
>  {
>  BYTE PLCFamily;  /* See MF_XXX defines above */
>  BYTE Unused1;
>  BYTE ModuleType;  /* See MT_XXX defines above */
>  BYTE StatusCode;
>  BYTE EthernetAddress[6]; /* Hardware ethernet address */
>  WORD RamSize;      /* In K-Byte increments */
>  WORD FlashSize;    /* In K-Byte increments */
>  BYTE DIPSettings;   /* Settings of the 8 dip switches. */
>  BYTE MediaType;    /* 0 == 10-Base T */
>         /* 1 == 10-Base F */
>  DWORD EPFCount;    /* Early power fail count (405 EBC)*/
> #if defined (ANSI_C)
>  BYTE  Status;
> #else
>  BYTE RunRelay : 1;  /* 405 EBC Run Relay Status */
>  BYTE BattLow : 1;   /* 405 EBC Battery Low indicator */
>  BYTE UnusedBits : 6;  /* Unused status bits */
> #endif
>  WORD BattRamSize;   /* Size in K-Bytes of battery-backed ram */
>  BYTE ExtraDIPS;   /* Extra Dip switches on Terminator EBC's */
>  BYTE ModelNumber;
>  BYTE EtherSpeed;   /* 0=10MBit; 1=100MBit */
>  BYTE PLDRev[2];
>  BYTE Unused[14];
>  } DeviceDef;
> typedef struct
>  {
>  DWORD Timeout;  /* Timeout 0 == Don't use link monitor */
>  BYTE Mode;   /* Mode: */
>        /*   0 == Clear outputs */
>        /*   1 == Set outputs to given I/O data pattern */
>  BYTE Data[251]; /* Pattern:  Used with set outputs,  same format */
>        /*     as data for HEIWriteIO call. */
>  } LinkMonitor;
> typedef struct
>  {
>  BYTE Algorithm;   /* Algorithm to use for encryption */
>        /*  0 == No encryption */
>        /*  1 == Private key encryption */
>        /* */
>  BYTE Unused[3];  /* Reserved for later */
>  BYTE Key[60];  /* Encryption key (null terminated) */
>  }  Encryption;
>
> typedef struct
>  {
>  WORD Type;   /* Type of memory */
>  DWORD Size;   /* Size of memory */
>  DWORD UnitSize; /* 0 = DWORD, 1 = BYTE, 2 = WORD, 4 = DWORD */
>  DWORD Unused[3]; /* Unused */
>  } MemoryTypeDef;
>
> typedef struct
>  {
>  WORD SizeofSettings  ;    /* sizeof(HEISettings) */
>
>  /* Action items. */
>  DWORD Flags;              /* Flags used to control things. */
>              /* Bit:    Function:                    */
>              /*  0-31   Unused                    */
>
>  /* RXWX Config items. */
>  WORD RXWXACKTimeout    ;   /* Timeout for receiving ACK / NAK */
>  WORD RXWXResponseTimeout  ;   /* Timeout for receiving response. */
>  WORD RXWXMaxRetrys   ;   /* Number of times to retry a transaction.  
> */
>
>  /* RXWX Stat Items. */
>  WORD RXWXMaxACKTime   ;   /* STAT: Max number of ms we have waited  
> for an ack. */
>  WORD RXWXMaxRSPTime   ;   /* STAT: Max number of ms we have waited  
> for a response. */
>  DWORD RXWXACKRetrys   ;       /* STAT: Number of retrys for an ack.  
> */
>  DWORD RXWXRSPRetrys   ;   /* STAT: Number of retrys for a response.  
> */
>  DWORD RXWXCompleted   ;   /* STAT: Number of successfully completed  
> transactions */
>  DWORD RXWXTimeouts   ;   /* STAT: Number of timeouts on  
> transactions (after retrys) */
>  DWORD RXWXOverruns   ;   /* STAT: Number of times the PLC requested  
> a transaction while */
>              /* one was being processed. */
>  DWORD RXWXErrors    ;   /* STAT: Number of times an invalid code  
> was found or a transaction */
>              /* was NAKed. */
>
>  /* Other stuff */
>  BYTE Version;        /* Version of this structure.  Currently 0 */
>
>  /* K-Sequence Retrys */
>  WORD KSeqMaxRetrys;      /* Max number of times to retry a K- 
> Sequence request  */
>  WORD KSeqRetrys;       /* STAT: Number of K-Sequence retrys.         
> */
>  WORD KSeqTimeouts;      /* STAT: Number of K-Sequence timeouts. */
>
>  BYTE Unused[81];       /* Reserved for future use.  (Configure  
> protocol, etc. */
>  } HEISettings;
>
> typedef struct
>  {
>  BYTE RunRelayMode;  /* Relay Mode */
>          /* See Relay modes below. */
>  DWORD SerialTimeout;  /* Used for RRM_DRIVE_COMM_BAD */
>  DWORD EthernetTimeout; /* Used for RRM_DRIVE_COMM_BAD */
>  BYTE Unused[55];
>  } ModuleSetup;
>
> typedef struct
>  {
>  /*
>  ** GS Series drive setup timeouts.
>  ** In order for a value to be used, set the most significant bit.
>  */
>  WORD ReceiveCharTimeout[4];
>  WORD CommandResponseTimeout[4];
>  WORD WriteCacheClearTime;   /* 250 ms default */
>  WORD TimeoutsBeforeAutoBaud;  /*  50 ms default */
>  WORD RTSPreTransmitDelay;   /*   4 ms default */
>  WORD RTSPostTransmitDelay;   /*   4 ms default */
>  WORD AutoBaudDelay;     /*  10 ms default */
>  WORD ProcessSlaveIdle;    /*  10 ms default */
>  WORD RetryDelay;      /*  20 ms default */
>  WORD Unused[49];
>  } DriveSetup;
>
> /* Relay Modes */
> #define RRM_LINK_GOOD  0 /* Run relay on when link is good (default)  
> */
> #define RRM_LINK_NOT_GOOD 1 /* Run relay on when link is not good */
> #define RRM_POWERUP_ON  2 /* EBC turns run relay mode on on  
> powerup   */
> #define RRM_MANUAL_ON  3 /* Run relay mode is controlled by control  
> software */
> #define RRM_DRIVE_COMM_BAD 4 /* Relay on if serial or ethernet comm  
> lost (for Drive controller card) */
>
> #define ACCESS_READ  0
> #define ACCESS_WRITE 1
> typedef struct sMemRefDetail
>  {
>  BYTE Direction; /* ACCESS_READ == Read, ACCESS_WRITE == Write */
>  WORD Type;   /* Memory type */
>  DWORD Offset;  /* Memory Offset */
>  WORD NumBytes;  /* Number of bytes */
>  } MemRefDetail;
> typedef struct
>  {
>  MemRefDetail Detail;
>  BYTE *pBuffer;  /* Data buffer */
>  } MemRef;
> /* RescanFlags */
> #define RESCAN_LEAVE_IMAGE_RAM 0  /* Don't clear the image RAM */
> #define RESCAN_CLEAR_IMAGE_RAM 1  /* Clear the image RAM */
> /* Protocol Defines */
> #define HEIP_HOST     1
> #define HEIP_IPX     2
> #define HEIP_IP   3
> #define HEIP_SERIAL  4
>
> #if !defined(FIRMWARE)
> #if defined(HEIDEFS)
> typedef int  BOOL;
> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD;
> #define FALSE 0
> #define TRUE 1
> #endif /* #if defined(HEIDEFS) */
> #define HEIAPIVERSION 3
> #define HEIAPIVERSIONSTRING "3"
> #define HEIT_HOST   1
> #define HEIT_IPX   2
> #define HEIT_WINSOCK  4
> #define HEIT_OTHER_TRANSPORT 8
> #define HEIT_UNIX   16
> #define HEIT_SERIAL  32
> /* Encryption Algorithms */
> #define HEIEN_NONE   0
> #define HEIEN_A1   1
> #define PACKET_HEADER_SIZE 9
> #if defined(HEIDOS)
> #define __declspec(dllexport)
> #endif /* #if defined(HEIDOS) */
> #if defined(HEI16)
> #define __declspec(dllexport)
> #endif /* #if defined(HEI16) */
> #if defined(HEIUNIX)
> #define __declspec(dllexport)
> #endif /* #if defined(HEIT_UNIX) */
>
> /* Default values for HEIOpenDevice */
> #define DefDevTimeout 100
> #define DefDevRetrys  3
> #define DefDevUseAddressedBroadcast FALSE
>
> typedef struct
>  {
>  union
>   {
>   /* Use this for HEIP_HOST protocol addressing. */
>   struct
>    {
>    short Family;   /* AF_UNSPEC == 0 */
>    char Nodenum[6];  /* Ethernet network address */
>    unsigned short LANNum; /* Lana number */
>    } AddressHost;
>   /* Use this for HEIP_IPX protocol addressing. */
>   struct
>    {
>    short Family;   /* AF_IPX == 6 */
>    char Netnum[4];   /* Network number */
>    char Nodenum[6];  /* Ethernet network address */
>    unsigned short Socket; /* Socket number == 0x7070 */
>    } AddressIPX;
>   /* Use this for HEIP_IP protocol addressing. */
>   struct
>    {
>    short Family;   /* AF_INET == 2 */
>    unsigned short Port; /* Port number == 0x7070 */
>    union     /* Internet address */
>     {
>     struct { unsigned char b1,b2,b3,b4; } bAddr;/* Byte addressing */
>     struct { unsigned short w1,w2; } wAddr;  /* Word addressing */
>     unsigned long lAddr;      /* DWord addressing */
>     } AddressingType;
>    char  Zero[8];   /* Initialize to zeros */
>    } AddressIP;
>   /* This is the generic address buffer. */
>   BYTE Raw[20];
> #ifdef ANSI_C /*  ANSI C cannot have anonymous structures */
>   } Address;
> #else
>   };
> #endif
>  } ENetAddress;
>
> #if defined(__cplusplus)
> extern "C"
>  {
> #endif /* #if defined(__cplusplus) */
>  /* INITIALIZATION / SHUTDOWN */
>  __declspec(dllexport) int HEIOpen(WORD HEIAPIVersion);
>  __declspec(dllexport) int HEIClose();
>
>  /* Protocol Stuff */
>  typedef struct
>   {
>   WORD Transport;  /* HEIT_HOST */
>        /* HEIT_IPX */
>        /* HEIT_NETBIOS */
>        /* HEIT_WINSOCK */
>   WORD Protocol;  /* HEIP_HOST*/
>        /* HEIP_IPX */
>        /* HEIP_IP */
>        /* HEIP_NETBIOS */
>   /* Encryption stuff. */
>   Encryption Encrypt; /* Set this up before calling  
> HEIOpenTransport  */
>        /* .Algorithm == HEIEN_NONE OR HEIEN_A1 */
>        /* .Key == Encryption key */
>
>   /* DWORD NetworkAddress; */
>   ENetAddress *pSourceAddress; /* Used for multiple ethernet cards.   
> This address is the address of the card to use. */
>   /*int (*pSendPacket)(HEIDevice *pDevice, BYTE *pPacket, WORD  
> PacketSize);*/
>   /*int (*pReceivePacket)(HEIDevice *pDevice, BYTE *pResponse, int  
> *pResponseSize);*/
> #if HEIAPIVERSION==3
>   BYTE Reserved[48];  /* Reserved bytes, set to zero */
> #endif
>   } HEITransport;
>
>  __declspec(dllexport) int HEIOpenTransport(HEITransport  
> *pTransport, WORD Version,  ENetAddress *pSourceAddress);
>  /* __declspec(dllexport) int HEIOpenTransport(HEITransport  
> *pTransport, WORD Version, DWORD NetworkAddress );*/
>  /* __declspec(dllexport) int HEIOpenTransport(HEITransport  
> *pTransport, WORD Version, DWORD NetworkAddress = 0); */
>  __declspec(dllexport) int HEICloseTransport(HEITransport  
> *pTransport);
>
>
>  /* DEVICE Stuff */
>  typedef struct
>   {
>   union
>    {
>    /* Use this for HEIP_HOST protocol addressing. */
>    struct
>     {
>     short Family;   /* AF_UNSPEC == 0 */
>     char Nodenum[6];  /* Ethernet network address */
>     unsigned short LANNum; /* Lana number */
>     } AddressHost;
>    /* Use this for HEIP_IPX protocol addressing. */
>    struct
>     {
>     short Family;   /* AF_IPX == 6 */
>     char Netnum[4];   /* Network number */
>     char Nodenum[6];  /* Ethernet network address */
>     unsigned short Socket; /* Socket number == 0x7070 */
>     } AddressIPX;
>    /* Use this for HEIP_IP protocol addressing. */
>    struct
>     {
>     short Family;   /* AF_INET == 2 */
>     unsigned short Port; /* Port number == 0x7070 */
>     union     /* Internet address */
>      {
>      struct { unsigned char b1,b2,b3,b4; } bAddr;/* Byte addressing */
>      struct { unsigned short w1,w2; } wAddr;  /* Word addressing */
>      unsigned long lAddr;      /* DWord addressing */
>      } AddressingType;
>     char  Zero[8];   /* Initialize to zeros */
>     } AddressIP;
>    struct
>     {
>     BYTE CommPort;
>     BYTE ByteSize;
>     BYTE Parity;
>     BYTE StopBits;
>     DWORD Baud;
>     void *hLocal;
>     } AddressSerial;
>    /* This is the generic address buffer. */
>    BYTE Raw[20];
>    } Address;
>   WORD wParam;    /* Application can use this. */
>   DWORD dwParam;    /* Application can use this. */
>   WORD Timeout;    /* Timeout value in ms (can be changed without  
> closing the device). */
>   WORD Retrys;    /* Number of times to retry (can be changed  
> without closing the device). */
>   BYTE ENetAddress[6];  /* The ethernet address is placed here in  
> the HEIQueryDevices call. */
>   WORD RetryCount;   /* Number of retrys which have occured. */
>   WORD BadCRCCount;    /* Number of packets received with bad CRC */
>   WORD LatePacketCount;   /* Number of packets received, but after a  
> timeout */
>   BOOL ParallelPackets;  /* Setting this to TRUE (after  
> HEIOpenDevice) will enable an application */
>          /* to send multiple HEIReadIO, HEIWriteIO, HEICCMRequest  
> or  HEIKSEQRequest requests  */
>          /* (to different) modules before waiting for any  
> responses.   */
>          /* The application will then need to implement its own  
> retry / timeout mechanism  */
>          /* while waiting for the responses. */
>          /* The application uses HEIGetResponse to see if a response  
> for a module has arrived. */
>          /* NOTE: The application should not send multiple requests  
> to a single module */
>          /*       without waiting for the response in between. */
>   /* Internal - Do not touch!! */
>   BOOL UseAddressedBroadcast; /* Need to close the device and reopen  
> it to change this! */
>   BOOL UseBroadcast;
>   DWORD _dwParam;
>   WORD DataOffset;
>   HEITransport *_pTransport; /* Need to close the device and reopen  
> it to change this! */
>   int SizeOfData;
>   BYTE *pData;
>   void *pBuffer;
>   unsigned short LastAppVal;
> #if HEIAPIVERSION==3
>   BYTE UseProxy;
>   BYTE ProxyBase;
>   BYTE ProxySlot;
>   BYTE ProxyDevNum;
>   BYTE Reserved[44];  /* Reserved bytes, set to zero */
> #endif
>   } HEIDevice;
>
>  __declspec(dllexport) int HEIQueryDevices(HEITransport *pTransport,  
> HEIDevice *pDevices, WORD *pNumDevices, WORD HEIAPIVersion);
>
>  __declspec(dllexport) int HEIOpenDevice(HEITransport *pTransport,  
> HEIDevice *pDevice, WORD HEIAPIVersion, WORD Timeout, WORD Retrys,  
> BOOL UseAddressedBroadcast);
>  /* __declspec(dllexport) int HEIOpenDevice(HEITransport  
> *pTransport, HEIDevice *pDevice, WORD HEIAPIVersion, WORD  
> Timeout=DefDevTimeout, WORD Retrys=DefDevRetrys, BOOL  
> UseAddressedBroadcast=DefDevUseAddressedBroadcast); */
>  __declspec(dllexport) int HEICloseDevice(HEIDevice *pDevice);
>
>  __declspec(dllexport) int HEIQueryDeviceData(HEITransport  
> *pTransport, HEIDevice *pDevices, WORD *pNumDevices, WORD  
> HEIAPIVersion, WORD DataType, BYTE *pData, WORD SizeofData);
>
>  /* SUPPORT INFORMATION */
>  __declspec(dllexport) int HEIReadSupportInfo(HEIDevice *pDevice,  
> BYTE *pSupportInfo, WORD SizeOfSupportInfo);
>
>
>  /* VERSION INFORMATION */
>  __declspec(dllexport) int HEIReadVersionInfo(HEIDevice *pDevice,  
> BYTE *pVerInfo, WORD SizeVerInfo);
>
>
>  /* BASE DEFINITION */
>  __declspec(dllexport) int HEIReadBaseDef(HEIDevice *pDevice, BYTE  
> *pBaseDefInfo, WORD *pSizeOfBaseDefInfo);
>  __declspec(dllexport) int HEIWriteBaseDef(HEIDevice *pDevice, BYTE  
> *pInputBaseDef, WORD SizeOfInputBaseDef, BYTE *pOutputBaseDef, WORD  
> *pSizeOfOutputBaseDef);
>  __declspec(dllexport) int HEIInitBaseDef(HEIDevice *pDevice, BYTE  
> *pBaseDefInfo, WORD *pSizeOfBaseDefInfo);
>  __declspec(dllexport) int HEIRescanBase(HEIDevice *pDevice, DWORD  
> RescanFlags, BYTE *pBaseDefInfo, WORD *pSizeOfBaseDefInfo);
>
>
>  /* DEVICE DEFINITION */
>  __declspec(dllexport) int HEIReadDeviceDef(HEIDevice *pDevice, BYTE  
> *pModuleDefInfo, WORD SizeOfModuleDefInfo);
>  /* IO ACCESS */
>  __declspec(dllexport) int HEIReadIO(HEIDevice *pDevice, BYTE  
> *pData, WORD *DataSize);
>  __declspec(dllexport) int HEIWriteIO(HEIDevice *pDevice, BYTE  
> *pData, WORD SizeofData, BYTE *pReturnData, WORD *pSizeofReturnData);
>  __declspec(dllexport) int HEIWriteIONoRead(HEIDevice *pDevice, BYTE  
> *pData, WORD SizeofData);
>  __declspec(dllexport) int HEIReadIOEx(HEIDevice *apDevice[], BYTE  
> *apData[], WORD aSizeofData[], int aErrorCode[], int DeviceCount);
>  __declspec(dllexport) int HEIWriteIOEx(HEIDevice *apDevice[], BYTE  
> *apData[], WORD aSizeofData[], BYTE *apReturnData[], WORD  
> aSizeofReturnData[], int aErrorCode[], int DeviceCount);
>  /* CONFIG */
>  __declspec(dllexport) int HEIReadConfigData(HEIDevice *pDevice,  
> BYTE *pData, WORD *DataSize);
>  __declspec(dllexport) int HEIWriteConfigData(HEIDevice *pDevice,  
> BYTE *pData, WORD SizeofData, BYTE *pReturnData, WORD  
> *pSizeofReturnData);
>  // NOTE: You can also Use HEIWriteIO to write config data using  
> type DF_CONFIG
>
>  /* SETUP */
>  __declspec(dllexport) int HEIReadSetupData(HEIDevice *pDevice, WORD  
> SetupType, BYTE *pData, WORD *pSizeofData);
>  __declspec(dllexport) int HEIWriteSetupData(HEIDevice *pDevice,  
> WORD SetupType, BYTE *pData, WORD SizeofData);
>  __declspec(dllexport) int HEIDeleteSetupData(HEIDevice *pDevice,  
> WORD SetupType);
>  __declspec(dllexport) int HEIEnumSetupData(HEIDevice *pDevice, WORD  
> *pData, WORD *pSizeofDataInWords);
>  /* WATCHDOG */
>  __declspec(dllexport) int HEIPetDevice(HEIDevice *pDevice);
>  /* STATISTICS */
>  __declspec(dllexport) int HEIReadEthernetStats(HEIDevice *pDevice,  
> BYTE *pData, WORD *DataSize, BOOL Clear);
>  /* __declspec(dllexport) int HEIReadEthernetStats(HEIDevice  
> *pDevice, BYTE *pData, WORD *DataSize, BOOL Clear=FALSE); */
>  /* MODULES STATUS */
>  __declspec(dllexport) int HEIReadModuleStatus(HEIDevice *pDevice,  
> BYTE *pData, WORD *DataSize, BOOL Reset);
>  /* __declspec(dllexport) int HEIReadModuleStatus(HEIDevice  
> *pDevice, BYTE *pData, WORD *DataSize, BOOL Reset=FALSE); */
>  /* Multiple Packet Stuff. */
>  __declspec(dllexport) int HEIGetResponse(HEIDevice *pDevice, BYTE  
> *pResponse, int *pResponseSize, BOOL CheckAppVal);
>  /* __declspec(dllexport) int HEIGetResponse(HEIDevice *pDevice,  
> BYTE *pResponse, int *pResponseSize, BOOL CheckAppVal=TRUE); */
>    /* ECOM STUFF */
>  __declspec(dllexport) int HEICCMRequest(HEIDevice *pDevice, BOOL  
> bWrite, BYTE DataType, WORD Address, WORD DataLen, BYTE *pData);
>  __declspec(dllexport) int HEIKSEQRequest(HEIDevice *pDevice, WORD  
> DataLenIn, BYTE *pData, WORD *pDataLen);
>  /* SERIAL PORT STUFF */
>  __declspec(dllexport) int HEIWriteComm(HEIDevice *pDevice, WORD  
> Num2Write, BYTE *pData);
>  __declspec(dllexport) int HEIReadComm(HEIDevice *pDevice, WORD  
> *pNum2Read, BYTE *pData);
>  __declspec(dllexport) int HEIGetRXAvailable(HEIDevice *pDevice,  
> WORD *pAvailable);
>  __declspec(dllexport) int HEIFlushRXQueue(HEIDevice *pDevice);
>  __declspec(dllexport) int HEIGetTXLeft(HEIDevice *pDevice, WORD  
> *pLeft);
>  __declspec(dllexport) int HEISetupSerialPort(HEIDevice *pDevice,  
> SerialSetup *pSetup, BOOL WriteToFlash);
>  __declspec(dllexport) int HEIReadSerialPortSetup(HEIDevice  
> *pDevice, SerialSetup *pSetup);
>
>  /* SERIAL PORT STUFF (EX) */
>  __declspec(dllexport) int HEIWriteCommEx(HEIDevice *pDevice,BYTE  
> Port ,WORD Num2Write, BYTE *pData);
>  __declspec(dllexport) int HEIReadCommEx(HEIDevice *pDevice, BYTE  
> Port, WORD *pNum2Read, BYTE *pData);
>  __declspec(dllexport) int HEIGetRXAvailableEx(HEIDevice *pDevice,  
> BYTE Port, WORD *pAvailable);
>  __declspec(dllexport) int HEIFlushRXQueueEx(HEIDevice *pDevice,  
> BYTE Port);
>  __declspec(dllexport) int HEIFlushTXQueueEx(HEIDevice *pDevice,  
> BYTE Port);
>  __declspec(dllexport) int HEIGetTXLeftEx(HEIDevice *pDevice, BYTE  
> Port, WORD *pLeft);
>  __declspec(dllexport) int HEISetupSerialPortEx(HEIDevice *pDevice,  
> BYTE Port, SerialSetup *pSetup, BOOL WriteToFlash);
>  __declspec(dllexport) int HEIReadSerialPortSetupEx(HEIDevice  
> *pDevice, BYTE Port, SerialSetup *pSetup);
>  __declspec(dllexport) int HEIAccessComm(HEIDevice *pDevice, WORD  
> SendDataSize, BYTE *pSendData, WORD *pReturnDataSize, BYTE  
> *pReturnData);
>
>  /* MEMORY STUFF (see below for types) */
>  __declspec(dllexport) int HEIReadMemory(HEIDevice *pDevice, WORD  
> Type, DWORD Offset, WORD NumBytes, BYTE *pBuffer);
>  __declspec(dllexport) int HEIWriteMemory(HEIDevice *pDevice, WORD  
> Type, DWORD Offset, WORD NumBytes, BYTE *pBuffer);
>  __declspec(dllexport) int HEIENumMemory(HEIDevice *pDevice, WORD  
> *pNumWords, MemoryTypeDef *pBuffer);
>  __declspec(dllexport) int HEIAccessMemory(HEIDevice *pDevice,  
> MemRef MemRefs[], WORD NumRefs);
>
>  /* SHARED RAM STUFF (for Intelligent modules) */
>  __declspec(dllexport) int HEIReadSharedRAM(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Address, WORD Bytes2Read, BYTE *pBuffer);
>  __declspec(dllexport) int HEIWriteSharedRAM(HEIDevice *pDevice,  
> WORD Base, WORD Slot, WORD Address, WORD Bytes2Write, BYTE *pBuffer);
>
>  /* WinPLC specific functions */
> #ifndef WINPLC
>  __declspec(dllexport) int WPLCSetOSLoad(HEIDevice *pDevice, int Val);
>  __declspec(dllexport) int WPLCReboot(HEIDevice *pDevice);
>  __declspec(dllexport) int WPLCRunProgram(HEIDevice *pDevice, BYTE  
> *pProgram);
>  __declspec(dllexport) int HEIWriteERMData(HEIDevice *pDevice, WORD  
> Base, WORD Slot, BYTE DataType, BYTE *pData, WORD NumBytes, WORD  
> Offset);
>  __declspec(dllexport) int HEIReadERMData(HEIDevice *pDevice, WORD  
> Base, WORD Slot, BYTE DataType, BYTE *pData, WORD NumBytes, WORD  
> Offset);
>  __declspec(dllexport) int HEIDoERMCommand(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Command);
>  __declspec(dllexport) int HEIDoERMCommandEx(HEIDevice *pDevice,  
> WORD Base, WORD Slot, WORD Command, BYTE *pExtra, WORD ExtraLen);
>  __declspec(dllexport) int WPLCWriteERMData(HEIDevice *pDevice, WORD  
> Base, WORD Slot, BYTE DataType, BYTE *pData, WORD NumBytes, WORD  
> Offset);
>  __declspec(dllexport) int WPLCReadERMData(HEIDevice *pDevice, WORD  
> Base, WORD Slot, BYTE DataType, BYTE *pData, WORD NumBytes, WORD  
> Offset);
>  __declspec(dllexport) int WPLCDoERMCommand(HEIDevice *pDevice, WORD  
> Base, WORD Slot, WORD Command);
>  __declspec(dllexport) int WPLCDoERMCommandEx(HEIDevice *pDevice,  
> WORD Base, WORD Slot, WORD Command, BYTE *pExtra, WORD ExtraLen);
> #endif
>  /*
>  ** Query timeout function
>  */
>  /* Sets new query timeout value and returns the old query timeout  
> value */
>  __declspec(dllexport) DWORD HEISetQueryTimeout(DWORD NewTimeout);
>  /* Gets current query timeout value */
>  __declspec(dllexport) DWORD HEIGetQueryTimeout();
>  /*
>  ** Async Handler for handling extra packets.
>  */
>  __declspec(dllexport) int HEISetAsyncHandler(void (*pFun)(HEIDevice  
> *pDevice, BYTE *pResponse, int ResponseLen));
>  __declspec(dllexport) int HEIGetAsyncHandler(void (**pFun) 
> (HEIDevice *pDevice, BYTE *pResponse, int ResponseLen));
> /*
> ** EZ-Ethernet defs
> */
> typedef signed   char    SBIT8;
> #define MAX_PGM_DATA_LEN  255   // Max packet sent by AVG.
> #define MAX_ERR_MSG_SZ     40   // Forty bytes of error message space.
> #define MAC_LEN             6   // Six bytes for MAC address
> #define SPARE_BYTES         4   // Four spare bytes for future use.
> #ifndef NO_ERROR
> #define NO_ERROR     0L
> #endif
> typedef struct
> {
>     unsigned char Name[20];
>     unsigned char Node_ID[2];
>     HEIDevice    *pDevice;
> } NODELIST;
>
> /*
> ** Layout of the control buffer.
> */
> typedef struct CntlBuffer
> {
>     BYTE   TaskCode;               /*  Taskcode byte (future use)*/
>  BYTE   PanelLock;              /*  1 - Panel has lock, 0 - not  
> locked*/
>  BYTE   AdapterLock;            /*  1 - Adapter has lock, 0 - not  
> locked*/
>  BYTE   InStatus;               /*  Incoming status*/
>  BYTE   OutStatus;              /*  Outgoing status*/
>  SBIT8  Seq;                    /*  Sequence number assigned by  
> panel*/
>  BYTE   ErrorOffset;            /*  Offset into error array*/
>     BYTE   ItemCnt[2];             /*  Two bytes since read tags can  
> be > 256.*/
>  BYTE   ErrMsg[MAX_ERR_MSG_SZ]; /*  40 character string.*/
>     BYTE   EcomOffset;             /*  Used for panel to panel  
> communications.*/
>     BYTE   Mac[MAC_LEN];           /*  Stores mac address of  
> responding device.*/
>  BYTE   Spare[SPARE_BYTES];     /*  Future use*/
> } CNTL_BUF;
> /*
> ** Layout of the program shared ram frame
> */
> typedef struct PgmBuffer
> {
>     CNTL_BUF   CntlBuf;
>  BYTE       PgmData[MAX_PGM_DATA_LEN];
>
> } PGM_BUF;
>
>  /*
>  ** EZ-Ethernet functions
>  */
>  __declspec(dllexport) int HEIWriteEZethernetPgmSpace(HEIDevice  
> *pDevice, BYTE *pData, WORD SizeofData);
>  __declspec(dllexport) BOOL EZSendPacket(HEIDevice *pDevice, PGM_BUF  
> *pBuffer, BYTE *Error_message, unsigned short int Len);
>  __declspec(dllexport) NODELIST *EZGetNodeList(unsigned short int  
> *TotalEZ);
>  __declspec(dllexport) int SetCRCMode(int Mode);
>  __declspec(dllexport) int SendPacketTwoResponses(HEIDevice  
> *pDevice, BYTE *pPacket, WORD PacketSize, BYTE *pResponse, int  
> *pResponseSize,
>          BOOL WaitForResponse, BOOL ReturnWarnings, WORD  
> Bytes2Verify, BYTE *pVerifyData,
>          WORD ExtraTime, BOOL ProcessTimeout, BOOL CheckAppVal);
> #if defined(__cplusplus)
>  }
> #endif /* #if defined(__cplusplus) */
> #endif /* #if !defined(FIRMWARE) */
> /* Errors */
> #define HEIE_NULL        0 /* No Error */
> #define HEIE_FIRST_ERROR     0x8000 /* Number for First Error */
> #define HEIE_LAST_ERROR      0xFFFF /* Number for Last Error */
> #define HEIE_NOT_IMPLEMENTED    0x8000 /* Function not implemented */
> #define HEIE_VER_MISMATCH     0x8001 /* Version passed to function  
> not correct for library */
> #define HEIE_UNSUPPORTED_TRANSPORT   0x8002 /* Supplied transport  
> not supported */
> #define HEIE_INVALID_DEVICE     0x8003 /* Supplied device is not  
> valid */
> #define HEIE_BUFFER_TOO_SMALL    0x8004 /* Supplied buffer is too  
> small */
> #define HEIE_ZERO_BYTES_RECEIVED   0x8005 /* Zero bytes were  
> returned in the packet */
> #define HEIE_TIMEOUT      0x8006 /* Timeout error */
> #define HEIE_UNSUPPORTED_PROTOCOL   0x8007 /* Supplied protocol not  
> supported */
> #define HEIE_IP_ADDR_NOT_INITIALIZED  0x8008 /* The devices IP  
> address has not be set. NOTE: Need to use */
>              /* addressed broadcast to talk to the module (with IP)  
> to setup */
>              /* the IP address. */
> #define HEIE_NULL_TRANSPORT      0x8009 /* No transport specified. */
> #define HEIE_IPX_NOT_INSTALLED    0x800A /* IPX Transport not  
> installed. */
> #define HEIE_IPX_OPEN_SOCKET     0x800B /* Error opening IPX Socket.  
> */
> #define HEIE_NO_PACKET_DRIVER    0x800C /* No packet driver found. */
> #define HEIE_CRC_MISMATCH     0x800D /* CRC did not match. */
> #define HEIE_ALLOCATION_ERROR    0x800E /* Memory allocation error  
> failed. */
> #define HEIE_NO_IPX_CACHE     0x800F /* No cache has been allocated  
> for IPX */
> #define HEIE_INVALID_REQUEST    0x8010 /* Invalid request */
> #define HEIE_NO_RESPONSE     0x8011 /* No response was available./  
> requested */
> #define HEIE_INVALID_RESPONSE    0x8012 /* Invalid format response  
> was received. */
> #define HEIE_DATA_TOO_LARGE     0x8013 /* Given data is too large */
> #define HEIE_LOAD_PROC_ERROR    0x8014  /* Error loading procedures */
> #define HEIE_NOT_LOADED      0x8015 /* Attempted command before  
> successfull OpenTransport */
> #define HEIE_ALIGNMENT_ERROR    0x8016 /* Data not aligned on proper  
> boundary */
> #define HEIE_FILE_NOT_OPEN     0x8017    /* File not open */
> #define HEIE_LOAD_ERROR      0x8100 /* Mask for WinSock load Error  
> see below (from HEIOpenTransport) */
> #define HEIE_LAST_LOAD_ERROR    0x811F /* Last in the range of  
> WinSock load Errors */
> #define HEIE_IO_ERROR      0x9000 /* Mask for IO Error condition  
> (from HEIReadModuleStatus, HEIReadIO, or HEIWriteIO) */
> #define HEIE_IO_WARNING      0xA000 /* Mask for IO Warning condition  
> (from HEIReadModuleStatus, HEIReadIO, or HEIWriteIO) */
> #define HEIE_IO_INFO       0xC000 /* Mask for IO Info condition  
> (from HEIReadModuleStatus, HEIReadIO, or HEIWriteIO) */
> #define HEIE_ICMP_PKT_FOUND    65
> #define HEIE_ARP_PKT_FOUND       66
> #define HEIE_TYPE_NOT_HANDLED      67
> #define HEIE_LINK_SENSE_TRIGGERED  68
> #define HEIE_UNK_IP_PACKET     100
> #define HEIE_UNK_ETHERTYPE     101
> #define HEIE_UNK_PACKET_TYPE     102
> #define HEIE_UNK_802X_PACKET_TYPE  103
> #define HEIE_UNK_LLC_TYPE     104
> #define HEIE_CRC_DOES_NOT_MATCH   105
> #define HEIE_CRC_NO_DATA     106
> #define HEIE_ENET_ADDR_REPROGRAMMED  107
> #define HEIE_NULL_DATA_POINTER   108
> #define HEIE_SIZE_ERROR      109
> #define HEIE_NOT_FOUND      110
> #define HEIE_INVALID_TYPE     111
> #define HEIE_RAM_ALREADY_LOCKED   112
> #define HEIE_INVALID_REQUEST_INT   113
> #define HEIE_TIMEOUT_ERROR     114
> #define HEIE_FLASH_PROGRAM_ERROR   115
> #define HEIE_INVALID_OS      116
> #define HEIE_INVALID_LOCATION    117
> #define HEIE_INVALID_SLOT_NUMBER   118
> #define HEIE_INVALID_DATA     119
> #define HEIE_MODULE_BUSY     120
> #define HEIE_CHANNEL_FAILURE    121
> #define HEIE_UNUSED_CHANNELS_EXIST  122
> #define HEIE_INVALID_UDP_PORT    123
> #define HEIE_SHUTDOWN_OS     124
> #define HEIE_NOT_MY_IP_ADDRESS   125
> #define HEIE_PROTECTION_ERROR    126
> #define HEIE_UNK_TYPE_ERROR    127
> #define HEIE_BACKPLANE_INIT_ERROR  128
> #define HEIE_UNK_RESPONSE     129
> #define HEIE_UNK_RXWX_FORMAT    130
> #define HEIE_UNK_ACK       131
> #define HEIE_UNK_NAK       132
> #define HEIE_RANGE_ERROR     133
> #define HEIE_LENGTH_WARNING    134
> #define HEIE_INVALID_BASE_NUMBER   135
> #define HEIE_INVALID_MODULE_TYPE   136
> #define HEIE_INVALID_OFFSET    137
> #define HEIE_INVALID_BOOT_VER_FOR_OS 138
> #define HEIE_BROKEN_TRANSMITTER   139
> #define HEIE_INVALID_ADDRESS    140
> #define HEIE_TIMING       141
> #define HEIE_CHANNEL_FAILURE_MULTI  142
> #define HEIE_SERIAL_SETUP_ERROR   143
> #define HEIE_NOT_INITIALIZED    144
> #define HEIE_INVALID_MODE     145
> #define HEIE_COMM_FAILURE     146
> #define HEIE_OPERATION_ABORTED   147
> #define HEIE_INVALID_RX_CHAR    148
> #define HEIE_REQUEST_NAKED     149
> #define HEIE_INVALID_OPERATION   150
> #define HEIE_VAL_ALREADY_USED    151
> /* define HEIE_MODULE_ERROR     152 */
> #define HEIE_MODULE_NOT_RESPONDING  153
> #define HEIE_BASE_CHANGED     154 /* I/O Base has changed */
> #define HEIE_MODULE_FAILURE    155
> #define HEIE_PARITY_ERROR     156
> #define HEIE_FRAMING_ERROR     157
> #define HEIE_OVER_RUN_ERROR    158
> #define HEIE_BUFFER_OVERFLOW    159
> #define HEIE_ABORT       160
> #define HEIE_BUSY        161
> #define HEIE_DRIVE_TRIP      162  /* Drive has tripped */
> #define HEIE_COMMAND_PENDING    163
>
> #define HEIE_CHANNELS_UNUSED_0   200
> #define HEIE_CHANNELS_UNUSED_1   201
> #define HEIE_CHANNELS_UNUSED_2   202
> #define HEIE_CHANNELS_UNUSED_3   203
> #define HEIE_CHANNELS_UNUSED_4   204
> #define HEIE_CHANNELS_UNUSED_5   205
> #define HEIE_CHANNELS_UNUSED_6   206
> #define HEIE_CHANNELS_UNUSED_7   207
> #define HEIE_CHANNELS_UNUSED_8   208
> #define HEIE_CHANNELS_UNUSED_9   209
> #define HEIE_CHANNELS_UNUSED_10   210
> #define HEIE_CHANNELS_UNUSED_11   211
> #define HEIE_CHANNELS_UNUSED_12   212
> #define HEIE_CHANNELS_UNUSED_13   213
> #define HEIE_CHANNELS_UNUSED_14   214
> #define HEIE_CHANNELS_UNUSED_15   215
> #define HEIE_CHANNELS_UNUSED_16   216
>
> /*  Winsock Load Errors
> If OpenTransport for WinSock fails, it will return one of the  
> following errors:
> 0x8014 Error getting addresses from WinSock.DLL
> 0x8100 System was out of memory, executable file was corrupt, or  
> relocations were invalid.
> 0x8101 Unused
> 0x8102 File was not found.
> 0x8103 Path was not found.
> 0x8104 Unused
> 0x8105 Attempt was made to dynamically link to a task, or there was  
> a sharing or network-protection error.
> 0x8106 Library required separate data segments for each task.
> 0x8107  Unused
> 0x8108 There was insufficient memory to start the application.
> 0x8109  Unused
> 0x810A Windows version was incorrect.
> 0x810B Executable file was invalid. Either it was not a Windows  
> application or there was an error in the .EXE image.
> 0x810C Application was designed for a different operating system.
> 0x810D Application was designed for MS-DOS 4.0.
> 0x810E Type of executable file was unknown.
> 0x810F Attempt was made to load a real-mode application (developed  
> for an earlier version of Windows).
> 0x8110 Attempt was made to load a second instance of an executable  
> file containing multiple data segments that were not marked read-only.
> 0x8111 Unused
> 0x8112 Unused
> 0x8113 Attempt was made to load a compressed executable file. The  
> file must be decompressed before it can be loaded.
> 0x8114 Dynamic-link library (DLL) file was invalid. One of the DLLs  
> required to run this application was corrupt.
> 0x8115 Application requires Microsoft Windows 32-bit extensions.
> 0x8116-0x811F Unused
> */
>
> /* Warnings */
> #define HEIW_FIRST_WARNING     0x2000 /* Number for First Error */
> #define HEIW_LAST_WARNING     0x2FFF /* Number for Last Error */
> #define HEIW_RETRY       0x2000 /* One or more retrys have occurred.  
> */
>
> /* These are masks for values returned from HEIReadIO and/or  
> HEIWriteIO and indicate that some  */
> /* error/warning/info condition exists for some module in the base  
> (it could be an I/O  */
> /* module or it could be the ethernet module.  The function  
> HEIReadModuleStatus can then be used  */
> /* to retrieve the actual conditions.  Note that more than one of  
> the conditions can exist at any time. */
> #define MASK_DEVICE_ERROR   0x1000
> #define MASK_DEVICE_WARNING    0x2000
> #define MASK_DEVICE_INFO       0x4000
>
> /* Data Types */
> #define DT_IP_ADDRESS    0x0010 /* 4 Byte IP address */
> #define DT_NODE_NUMBER    0x0020 /* 4 Byte Node Number */
> #define DT_SUBNET_MASK    0x0030 /* 4 Byte Subnet Mask */
> #define DT_GATEWAY_ADDRESS   0x0040 /* 4 Byte Gateway Address */
> #define DT_ERASE_COUNT    0x0050   /* 4 Byte used internally */
> #define DT_SERIAL_SETUP    0x0011 /* 8 Byte Serial Setup (see  
> SerialSetup)*/
> #define DT_SET_PARM     0x8011 /* 8 Byte Parm Setup (see PARM_XXXX  
> defines) */
> #define DT_SETUP_ERROR_LIGHT  0x8012 /* 16 Byte Error Light Setup  
> (see ErrorLightSetup) */
> #define DT_STARTUP_SETTINGS  0x0013 /* 32 Byte Startup settings data  
> (see StartupSettings above) */
> #define DT_TIME_OF_DAY    0x8013 /* SYSTEMTIME structure */
> #define DT_TYPE_STRING    0x0033 /* 32 Byte ASCII String for netedit  
> type identification */
> #define DT_ENCRYPT_KEY_FLASH  0x0014 /* 64 Byte key data from FALSH  
> See Encryption structure */
> #define DT_ENCRYPT_KEY_RAM   0x8014 /* 64 Byte key data from RAM -  
> This is the working copy! */
>               /* See Encryption structure */
> #define DT_MODULE_SETUP    0x0024 /* 64 Byte data from FLASH. See  
> ModuleSetup structure */
> #define DT_RXWX_SETTINGS   0x0015 /* 128 Bytes settings see  
> HEISettings */
> #define DT_SETTINGS     0x0015 /* 128 Bytes settings see HEISettings  
> */
> #define DT_DRIVE_SETUP    0x0025 /* 128 Byte DriveSetup structure */
> #define DT_NODE_NAME     0x0016 /* 256 Byte Node Name */
> #define DT_DESCRIPTION    0x0026 /* 256 Byte Node Description */
> #define DT_LINK_MONITOR    0x8006 /* 256 Byte Link monitor setup  
> (Ram Based) */
>               /* See LinkMonitor structure below */
> #define DT_IP_SETUP     0x0036 /* 256 Byte IP Setup structure (see  
> IPSetup) */
> #define DT_WPLC_SYS_INFO   0x0046 /* 256 Byte WinPLC system info  
> (see WPLCSystemInformation) */
> #define DT_ERM_CONFIG    0x0056 /* 256 Byte ERM Config info (see  
> sERMConfig) */
> #define DT_ERM_INFO     0x8016 /* 256 Byte ERM Info (see sERMInfo) */
> #define DT_DEV_COMMAND    0x8026 /* 32 Byte ERM Command (see  
> sDevCommand) */
> #define DT_BASE_DEF     0x0017 /* 512 Byte Base Def (405  
> HEIWriteBaseDef) */
> #define DT_RXWX_NODE_ADDR_1  0x0027 /* 512 Byte node address data  
> for addr 00-31 */
> #define DT_RXWX_NODE_ADDR_2  0x0037 /* 512 Byte node address data  
> for addr 32-63 */
> #define DT_RXWX_NODE_ADDR_3  0x0047 /* 512 Byte node address data  
> for addr 64-95 */
> #define DT_R_W_IO_DEF    0x0057 /* 512 Byte read/write IO def (for  
> Drive card) (base 0) (see MemoryItemBase) */
> #define DT_ERM_DEV_00_03   0x0067 /* 512 Byte ERM device data  
> (Devices numbers 00 - 03) (See sERMDevice) */
> #define DT_ERM_DEV_04_07   0x0077 /* 512 Byte ERM device data  
> (Devices numbers 04 - 07) (See sERMDevice) */
> #define DT_ERM_DEV_08_11   0x0087 /* 512 Byte ERM device data  
> (Devices numbers 08 - 11) (See sERMDevice) */
> #define DT_ERM_DEV_12_15   0x0097 /* 512 Byte ERM device data  
> (Devices numbers 12 - 15) (See sERMDevice) */
> #define DT_RESET      0x8010 /* 4 Byte (32-Bit) reset flag.   
> (RESET_XXX values below) */
> #define DT_BOOT_OS     0x0023 /* 32 Byte OS Boot data */
> #define DT_MODULE_INIT_BASE  0x8057 /* 512 Byte Module  
> Initialization data: (from I/O Base) */
>
> /* Common functions. */
> #define FUN_POLLING      0x00  /* Polling one module */
> #define FUN_READ_VER_INFO   0x01  /* Read Version Info from module */
> #define FUN_READ_SUPPORT_INFO  0x02  /* Read Support Info from  
> module */
>            /* 0x03 UNUSED                         */
> #define FUN_READ_DEVICE_INFO  0x04  /* Read Device Info from module */
> #define FUN_POLLING_ALL    0x05  /* Polling all bases on the network  
> (returns ethernet address) */
>            /* Used as a broadcast function to locate devices on the  
> network. */
> #define FUN_WRITE_IO    0x06  /* Write IO data to the base */
> #define FUN_READ_IO     0x07  /* Read IO data from Base */
> #define FUN_READ_BASE_DEF   0x08  /* Read Base Definition */
> #define FUN_QUERY_SETUP_DATA  0x09 /* Query the network for a  
> particular type of data with a particular value */
> #define FUN_ENUM_SETUP_DATA   0x0A /* Enumerate the types of data  
> stored in a module */
> #define FUN_READ_SETUP_DATA   0x0B /* Read a particular type of data  
> from a module */
> #define FUN_WRITE_SETUP_DATA  0x0C /* Write a particular type of  
> data to a module */
> #define FUN_DELETE_SETUP_DATA  0x0D /* Delete a particular type of  
> data from a module */
> #define FUN_READ_ETHERNET_STATS  0x0E /* Read ethernet statistics  
> from the module. */
> #define FUN_WRITE_BASE_DEF   0x0F /* Write Base Definition (305/405  
> EBC) */
>            /* 0x10 UNUSED                         */
>            /* 0x11 UNUSED                         */
>            /* 0x12 UNUSED                         */
>            /* 0x13 UNUSED                         */
> #define FUN_PET_LINK    0x14  /* Used to keep the link sense timer  
> from firing in the absense of ReadIO or WriteIO messages */
> #define FUN_ADDRESSED_BROADCAST  0x15 /* Used to broadcast to a  
> particular ethernet address. Used to setup IP address in a new  
> module. */
> #define FUN_DATA_BROADCAST   0x16 /* Used to broadcast to a  
> particular data type. */
> #define FUN_READ_MODULE_STATUS  0x17 /* Read the status bytes from  
> each of the slots of the module. */
> #define FUN_INIT_BASE_DEF   0x18 /* Initialize the base def by re- 
> reading from the backplane */
> #define FUN_CCM_REQUEST    0x19 /* Perform a CCM Request with an  
> ECom Module */
> #define FUN_KSEQ_REQUEST   0x1A /* Perform a K-Seq Request with an  
> ECom Module */
> #define FUN_BACKPLANE_REQUEST  0x1B /* Perform a backplane request  
> on an ECom Module */
> #define FUN_EXTEND_RESPONSE   0x1C  /* Extends the response packet. */
> #define FUN_ACK      0x20 /* Acknowledge */
> #define FUN_NAK      0x21 /* Not acknowledge */
> #define FUN_RESPONSE    0x22 /* Response */
> #define FUN_SERIAL_PORT    0x23 /* Execute serial port function (see  
> below) */
> #define FUN_WRITE_MEMORY   0x24 /* Write a particular memory type */
> #define FUN_READ_MEMORY    0x25 /* Read a particular memory type */
> #define FUN_ENUM_MEMORY    0x26 /* Get list of all memory types */
> #define FUN_ACCESS_MEMORY   0x27 /* Access (Read/Write) multiple  
> memory types */
> #define FUN_READ_SHARED_RAM   0x28 /* Read shared ram */
> #define FUN_WRITE_SHARED_RAM  0x29 /* Write shared ram */
> #define FUN_WRITE_IO_NO_READ  0x30 /* Write IO without returned read  
> */
> #define FUN_COMM_RESPONSE   0x31 /* Response to PLC generated COMM  
> request */
> #define FUN_COMM_REQ_ACK   0x32 /* Function from PLC generated COMM  
> request */
> #define FUN_COMM_NO_REQ_ACK  0x33 /* Function from PLC generated  
> COMM request */
> #define FUN_RUN_PROGRAM    0x34 /* Function to execute a program */
> #define FUN_REMOTE_API    0x35 /* Function to execute a function on  
> remote device */
> #define FUN_NOTIFY     0x36 /* Indicates a notification */
> #define FUN_COMPLETION    0x37 /* Indicates completion of some  
> activity */
> #define FUN_PROXY      0x38 /* Indicates a proxy function request */
> #define FUN_QUERY_RESPONSE   0x55 /* This is a response to a query  
> function */
> #define FUN_USER_CONFIG_PANEL    0x60    /* User specific data for  
> AVG Panel */
> #define FUN_WRITE_CONFIG_DATA  0x61  /* Write Config data to the  
> base */
> #define FUN_READ_CONFIG_DATA  0x62  /* Read Config data from Base */
> #define FUN_UNSUPPORTED    0x99 /* This function will never be  
> supported by any device (internal use only) */
> #define FUN_SET_OS_LOAD    0xF9 /* Set Load OS Parm. */
> #define FUN_REBOOT     0xFA /* Reboot OS   */
>
> /* Serial port functions */
> #define SPF_WRITE_COMM    0x01  /* Writes one or more characters to  
> the serial port */
> #define SPF_READ_COMM    0x02  /* Reads zero or more characters from  
> the serial port */
> #define SPF_RX_AVAILABLE   0x03  /* Returns number of characters  
> available in the input queue */
> #define SPF_RX_FLUSH     0x04  /* Flushs the serial port input queue  
> */
> #define SPF_SETUP      0x05  /* Setup serial port (see SerialSetup  
> above) */
> #define SPF_TX_LEFT     0x06  /* Returns number of characters left  
> in the output queue */
> #define SPF_READ_SETUP    0x07  /* Read Setup serial port (see  
> SerialSetup above) */
> #define SPF_ACCESS_COMM    0x08  /* Used to read / write multiple  
> ports */
> #define SPF_TX_FLUSH     0x09  /* Flushs the serial port output  
> queue */
> /* Serial port commands for HEIAccessComm */
> #define SPC_WRITE_PORT    0x01
> #define SPC_READ_PORT    0x02
> #define SPC_RX_FLUSH     0x04
> #define SPC_TX_FLUSH     0x09
> #define SPC_ERROR      0x80
> #define SPC_READ_RESPONSE   0x82
> #define SPC_DONE      0xFF
> /* Reset values */
> #define RESET_DRIVE_RELAY   0x01 /* Reset relay on ethernet drive  
> card */
> /* Parm values */
> #define PARM_RETURN_SYS_ERRORS 0x01
>
> /*
>  Memory Types.
>  Description of memory types.
>  A memory type is a 16 bit value that is divided up as follows:
>    FEDCBA9876543210
>    PKAAFFFFTTTTUNNN
>    ||| |   |   ||
>    ||| |   |   ||-- Number: Index number from 0 to 7
>    ||| |   |   |
>    ||| |   |   |-- Undefined (set to zero)
>    ||| |   |
>    ||| |   |-- Type: 0000 = General Purpose
>    ||| |             0001 = Program
>    ||| |             0010 = System
>    ||| |             0011 = Timer
>    ||| |             0100 = Counter
>    ||| |             0101 = Setup
>    ||| |             0110 = Input
>    ||| |             0111 = Output
>    ||| |             1000 = Undefined
>    ||| |             1001 = Undefined
>    ||| |             1010 = Undefined
>    ||| |             1011 = Undefined
>    ||| |             1100 = Undefined
>    ||| |             1101 = Undefined
>    ||| |             1110 = Undefined
>    ||| |             1111 = Undefined
>    ||| |
>    ||| |-- Format: 0000 = Bit
>    |||             0001 = Byte
>    |||             0010 = Word
>    |||             0011 = DWord
>    |||             0100 = Float
>    |||             0101 = Undefined
>    |||             0110 = Undefined
>    |||             0111 = Undefined
>    |||             1000 = Undefined
>    |||             1001 = Undefined
>    |||             1010 = Undefined
>    |||             1011 = Undefined
>    |||             1100 = Undefined
>    |||             1101 = Undefined
>    |||             1110 = Undefined
>    |||             1111 = Undefined
>    |||
>    |||-- Access:  00 = Read / write
>    ||             01 = Read Only
>    ||             10 = Write Only
>    ||             11 = Undefined
>    ||
>    ||-- Kind of memory: 0 = Ram;  1 = Flash
>    |
>    |-- Protection:  1 = Protected;  0 = Not Protected
>
>
>   Example:
>    V-Memory in Koyo boxes (205/405) is General Purpose, WORD format,  
> Read / Write, RAM.
>    this would make the type be: 0000 0010 0000 0000 = 0200h = 512
>
>    CR Memory in Koyo boxes is General Purpose, Bit format, Read /  
> Write, RAM,
>    this would make the type be: 0000 0000 0000 0000 = 0000h = 0
>
>    Scratch Pad Memory in Koyo boxes is System, Byte Format, Read /  
> Write, RAM.
>    this would make the type be: 0000 0001 0010 0000 = 0120h = 288
>
>    SP's in Koyo boxes is System, Bit Format, Read Only, RAM
>    this would make the type be: 0001 0000 0010 0000 = 1020h = 4128
> */
> #define MT_KOYO_V  0x0200  /* V-Memory */
> #define MT_KOYO_C  0x0000  /* C-Memory */
> #define MT_KOYO_Z  0x0120  /* Scratch Pad Memory */
> #define MT_KOYO_SP 0x1020  /* SP-Memory */
> #define MT_DRIVE_FIRST 0x300  /* First memory type for Hitachi  
> Drives */
> #define MT_HITACHI_D 0x300   /* Hitachi Drive Memory: Monitoring  
> functions */
> #define MT_HITACHI_F 0x301   /* Hitachi Drive Memory: Basic Profile  
> functions */
> #define MT_HITACHI_A 0x302   /* Hitachi Drive Memory: Standard  
> functions */
> #define MT_HITACHI_B 0x303   /* Hitachi Drive Memory: Fine tuning  
> functions */
> #define MT_HITACHI_C 0x304   /* Hitachi Drive Memory: Intelligent  
> terminal functions */
> #define MT_HITACHI_H 0x305   /* Hitachi Drive Memory: Sensorless  
> vector functions */
> #define MT_HITACHI_O 0x306   /* Hitachi Drive Memory: Other  
> functions */
> #define MT_HITACHI_OP 0x307  /* Hitachi Drive Memory: Option Board */
> #define MT_HITACHI_R 0x308   /* Hitachi Drive Memory: Reference  
> codes */
> /* The following offsets can only be used with HEIReadMemory (not  
> HEIAccessMemory) */
> #define MT_INFO_OFFSET   0x100  /* Add MT_INFO_OFFSET to above  
> MT_HITACHI_? types to get MemoryTypeInfo for the given ID */
> #define MT_VALID_IDS_OFFSET 0x200  /* Add MT_VALID_IDS_OFFSET to  
> above MT_HITACHI_? types to get the valid Ids for the given memory  
> type */
> #define MT_MEMORY_TYPE_STRING 0x300  /* Add MT_MEMORY_TYPE_STRING to  
> above MT_HITACHI_? types to get the string name for the memory type  
> (use 128 byte length) */
> #define MT_DRIVE_STRING   0x400  /* Add MT_DRIVE_STRING to any of  
> the MT_HITACHI_? types to get the string name for the current drive  
> (use 32 byte length) */
> #define MT_VERSION_STRING  0x500  /* Add MT_DRIVE_STRING to any of  
> the MT_HITACHI_? types to get the version string current drive (use  
> 32 byte length) */
> typedef struct
>  {
>  DWORD MinVal;   /* Minimum value for this type */
>  DWORD MaxVal;   /* Maximum value for this type */
>  BYTE Magnitude;  /* Magnitude of type.  See MAG_XXXX values */
>  BYTE RunModeEdit; /* If TRUE, this field can be edited in run mode */
>  BYTE ReadOnly;  /* If TRUE, this field is read-only */
>  BYTE FieldType;  /* Type of memory.  see FIELD_XXXX values */
>  BYTE NumBits;   /* If FieldType == FIELD_BIT, this tells the number  
> of bits */
>  BYTE StartBit;  /* If FieldType == FIELD_BIT, this tells the  
> starting bit number */
>  BYTE  Size;    /* Internal size in bytes */
>  WORD  Addr;    /* Internal address */
>  BYTE Unused[13];  /* Unused */
>  WORD NameLength;  /* Length of pName (including null terminator) */
>  char Name[224];  /* Name string for the given memory type */
>  } MemoryTypeInfo;
>
> typedef struct
>  {
>  WORD Type;
>  WORD Id;
>  } MemoryItem;
> typedef struct
>  {
>  MemoryItem Items[16];
>  } MemoryItemSlot;
> typedef struct
>  {
>  MemoryItemSlot Slot[8];
>  } MemoryItemBase;
> #define FIELD_NORMAL  0
> #define FIELD_CODE  1
> #define FIELD_BIT   2
> #define MAG_00001   0
> #define MAG_00010   1
> #define MAG_00100   2
> #define MAG_01000   3
>
> /* Hitachi Drive type defines */
> #define L100 1
> #define SJ100 2
> #define J300 3
> #define SJ300 4
> /* GS Drive type defines */
> #define GS1  1
> #define GS2  2
> #define GS3  3
> #define GS4  4
> /* Defines for Data formats */
> #define DF_BIT_IN   0x03
> #define DF_BIT_OUT  0x04
> #define DF_BYTE_IN  0x10
> #define DF_BYTE_OUT  0x11
> #define DF_WORD_IN  0x05
> #define DF_WORD_OUT  0x06
> #define DF_DWORD_IN  0x08
> #define DF_DWORD_OUT  0x09
> #define DF_DOUBLE_IN  0x12
> #define DF_DOUBLE_OUT 0x13
> #define DF_FLOAT_IN  0x14
> #define DF_FLOAT_OUT  0x15
> #define DF_CONFIG   0x16
>
> /* Data type defines for HX-ERM */
> #define DATA_SIZE_INFO  0  /* Used to read the size info for     */
> #define DATA_INPUT   1  /* Used to read/write all input data    */
> #define DATA_OUTPUT   2  /* Used to read/write all output data    */
> #define DATA_DESCRIPTION 3  /* Used to read description/layout of I/ 
> O data */
> #define DATA_COMMAND   4  /* Used to read/write to command buffer   */
> #define DATA_ERMINFO   5  /* Used to read sERMInfo structure     */
> /* Commands for the HX-ERM module */
> #define COMMAND_PROCESS_IO      1
> #define COMMAND_ABORT       2
> #define COMMAND_PROCESS_COMMAND_BUFFER  3
>
> /* Restore structure alignment boundary */
> #pragma pack()
>
> #endif /* #if !defined(__HEI_H) */
>
>
> #include "defs.h"
> #include <memory.h>
> #include <malloc.h>
> #include "hei.h"
> #define TimeDiff(StartTime, EndTime)  (((DWORD)EndTime >  
> (DWORD)StartTime) ? ((DWORD)EndTime - (DWORD)StartTime) :  
> ((DWORD)EndTime + ((DWORD)ULONG_MAX - (DWORD)StartTime) + 1))
> DWORD HEIIGetCounter();
> int GetResponseEx(HEIDevice *apDevice[], BYTE *apData[], WORD  
> aSizeofData[], int aErrorCode[], int DeviceCount)
>  {
>  int Done = TRUE;
>  int idx = 0;
>  for(idx = 0; idx < DeviceCount; idx++)
>   {
>   /* Handle NULL device */
>   if(!apDevice[idx])
>    continue;
>   if(aErrorCode[idx] == HEIE_NO_RESPONSE)
>    {
>    BYTE Buff[500];
>    int BuffLen = sizeof(Buff);
>    aErrorCode[idx] = HEIGetResponse(apDevice[idx], Buff, &BuffLen,  
> TRUE);
>    /* If no response, continue */
>    if(aErrorCode[idx] == HEIE_NO_RESPONSE)
>     {
>     Done = FALSE;
>     continue;
>     }
>    /* Check for error and not warning. */
>    if(aErrorCode[idx] && !(aErrorCode[idx] & HEIW_FIRST_WARNING))
>     {
>     /* Set data size to 0 */
>     aSizeofData[idx] = 0;
>     }
>    else
>     {
>     if(BuffLen)
>      {
>      short int *pInt = (short int *)&Buff[PACKET_HEADER_SIZE];
>      BuffLen -= PACKET_HEADER_SIZE;
>      BuffLen -= 2;
>      if((WORD)BuffLen > aSizeofData[idx])
>       {
>       BuffLen = aSizeofData[idx];
>       aErrorCode[idx] = HEIE_BUFFER_TOO_SMALL;
>       }
>      if(*pInt)
>       aErrorCode[idx] = (*pInt) | 0x8000;
>      memcpy(apData[idx], Buff+PACKET_HEADER_SIZE+2, BuffLen);
>      aSizeofData[idx] = BuffLen;
>      }
>     else
>      {
>      /* Set data size to 0 */
>      aSizeofData[idx] = 0;
>      aErrorCode[idx] = HEIE_ZERO_BYTES_RECEIVED;
>      }
>     }
>    }
>   }
>  return Done;
>  }
> DWORD StartHEIReadIO(HEIDevice *pDevice, BYTE *pData, WORD  
> *pSizeofData, int *pErrorCode)
>  {
>  DWORD StartTime = 0;
>  BOOL OldPP = FALSE;
>  /* Force parallel packet mode */
>  OldPP = pDevice->ParallelPackets;
>  pDevice->ParallelPackets = TRUE;
>  /* Init error code */
>  *pErrorCode = HEIE_NO_RESPONSE;
>  /* Log the time */
>  StartTime = HEIIGetCounter();
>  /* Send request */
>  HEIReadIO(pDevice, pData, pSizeofData);
>  /* Restore parallel packet mode */
>  pDevice->ParallelPackets = OldPP;
>  return StartTime;
>  }
> __declspec(dllexport) int HEIReadIOEx
>  (
>  HEIDevice *apDevice[],
>  BYTE *apData[],
>  WORD aSizeofData[],
>  int aErrorCode[],
>  int DeviceCount
>  )
>  {
>  int idx = 0;
>  BOOL Done = FALSE;
>  DWORD *pStartTime = (DWORD *)calloc(sizeof(DWORD), DeviceCount);
>  int MaxStarted = 0;
>  int StartAt = 0;
>  /* Reset retry count */
>  for(idx = 0; idx < DeviceCount; idx++)
>   if(apDevice[idx])
>    apDevice[idx]->SizeOfData = 0;
>  while(!Done)
>   {
>   /* Start a request */
>   for(idx = StartAt; idx < DeviceCount; idx++)
>    {
>    /* Handle NULL device */
>    if(!apDevice[idx])
>     {
>     StartAt = idx + 1;
>     if(idx+1 > MaxStarted)
>      MaxStarted = idx + 1;
>     }
>    /* If request not started, start it */
>    else if(!pStartTime[idx])
>     {
>     pStartTime[idx] = StartHEIReadIO(apDevice[idx], apData[idx],  
> &aSizeofData[idx], &aErrorCode[idx]);
>     StartAt = idx + 1;
>     if(idx+1 > MaxStarted)
>      MaxStarted = idx + 1;
>     break;
>     }
>    }
>   /* Test for completion of requests */
>   GetResponseEx(apDevice, apData, aSizeofData, aErrorCode,  
> MaxStarted);
>   /* When all have been started, we're done until proven otherwise */
>   Done = MaxStarted == DeviceCount;
>
>   /* Test for timeout of requests */
>   for(idx = 0; idx < MaxStarted; idx++)
>    {
>    /* Handle NULL device */
>    if(!apDevice[idx])
>     continue;
>    /* If request started, test timeout */
>    if(aErrorCode[idx] == HEIE_NO_RESPONSE && pStartTime[idx])
>     {
>     /* Check timeout for device */
>     if(TimeDiff(pStartTime[idx], HEIIGetCounter()) >= apDevice[idx]- 
> >Timeout)
>      {
>      /* Timed out, check retries */
>      if(apDevice[idx]->SizeOfData < apDevice[idx]->Retrys)
>       {
>       apDevice[idx]->SizeOfData++;
>       apDevice[idx]->RetryCount++;
>       /* Reset */
>       pStartTime[idx] = 0;
>       aErrorCode[idx] == HEIE_NO_RESPONSE;
>       if(idx < StartAt)
>        StartAt = idx;
>
>       /* Not done */
>       Done = FALSE;
>       }
>      /* No more retries */
>      else
>       {
>       /* Set error code */
>       aErrorCode[idx] = HEIE_TIMEOUT;
>
>       /* This device is done */
>       }
>      }
>     /* Started but not timed out */
>     else
>      /* Not done */
>      Done = FALSE;
>     }
>    /* If not started... */
>    else if(!pStartTime[idx])
>     {
>     /* Can't be done */
>     Done = FALSE;
>     }
>    }
>   }
>  free(pStartTime);
>  return 0;
>  }
> DWORD StartHEIWriteIO(HEIDevice *pDevice, BYTE *pData, WORD  
> SizeofData, BYTE *pReturnData, WORD *pSizeofReturnData, int  
> *pErrorCode)
>  {
>  DWORD StartTime = 0;
>  BOOL OldPP = FALSE;
>  /* Force parallel packet mode */
>  OldPP = pDevice->ParallelPackets;
>  pDevice->ParallelPackets = TRUE;
>  /* Init error code */
>  *pErrorCode = HEIE_NO_RESPONSE;
>  /* Log the time */
>  StartTime = HEIIGetCounter();
>  /* Send request */
>  HEIWriteIO(pDevice, pData, SizeofData, pReturnData,  
> pSizeofReturnData);
>  /* Restore parallel packet mode */
>  pDevice->ParallelPackets = OldPP;
>  return StartTime;
>  }
> __declspec(dllexport) int HEIWriteIOEx
>  (
>  HEIDevice *apDevice[],
>  BYTE *apData[],
>  WORD aSizeofData[],
>  BYTE *apReturnData[],
>  WORD aSizeofReturnData[],
>  int aErrorCode[],
>  int DeviceCount
>  )
>  {
>  int idx = 0;
>  BOOL Done = FALSE;
>  DWORD *pStartTime = (DWORD *)calloc(sizeof(DWORD), DeviceCount);
>  int MaxStarted = 0;
>  int StartAt = 0;
>  /* Reset retry count */
>  for(idx = 0; idx < DeviceCount; idx++)
>   if(apDevice[idx])
>    apDevice[idx]->SizeOfData = 0;
>  while(!Done)
>   {
>   /* Start a request */
>   for(idx = StartAt; idx < DeviceCount; idx++)
>    {
>    /* Handle NULL device */
>    if(!apDevice[idx])
>     {
>     StartAt = idx + 1;
>     if(idx+1 > MaxStarted)
>      MaxStarted = idx + 1;
>     }
>    /* If request not started, start it */
>    else if(!pStartTime[idx])
>     {
>     pStartTime[idx] = StartHEIWriteIO(apDevice[idx], apData[idx],  
> aSizeofData[idx], apReturnData[idx], &aSizeofReturnData[idx],  
> &aErrorCode[idx]);
>     StartAt = idx + 1;
>     if(idx+1 > MaxStarted)
>      MaxStarted = idx + 1;
>     break;
>     }
>    }
>   /* Test for completion of requests */
>   GetResponseEx(apDevice, apReturnData, aSizeofReturnData,  
> aErrorCode, MaxStarted);
>   /* When all have been started, we're done until proven otherwise */
>   Done = MaxStarted == DeviceCount;
>
>   /* Test for timeout of requests */
>   for(idx = 0; idx < MaxStarted; idx++)
>    {
>    /* Handle NULL device */
>    if(!apDevice[idx])
>     continue;
>    /* If request started, test timeout */
>    if(aErrorCode[idx] == HEIE_NO_RESPONSE && pStartTime[idx])
>     {
>     /* Check timeout for device */
>     if(TimeDiff(pStartTime[idx], HEIIGetCounter()) >= apDevice[idx]- 
> >Timeout)
>      {
>      /* Timed out, check retries */
>      if(apDevice[idx]->SizeOfData < apDevice[idx]->Retrys)
>       {
>       apDevice[idx]->SizeOfData++;
>       apDevice[idx]->RetryCount++;
>       /* Reset */
>       pStartTime[idx] = 0;
>       aErrorCode[idx] == HEIE_NO_RESPONSE;
>       if(idx < StartAt)
>        StartAt = idx;
>
>       /* Not done */
>       Done = FALSE;
>       }
>      /* No more retries */
>      else
>       {
>       /* Set error code */
>       aErrorCode[idx] = HEIE_TIMEOUT;
>
>       /* This device is done */
>       }
>      }
>     /* Started but not timed out */
>     else
>      /* Not done */
>      Done = FALSE;
>     }
>    /* If not started... */
>    else if(!pStartTime[idx])
>     {
>     /* Can't be done */
>     Done = FALSE;
>     }
>    }
>   }
>  free(pStartTime);
>  return 0;
>  }
>
> #if 0
> int GetResponseEx(HEIDevice *apDevice[], BYTE *apData[], WORD  
> aSizeofData[], int aErrorCode[], int DeviceCount)
>  {
>  int Done = TRUE;
>  int idx = 0;
>  for(idx = 0; idx < DeviceCount; idx++)
>   {
>   /* Handle NULL device */
>   if(!apDevice[idx])
>    continue;
>   if(aErrorCode[idx] == HEIE_NO_RESPONSE)
>    {
>    BYTE Buff[500];
>    int BuffLen = sizeof(Buff);
>    aErrorCode[idx] = HEIGetResponse(apDevice[idx], Buff, &BuffLen,  
> TRUE);
>    /* If no response, continue */
>    if(aErrorCode[idx] == HEIE_NO_RESPONSE)
>     {
>     Done = FALSE;
>     continue;
>     }
>    /* Check for error and not warning. */
>    if(aErrorCode[idx] && !(aErrorCode[idx] & HEIW_FIRST_WARNING))
>     {
>     /* Set data size to 0 */
>     aSizeofData[idx] = 0;
>     }
>    else
>     {
>     if(BuffLen)
>      {
>      short int *pInt = (short int *)&Buff[PACKET_HEADER_SIZE];
>      BuffLen -= PACKET_HEADER_SIZE;
>      BuffLen -= 2;
>      if((WORD)BuffLen > aSizeofData[idx])
>       {
>       BuffLen = aSizeofData[idx];
>       aErrorCode[idx] = HEIE_BUFFER_TOO_SMALL;
>       }
>      if(*pInt)
>       aErrorCode[idx] = (*pInt) | 0x8000;
>      memcpy(apData[idx], Buff+PACKET_HEADER_SIZE+2, BuffLen);
>      aSizeofData[idx] = BuffLen;
>      }
>     else
>      {
>      /* Set data size to 0 */
>      aSizeofData[idx] = 0;
>      aErrorCode[idx] = HEIE_ZERO_BYTES_RECEIVED;
>      }
>     }
>    }
>   }
>  return Done;
>  }
> __declspec(dllexport) int HEIReadIOEx
>  (
>  HEIDevice *apDevice[],
>  BYTE *apData[],
>  WORD aSizeofData[],
>  int aErrorCode[],
>  int DeviceCount,
>  DWORD Timeout
>  )
>  {
>  DWORD StartTime = HEIIGetCounter();
>  int idx = 0;
>  BOOL Done = FALSE;
>  BOOL OldPP = FALSE;
>  for(idx = 0; idx < DeviceCount; idx++)
>   {
>   /* Handle NULL device */
>   if(!apDevice[idx])
>    continue;
>   /* Force parallel packet mode */
>   OldPP = apDevice[idx]->ParallelPackets;
>   apDevice[idx]->ParallelPackets = TRUE;
>   /* Init error code */
>   aErrorCode[idx] = HEIE_NO_RESPONSE;
>   /* Send request */
>   HEIReadIO(apDevice[idx], apData[idx], &aSizeofData[idx]);
>   /* Check for response */
>   GetResponseEx(apDevice, apData, aSizeofData, aErrorCode, idx+1);
>   /* Restore parallel packet mode */
>   apDevice[idx]->ParallelPackets = OldPP;
>   }
>  /* Spin on GetResponseEx waiting for timeout */
>  while(!Done)
>   {
>   Done = GetResponseEx(apDevice, apData, aSizeofData, aErrorCode,  
> idx);
>   if(TimeDiff(StartTime, HEIIGetCounter()) >= Timeout)
>    return HEIE_TIMEOUT;
>   }
>  return 0;
>  }
> __declspec(dllexport) int HEIWriteIOEx
>  (
>  HEIDevice *apDevice[],
>  BYTE *apData[],
>  WORD aSizeofData[],
>  BYTE *apReturnData[],
>  WORD aSizeofReturnData[],
>  int aErrorCode[],
>  int DeviceCount,
>  DWORD Timeout
>  )
>  {
>  DWORD StartTime = HEIIGetCounter();
>  int idx = 0;
>  BOOL Done = FALSE;
>  BOOL OldPP = FALSE;
>  for(idx = 0; idx < DeviceCount; idx++)
>   {
>   /* Handle NULL device */
>   if(!apDevice[idx])
>    continue;
>   /* Force parallel packet mode */
>   OldPP = apDevice[idx]->ParallelPackets;
>   apDevice[idx]->ParallelPackets = TRUE;
>   /* Init error code */
>   aErrorCode[idx] = HEIE_NO_RESPONSE;
>   /* Send request */
>   HEIWriteIO(apDevice[idx], apData[idx], aSizeofData[idx],  
> apReturnData[idx], &aSizeofReturnData[idx]);
>   /* Check for response */
>   GetResponseEx(apDevice, apReturnData, aSizeofReturnData,  
> aErrorCode, idx+1);
>   /* Restore parallel packet mode */
>   apDevice[idx]->ParallelPackets = OldPP;
>   }
>  /* Spin on GetResponseEx waiting for timeout */
>  while(!Done)
>   {
>   Done = GetResponseEx(apDevice, apReturnData, aSizeofReturnData,  
> aErrorCode, idx);
>   if(TimeDiff(StartTime, HEIIGetCounter()) >= Timeout)
>    return HEIE_TIMEOUT;
>   }
>  return 0;
>  }
> #endif
>
> /*
> ** HEI.C - Platform dependent code for communicating with Host  
> Automation Products
> **   line of ethernet modules using the WinSock transport.
> **
> ** Copyright (C) - 1996-1998 Host Automation Products, Inc.
> **
> */
> #include "winsock.h"  /* Needed for winsock calls */
> #include "wsipx.h"   /* Needed for winsock IPX calls */
> #include "mmsystem.h"  /* Needed for timer stuff */
> #include "hei.h"
> #include <memory.h>
> /*
> ** Notes for porting code to another platform:
> **
> ** This file contains the transport/system dependant code for use  
> with the
> ** Host Ethernet Interface (HEI).  There are nine functions which  
> must be
> ** implemented by this code:
> **
> **  1) int HEIIOpen();
> **  2) int HEIIClose();
> **  3) int HEIIOpenTransport(HEITransport *pTransport);
> **  4) int HEIICloseTransport(HEITransport *pTransport);
> **  5) int HEIIOpenDevice(HEITransport *pTransport, HEIDevice  
> *pDevice);
> **  6) int HEIICloseDevice(HEIDevice *pDevice);
> **  7) int HEIIReceivePacket(HEIDevice *pDevice, BYTE *pResponse,  
> int *pResponseSize);
> **  8) int HEIISendPacket(HEIDevice *pDevice, BYTE *pPacket, WORD  
> PacketSize);
> **  9) DWORD HEIIGetCounter();
> **
> ** Make changes in this file, do not change HEI.C or any structures  
> in HEI.H!
> ** If you find that you must change something in HEI.C, contact the  
> person
> ** you got this source from.
> **
> ** Feel free to remove any of the WinSock specific code from this  
> module.
> **
> ** To compile the code for ANSI C, ANSI_C must be defined!
> **
> ** See all sections containing "TODO_FOR_OTHER_SYSTEM" for further  
> details.
> **
> */
>
> /* Counter for the number of times that OpenTransport has been  
> called */
> static int WinSockLoadCount = 0;
> /*
> ** Windows version gets stored here.  It is used for setting winsock  
> options
> ** Win 16 is slightly different than Win 32.
> */
> WORD  WinVer=0;
> /* This is the port number to use when talking to a module. */
> #define PORT_ID 0x7070
> /* This function should return a millisecond resolution tick  
> counter. */
> DWORD HEIIGetCounter()
>  {
>  /*return timeGetTime(); */
>  LARGE_INTEGER freq, count;
>  QueryPerformanceFrequency(&freq);
>  QueryPerformanceCounter(&count);
>  return (DWORD)((count.QuadPart * 1000) / freq.QuadPart);
>  }
>
> /*
> ** This function is called from within HEIOpen. It gives the  
> opportunity
> ** to do initialization type stuff.  NOTE: This function may be  
> called more
> ** than once!
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIIOpen()
>  {
>  /* Save the windows version for later use. */
>  DWORD dwVersion = GetVersion();
>  WinVer = LOWORD(dwVersion);
>  /*
>  ** TODO_FOR_OTHER_SYSTEM
>  ** Do system level init stuff here.
>  ** Be aware that this may be called more than once.
>  */
>  return HEIE_NULL;
>  }
>
> /*
> ** This function is called from within HEIClose. It gives the  
> opportunity
> ** to do shutdown type stuff.  NOTE: This function may be called more
> ** than once!
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIIClose()
>  {
>  /*
>  ** TODO_FOR_OTHER_SYSTEM
>  ** Do system level shut down stuff here.
>  ** Be aware that this may be called more than once.
>  */
>  return HEIE_NULL;
>  }
>
> /*
> ** This function is called from within HEIOpenTransport.  It is used  
> to prepare
> ** the given Transport to be used in subsequent HEIOpenDevice calls.
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIIOpenTransport(HEITransport *pTransport)
>  {
>  switch (pTransport->Transport)
>   {
>   case HEIT_WINSOCK:   /* Open Transport type HEIT_WINSOCK */
>    {
>    /* WinSock Transport. Protocol must be either IPX or IP */
>    if (pTransport->Protocol == HEIP_IPX || pTransport->Protocol ==  
> HEIP_IP)
>     {
>     /* Keep track of load count, Initialize winsock if zero. */
>     if (!WinSockLoadCount)
>      {
>      WSADATA wsaData;
>      WORD wVersionRequested = MAKEWORD(2, 0);
>
>      /* Initialize winsock dll */
>      if(WSAStartup(wVersionRequested, &wsaData) == SOCKET_ERROR)
>       return WSAGetLastError();
>      }
>     WinSockLoadCount++;
>     }
>    else
>     return HEIE_UNSUPPORTED_PROTOCOL;
>    break;
>    }
>
>   case HEIT_OTHER_TRANSPORT:
>    {
>    /*
>    ** TODO_FOR_OTHER_SYSTEM
>    ** Do one time init stuff by keeping track of the number of times  
> this
>    ** transport has been opened.
>    ** Don't return HEIE_UNSUPPORTED_TRANSPORT
>    */
>    return HEIE_UNSUPPORTED_TRANSPORT;
>    }
>
>   default:
>    return HEIE_UNSUPPORTED_TRANSPORT;
>   }
>
>  return HEIE_NULL;
>    }
>
>
> /*
> ** This function is called from within HEICloseTransport.  It  
> indicates
> ** that the given Transport is no longer in use.
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIICloseTransport(HEITransport *pTransport)
>  {
>  switch (pTransport->Transport)
>   {
>   case HEIT_WINSOCK:      /* Close Transport type HEIT_WINSOCK */
>    {
>    /* WinSock Transport. Protocol must be IPX or IP */
>    if (pTransport->Protocol == HEIP_IPX || pTransport->Protocol ==  
> HEIP_IP)
>     {
>     /* Decrement load count.  Shut down WinSock if zero */
>     if (WinSockLoadCount)
>      {
>      WinSockLoadCount--;
>      if (!WinSockLoadCount)
>       WSACleanup();
>      }
>     }
>    else
>     return HEIE_UNSUPPORTED_PROTOCOL;
>
>    break;
>    }
>
>   case HEIT_OTHER_TRANSPORT:
>    {
>    /*
>    ** TODO_FOR_OTHER_SYSTEM
>    ** Decrement load counter, do cleanup stuff if zero.
>    ** Don't return HEIE_UNSUPPORTED_TRANSPORT
>    */
>    return HEIE_UNSUPPORTED_TRANSPORT;
>    }
>
>   default:
>    return HEIE_UNSUPPORTED_TRANSPORT;
>   }
>
>  return HEIE_NULL;
>    }
>
>
> /*
> ** This function is called from within HEIOpenDevice.  It is used to  
> prepare
> ** the given Device to be used with the given Transprot.
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIIOpenDevice(HEITransport *pTransport, HEIDevice *pDevice)
>  {
>  switch (pTransport->Transport)
>   {
>   case HEIT_WINSOCK:  /* Open Device type HEIT_WINSOCK */
>    {
>    /* WinSock Transport. */
>    SOCKET sock;
>    struct sockaddr *pRemAddr, *pMyAddr;
>    int SizeRemAddr, SizeMyAddr;
>    u_long NonBlockingMode;
>    if (pTransport->Protocol == HEIP_IPX)
>     {
>     static SOCKADDR_IPX RemAddr, MyAddr;
>     /* Initialize remote address */
>     if (!pDevice->UseBroadcast)
>      memcpy(&RemAddr, pDevice->Address.Raw, sizeof(SOCKADDR_IPX));
>     if (pTransport->pSourceAddress)
>      {
>      MyAddr.sa_family = pTransport->pSourceAddress->AddressIPX.Family;
>      memcpy(MyAddr.sa_netnum, pTransport->pSourceAddress- 
> >AddressIPX.Netnum, 4);
>      memcpy(MyAddr.sa_nodenum, pTransport->pSourceAddress- 
> >AddressIPX.Nodenum, 6);
>      MyAddr.sa_socket = pTransport->pSourceAddress->AddressIPX.Socket;
>      }
>     else
>      {
>      /* Initialize MyAddr to all zeros so that windows can tell me  
> who I am! */
>      MyAddr.sa_family = AF_IPX;
>      /*memcpy(MyAddr.sa_netnum, &pTransport->NetworkAddress, 4);*/
>      memset(MyAddr.sa_netnum, 0, 4);
>      memset(MyAddr.sa_nodenum, 0, 6);
>      MyAddr.sa_socket = 0x00;
>      }
>     /* get socket handle */
>     sock = socket(AF_IPX,        /* IPX family */
>          SOCK_DGRAM,    /* Datagram */
>          NSPROTO_IPX);
>     pRemAddr = (struct sockaddr *) &RemAddr;
>     pMyAddr = (struct sockaddr *) &MyAddr;
>     SizeRemAddr = sizeof(RemAddr);
>     SizeMyAddr = sizeof(MyAddr);
>     }
>    else if (pTransport->Protocol == HEIP_IP)
>     {
>     static struct sockaddr_in RemAddr, MyAddr;
>     /*
>     ** If Protocol is IP and we are not using broadcast, and
>     ** Address.Raw[19] == 1 then the IP address in the module
>     ** is undefined.
>     */
>     if (!pDevice->UseBroadcast && (pDevice->Address.Raw[19] == 1))
>      return HEIE_IP_ADDR_NOT_INITIALIZED;
>
>     /* Initialize remote address */
>     if (!pDevice->UseBroadcast)
>      memcpy(&RemAddr, pDevice->Address.Raw, sizeof(RemAddr));
>     if (pTransport->pSourceAddress)
>      {
>      MyAddr.sin_family = pTransport->pSourceAddress->AddressIP.Family;
>      MyAddr.sin_port = pTransport->pSourceAddress->AddressIP.Port;
>      MyAddr.sin_addr.s_addr = pTransport->pSourceAddress- 
> >AddressIP.AddressingType.lAddr;
>      }
>     else
>      {
>      /* Initialize MyAddr to all zeros so that windows can tell me  
> who I am! */
>      MyAddr.sin_family = AF_INET;
>      MyAddr.sin_port = 0;
>      MyAddr.sin_addr.s_addr = 0;
>      }
>     /* get socket handle */
>     sock = socket(AF_INET,       /* IP family */
>          SOCK_DGRAM,    /* Datagram */
>          IPPROTO_UDP);
>     pRemAddr = (struct sockaddr *) &RemAddr;
>     pMyAddr = (struct sockaddr *) &MyAddr;
>     SizeRemAddr = sizeof(RemAddr);
>     SizeMyAddr = sizeof(MyAddr);
>     }
>    else
>     return HEIE_UNSUPPORTED_PROTOCOL;
>
>    if(sock == INVALID_SOCKET)
>     return WSAGetLastError();
>    if (bind (sock, pMyAddr, SizeMyAddr) == SOCKET_ERROR)
>     {
>     int Error = WSAGetLastError();
>     closesocket(sock);
>     return Error;
>     }
>    if (pDevice->UseBroadcast)
>     {
>     int rSetSockOpt;
>
>     if (WinVer < 0x0332) /* Check for WinVer < 3.50 */
>      {
>      /* 16 Bit uses int type. */
>      int AllowBroadcast = TRUE;
>      rSetSockOpt = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const  
> char *) &AllowBroadcast, sizeof(AllowBroadcast));
>      }
>     else
>      {
>      /* 32 Bit uses long type. */
>      long AllowBroadcast = TRUE;
>      rSetSockOpt = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const  
> char *) &AllowBroadcast, sizeof(AllowBroadcast));
>      }
>
>     if (rSetSockOpt == SOCKET_ERROR)
>      {
>      int Error = WSAGetLastError();
>      closesocket(sock);
>      return Error;
>      }
>     }
>    else
>     {
>     if (connect (sock, pRemAddr, SizeRemAddr) == SOCKET_ERROR)
>      {
>      int Error = WSAGetLastError();
>      closesocket(sock);
>      return Error;
>      }
>     }
>    /* Setup for non-blocking mode */
>    NonBlockingMode = 1;
>    if (ioctlsocket (sock, FIONBIO, &NonBlockingMode) == SOCKET_ERROR)
>     {
>     int Error = WSAGetLastError();
>     closesocket(sock);
>     return Error;
>     }
>
>    pDevice->_dwParam = (DWORD) sock;
>    break;
>    }
>
>   case HEIT_OTHER_TRANSPORT:
>    {
>    /*
>    ** TODO_FOR_OTHER_SYSTEM
>    ** Prepare to communicate with the given device.
>    ** The address to talk to is stored in pDevice->Address (see  
> HEI.H for format)
>    ** Be aware that pDevice->UseBroadcast indicates that we
>    ** will be broadcasting to the module.
>    ** For IP, pDevice->Address.Raw[19] == 1 (after a query)
>    ** if the given module's IP address is not initialized.  In
>    ** this case, the only way to talk to it (using IP) is by
>    ** using addressed broadcast.
>    ** You can use pDevice->_dwParam to store whatever (such as
>    ** a socket number).
>    ** Don't return HEIE_UNSUPPORTED_TRANSPORT
>    */
>    return HEIE_UNSUPPORTED_TRANSPORT;
>    }
>
>   default:
>    return HEIE_UNSUPPORTED_TRANSPORT;
>   }
>
>  return HEIE_NULL;
>  }
>
> /*
> ** This function is called from within HEICloseDevice.  It indicates
> ** that the given Device is no longer in use.
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIICloseDevice(HEIDevice *pDevice)
>  {
>  switch (pDevice->_pTransport->Transport)
>   {
>   case HEIT_WINSOCK:  /* Close Device type HEIT_WINSOCK */
>    {
>    /* WinSock Transport. */
>    if (pDevice->_pTransport->Protocol == HEIP_IPX || pDevice- 
> >_pTransport->Protocol == HEIP_IP)
>     {
>     SOCKET sock = (SOCKET) pDevice->_dwParam;
>
>     if (closesocket(sock) == SOCKET_ERROR)
>      return WSAGetLastError();
>     }
>    else
>     return HEIE_UNSUPPORTED_PROTOCOL;
>    break;
>    }
>
>   case HEIT_OTHER_TRANSPORT:
>    {
>    /*
>    ** TODO_FOR_OTHER_SYSTEM
>    ** Do device type shutdown stuff.
>    ** Don't return HEIE_UNSUPPORTED_TRANSPORT
>    */
>    return HEIE_UNSUPPORTED_TRANSPORT;
>    }
>
>   default:
>    return HEIE_UNSUPPORTED_TRANSPORT;
>   }
>
>  return HEIE_NULL;
>  }
>
>
> /*
> ** This is the code for receiving a packet from the ethernet driver  
> for the given
> **  device.  The response should be stored in the given response  
> buffer - pResponse.
> **  On entry, pResponseSize contains the size of the response buffer  
> (pResponse).
> **  On exit, pResponseSize MUST contain the number of bytes copied  
> to the response buffer.
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIIReceivePacket(HEIDevice *pDevice, BYTE *pResponse, int  
> *pResponseSize)
>  {
>  int Retval = HEIE_NULL;
>
>  switch (pDevice->_pTransport->Transport)
>   {
>   case HEIT_WINSOCK:  /* GetResponse from HEIT_WINSOCK */
>    {
>    int NumBytes;
>    SOCKET sock = (SOCKET) pDevice->_dwParam;
>
>    if (pDevice->UseBroadcast)
>     {
>     struct sockaddr FromAddr;
>     int FromLen = sizeof(FromAddr);
>
>     NumBytes = recvfrom(sock, (char *) pResponse, *pResponseSize, 0,  
> &FromAddr, &FromLen);
>
>     if (pDevice->pData)
>      {
>      /* Need to copy FROM address. */
>      int Num2Copy = FromLen;
>
>      if (pDevice->SizeOfData < Num2Copy)
>       {
>       Retval = HEIE_BUFFER_TOO_SMALL;
>       Num2Copy = pDevice->SizeOfData;
>       }
>
>      memcpy(pDevice->pData, &FromAddr, Num2Copy);
>      }
>     }
>    else
>     {
>     NumBytes = recv(sock, (char *) pResponse, *pResponseSize, 0);
>     }
>
>    if (NumBytes == SOCKET_ERROR)
>     {
>     /* Check to see if the error is WSAWOULDBLOCK. */
>     int Error = WSAGetLastError();
>
>     if (Error != WSAEWOULDBLOCK)
>      {
>      *pResponseSize = 0;
>      Retval = Error;
>      }
>     else
>      {
>      Retval = HEIE_NO_RESPONSE;
>      }
>     }
>    else
>     {
>     (*pResponseSize) = NumBytes;
>     }
>
>    break;
>    }
>   case HEIT_OTHER_TRANSPORT:
>    {
>    /*
>    ** TODO_FOR_OTHER_SYSTEM
>    ** Receive a packet for the given device into the buffer pResponse.
>    ** *pResponseSize indicates the length of the pResponse buffer.
>    ** If pDevice->UseBroadcast && pDevice->pData,
>    ** then we need to copy the FROM address into pDevice->pData.
>    ** pDevice->SizeOfData tells how long the buffer pDevice->pData is.
>    ** Store the number of bytes received in (*pResponseSize).
>    ** Don't return HEIE_UNSUPPORTED_TRANSPORT
>    */
>    return HEIE_UNSUPPORTED_TRANSPORT;
>    }
>
>   default:
>    return HEIE_UNSUPPORTED_TRANSPORT;
>   }
>
>  return Retval;
>  }
>
>
> /*
> ** This is the code for sending the given packet for the given device.
> ** pPacket is the pointer to the actual packet data, and PacketSize  
> is the
> ** number of bytes in the packet to be sent.
> **
> ** RETURNS:  0 on success
> **           non-zero on error.
> */
> int HEIISendPacket(HEIDevice *pDevice, BYTE *pPacket, WORD PacketSize)
>  {
>  switch (pDevice->_pTransport->Transport)
>   {
>   case HEIT_WINSOCK:   /* Send packet of type HEIT_WINSOCK */
>    {
>    /* WinSock Transport. */
>    SOCKET sock = (SOCKET) pDevice->_dwParam;
>    if (pDevice->UseBroadcast)
>     {
>     /* Initialize remote address */
>     struct sockaddr *pRemAddr = (struct sockaddr *) NULL;
>     int SizeRemAddr = 0;
>     if (pDevice->_pTransport->Protocol == HEIP_IP)
>      {
>      static struct sockaddr_in RemAddr;
>
>      RemAddr.sin_family = AF_INET;
>      RemAddr.sin_port = PORT_ID;
>      RemAddr.sin_addr.s_addr = INADDR_BROADCAST;
>
>      pRemAddr = (struct sockaddr *) &RemAddr;
>      SizeRemAddr = sizeof(RemAddr);
>      }
>     else if (pDevice->_pTransport->Protocol == HEIP_IPX)
>      {
>      static SOCKADDR_IPX RemAddr;
>
>      RemAddr.sa_family = AF_IPX;
>      memset(RemAddr.sa_netnum, 0, 4);
>      memset(RemAddr.sa_nodenum, 0xFF, 6);
>      RemAddr.sa_socket = PORT_ID;
>      if (pDevice->_pTransport->pSourceAddress)
>       memcpy(RemAddr.sa_netnum, pDevice->_pTransport->pSourceAddress- 
> >AddressIPX.Netnum, 4);
>       /*memcpy(RemAddr.sa_netnum, &pDevice->_pTransport- 
> >NetworkAddress, 4);*/
>
>      pRemAddr = (struct sockaddr *) &RemAddr;
>      SizeRemAddr = sizeof(RemAddr);
>      }
>     if (sendto(sock, (char *) pPacket, PacketSize, 0, pRemAddr,  
> SizeRemAddr) == SOCKET_ERROR)
>      return  WSAGetLastError();
>     }
>    else
>     {
>     if (send(sock, (char *) pPacket, PacketSize, 0) == SOCKET_ERROR)
>      return  WSAGetLastError();
>     }
>
>    return HEIE_NULL;
>    }
>   case HEIT_OTHER_TRANSPORT:
>    {
>    /*
>    ** TODO_FOR_OTHER_SYSTEM
>    ** Send a packet to the given device.
>    ** If pDevice->UseBroadcast, then we need to broadcast the packet.
>    ** Don't return HEIE_UNSUPPORTED_TRANSPORT
>    */
>    return HEIE_UNSUPPORTED_TRANSPORT;
>    }
>
>   default:
>    return HEIE_UNSUPPORTED_TRANSPORT;
>   }
>  }
>
>
>
>
>
> <HEISrc.zip>_______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ





Más información sobre la lista de distribución Cconclase