/* CIN source file */

#include "extcode.h"
#include <windows.h>
#include "..\..\..\Include\wrRtusbapi.h"

/* Typedefs */

typedef struct {
	int32 dimSize;
	int16 BufferEl[1];
	} TD4;
typedef TD4 **TD4Hdl;

typedef struct {
	TD4Hdl Buffer;
	uInt32 ReadOv;
	uInt32 ReadEvent;
	} TD3;

typedef struct {
	int32 dimSize;
	TD3 ReadBufferPars[1];
	} TD2;
typedef TD2 **TD2Hdl;

typedef struct {
	TD4Hdl Buffer;
	uInt32 WriteOv;
	uInt32 WriteEvent;
	} TD6;

typedef struct {
	int32 dimSize;
	TD6 WriteBufferPars[1];
	} TD5;
typedef TD5 **TD5Hdl;

typedef struct {
	uInt32 DllVersion;
	uInt32 InterfaceType;
	uInt32 InterfaceInstance;
	uInt32 ModuleHandle;
	TD2Hdl ReadBuffersParsArray;
	TD5Hdl WriteBuffersParsArray;
	} TD1;

typedef struct {
	LVBoolean Status;
	uInt32 ViErrorNumber;
	LStrHandle ViName;
	LStrHandle ViErrorString;
	LStrHandle CinName;
	LStrHandle CinErrorString;
	} TD7;

enum {UNKNOWN_MODULE, USB2185_MODULE, USB3000_MODULE};

// объявления функций
CIN MgErr CINRun(TD1 *InterfaceInfo, TD7 *ViStatus);
CIN MgErr CINProperties(int32 prop, void *data);

// ---------------------------------------------------------------
// 
// ---------------------------------------------------------------
MgErr CINRun(TD1 *InterfaceInfo, TD7 *ViStatus)
{
	uInt16 i;
	// указатель на интерфейс модуля
	LPVOID pModule;
	// ошибка подпрограмм LabVIEW
	MgErr Error;

	// указатель на интерфейс модуля
	pModule = (LPVOID)InterfaceInfo->InterfaceInstance;

	// с каким модулем работаем?
	if(InterfaceInfo->InterfaceType == USB3000_MODULE)
	{
		// существует ли готовый интерфейс с модулем USB3000?
		if(pModule != NULL)
		{
			// прервём все вложенные запросы сбора данных
			if(!CancelIo((HANDLE)InterfaceInfo->ModuleHandle))
			{
				ViStatus->Status= LVFALSE;
			}

			// освободим интерфейс модуля USB3000
			if(!ReleaseInstance_Usb3000(pModule))
			{
				ViStatus->Status= LVFALSE;
			}
			// обнулим указатель на интерфейс модуля
			InterfaceInfo->InterfaceInstance = (DWORD)NULL;

			// подчистим ранее выделенные ресурсы для работы с вводом данных
			for(i = 0x0; i < (*InterfaceInfo->ReadBuffersParsArray)->dimSize; i++)
			{
				// обнулим массив для входных данных
				Error = NumericArrayResize(iW, 1L, (UHandle*)&(*InterfaceInfo->ReadBuffersParsArray)->ReadBufferPars[i].Buffer, 0x0);
				if(Error != noErr) { ViStatus->Status= LVFALSE; }
				(*(*InterfaceInfo->ReadBuffersParsArray)->ReadBufferPars[i].Buffer)->dimSize = 0x0;

				// закрываем событие ReadEvent
				if(!CloseHandle((HANDLE)((*InterfaceInfo->ReadBuffersParsArray)->ReadBufferPars[i].ReadEvent)))
				{
					ViStatus->Status= LVFALSE;
				}
				(*InterfaceInfo->ReadBuffersParsArray)->ReadBufferPars[i].ReadEvent = (DWORD)INVALID_HANDLE_VALUE;

				// зачищаем структуру OVERLAPPED
				free((void *)((*InterfaceInfo->ReadBuffersParsArray)->ReadBufferPars[i].ReadOv));
				(*InterfaceInfo->ReadBuffersParsArray)->ReadBufferPars[i].ReadOv = (DWORD)NULL;
			}
			// подчистим ReadBuffersParsArray
			Error = NumericArrayResize(uB, 1L, (UHandle*)&InterfaceInfo->ReadBuffersParsArray, 0x0);
			if(Error != noErr) { ViStatus->Status= LVFALSE; }
			else (*InterfaceInfo->ReadBuffersParsArray)->dimSize = 0x0;
		}
		else
		{
			ViStatus->Status= LVFALSE;
		}
	}
	else 
	{ 
		ViStatus->Status= LVFALSE; 
	}

	return noErr;
}

// ---------------------------------------------------------------
// заявляем, что данный CIN - потокобезопасный
// ---------------------------------------------------------------
CIN MgErr CINProperties(int32 prop, void *data)
{
	switch (prop) 
	{
		case kCINIsReentrant:
		*(Bool32 *)data = TRUE;
		return noErr;
	}
	return mgNotSupported;
}
