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