#include "stdafx.h"

#include "OkReadBadge.h"
#pragma comment (lib, "setupapi.lib")
#pragma comment (lib, "hid.lib")

void OkReadBadge::BadgeUnmanaged::GetDeviceUSB(std::wstring vid, std::wstring pid, std::wstring pid2)
{
	SP_DEVINFO_DATA deviceInfoData;
	DWORD deviceIndex = 0;
	deviceInfoData.cbSize = sizeof(deviceInfoData);
	SP_DEVICE_INTERFACE_DATA deviceInterfaceData;

	GUID hid;
	HidD_GetHidGuid(&hid);
	//buried somewhere deep in the ddk
	/*static GUID GUID_DEVINTERFACE_USB_HUB = { 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
	static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
	static GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27} };*/

	//get usb device interfaces
	HDEVINFO deviceInterfaceSet = SetupDiGetClassDevs(&hid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

	DWORD DeviceInstanceIdSize = 500;
	DWORD RequiredSize = 0;
	WCHAR * DeviceInstanceId = new WCHAR(DeviceInstanceIdSize);
	DeviceType = 0;

	while (DeviceType == 0 && SetupDiEnumDeviceInfo(deviceInterfaceSet, deviceIndex, &deviceInfoData))
	{
		deviceInfoData.cbSize = sizeof(deviceInfoData);
		ULONG IDSize = 0;
		bool rv = CM_Get_Device_ID_Size(&IDSize, deviceInfoData.DevInst, 0);
		TCHAR* deviceID = new TCHAR[IDSize];
		CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, IDSize, 0);
		std::wstring sDeviceID(deviceID);
		auto x = sDeviceID.find(vid);
		auto y = sDeviceID.find(pid);
		auto z = sDeviceID.find(pid2);
		if (x < 100) 
		{
			System::Diagnostics::Trace::WriteLine( gcnew System::String(sDeviceID.c_str()));
		}
		if (x < 100 && (y < 100 || z < 100))
		{
			DWORD deviceInterfaceIndex = 0;
			deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
			System::Diagnostics::Trace::WriteLine(String::Format("x {0}", x));
			if (SetupDiEnumDeviceInterfaces(deviceInterfaceSet, &deviceInfoData, &hid, deviceInterfaceIndex, &deviceInterfaceData))
			{
				deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
				DWORD requiredBufferSize = 0, requiredBufferSize2 = 0;

				SetupDiGetDeviceInterfaceDetail(deviceInterfaceSet, &deviceInterfaceData, NULL, 0, &requiredBufferSize, &deviceInfoData);
				PSP_INTERFACE_DEVICE_DETAIL_DATA ifdetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredBufferSize);
				memset(ifdetail, 0, requiredBufferSize);
				ifdetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
				int rv = SetupDiGetDeviceInterfaceDetail(deviceInterfaceSet, &deviceInterfaceData, ifdetail, requiredBufferSize, &requiredBufferSize2, &deviceInfoData);
				DevicePath = _wcsdup(ifdetail->DevicePath);
				if (z < 100) DeviceType = 2; else DeviceType = 1;
				free(ifdetail);
				deviceInterfaceIndex++;
			}
		}
		deviceIndex++;
	}
}

int OkReadBadge::BadgeUnmanaged::read()
{
	//const string x ="USB\\VID_076B&PID_5128&MI_00\\6&13A62366&0&0000";
	//const wchar_t *devicePath0 = L"\\\\?\\hid#vid_076b&pid_5128&mi_00#7&1ddf3054&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}";
	int rv = 0;
	//const wchar_t *devicePath1 = L"\\\\?\\hid#vid_076b&pid_5428&mi_00#7&95573f7&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}";
	if (DevicePath == nullptr) return 0;
	HANDLE HIDfile = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, nullptr); //FILE_FLAG_OVERLAPPED|
	DWORD err = GetLastError();
	completed = false;
	if (err != 0) {
		//_tprintf(TEXT("unable to obtain read permissions for the HID device, error:\n "));
	}
	else {
		buffer[0] = 0x00; // Feature report 0x0F
		bread = 0;
		rv = 1;
		err = 0;
		while (err==0 && !completed)
		{
			rv = ReadFile(HIDfile, buffer, 100, &bread, Overlapped);
			if (rv == 0) 
			{
				err = GetLastError();
				if (err == ERROR_IO_PENDING) 
				{
					do {
						rv = GetOverlappedResultEx(HIDfile, Overlapped, &bread, 5000, false);
							if (rv == 0) err = GetLastError(); else err = 0;
					} while (err == WAIT_TIMEOUT);
					if (err == 0) {
						// Ok
						Message(0,(LPARAM)this);
					}
					else {
						//Probleem
						Message(err, (LPARAM)this);
					}
				}
				else {
					//1784 = bad buffer
					Message(err, (LPARAM)this);
				}
			}
			else {
				//Ok
				Message(0, (LPARAM)this);
			}
		}
	}
	CloseHandle(HIDfile);
	return 0;
}

OkReadBadge::BadgeUnmanaged::BadgeUnmanaged(BadgeMessageHandler^ clr)
{
	m_clr = clr;
	Overlapped = new OVERLAPPED();
	memset(Overlapped, 0, sizeof(OVERLAPPED));
	Overlapped->Offset = 0;
	Overlapped->hEvent = CreateEvent(nullptr, true, false, nullptr);
	buffer[100];
	memset(buffer, 0, sizeof(buffer));
	buffer[0] = 0x00; // Feature report 0x0F
	bread = 0;
	GetDeviceUSB(L"VID_076B", L"PID_5428", L"PID_5128");
}