www.pudn.com > PROFIBUS_DP_protocol_source.ZIP > scp.c, change:2004-03-17,size:8041b


//----------------------------------------------------------------------------- 
// $Id: SCP.c,v 1.0.0                                               2004/01/13 
//----------------------------------------------------------------------------- 
// 
//      ProfiM - PROFIBUS MASTER DRIVER FOR WINDOWS NT/2000 
// 
// Author:   
//      Pavel Trnka, CTU FEE 
//      trnkap@seznam.cz 
// With help and advices from: 
//      Ing. Petr Smolik, CTU FEE 
//      Ing. Pavel Pisa, CTU FEE 
//      Ing. Pavel Burget, CTU FEE 
// 
//----------------------------------------------------------------------------- 
// 
// Description: 
// ------------ 
//   The FDL programming interface is made available to the FDL 
// application in the form of a library. The library functions of the FDL 
// programming interface handle the transfer of FDL jobs to the CP for 
// the FDL application. 
// 
// Functions: 
// ---------- 
// 
// SCP_open   Logon function for the FDL application 
// SCP_send   Sending jobs, data 
// SCP_receive  Receiving data (jobs, acknowledgments) 
// SCP_close  Logoff function for the FDL application 
// SCP_errno  Fetching error IDs 
// 
//----------------------------------------------------------------------------- 
//----------------------------------------------------------------------------- 
 
 
#include <windows.h> 
#include <winioctl.h> 
 
#include "fdl_rb.h" 
 
 
int   errno; 
int   MIDCounter = 0; 
 
 
 
//***************************************************************************** 
// 
//  Using the SCP_open function, the FDL application logs on at the driver.  
// 
//***************************************************************************** 
 
INT WINAPI SCP_open ( CHAR * dev ) 
{ 
    UCHAR   DefaultName[] = "\\\\.\\ProfiM"; 
  HANDLE  handle; 
 
  if ( !dev || dev=="" ) 
    dev = DefaultName; 
 
  // 
  // Open a channel to the driver 
  // 
  handle = CreateFile (dev, GENERIC_READ | GENERIC_WRITE, 
                             0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); 
 
  // 
  // Do we have a valid handle? (If not, the driver probably isn't loaded) 
  // 
  if (handle == INVALID_HANDLE_VALUE)  
  { 
    errno = 4867; // Channel name does not exist 
    return SCP_ERROR; 
  } 
 
  errno = 0; // job executed correctly 
  return (int) handle; 
} 
 
 
 
//***************************************************************************** 
// 
// Using the SCP_close function, an FDL application logs off at the driver. 
// Following this call, productive communication is no longer possible with 
// this handle. 
// 
//***************************************************************************** 
 
INT WINAPI SCP_close ( INT handle ) 
{ 
  if (handle) 
    if ( CloseHandle( (HANDLE) handle ) ) 
    { 
      errno = 0; // job executed correctly 
      return SCP_SUCCESS; 
    } 
    else 
    { 
      errno = 207; // Device already/not yet open. 
      return SCP_ERROR; 
    } 
 
  errno = 0; // job executed correctly 
  return SCP_SUCCESS; 
} 
 
 
 
//***************************************************************************** 
// 
// Using the SCP_send function, request blocks are transferred to the driver 
// for processing. 
// 
//***************************************************************************** 
 
INT WINAPI SCP_send ( INT handle, UWORD length, char *rb ) 
{ 
  unsigned long BytesWritten; 
  int       status; 
  OVERLAPPED    OL; 
 
  if ( ! handle ) 
  { 
    errno = 207; // device already/not yet open 
    return SCP_ERROR; 
  } 
 
  OL.Offset=0; 
  OL.OffsetHigh=0; 
  OL.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); 
 
  status = WriteFile ( (HANDLE) handle, rb, length, &BytesWritten, &OL ); 
  // 
  // Wait for WriteFile to complete. Should be immediately, because 
  // Request Block (rb) is only stored in Request Buffer. 
  // 
  WaitForSingleObject( OL.hEvent, 1000 ); 
  CloseHandle( OL.hEvent ); 
 
  if (status) 
  { 
    errno = 0; // job executed correctly 
    return SCP_SUCCESS; 
  } 
  else 
  { 
    errno = 208; // CP not reacting 
    return SCP_ERROR; 
  } 
} 
 
 
 
//***************************************************************************** 
// 
// With this call, the FDL application receives back job acknowledgments 
// and data from the driver. They are returned in a buffer provided by the 
// application. 
// The FDL application has the choice between a synchronous mode in 
// which the call is only completed when a request block is received, and 
// an asynchronous mode, that allows the results to be polled. 
// 
//***************************************************************************** 
 
#define FILE_DEVICE_PROFIM  0x00009000 
#define PROFIM_IOCTL_INDEX  0x900 
#define IOCTL_PROFIM_GET_RESULT       CTL_CODE(FILE_DEVICE_PROFIM, PROFIM_IOCTL_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS) 
#define IOCTL_PROFIM_CANCEL_WAITING   CTL_CODE(FILE_DEVICE_PROFIM, PROFIM_IOCTL_INDEX+3, METHOD_BUFFERED, FILE_ANY_ACCESS) 
 
INT WINAPI SCP_receive ( INT handle, UWORD timeout, UWORD *data_len, UWORD length, CHAR *buffer ) 
{ 
  OVERLAPPED    OL, OL2; 
  int           IOResult; 
  int           Result; 
  unsigned long BytesWritten, temp; 
  int           InBuffer[2]; 
  int           MID; 
 
  if ( ! handle ) 
  { 
    errno = 207; // device already/not yet open 
    return SCP_ERROR; 
  } 
 
  OL.Offset=0; 
  OL.OffsetHigh=0; 
  OL.hEvent=CreateEvent( NULL, FALSE, FALSE, NULL ); 
 
  MID=MIDCounter++; 
  InBuffer[0]=MID; 
  InBuffer[1]=timeout; 
  IOResult=DeviceIoControl ( (HANDLE) handle, IOCTL_PROFIM_GET_RESULT, 
                          InBuffer, sizeof(InBuffer), 
                          buffer, length, &BytesWritten, &OL ); 
 
  if ( ! IOResult ) 
    if ( GetLastError() == ERROR_IO_PENDING ) 
      IOResult = 1; 
 
  if ( timeout != SCP_NOWAIT ) 
  { 
    if ( timeout == SCP_FOREVER ) 
      Result=WaitForSingleObject( OL.hEvent, INFINITE ); 
    else 
      Result=WaitForSingleObject( OL.hEvent, timeout ); 
 
    if ( Result == WAIT_TIMEOUT ) 
    { 
      errno = 219; // Timeout expired 
      InBuffer[0]=MID; 
      OL2.Offset=0; 
      OL2.OffsetHigh=0; 
      OL2.hEvent=CreateEvent( NULL, FALSE, FALSE, NULL ); 
      DeviceIoControl ( (HANDLE) handle, IOCTL_PROFIM_CANCEL_WAITING, 
                        InBuffer, sizeof(InBuffer), 
                        NULL, 0, &temp, &OL2 ); 
      WaitForSingleObject( OL2.hEvent, 300 ); // just to safely close the handle                         
      if ( OL2.hEvent ) 
        CloseHandle( OL2.hEvent ); 
    } 
    else 
      errno = 0; // job executed correctly 
  } 
  else 
    errno = 0; // job executed correctly 
 
  if ( OL.hEvent ) 
    CloseHandle( OL.hEvent ); 
 
  *data_len = sizeof(fdl_rb);   // BytesWritten; 
 
  if ( IOResult ) 
  { 
    return SCP_SUCCESS; 
  } 
  else 
  { 
    errno = 208; // CP not reacting 
    return SCP_ERROR; 
  } 
} 
 
 
 
//***************************************************************************** 
// 
//  NOT SUPPORTED  
// 
//  With this function application can register window to the driver for 
//  receiving notification on new messages by WM_SINEC message. 
// 
//***************************************************************************** 
 
INT WINAPI SetSinecHWnd( INT handle, HANDLE hWnd ) 
{ 
  errno = 305; // Function not implemented 
  return SCP_ERROR; 
} 
 
 
 
//***************************************************************************** 
// 
//  NOT SUPPORTED 
// 
//***************************************************************************** 
 
INT WINAPI SetSinecHWndMsg( INT handle, HANDLE hWnd, ULONG msg_id ) 
{ 
  errno = 305; // Function not implemented 
  return SCP_ERROR; 
} 
 
 
 
//***************************************************************************** 
// 
// Using the SCP_get_errno function, an application can query the cause 
// of an error that occurred in an SCP function. 
// 
//***************************************************************************** 
 
INT WINAPI SCP_get_errno( VOID ) 
{ 
  return errno; 
}