⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scp.c

📁 profibus-dp主站源代码
💻 C
字号:
//-----------------------------------------------------------------------------
// $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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -