📄 scp.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 + -