//****************************************************************************
//*                           cl_mscCall.pas
//****************************************************************************
//*   Purpose:    Irinos MscDll low-level integration
//*
//****************************************************************************
//*   Comment:    For use with MscDll
//*
//****************************************************************************
//*             (c) Messtechnik Sachs GmbH, D-73614 Schorndorf
//****************************************************************************

unit cl_mscCall;

interface

uses 	cl_Opcodes, Winapi.Windows;

const
	MSC_MAX_UNIQUEID_SIZE             =	80;

  // Return codes for various Dll functions
	MSC_STATUS_SUCCESS                = $00000000;  // no error detected
	MSC_STATUS_FAILED	                =	$F0000001;  // general error
	MSC_STATUS_INVALID_HANDLE         =	$F0000002;  // call an invalid handle
	MSC_STATUS_INVALID_PARAMS         =	$F0000003;	// invalid parameter
	MSC_STATUS_NO_RESOURCES           =	$F0000004;	// no resources for creation
	MSC_STATUS_NO_DEVICES             =	$F0000005;	// no device found
	MSC_STATUS_NOT_INITIALIZED        =	$F0000006;	// member not initialzed
	MSC_STATUS_ALREADY_INITIALIZED    =	$00000007;	// cfi interface is already initialzed, repeated call
	MSC_STATUS_INVALID_OBJECT_TYPE    =	$F0000008;	// handle identifies an invalid object type, handle is invalid for this function call
	MSC_STATUS_INVALID_CHANNEL_TYPE   =	$F0000009;	// channel don't have the correct type for this function
	MSC_STATUS_DEVICE_DISCONNECTED    =	$F0000010;	// device disconnected, disconnect timeout passed
	MSC_STATUS_FUNCTION_NOT_ALLOWED   =	$F0000100;	// function not allowed at time
	MSC_STATUS_NO_DATA_AVAILABLE      =	$F0000200;	// no data available
	MSC_STATUS_NO_MORE_DATA           =	$F0000400;	// no more data
	MSC_STATUS_BUFFER_TO_SHORT        =	$F0000401;	// buffer too short


type
	MSC_STATUS = cardinal;
	MSC_HANDLE = Pointer;

  // ### Declaration of DLL functions. See Dll-Documentation for information about the various functions.

	T_MSC_GetVersion = procedure ( var ApiVersion : Cardinal;
                                 var DllVersion : Cardinal ); stdcall;
	P_MSC_GetVersion = ^T_MSC_GetVersion;


	T_MSC_EnumerateDevices = function( var DeviceNumber : cardinal ) : MSC_STATUS; stdcall;
	P_MSC_EnumerateDevices = ^T_MSC_EnumerateDevices;


	T_MSC_GetDeviceInfo = function ( Index : cardinal;
                                   var BusType : cardinal;
                                   UniqueID : PAnsiChar	) : MSC_STATUS; stdcall;
	P_MSC_GetDeviceInfo = ^T_MSC_GetDeviceInfo;


	T_MSC_OpenDevice = function ( Index : cardinal;
                                var Handle : MSC_HANDLE ) : MSC_STATUS; stdcall;
	P_MSC_OpenDevice = ^T_MSC_OpenDevice;


	T_MSC_InitDevice = function ( Handle : MSC_HANDLE ) : MSC_STATUS; stdcall;
	P_MSC_InitDevice = ^T_MSC_InitDevice;


	T_MSC_CloseDevice = function ( Handle : MSC_HANDLE ) : MSC_STATUS; stdcall;
	P_MSC_CloseDevice = ^T_MSC_CloseDevice;


	T_MSC_SetNotificationMessage = function ( Handle : MSC_HANDLE;
                                            OpCode : integer;
															              hWnd : THandle;
															              MsgCode : Cardinal;
                                            wParam : Cardinal;
                                            lParam : Cardinal ) : MSC_STATUS; stdcall;
	P_MSC_SetNotificationMessage = ^T_MSC_SetNotificationMessage;


	T_MSC_Start = function ( Handle : MSC_HANDLE;
                           SndPeriod : Cardinal;          // ms
                           DisconnectTimeout : Cardinal;  // ms
                           RetryCount : Cardinal;
                           ResponseTimeout : cardinal ) : MSC_STATUS; stdcall;  // ms
	P_MSC_Start = ^T_MSC_Start;


	T_MSC_Stop = function ( Handle : MSC_HANDLE ) : MSC_STATUS; stdcall;
	P_MSC_Stop = ^T_MSC_Stop;


	T_MSC_WriteCommand = function (	Handle : MSC_HANDLE;
                                  OpCode : byte;
												          SndBufferSize : cardinal;
                                  SndBuffer : Pointer;
												          RcvBufferSize : cardinal;
                                  RcvBuffer : Pointer;
												          var BytesReceived : cardinal;
                                  Timeout : cardinal ) : MSC_STATUS; stdcall; // ms
	P_MSC_WriteCommand = ^T_MSC_WriteCommand;


	T_MSC_SetupStaticChannel = function ( Handle : MSC_HANDLE;
                                        OpCode : byte;
                                        SndBufferSize : cardinal;
                                        SndBuffer : Pointer;
														            RcvBufferSize : cardinal ) : MSC_STATUS; stdcall;
	P_MSC_SetupStaticChannel = ^T_MSC_SetupStaticChannel;


	T_MSC_SetupExtendedDynamicChannel = function ( Handle : MSC_HANDLE;
                                                 Opcode : byte;
                                                 NumberOfSubChannels : byte;
                                                 SndBufferSize : Cardinal;
																	               SndBuffer : Pointer ) : MSC_STATUS; stdcall;
	P_MSC_SetupExtendedDynamicChannel = ^T_MSC_SetupExtendedDynamicChannel;


	T_MSC_AttachSubChannelBuffer = function ( Handle : MSC_HANDLE;
                                            Opcode : byte;
															              SubChannel : byte;
                                            BufferSize : Cardinal;
															              Buffer : Pointer ) : MSC_STATUS; stdcall;
	P_MSC_AttachSubChannelBuffer = ^T_MSC_AttachSubChannelBuffer;


	T_MSC_DetachSubChannelBuffers = function ( Handle : MSC_HANDLE;
                                             OpCode : byte ) : MSC_STATUS; stdcall;
	P_MSC_DetachSubChannelBuffers = ^T_MSC_DetachSubChannelBuffers;


	T_MSC_GetPosition = function ( Handle : MSC_HANDLE;
                                 OpCode : byte;
												         var Position : Cardinal ) : MSC_Status; stdcall;
	P_MSC_GetPosition = ^T_MSC_GetPosition;


  T_MSC_RefreshChannel = function ( Handle : MSC_HANDLE;
                                    Opcode : byte ) : MSC_STATUS; stdcall;
  P_MSC_RefreshChannel = ^T_MSC_RefreshChannel;


	T_MSC_GetDeviceState = function (	Handle : MSC_HANDLE;
													          var LastMsgReceived : Cardinal;
                                    var SndErrorCounter : Cardinal;
													          var RcvErrorCounter : Cardinal;
                                    var CmdDiscarded : Cardinal;
													          CmdDiscardedArray : Pointer;
                                    Flags : cardinal ) : MSC_STATUS; stdcall;
	P_MSC_GetDeviceState = ^T_MSC_GetDeviceState;


	T_MSC_ReadStatic = function (	Handle : MSC_HANDLE;
											          opcode : byte;
                                BufferSize : cardinal;
											          Buffer : Pointer;
                                var DataCount : cardinal ) : MSC_STATUS; stdcall;
	P_MSC_ReadStatic = ^T_MSC_ReadStatic;


  T_MSC_GetDwordValue = function ( SectionName : Pointer;
                                   KeyName : Pointer;
                                   var Value : Cardinal ) : MSC_STATUS; stdcall;
  P_MSC_GetDwordValue = ^T_MSC_GetDwordValue;



	TCMscDll = class
		public
			constructor create;
			function		Load( DllName : string ) : boolean;
		private
			hdriver : Integer;
		public
			F_MSC_GetVersion                :	T_MSC_GetVersion;
			F_MSC_EnumerateDevices 					:	T_MSC_EnumerateDevices;
			F_MSC_GetDeviceInfo 						:	T_MSC_GetDeviceInfo;
			F_MSC_OpenDevice 							  :	T_MSC_OpenDevice;
			F_MSC_InitDevice 							  :	T_MSC_InitDevice;
			F_MSC_Start 								    :	T_MSC_Start;
			F_MSC_Stop 									    :	T_MSC_Stop;
			F_MSC_ReadStatic 							  :	T_MSC_ReadStatic;
			F_MSC_WriteCommand 						  :	T_MSC_WriteCommand;
			F_MSC_GetDeviceState 					  :	T_MSC_GetDeviceState;
			F_MSC_CloseDevice 						  :	T_MSC_CloseDevice;
			F_MSC_SetNotificationMessage 		:	T_MSC_SetNotificationMessage;
			F_MSC_SetupStaticChannel 				:	T_MSC_SetupStaticChannel;
			F_MSC_SetupExtendedDynamicChannel :	T_MSC_SetupExtendedDynamicChannel;
			F_MSC_AttachSubChannelBuffer		:	T_MSC_AttachSubChannelBuffer;
			F_MSC_DetachSubChannelBuffers		:	T_MSC_DetachSubChannelBuffers;
			F_MSC_GetPosition							  :	T_MSC_GetPosition;
      F_MSC_RefreshChannel            : T_MSC_RefreshChannel;
      F_MSC_GetDwordValue             : T_MSC_GetDwordValue;
	end;

implementation



constructor TCMscDll.create;
begin
	inherited create;
end;


//*****************************************************************************
// FUNCTION: cl_MscDll::Load
//-----------------------------------------------------------------------------
// Loads the Msc-DLL and initializes all function pointers to the DLL.
// If the DLL or at least one function pointer can not be loaded/initialized,
// the return value is false.
//-----------------------------------------------------------------------------
// PARAMETERS:
// dllName: Path and filename of MscDll.dll.
//-----------------------------------------------------------------------------
// Return: true on success, otherwise false
//*****************************************************************************
function TCMscDll.Load( dllName : string ) : boolean;
var
	bad : boolean;
begin
	Result := true;
	if Length( dllname ) > 0 then begin
		if hDriver = 0 then begin
			// Load MscDll
			hDriver := LoadLibrary( PCHAR(dllName) );
			if hDriver = 0 then
				bad := True
			else begin
				// Get addresses of DLL functions
				bad := False;
				@F_MSC_GetVersion	:= P_MSC_GetVersion ( GetProcAddress( hDriver, 'MSC_GetVersion' ) );
				if @F_MSC_GetVersion = nil then
					bad := True;
				@F_MSC_EnumerateDevices	:= P_MSC_EnumerateDevices ( GetProcAddress( hDriver, 'MSC_EnumerateDevices' ) );
				if @F_MSC_EnumerateDevices = nil then
					bad := True;
				@F_MSC_GetDeviceInfo	:= P_MSC_GetDeviceInfo ( GetProcAddress( hDriver, 'MSC_GetDeviceInfo' ) );
				if @F_MSC_GetDeviceInfo = nil then
					bad := True;
				@F_MSC_OpenDevice	:= P_MSC_OpenDevice ( GetProcAddress( hDriver, 'MSC_OpenDevice' ) );
				if @F_MSC_OpenDevice = nil then
					bad := True;
				@F_MSC_InitDevice	:= P_MSC_InitDevice ( GetProcAddress( hDriver, 'MSC_InitDevice' ) );
				if @F_MSC_InitDevice = nil then
					bad := True;
				@F_MSC_CloseDevice	:= P_MSC_CloseDevice ( GetProcAddress( hDriver, 'MSC_CloseDevice' ) );
				if @F_MSC_CloseDevice = nil then
					bad := True;
				@F_MSC_SetNotificationMessage := P_MSC_SetNotificationMessage ( GetProcAddress( hDriver, 'MSC_SetNotificationMessage' ) );
				if @F_MSC_SetNotificationMessage = nil then
					bad := True;
				@F_MSC_Start := P_MSC_Start ( GetProcAddress( hDriver, 'MSC_Start' ) );
				if @F_MSC_Start = nil then
					bad := True;
				@F_MSC_Stop := P_MSC_Stop ( GetProcAddress( hDriver, 'MSC_Stop' ) );
				if @F_MSC_Stop = nil then
					bad := True;
				@F_MSC_WriteCommand := P_MSC_WriteCommand ( GetProcAddress( hDriver, 'MSC_WriteCommand' ) );
				if @F_MSC_WriteCommand = nil then
					bad := True;
				@F_MSC_SetupStaticChannel := P_MSC_SetupStaticChannel ( GetProcAddress( hDriver, 'MSC_SetupStaticChannel' ) );
				if @F_MSC_SetupStaticChannel = nil then
					bad := True;
				@F_MSC_SetupExtendedDynamicChannel := P_MSC_SetupExtendedDynamicChannel ( GetProcAddress( hDriver, 'MSC_SetupExtendedDynamicChannel' ) );
				if @F_MSC_SetupExtendedDynamicChannel = nil then
					bad := true;
				@F_MSC_AttachSubChannelBuffer := P_MSC_AttachSubChannelBuffer ( GetProcAddress( hDriver, 'MSC_AttachSubChannelBuffer' ) );
				if @F_MSC_AttachSubChannelBuffer = nil then
					bad := True;
				@F_MSC_DetachSubChannelBuffers := P_MSC_DetachSubChannelBuffers ( GetProcAddress( hDriver, 'MSC_DetachSubChannelBuffers' ) );
				if @F_MSC_DetachSubChannelBuffers = nil then
					bad := True;
				@F_MSC_GetPosition := P_MSC_GetPosition ( GetProcAddress( hDriver, 'MSC_GetPosition' ) );
				if @F_MSC_GetPosition = nil then
					bad := True;
				@F_MSC_GetDeviceState := P_MSC_GetDeviceState ( GetProcAddress( hDriver, 'MSC_GetDeviceState' ) );
				if @F_MSC_GetDeviceState = nil then
					bad := True;
        @F_MSC_RefreshChannel := P_MSC_RefreshChannel ( GetProcAddress( hDriver, 'MSC_RefreshChannel' ) );
        if @F_MSC_RefreshChannel = nil then
          bad := True;
				@F_MSC_ReadStatic := P_MSC_ReadStatic ( GetProcAddress( hDriver, 'MSC_ReadStatic' ) );
				if @F_MSC_ReadStatic = nil then
					bad := True;
        @F_MSC_GetDwordValue := P_MSC_GetDwordValue ( GetProcAddress( hDriver, 'MSC_GetDwordValue' ) );
        if @F_MSC_GetDwordValue = nil then
          bad := True;
			end;

			if bad then begin
				Result := False;
			end;
		end;
	end;
end;

end.
